uxa-render.c revision 03b705cf
1/* 2 * Copyright © 2001 Keith Packard 3 * 4 * Partly based on code that is Copyright © The XFree86 Project Inc. 5 * 6 * Permission to use, copy, modify, distribute, and sell this software and its 7 * documentation for any purpose is hereby granted without fee, provided that 8 * the above copyright notice appear in all copies and that both that 9 * copyright notice and this permission notice appear in supporting 10 * documentation, and that the name of Keith Packard not be used in 11 * advertising or publicity pertaining to distribution of the software without 12 * specific, written prior permission. Keith Packard makes no 13 * representations about the suitability of this software for any purpose. It 14 * is provided "as is" without express or implied warranty. 15 * 16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 * PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include <stdlib.h> 30 31#include "uxa-priv.h" 32#include "uxa-glamor.h" 33#include <xorgVersion.h> 34 35#ifdef RENDER 36#include "mipict.h" 37 38/* Note: when using glamor we can not fail through to the ordinary UXA 39 * code paths, as glamor keeps an internal texture which will become 40 * inconsistent with the original bo. (The texture is replaced whenever 41 * the format changes, e.g. switching between xRGB and ARGB, for which mesa 42 * will allocate its own bo.) 43 * 44 * Ergo it is unsafe to fall through to the original backend operations if 45 * glamor is enabled. 46 * 47 * XXX This has some serious implications for mixing Render, DRI, scanout... 48 */ 49 50static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, 51 int n) 52{ 53 char format[20]; 54 char size[20]; 55 char loc; 56 57 if (!pict) { 58 snprintf(string, n, "None"); 59 return; 60 } 61 62 if (pict->pDrawable == NULL) { 63 snprintf(string, n, "source-only"); 64 return; 65 } 66 67 switch (pict->format) { 68 case PICT_a8r8g8b8: 69 snprintf(format, 20, "ARGB8888"); 70 break; 71 case PICT_x8r8g8b8: 72 snprintf(format, 20, "XRGB8888"); 73 break; 74 case PICT_r5g6b5: 75 snprintf(format, 20, "RGB565 "); 76 break; 77 case PICT_x1r5g5b5: 78 snprintf(format, 20, "RGB555 "); 79 break; 80 case PICT_a8: 81 snprintf(format, 20, "A8 "); 82 break; 83 case PICT_a1: 84 snprintf(format, 20, "A1 "); 85 break; 86 default: 87 snprintf(format, 20, "0x%x", (int)pict->format); 88 break; 89 } 90 91 loc = uxa_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm'; 92 93 snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, 94 pict->pDrawable->height, pict->repeat ? " R" : ""); 95 96 snprintf(string, n, "%p:%c fmt %s (%s)%s", 97 pict->pDrawable, loc, format, size, 98 pict->alphaMap ? " with alpha map" :""); 99} 100 101static const char * 102op_to_string(CARD8 op) 103{ 104 switch (op) { 105#define C(x) case PictOp##x: return #x 106 C(Clear); 107 C(Src); 108 C(Dst); 109 C(Over); 110 C(OverReverse); 111 C(In); 112 C(InReverse); 113 C(Out); 114 C(OutReverse); 115 C(Atop); 116 C(AtopReverse); 117 C(Xor); 118 C(Add); 119 C(Saturate); 120 121 /* 122 * Operators only available in version 0.2 123 */ 124#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2 125 C(DisjointClear); 126 C(DisjointSrc); 127 C(DisjointDst); 128 C(DisjointOver); 129 C(DisjointOverReverse); 130 C(DisjointIn); 131 C(DisjointInReverse); 132 C(DisjointOut); 133 C(DisjointOutReverse); 134 C(DisjointAtop); 135 C(DisjointAtopReverse); 136 C(DisjointXor); 137 138 C(ConjointClear); 139 C(ConjointSrc); 140 C(ConjointDst); 141 C(ConjointOver); 142 C(ConjointOverReverse); 143 C(ConjointIn); 144 C(ConjointInReverse); 145 C(ConjointOut); 146 C(ConjointOutReverse); 147 C(ConjointAtop); 148 C(ConjointAtopReverse); 149 C(ConjointXor); 150#endif 151 152 /* 153 * Operators only available in version 0.11 154 */ 155#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11 156 C(Multiply); 157 C(Screen); 158 C(Overlay); 159 C(Darken); 160 C(Lighten); 161 C(ColorDodge); 162 C(ColorBurn); 163 C(HardLight); 164 C(SoftLight); 165 C(Difference); 166 C(Exclusion); 167 C(HSLHue); 168 C(HSLSaturation); 169 C(HSLColor); 170 C(HSLLuminosity); 171#endif 172 default: return "garbage"; 173#undef C 174 } 175} 176 177static void 178uxa_print_composite_fallback(const char *func, CARD8 op, 179 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) 180{ 181 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 182 char srcdesc[40], maskdesc[40], dstdesc[40]; 183 184 if (! uxa_screen->fallback_debug) 185 return; 186 187 /* Limit the noise if fallbacks are expected. */ 188 if (uxa_screen->force_fallback) 189 return; 190 191 uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40); 192 uxa_composite_fallback_pict_desc(pMask, maskdesc, 40); 193 uxa_composite_fallback_pict_desc(pDst, dstdesc, 40); 194 195 ErrorF("Composite fallback at %s:\n" 196 " op %s, \n" 197 " src %s, \n" 198 " mask %s, \n" 199 " dst %s, \n", 200 func, op_to_string (op), srcdesc, maskdesc, dstdesc); 201} 202 203Bool uxa_op_reads_destination(CARD8 op) 204{ 205 /* FALSE (does not read destination) is the list of ops in the protocol 206 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. 207 * That's just Clear and Src. ReduceCompositeOp() will already have 208 * converted con/disjoint clear/src to Clear or Src. 209 */ 210 switch (op) { 211 case PictOpClear: 212 case PictOpSrc: 213 return FALSE; 214 default: 215 return TRUE; 216 } 217} 218 219static Bool 220uxa_get_pixel_from_rgba(CARD32 * pixel, 221 CARD16 red, 222 CARD16 green, 223 CARD16 blue, 224 CARD16 alpha, 225 CARD32 format) 226{ 227 int rbits, bbits, gbits, abits; 228 int rshift, bshift, gshift, ashift; 229 230 rbits = PICT_FORMAT_R(format); 231 gbits = PICT_FORMAT_G(format); 232 bbits = PICT_FORMAT_B(format); 233 abits = PICT_FORMAT_A(format); 234 if (abits == 0) 235 abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 236 237 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 238 *pixel = alpha >> (16 - abits); 239 return TRUE; 240 } 241 242 if (!PICT_FORMAT_COLOR(format)) 243 return FALSE; 244 245 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 246 bshift = 0; 247 gshift = bbits; 248 rshift = gshift + gbits; 249 ashift = rshift + rbits; 250 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 251 rshift = 0; 252 gshift = rbits; 253 bshift = gshift + gbits; 254 ashift = bshift + bbits; 255#if XORG_VERSION_CURRENT >= 10699900 256 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 257 ashift = 0; 258 rshift = abits; 259 gshift = rshift + rbits; 260 bshift = gshift + gbits; 261#endif 262 } else { 263 return FALSE; 264 } 265 266 *pixel = 0; 267 *pixel |= (blue >> (16 - bbits)) << bshift; 268 *pixel |= (green >> (16 - gbits)) << gshift; 269 *pixel |= (red >> (16 - rbits)) << rshift; 270 *pixel |= (alpha >> (16 - abits)) << ashift; 271 272 return TRUE; 273} 274 275Bool 276uxa_get_rgba_from_pixel(CARD32 pixel, 277 CARD16 * red, 278 CARD16 * green, 279 CARD16 * blue, 280 CARD16 * alpha, 281 CARD32 format) 282{ 283 int rbits, bbits, gbits, abits; 284 int rshift, bshift, gshift, ashift; 285 286 rbits = PICT_FORMAT_R(format); 287 gbits = PICT_FORMAT_G(format); 288 bbits = PICT_FORMAT_B(format); 289 abits = PICT_FORMAT_A(format); 290 291 if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 292 rshift = gshift = bshift = ashift = 0; 293 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 294 bshift = 0; 295 gshift = bbits; 296 rshift = gshift + gbits; 297 ashift = rshift + rbits; 298 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 299 rshift = 0; 300 gshift = rbits; 301 bshift = gshift + gbits; 302 ashift = bshift + bbits; 303#if XORG_VERSION_CURRENT >= 10699900 304 } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 305 ashift = 0; 306 rshift = abits; 307 if (abits == 0) 308 rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 309 gshift = rshift + rbits; 310 bshift = gshift + gbits; 311#endif 312 } else { 313 return FALSE; 314 } 315 316 if (rbits) { 317 *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 318 while (rbits < 16) { 319 *red |= *red >> rbits; 320 rbits <<= 1; 321 } 322 } else 323 *red = 0; 324 325 if (gbits) { 326 *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 327 while (gbits < 16) { 328 *green |= *green >> gbits; 329 gbits <<= 1; 330 } 331 } else 332 *green = 0; 333 334 if (bbits) { 335 *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 336 while (bbits < 16) { 337 *blue |= *blue >> bbits; 338 bbits <<= 1; 339 } 340 } else 341 *blue = 0; 342 343 if (abits) { 344 *alpha = 345 ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 346 while (abits < 16) { 347 *alpha |= *alpha >> abits; 348 abits <<= 1; 349 } 350 } else 351 *alpha = 0xffff; 352 353 return TRUE; 354} 355 356Bool 357uxa_get_color_for_pixmap (PixmapPtr pixmap, 358 CARD32 src_format, 359 CARD32 dst_format, 360 CARD32 *pixel) 361{ 362 CARD16 red, green, blue, alpha; 363 364 *pixel = uxa_get_pixmap_first_pixel(pixmap); 365 366 if (src_format != dst_format) { 367 if (!uxa_get_rgba_from_pixel(*pixel, 368 &red, &green, &blue, &alpha, 369 src_format)) 370 return FALSE; 371 372 if (!uxa_get_pixel_from_rgba(pixel, 373 red, green, blue, alpha, 374 dst_format)) 375 return FALSE; 376 } 377 378 return TRUE; 379} 380 381static int 382uxa_try_driver_solid_fill(PicturePtr pSrc, 383 PicturePtr pDst, 384 INT16 xSrc, 385 INT16 ySrc, 386 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 387{ 388 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 389 RegionRec region; 390 BoxPtr pbox; 391 int nbox; 392 int dst_off_x, dst_off_y; 393 PixmapPtr pSrcPix = NULL, pDstPix; 394 CARD32 pixel; 395 396 if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES)) 397 return -1; 398 399 pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); 400 if (!pDstPix) 401 return -1; 402 403 xDst += pDst->pDrawable->x; 404 yDst += pDst->pDrawable->y; 405 406 if (pSrc->pDrawable) { 407 pSrcPix = uxa_get_drawable_pixmap(pSrc->pDrawable); 408 xSrc += pSrc->pDrawable->x; 409 ySrc += pSrc->pDrawable->y; 410 } 411 412 if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, 413 xSrc, ySrc, 0, 0, xDst, yDst, 414 width, height)) 415 return 1; 416 417 if (pSrcPix) { 418 if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) { 419 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 420 return -1; 421 } 422 } else { 423 SourcePict *source = pSrc->pSourcePict; 424 PictSolidFill *solid = &source->solidFill; 425 426 if (source == NULL || source->type != SourcePictTypeSolidFill) { 427 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 428 return -1; 429 } 430 431 if (pDst->format == PICT_a8r8g8b8) { 432 pixel = solid->color; 433 } else if (pDst->format == PICT_x8r8g8b8) { 434 pixel = solid->color | 0xff000000; 435 } else { 436 CARD16 red, green, blue, alpha; 437 438 if (!uxa_get_rgba_from_pixel(solid->color, 439 &red, &green, &blue, &alpha, 440 PICT_a8r8g8b8) || 441 !uxa_get_pixel_from_rgba(&pixel, 442 red, green, blue, alpha, 443 pDst->format)) { 444 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 445 return -1; 446 } 447 } 448 } 449 450 if (!(*uxa_screen->info->prepare_solid) 451 (pDstPix, GXcopy, FB_ALLONES, pixel)) { 452 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 453 return -1; 454 } 455 456 REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); 457 458 nbox = REGION_NUM_RECTS(®ion); 459 pbox = REGION_RECTS(®ion); 460 461 while (nbox--) { 462 (*uxa_screen->info->solid) (pDstPix, pbox->x1, pbox->y1, 463 pbox->x2, pbox->y2); 464 pbox++; 465 } 466 467 (*uxa_screen->info->done_solid) (pDstPix); 468 469 REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); 470 return 1; 471} 472 473static PicturePtr 474uxa_picture_for_pixman_format(ScreenPtr screen, 475 pixman_format_code_t format, 476 int width, int height) 477{ 478 PicturePtr picture; 479 PixmapPtr pixmap; 480 int error; 481 482 if (format == PIXMAN_a1) 483 format = PIXMAN_a8; 484 485 /* fill alpha if unset */ 486 if (PIXMAN_FORMAT_A(format) == 0) 487 format = PIXMAN_a8r8g8b8; 488 489 pixmap = screen->CreatePixmap(screen, width, height, 490 PIXMAN_FORMAT_DEPTH(format), 491 UXA_CREATE_PIXMAP_FOR_MAP); 492 if (!pixmap) 493 return 0; 494 495 if (!uxa_pixmap_is_offscreen(pixmap)) { 496 screen->DestroyPixmap(pixmap); 497 return 0; 498 } 499 500 picture = CreatePicture(0, &pixmap->drawable, 501 PictureMatchFormat(screen, 502 PIXMAN_FORMAT_DEPTH(format), 503 format), 504 0, 0, serverClient, &error); 505 screen->DestroyPixmap(pixmap); 506 if (!picture) 507 return 0; 508 509 ValidatePicture(picture); 510 511 return picture; 512} 513 514static PicturePtr 515uxa_picture_from_pixman_image(ScreenPtr screen, 516 pixman_image_t * image, 517 pixman_format_code_t format) 518{ 519 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 520 PicturePtr picture; 521 PixmapPtr pixmap; 522 int width, height; 523 524 width = pixman_image_get_width(image); 525 height = pixman_image_get_height(image); 526 527 picture = uxa_picture_for_pixman_format(screen, format, 528 width, height); 529 if (!picture) 530 return 0; 531 532 if (uxa_screen->info->put_image && 533 ((picture->pDrawable->depth << 24) | picture->format) == format && 534 uxa_screen->info->put_image((PixmapPtr)picture->pDrawable, 535 0, 0, 536 width, height, 537 (char *)pixman_image_get_data(image), 538 pixman_image_get_stride(image))) 539 return picture; 540 541 pixmap = GetScratchPixmapHeader(screen, width, height, 542 PIXMAN_FORMAT_DEPTH(format), 543 PIXMAN_FORMAT_BPP(format), 544 pixman_image_get_stride(image), 545 pixman_image_get_data(image)); 546 if (!pixmap) { 547 FreePicture(picture, 0); 548 return 0; 549 } 550 551 if (((picture->pDrawable->depth << 24) | picture->format) == format) { 552 GCPtr gc; 553 554 gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen); 555 if (!gc) { 556 FreeScratchPixmapHeader(pixmap); 557 FreePicture(picture, 0); 558 return 0; 559 } 560 ValidateGC(picture->pDrawable, gc); 561 562 (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable, 563 gc, 0, 0, width, height, 0, 0); 564 565 FreeScratchGC(gc); 566 } else { 567 PicturePtr src; 568 int error; 569 570 src = CreatePicture(0, &pixmap->drawable, 571 PictureMatchFormat(screen, 572 PIXMAN_FORMAT_DEPTH(format), 573 format), 574 0, 0, serverClient, &error); 575 if (!src) { 576 FreeScratchPixmapHeader(pixmap); 577 FreePicture(picture, 0); 578 return 0; 579 } 580 ValidatePicture(src); 581 582 if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) { 583 fbComposite(PictOpSrc, src, NULL, picture, 584 0, 0, 0, 0, 0, 0, width, height); 585 uxa_picture_finish_access(picture, UXA_ACCESS_RW); 586 } 587 588 FreePicture(src, 0); 589 } 590 FreeScratchPixmapHeader(pixmap); 591 592 return picture; 593} 594 595static PicturePtr 596uxa_create_solid(ScreenPtr screen, uint32_t color) 597{ 598 PixmapPtr pixmap; 599 PicturePtr picture; 600 XID repeat = RepeatNormal; 601 int error = 0; 602 603 pixmap = (*screen->CreatePixmap)(screen, 1, 1, 32, 604 UXA_CREATE_PIXMAP_FOR_MAP); 605 if (!pixmap) 606 return 0; 607 608 if (!uxa_prepare_access((DrawablePtr)pixmap, UXA_ACCESS_RW)) { 609 (*screen->DestroyPixmap)(pixmap); 610 return 0; 611 } 612 *((uint32_t *)pixmap->devPrivate.ptr) = color; 613 uxa_finish_access((DrawablePtr)pixmap, UXA_ACCESS_RW); 614 615 picture = CreatePicture(0, &pixmap->drawable, 616 PictureMatchFormat(screen, 32, PICT_a8r8g8b8), 617 CPRepeat, &repeat, serverClient, &error); 618 (*screen->DestroyPixmap)(pixmap); 619 620 return picture; 621} 622 623static PicturePtr 624uxa_solid_clear(ScreenPtr screen) 625{ 626 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 627 PicturePtr picture; 628 629 if (!uxa_screen->solid_clear) { 630 uxa_screen->solid_clear = uxa_create_solid(screen, 0); 631 if (!uxa_screen->solid_clear) 632 return 0; 633 } 634 picture = uxa_screen->solid_clear; 635 return picture; 636} 637 638PicturePtr 639uxa_acquire_solid(ScreenPtr screen, SourcePict *source) 640{ 641 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 642 PictSolidFill *solid = &source->solidFill; 643 PicturePtr picture; 644 int i; 645 646 if ((solid->color >> 24) == 0) { 647 picture = uxa_solid_clear(screen); 648 if (!picture) 649 return 0; 650 651 goto DONE; 652 } else if (solid->color == 0xff000000) { 653 if (!uxa_screen->solid_black) { 654 uxa_screen->solid_black = uxa_create_solid(screen, 0xff000000); 655 if (!uxa_screen->solid_black) 656 return 0; 657 } 658 picture = uxa_screen->solid_black; 659 goto DONE; 660 } else if (solid->color == 0xffffffff) { 661 if (!uxa_screen->solid_white) { 662 uxa_screen->solid_white = uxa_create_solid(screen, 0xffffffff); 663 if (!uxa_screen->solid_white) 664 return 0; 665 } 666 picture = uxa_screen->solid_white; 667 goto DONE; 668 } 669 670 for (i = 0; i < uxa_screen->solid_cache_size; i++) { 671 if (uxa_screen->solid_cache[i].color == solid->color) { 672 picture = uxa_screen->solid_cache[i].picture; 673 goto DONE; 674 } 675 } 676 677 picture = uxa_create_solid(screen, solid->color); 678 if (!picture) 679 return 0; 680 681 if (uxa_screen->solid_cache_size == UXA_NUM_SOLID_CACHE) { 682 i = rand() % UXA_NUM_SOLID_CACHE; 683 FreePicture(uxa_screen->solid_cache[i].picture, 0); 684 } else 685 uxa_screen->solid_cache_size++; 686 687 uxa_screen->solid_cache[i].picture = picture; 688 uxa_screen->solid_cache[i].color = solid->color; 689 690DONE: 691 picture->refcnt++; 692 return picture; 693} 694 695PicturePtr 696uxa_acquire_pattern(ScreenPtr pScreen, 697 PicturePtr pSrc, 698 pixman_format_code_t format, 699 INT16 x, INT16 y, CARD16 width, CARD16 height) 700{ 701 PicturePtr pDst; 702 703 if (pSrc->pSourcePict) { 704 SourcePict *source = pSrc->pSourcePict; 705 if (source->type == SourcePictTypeSolidFill) 706 return uxa_acquire_solid (pScreen, source); 707 } 708 709 pDst = uxa_picture_for_pixman_format(pScreen, format, width, height); 710 if (!pDst) 711 return 0; 712 713 if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) { 714 fbComposite(PictOpSrc, pSrc, NULL, pDst, 715 x, y, 0, 0, 0, 0, width, height); 716 uxa_picture_finish_access(pDst, UXA_ACCESS_RW); 717 return pDst; 718 } else { 719 FreePicture(pDst, 0); 720 return 0; 721 } 722} 723 724static Bool 725transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty) 726{ 727 if (t == NULL) { 728 *tx = *ty = 0; 729 return TRUE; 730 } 731 732 if (t->matrix[0][0] != IntToxFixed(1) || 733 t->matrix[0][1] != 0 || 734 t->matrix[1][0] != 0 || 735 t->matrix[1][1] != IntToxFixed(1) || 736 t->matrix[2][0] != 0 || 737 t->matrix[2][1] != 0 || 738 t->matrix[2][2] != IntToxFixed(1)) 739 return FALSE; 740 741 if (xFixedFrac(t->matrix[0][2]) != 0 || 742 xFixedFrac(t->matrix[1][2]) != 0) 743 return FALSE; 744 745 *tx = xFixedToInt(t->matrix[0][2]); 746 *ty = xFixedToInt(t->matrix[1][2]); 747 return TRUE; 748} 749 750static PicturePtr 751uxa_render_picture(ScreenPtr screen, 752 PicturePtr src, 753 pixman_format_code_t format, 754 INT16 x, INT16 y, 755 CARD16 width, CARD16 height) 756{ 757 PicturePtr picture; 758 int ret = 0; 759 760 /* XXX we need a mechanism for the card to choose the fallback format */ 761 762 /* force alpha channel in case source does not entirely cover the extents */ 763 if (PIXMAN_FORMAT_A(format) == 0) 764 format = PIXMAN_a8r8g8b8; /* available on all hardware */ 765 766 picture = uxa_picture_for_pixman_format(screen, format, width, height); 767 if (!picture) 768 return 0; 769 770 if (uxa_picture_prepare_access(picture, UXA_ACCESS_RW)) { 771 if (uxa_picture_prepare_access(src, UXA_ACCESS_RO)) { 772 ret = 1; 773 fbComposite(PictOpSrc, src, NULL, picture, 774 x, y, 0, 0, 0, 0, width, height); 775 uxa_picture_finish_access(src, UXA_ACCESS_RO); 776 } 777 uxa_picture_finish_access(picture, UXA_ACCESS_RW); 778 } 779 780 if (!ret) { 781 FreePicture(picture, 0); 782 return 0; 783 } 784 785 return picture; 786} 787 788static int 789drawable_contains (DrawablePtr drawable, int x, int y, int w, int h) 790{ 791 if (x < 0 || y < 0) 792 return FALSE; 793 794 if (x + w > drawable->width) 795 return FALSE; 796 797 if (y + h > drawable->height) 798 return FALSE; 799 800 return TRUE; 801} 802 803PicturePtr 804uxa_acquire_drawable(ScreenPtr pScreen, 805 PicturePtr pSrc, 806 INT16 x, INT16 y, 807 CARD16 width, CARD16 height, 808 INT16 * out_x, INT16 * out_y) 809{ 810 PixmapPtr pPixmap; 811 PicturePtr pDst; 812 int depth, error; 813 int tx, ty; 814 GCPtr pGC; 815 816 depth = pSrc->pDrawable->depth; 817 if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) || 818 !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) || 819 depth == 1 || 820 pSrc->filter == PictFilterConvolution) { 821 /* XXX extract the sample extents and do the transformation on the GPU */ 822 pDst = uxa_render_picture(pScreen, pSrc, 823 pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24), 824 x, y, width, height); 825 if (!pDst) 826 return 0; 827 828 goto done; 829 } else { 830 if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) { 831 *out_x = x + pSrc->pDrawable->x; 832 *out_y = y + pSrc->pDrawable->y; 833 return pSrc; 834 } 835 } 836 837 pPixmap = pScreen->CreatePixmap(pScreen, 838 width, height, depth, 839 CREATE_PIXMAP_USAGE_SCRATCH); 840 if (!pPixmap) 841 return 0; 842 843 /* Skip the copy if the result remains in memory and not a bo */ 844 if (!uxa_pixmap_is_offscreen(pPixmap)) { 845 pScreen->DestroyPixmap(pPixmap); 846 return 0; 847 } 848 849 pGC = GetScratchGC(depth, pScreen); 850 if (!pGC) { 851 pScreen->DestroyPixmap(pPixmap); 852 return 0; 853 } 854 855 ValidateGC(&pPixmap->drawable, pGC); 856 pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC, 857 x + tx, y + ty, width, height, 0, 0); 858 FreeScratchGC(pGC); 859 860 pDst = CreatePicture(0, &pPixmap->drawable, 861 PictureMatchFormat(pScreen, depth, pSrc->format), 862 0, 0, serverClient, &error); 863 pScreen->DestroyPixmap(pPixmap); 864 if (!pDst) 865 return 0; 866 867 ValidatePicture(pDst); 868done: 869 pDst->componentAlpha = pSrc->componentAlpha; 870 *out_x = 0; 871 *out_y = 0; 872 return pDst; 873} 874 875static PicturePtr 876uxa_acquire_picture(ScreenPtr screen, 877 PicturePtr src, 878 pixman_format_code_t format, 879 INT16 x, INT16 y, 880 CARD16 width, CARD16 height, 881 INT16 * out_x, INT16 * out_y) 882{ 883 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 884 885 if (uxa_screen->info->check_composite_texture && 886 uxa_screen->info->check_composite_texture(screen, src)) { 887 if (src->pDrawable) { 888 *out_x = x + src->pDrawable->x; 889 *out_y = y + src->pDrawable->y; 890 } else { 891 *out_x = x; 892 *out_y = y; 893 } 894 return src; 895 } 896 897 if (src->pDrawable) { 898 PicturePtr dst; 899 900 dst = uxa_acquire_drawable(screen, src, 901 x, y, width, height, 902 out_x, out_y); 903 if (!dst) 904 return 0; 905 906 if (uxa_screen->info->check_composite_texture && 907 !uxa_screen->info->check_composite_texture(screen, dst)) { 908 if (dst != src) 909 FreePicture(dst, 0); 910 return 0; 911 } 912 913 return dst; 914 } 915 916 *out_x = 0; 917 *out_y = 0; 918 return uxa_acquire_pattern(screen, src, 919 format, x, y, width, height); 920} 921 922static PicturePtr 923uxa_acquire_source(ScreenPtr screen, 924 PicturePtr pict, 925 INT16 x, INT16 y, 926 CARD16 width, CARD16 height, 927 INT16 * out_x, INT16 * out_y) 928{ 929 return uxa_acquire_picture (screen, pict, 930 PICT_a8r8g8b8, 931 x, y, 932 width, height, 933 out_x, out_y); 934} 935 936static PicturePtr 937uxa_acquire_mask(ScreenPtr screen, 938 PicturePtr pict, 939 INT16 x, INT16 y, 940 INT16 width, INT16 height, 941 INT16 * out_x, INT16 * out_y) 942{ 943 return uxa_acquire_picture (screen, pict, 944 PICT_a8, 945 x, y, 946 width, height, 947 out_x, out_y); 948} 949 950static int 951uxa_try_driver_composite(CARD8 op, 952 PicturePtr pSrc, 953 PicturePtr pMask, 954 PicturePtr pDst, 955 INT16 xSrc, INT16 ySrc, 956 INT16 xMask, INT16 yMask, 957 INT16 xDst, INT16 yDst, 958 CARD16 width, CARD16 height) 959{ 960 ScreenPtr screen = pDst->pDrawable->pScreen; 961 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 962 RegionRec region; 963 BoxPtr pbox; 964 int nbox; 965 int xDst_copy = 0, yDst_copy = 0; 966 int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; 967 PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; 968 PicturePtr localSrc, localMask = NULL; 969 PicturePtr localDst = pDst; 970 971 if (uxa_screen->info->check_composite && 972 !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height)) 973 return -1; 974 975 if (uxa_screen->info->check_composite_target && 976 !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { 977 int depth = pDst->pDrawable->depth; 978 PixmapPtr pixmap; 979 int error; 980 GCPtr gc; 981 982 pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); 983 if (uxa_screen->info->check_copy && 984 !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) 985 return -1; 986 987 pixmap = screen->CreatePixmap(screen, 988 width, height, depth, 989 CREATE_PIXMAP_USAGE_SCRATCH); 990 if (!pixmap) 991 return 0; 992 993 gc = GetScratchGC(depth, screen); 994 if (!gc) { 995 screen->DestroyPixmap(pixmap); 996 return 0; 997 } 998 999 ValidateGC(&pixmap->drawable, gc); 1000 gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, 1001 xDst, yDst, width, height, 0, 0); 1002 FreeScratchGC(gc); 1003 1004 xDst_copy = xDst; xDst = 0; 1005 yDst_copy = yDst; yDst = 0; 1006 1007 localDst = CreatePicture(0, &pixmap->drawable, 1008 PictureMatchFormat(screen, depth, pDst->format), 1009 0, 0, serverClient, &error); 1010 screen->DestroyPixmap(pixmap); 1011 1012 if (!localDst) 1013 return 0; 1014 1015 ValidatePicture(localDst); 1016 } 1017 1018 pDstPix = 1019 uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y); 1020 if (!pDstPix) { 1021 if (localDst != pDst) 1022 FreePicture(localDst, 0); 1023 return -1; 1024 } 1025 1026 xDst += localDst->pDrawable->x; 1027 yDst += localDst->pDrawable->y; 1028 1029 localSrc = uxa_acquire_source(screen, pSrc, 1030 xSrc, ySrc, 1031 width, height, 1032 &xSrc, &ySrc); 1033 if (!localSrc) { 1034 if (localDst != pDst) 1035 FreePicture(localDst, 0); 1036 return 0; 1037 } 1038 1039 if (pMask) { 1040 localMask = uxa_acquire_mask(screen, pMask, 1041 xMask, yMask, 1042 width, height, 1043 &xMask, &yMask); 1044 if (!localMask) { 1045 if (localSrc != pSrc) 1046 FreePicture(localSrc, 0); 1047 if (localDst != pDst) 1048 FreePicture(localDst, 0); 1049 1050 return 0; 1051 } 1052 } 1053 1054 if (!miComputeCompositeRegion(®ion, localSrc, localMask, localDst, 1055 xSrc, ySrc, xMask, yMask, xDst, yDst, 1056 width, height)) { 1057 if (localSrc != pSrc) 1058 FreePicture(localSrc, 0); 1059 if (localMask && localMask != pMask) 1060 FreePicture(localMask, 0); 1061 if (localDst != pDst) 1062 FreePicture(localDst, 0); 1063 1064 return 1; 1065 } 1066 1067 pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable, 1068 &src_off_x, &src_off_y); 1069 if (!pSrcPix) { 1070 REGION_UNINIT(screen, ®ion); 1071 1072 if (localSrc != pSrc) 1073 FreePicture(localSrc, 0); 1074 if (localMask && localMask != pMask) 1075 FreePicture(localMask, 0); 1076 if (localDst != pDst) 1077 FreePicture(localDst, 0); 1078 1079 return 0; 1080 } 1081 1082 if (localMask) { 1083 pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable, 1084 &mask_off_x, &mask_off_y); 1085 if (!pMaskPix) { 1086 REGION_UNINIT(screen, ®ion); 1087 1088 if (localSrc != pSrc) 1089 FreePicture(localSrc, 0); 1090 if (localMask && localMask != pMask) 1091 FreePicture(localMask, 0); 1092 if (localDst != pDst) 1093 FreePicture(localDst, 0); 1094 1095 return 0; 1096 } 1097 } 1098 1099 if (!(*uxa_screen->info->prepare_composite) 1100 (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) { 1101 REGION_UNINIT(screen, ®ion); 1102 1103 if (localSrc != pSrc) 1104 FreePicture(localSrc, 0); 1105 if (localMask && localMask != pMask) 1106 FreePicture(localMask, 0); 1107 if (localDst != pDst) 1108 FreePicture(localDst, 0); 1109 1110 return -1; 1111 } 1112 1113 if (pMask) { 1114 xMask = xMask + mask_off_x - xDst; 1115 yMask = yMask + mask_off_y - yDst; 1116 } 1117 1118 xSrc = xSrc + src_off_x - xDst; 1119 ySrc = ySrc + src_off_y - yDst; 1120 1121 nbox = REGION_NUM_RECTS(®ion); 1122 pbox = REGION_RECTS(®ion); 1123 while (nbox--) { 1124 (*uxa_screen->info->composite) (pDstPix, 1125 pbox->x1 + xSrc, 1126 pbox->y1 + ySrc, 1127 pbox->x1 + xMask, 1128 pbox->y1 + yMask, 1129 pbox->x1 + dst_off_x, 1130 pbox->y1 + dst_off_y, 1131 pbox->x2 - pbox->x1, 1132 pbox->y2 - pbox->y1); 1133 pbox++; 1134 } 1135 (*uxa_screen->info->done_composite) (pDstPix); 1136 1137 REGION_UNINIT(screen, ®ion); 1138 1139 if (localSrc != pSrc) 1140 FreePicture(localSrc, 0); 1141 if (localMask && localMask != pMask) 1142 FreePicture(localMask, 0); 1143 1144 if (localDst != pDst) { 1145 GCPtr gc; 1146 1147 gc = GetScratchGC(pDst->pDrawable->depth, screen); 1148 if (gc) { 1149 ValidateGC(pDst->pDrawable, gc); 1150 gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, 1151 0, 0, width, height, xDst_copy, yDst_copy); 1152 FreeScratchGC(gc); 1153 } 1154 1155 FreePicture(localDst, 0); 1156 } 1157 1158 return 1; 1159} 1160 1161/** 1162 * uxa_try_magic_two_pass_composite_helper implements PictOpOver using two passes of 1163 * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component 1164 * alpha and limited 1-tmu cards. 1165 * 1166 * From http://anholt.livejournal.com/32058.html: 1167 * 1168 * The trouble is that component-alpha rendering requires two different sources 1169 * for blending: one for the source value to the blender, which is the 1170 * per-channel multiplication of source and mask, and one for the source alpha 1171 * for multiplying with the destination channels, which is the multiplication 1172 * of the source channels by the mask alpha. So the equation for Over is: 1173 * 1174 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A 1175 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R 1176 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G 1177 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B 1178 * 1179 * But we can do some simpler operations, right? How about PictOpOutReverse, 1180 * which has a source factor of 0 and dest factor of (1 - source alpha). We 1181 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture 1182 * blenders pretty easily. So we can do a component-alpha OutReverse, which 1183 * gets us: 1184 * 1185 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A 1186 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R 1187 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G 1188 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B 1189 * 1190 * OK. And if an op doesn't use the source alpha value for the destination 1191 * factor, then we can do the channel multiplication in the texture blenders 1192 * to get the source value, and ignore the source alpha that we wouldn't use. 1193 * We've supported this in the Radeon driver for a long time. An example would 1194 * be PictOpAdd, which does: 1195 * 1196 * dst.A = src.A * mask.A + dst.A 1197 * dst.R = src.R * mask.R + dst.R 1198 * dst.G = src.G * mask.G + dst.G 1199 * dst.B = src.B * mask.B + dst.B 1200 * 1201 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right 1202 * after it, we get: 1203 * 1204 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) 1205 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) 1206 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) 1207 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) 1208 */ 1209 1210static int 1211uxa_try_magic_two_pass_composite_helper(CARD8 op, 1212 PicturePtr pSrc, 1213 PicturePtr pMask, 1214 PicturePtr pDst, 1215 INT16 xSrc, INT16 ySrc, 1216 INT16 xMask, INT16 yMask, 1217 INT16 xDst, INT16 yDst, 1218 CARD16 width, CARD16 height) 1219{ 1220 ScreenPtr screen = pDst->pDrawable->pScreen; 1221 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1222 PicturePtr localDst = pDst; 1223 int xDst_copy, yDst_copy; 1224 1225 assert(op == PictOpOver); 1226 1227 if (uxa_screen->info->check_composite && 1228 (!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc, 1229 pMask, pDst, width, height) 1230 || !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask, 1231 pDst, width, height))) { 1232 return -1; 1233 } 1234 1235 if (uxa_screen->info->check_composite_target && 1236 !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) { 1237 int depth = pDst->pDrawable->depth; 1238 PixmapPtr pixmap; 1239 int error; 1240 GCPtr gc; 1241 1242 pixmap = uxa_get_drawable_pixmap(pDst->pDrawable); 1243 if (uxa_screen->info->check_copy && 1244 !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES)) 1245 return -1; 1246 1247 pixmap = screen->CreatePixmap(screen, 1248 width, height, depth, 1249 CREATE_PIXMAP_USAGE_SCRATCH); 1250 if (!pixmap) 1251 return 0; 1252 1253 gc = GetScratchGC(depth, screen); 1254 if (!gc) { 1255 screen->DestroyPixmap(pixmap); 1256 return 0; 1257 } 1258 1259 ValidateGC(&pixmap->drawable, gc); 1260 gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc, 1261 xDst, yDst, width, height, 0, 0); 1262 FreeScratchGC(gc); 1263 1264 xDst_copy = xDst; xDst = 0; 1265 yDst_copy = yDst; yDst = 0; 1266 1267 localDst = CreatePicture(0, &pixmap->drawable, 1268 PictureMatchFormat(screen, depth, pDst->format), 1269 0, 0, serverClient, &error); 1270 screen->DestroyPixmap(pixmap); 1271 1272 if (!localDst) 1273 return 0; 1274 1275 ValidatePicture(localDst); 1276 } 1277 1278 /* Now, we think we should be able to accelerate this operation. First, 1279 * composite the destination to be the destination times the source alpha 1280 * factors. 1281 */ 1282 uxa_composite(PictOpOutReverse, pSrc, pMask, localDst, 1283 xSrc, ySrc, 1284 xMask, yMask, 1285 xDst, yDst, 1286 width, height); 1287 1288 /* Then, add in the source value times the destination alpha factors (1.0). 1289 */ 1290 uxa_composite(PictOpAdd, pSrc, pMask, localDst, 1291 xSrc, ySrc, 1292 xMask, yMask, 1293 xDst, yDst, 1294 width, height); 1295 1296 if (localDst != pDst) { 1297 GCPtr gc; 1298 1299 gc = GetScratchGC(pDst->pDrawable->depth, screen); 1300 if (gc) { 1301 ValidateGC(pDst->pDrawable, gc); 1302 gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc, 1303 0, 0, width, height, xDst_copy, yDst_copy); 1304 FreeScratchGC(gc); 1305 } 1306 1307 FreePicture(localDst, 0); 1308 } 1309 1310 return 1; 1311} 1312 1313static int 1314compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src) 1315{ 1316 if (op == PictOpSrc) { 1317 if (src->format == dst->format) 1318 return 1; 1319 1320 /* Is the destination an alpha-less version of source? */ 1321 if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format), 1322 PICT_FORMAT_TYPE(src->format), 1323 0, 1324 PICT_FORMAT_R(src->format), 1325 PICT_FORMAT_G(src->format), 1326 PICT_FORMAT_B(src->format))) 1327 return 1; 1328 1329 /* XXX xrgb is promoted to argb during image upload... */ 1330#if 0 1331 if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8) 1332 return 1; 1333#endif 1334 } else if (op == PictOpOver) { 1335 if (PICT_FORMAT_A(src->format)) 1336 return 0; 1337 1338 return src->format == dst->format; 1339 } 1340 1341 return 0; 1342} 1343 1344void 1345uxa_composite(CARD8 op, 1346 PicturePtr pSrc, 1347 PicturePtr pMask, 1348 PicturePtr pDst, 1349 INT16 xSrc, INT16 ySrc, 1350 INT16 xMask, INT16 yMask, 1351 INT16 xDst, INT16 yDst, 1352 CARD16 width, CARD16 height) 1353{ 1354 uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); 1355 int ret = -1; 1356 Bool saveSrcRepeat = pSrc->repeat; 1357 Bool saveMaskRepeat = pMask ? pMask->repeat : 0; 1358 RegionRec region; 1359 int tx, ty; 1360 1361 if (uxa_screen->info->flags & UXA_USE_GLAMOR) { 1362 int ok; 1363 1364 uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW); 1365 uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO); 1366 if (pMask) 1367 uxa_picture_prepare_access(pMask, UXA_GLAMOR_ACCESS_RO); 1368 1369 ok = glamor_composite_nf(op, 1370 pSrc, pMask, pDst, xSrc, ySrc, 1371 xMask, yMask, xDst, yDst, 1372 width, height); 1373 1374 if (pMask) 1375 uxa_picture_finish_access(pMask, UXA_GLAMOR_ACCESS_RO); 1376 uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO); 1377 uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW); 1378 1379 if (!ok) 1380 goto fallback; 1381 1382 return; 1383 } 1384 1385 if (uxa_screen->force_fallback) 1386 goto fallback; 1387 1388 if (!uxa_drawable_is_offscreen(pDst->pDrawable)) 1389 goto fallback; 1390 1391 if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) 1392 goto fallback; 1393 1394 /* Remove repeat in source if useless */ 1395 if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution && 1396 transform_is_integer_translation(pSrc->transform, &tx, &ty) && 1397 (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) && 1398 drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height)) 1399 pSrc->repeat = 0; 1400 1401 if (!pMask) { 1402 if (op == PictOpClear) { 1403 PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen); 1404 if (clear && 1405 uxa_try_driver_solid_fill(clear, pDst, 1406 xSrc, ySrc, 1407 xDst, yDst, 1408 width, height) == 1) 1409 goto done; 1410 } 1411 1412 if (pSrc->pDrawable == NULL) { 1413 if (pSrc->pSourcePict) { 1414 SourcePict *source = pSrc->pSourcePict; 1415 if (source->type == SourcePictTypeSolidFill) { 1416 if (op == PictOpSrc || 1417 (op == PictOpOver && 1418 (source->solidFill.color & 0xff000000) == 0xff000000)) { 1419 ret = uxa_try_driver_solid_fill(pSrc, pDst, 1420 xSrc, ySrc, 1421 xDst, yDst, 1422 width, height); 1423 if (ret == 1) 1424 goto done; 1425 } 1426 } 1427 } 1428 } else if (pSrc->pDrawable->width == 1 && 1429 pSrc->pDrawable->height == 1 && 1430 pSrc->repeat && 1431 (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) { 1432 ret = uxa_try_driver_solid_fill(pSrc, pDst, 1433 xSrc, ySrc, 1434 xDst, yDst, 1435 width, height); 1436 if (ret == 1) 1437 goto done; 1438 } else if (compatible_formats (op, pDst, pSrc) && 1439 pSrc->filter != PictFilterConvolution && 1440 transform_is_integer_translation(pSrc->transform, &tx, &ty)) { 1441 if (!pSrc->repeat && 1442 drawable_contains(pSrc->pDrawable, 1443 xSrc + tx, ySrc + ty, 1444 width, height)) { 1445 xDst += pDst->pDrawable->x; 1446 yDst += pDst->pDrawable->y; 1447 xSrc += pSrc->pDrawable->x + tx; 1448 ySrc += pSrc->pDrawable->y + ty; 1449 1450 if (!miComputeCompositeRegion 1451 (®ion, pSrc, pMask, pDst, xSrc, ySrc, 1452 xMask, yMask, xDst, yDst, width, height)) 1453 goto done; 1454 1455 uxa_copy_n_to_n(pSrc->pDrawable, 1456 pDst->pDrawable, NULL, 1457 REGION_RECTS(®ion), 1458 REGION_NUM_RECTS(®ion), 1459 xSrc - xDst, ySrc - yDst, FALSE, 1460 FALSE, 0, NULL); 1461 REGION_UNINIT(pDst->pDrawable->pScreen, 1462 ®ion); 1463 goto done; 1464 } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal && 1465 pSrc->pDrawable->type == DRAWABLE_PIXMAP) { 1466 DDXPointRec patOrg; 1467 1468 /* Let's see if the driver can do the repeat 1469 * in one go 1470 */ 1471 if (uxa_screen->info->prepare_composite) { 1472 ret = uxa_try_driver_composite(op, pSrc, 1473 pMask, pDst, 1474 xSrc, ySrc, 1475 xMask, yMask, 1476 xDst, yDst, 1477 width, height); 1478 if (ret == 1) 1479 goto done; 1480 } 1481 1482 /* Now see if we can use 1483 * uxa_fill_region_tiled() 1484 */ 1485 xDst += pDst->pDrawable->x; 1486 yDst += pDst->pDrawable->y; 1487 xSrc += pSrc->pDrawable->x + tx; 1488 ySrc += pSrc->pDrawable->y + ty; 1489 1490 if (!miComputeCompositeRegion 1491 (®ion, pSrc, pMask, pDst, xSrc, ySrc, 1492 xMask, yMask, xDst, yDst, width, height)) 1493 goto done; 1494 1495 /* pattern origin is the point in the 1496 * destination drawable 1497 * corresponding to (0,0) in the source */ 1498 patOrg.x = xDst - xSrc; 1499 patOrg.y = yDst - ySrc; 1500 1501 ret = uxa_fill_region_tiled(pDst->pDrawable, 1502 ®ion, 1503 (PixmapPtr) pSrc-> 1504 pDrawable, &patOrg, 1505 FB_ALLONES, GXcopy); 1506 1507 REGION_UNINIT(pDst->pDrawable->pScreen, 1508 ®ion); 1509 1510 if (ret) 1511 goto done; 1512 } 1513 } 1514 } 1515 1516 /* Remove repeat in mask if useless */ 1517 if (pMask && pMask->pDrawable && pMask->repeat && 1518 pMask->filter != PictFilterConvolution && 1519 transform_is_integer_translation(pMask->transform, &tx, &ty) && 1520 (pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) && 1521 drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height)) 1522 pMask->repeat = 0; 1523 1524 if (uxa_screen->info->prepare_composite) { 1525 Bool isSrcSolid; 1526 1527 ret = 1528 uxa_try_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, 1529 xMask, yMask, xDst, yDst, width, 1530 height); 1531 if (ret == 1) 1532 goto done; 1533 1534 /* For generic masks and solid src pictures, mach64 can do 1535 * Over in two passes, similar to the component-alpha case. 1536 */ 1537 1538 isSrcSolid = 1539 pSrc->pDrawable ? 1540 pSrc->pDrawable->width == 1 && 1541 pSrc->pDrawable->height == 1 && 1542 pSrc->repeat : 1543 pSrc->pSourcePict ? 1544 pSrc->pSourcePict->type == SourcePictTypeSolidFill : 1545 0; 1546 1547 /* If we couldn't do the Composite in a single pass, and it 1548 * was a component-alpha Over, see if we can do it in two 1549 * passes with an OutReverse and then an Add. 1550 */ 1551 if (ret == -1 && op == PictOpOver && pMask && 1552 (pMask->componentAlpha || isSrcSolid)) { 1553 ret = 1554 uxa_try_magic_two_pass_composite_helper(op, pSrc, 1555 pMask, pDst, 1556 xSrc, ySrc, 1557 xMask, yMask, 1558 xDst, yDst, 1559 width, height); 1560 if (ret == 1) 1561 goto done; 1562 } 1563 1564 } 1565 1566fallback: 1567 uxa_print_composite_fallback("uxa_composite", 1568 op, pSrc, pMask, pDst); 1569 1570 uxa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, 1571 xMask, yMask, xDst, yDst, width, height); 1572 1573done: 1574 pSrc->repeat = saveSrcRepeat; 1575 if (pMask) 1576 pMask->repeat = saveMaskRepeat; 1577} 1578#endif 1579 1580/** 1581 * Same as miCreateAlphaPicture, except it uses uxa_check_poly_fill_rect instead 1582 * of PolyFillRect to initialize the pixmap after creating it, to prevent 1583 * the pixmap from being migrated. 1584 * 1585 * See the comments about uxa_trapezoids and uxa_triangles. 1586 */ 1587static PicturePtr 1588uxa_create_alpha_picture(ScreenPtr pScreen, 1589 PicturePtr pDst, 1590 PictFormatPtr pPictFormat, CARD16 width, CARD16 height) 1591{ 1592 PixmapPtr pPixmap; 1593 PicturePtr pPicture; 1594 int error; 1595 1596 if (width > 32767 || height > 32767) 1597 return 0; 1598 1599 if (!pPictFormat) { 1600 if (pDst->polyEdge == PolyEdgeSharp) 1601 pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1); 1602 else 1603 pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8); 1604 if (!pPictFormat) 1605 return 0; 1606 } 1607 1608 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1609 pPictFormat->depth, 1610 UXA_CREATE_PIXMAP_FOR_MAP); 1611 if (!pPixmap) 1612 return 0; 1613 pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, 1614 0, 0, serverClient, &error); 1615 (*pScreen->DestroyPixmap) (pPixmap); 1616 return pPicture; 1617} 1618 1619static void 1620uxa_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, 1621 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1622 int ntrap, xTrapezoid * traps) 1623{ 1624 ScreenPtr screen = dst->pDrawable->pScreen; 1625 1626 if (maskFormat) { 1627 PixmapPtr scratch = NULL; 1628 PicturePtr mask; 1629 INT16 xDst, yDst; 1630 INT16 xRel, yRel; 1631 BoxRec bounds; 1632 int width, height; 1633 pixman_image_t *image; 1634 pixman_format_code_t format; 1635 int error; 1636 1637 xDst = traps[0].left.p1.x >> 16; 1638 yDst = traps[0].left.p1.y >> 16; 1639 1640 miTrapezoidBounds (ntrap, traps, &bounds); 1641 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1642 return; 1643 1644 width = bounds.x2 - bounds.x1; 1645 height = bounds.y2 - bounds.y1; 1646 1647 format = maskFormat->format | 1648 (BitsPerPixel(maskFormat->depth) << 24); 1649 image = 1650 pixman_image_create_bits(format, width, height, NULL, 0); 1651 if (!image) 1652 return; 1653 1654 for (; ntrap; ntrap--, traps++) 1655 pixman_rasterize_trapezoid(image, 1656 (pixman_trapezoid_t *) traps, 1657 -bounds.x1, -bounds.y1); 1658 1659 1660 scratch = GetScratchPixmapHeader(screen, width, height, 1661 PIXMAN_FORMAT_DEPTH(format), 1662 PIXMAN_FORMAT_BPP(format), 1663 pixman_image_get_stride(image), 1664 pixman_image_get_data(image)); 1665 if (!scratch) { 1666 pixman_image_unref(image); 1667 return; 1668 } 1669 1670 mask = CreatePicture(0, &scratch->drawable, 1671 PictureMatchFormat(screen, 1672 PIXMAN_FORMAT_DEPTH(format), 1673 format), 1674 0, 0, serverClient, &error); 1675 if (!mask) { 1676 FreeScratchPixmapHeader(scratch); 1677 pixman_image_unref(image); 1678 return; 1679 } 1680 1681 xRel = bounds.x1 + xSrc - xDst; 1682 yRel = bounds.y1 + ySrc - yDst; 1683 CompositePicture(op, src, mask, dst, 1684 xRel, yRel, 1685 0, 0, 1686 bounds.x1, bounds.y1, 1687 width, height); 1688 FreePicture(mask, 0); 1689 1690 FreeScratchPixmapHeader(scratch); 1691 pixman_image_unref(image); 1692 } else { 1693 if (dst->polyEdge == PolyEdgeSharp) 1694 maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 1695 else 1696 maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 1697 1698 for (; ntrap; ntrap--, traps++) 1699 uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps); 1700 } 1701} 1702 1703/** 1704 * uxa_trapezoids is essentially a copy of miTrapezoids that uses 1705 * uxa_create_alpha_picture instead of miCreateAlphaPicture. 1706 * 1707 * The problem with miCreateAlphaPicture is that it calls PolyFillRect 1708 * to initialize the contents after creating the pixmap, which 1709 * causes the pixmap to be moved in for acceleration. The subsequent 1710 * call to RasterizeTrapezoid won't be accelerated however, which 1711 * forces the pixmap to be moved out again. 1712 * 1713 * uxa_create_alpha_picture avoids this roundtrip by using 1714 * uxa_check_poly_fill_rect to initialize the contents. 1715 */ 1716void 1717uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, 1718 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1719 int ntrap, xTrapezoid * traps) 1720{ 1721 ScreenPtr screen = dst->pDrawable->pScreen; 1722 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1723 BoxRec bounds; 1724 Bool direct; 1725 1726 if (uxa_screen->info->flags & UXA_USE_GLAMOR) { 1727 int ok; 1728 1729 uxa_picture_prepare_access(dst, UXA_GLAMOR_ACCESS_RW); 1730 uxa_picture_prepare_access(src, UXA_GLAMOR_ACCESS_RO); 1731 ok = glamor_trapezoids_nf(op, 1732 src, dst, maskFormat, xSrc, 1733 ySrc, ntrap, traps); 1734 uxa_picture_finish_access(src, UXA_GLAMOR_ACCESS_RO); 1735 uxa_picture_finish_access(dst, UXA_GLAMOR_ACCESS_RW); 1736 1737 if (!ok) 1738 goto fallback; 1739 1740 return; 1741 } 1742 1743 if (uxa_screen->force_fallback) { 1744fallback: 1745 uxa_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps); 1746 return; 1747 } 1748 1749 direct = op == PictOpAdd && miIsSolidAlpha(src); 1750 if (maskFormat || direct) { 1751 miTrapezoidBounds(ntrap, traps, &bounds); 1752 1753 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1754 return; 1755 } 1756 1757 /* 1758 * Check for solid alpha add 1759 */ 1760 if (direct) { 1761 DrawablePtr pDraw = dst->pDrawable; 1762 PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw); 1763 int xoff, yoff; 1764 1765 uxa_get_drawable_deltas(pDraw, pixmap, &xoff, &yoff); 1766 1767 xoff += pDraw->x; 1768 yoff += pDraw->y; 1769 1770 if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { 1771 PictureScreenPtr ps = GetPictureScreen(screen); 1772 1773 for (; ntrap; ntrap--, traps++) 1774 (*ps->RasterizeTrapezoid) (dst, traps, 0, 0); 1775 uxa_finish_access(pDraw, UXA_ACCESS_RW); 1776 } 1777 } else if (maskFormat) { 1778 PixmapPtr scratch = NULL; 1779 PicturePtr mask; 1780 INT16 xDst, yDst; 1781 INT16 xRel, yRel; 1782 int width, height; 1783 pixman_image_t *image; 1784 pixman_format_code_t format; 1785 1786 xDst = traps[0].left.p1.x >> 16; 1787 yDst = traps[0].left.p1.y >> 16; 1788 1789 width = bounds.x2 - bounds.x1; 1790 height = bounds.y2 - bounds.y1; 1791 1792 format = maskFormat->format | 1793 (BitsPerPixel(maskFormat->depth) << 24); 1794 image = 1795 pixman_image_create_bits(format, width, height, NULL, 0); 1796 if (!image) 1797 return; 1798 1799 for (; ntrap; ntrap--, traps++) 1800 pixman_rasterize_trapezoid(image, 1801 (pixman_trapezoid_t *) traps, 1802 -bounds.x1, -bounds.y1); 1803 if (uxa_drawable_is_offscreen(dst->pDrawable)) { 1804 mask = uxa_picture_from_pixman_image(screen, image, format); 1805 } else { 1806 int error; 1807 1808 scratch = GetScratchPixmapHeader(screen, width, height, 1809 PIXMAN_FORMAT_DEPTH(format), 1810 PIXMAN_FORMAT_BPP(format), 1811 pixman_image_get_stride(image), 1812 pixman_image_get_data(image)); 1813 mask = CreatePicture(0, &scratch->drawable, 1814 PictureMatchFormat(screen, 1815 PIXMAN_FORMAT_DEPTH(format), 1816 format), 1817 0, 0, serverClient, &error); 1818 } 1819 if (!mask) { 1820 if (scratch) 1821 FreeScratchPixmapHeader(scratch); 1822 pixman_image_unref(image); 1823 return; 1824 } 1825 1826 xRel = bounds.x1 + xSrc - xDst; 1827 yRel = bounds.y1 + ySrc - yDst; 1828 CompositePicture(op, src, mask, dst, 1829 xRel, yRel, 1830 0, 0, 1831 bounds.x1, bounds.y1, 1832 width, height); 1833 FreePicture(mask, 0); 1834 1835 if (scratch) 1836 FreeScratchPixmapHeader(scratch); 1837 pixman_image_unref(image); 1838 } else { 1839 if (dst->polyEdge == PolyEdgeSharp) 1840 maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 1841 else 1842 maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 1843 for (; ntrap; ntrap--, traps++) 1844 uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1845 1, traps); 1846 } 1847} 1848 1849static void 1850uxa_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst, 1851 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1852 int ntri, xTriangle *tri) 1853{ 1854 ScreenPtr screen = dst->pDrawable->pScreen; 1855 1856 if (maskFormat) { 1857 PixmapPtr scratch = NULL; 1858 PicturePtr mask; 1859 INT16 xDst, yDst; 1860 INT16 xRel, yRel; 1861 BoxRec bounds; 1862 int width, height; 1863 pixman_image_t *image; 1864 pixman_format_code_t format; 1865 int error; 1866 1867 xDst = pixman_fixed_to_int(tri[0].p1.x); 1868 yDst = pixman_fixed_to_int(tri[0].p1.y); 1869 1870 miTriangleBounds (ntri, tri, &bounds); 1871 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1872 return; 1873 1874 width = bounds.x2 - bounds.x1; 1875 height = bounds.y2 - bounds.y1; 1876 1877 format = maskFormat->format | 1878 (BitsPerPixel(maskFormat->depth) << 24); 1879 image = 1880 pixman_image_create_bits(format, width, height, NULL, 0); 1881 if (!image) 1882 return; 1883 1884 pixman_add_triangles(image, 1885 -bounds.x1, -bounds.y1, 1886 ntri, (pixman_triangle_t *)tri); 1887 1888 scratch = GetScratchPixmapHeader(screen, width, height, 1889 PIXMAN_FORMAT_DEPTH(format), 1890 PIXMAN_FORMAT_BPP(format), 1891 pixman_image_get_stride(image), 1892 pixman_image_get_data(image)); 1893 if (!scratch) { 1894 pixman_image_unref(image); 1895 return; 1896 } 1897 1898 mask = CreatePicture(0, &scratch->drawable, 1899 PictureMatchFormat(screen, 1900 PIXMAN_FORMAT_DEPTH(format), 1901 format), 1902 0, 0, serverClient, &error); 1903 if (!mask) { 1904 FreeScratchPixmapHeader(scratch); 1905 pixman_image_unref(image); 1906 return; 1907 } 1908 1909 xRel = bounds.x1 + xSrc - xDst; 1910 yRel = bounds.y1 + ySrc - yDst; 1911 CompositePicture(op, src, mask, dst, 1912 xRel, yRel, 1913 0, 0, 1914 bounds.x1, bounds.y1, 1915 width, height); 1916 FreePicture(mask, 0); 1917 1918 FreeScratchPixmapHeader(scratch); 1919 pixman_image_unref(image); 1920 } else { 1921 if (dst->polyEdge == PolyEdgeSharp) 1922 maskFormat = PictureMatchFormat(screen, 1, PICT_a1); 1923 else 1924 maskFormat = PictureMatchFormat(screen, 8, PICT_a8); 1925 1926 for (; ntri; ntri--, tri++) 1927 uxa_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri); 1928 } 1929} 1930 1931/** 1932 * uxa_triangles is essentially a copy of miTriangles that uses 1933 * uxa_create_alpha_picture instead of miCreateAlphaPicture. 1934 * 1935 * The problem with miCreateAlphaPicture is that it calls PolyFillRect 1936 * to initialize the contents after creating the pixmap, which 1937 * causes the pixmap to be moved in for acceleration. The subsequent 1938 * call to AddTriangles won't be accelerated however, which forces the pixmap 1939 * to be moved out again. 1940 * 1941 * uxa_create_alpha_picture avoids this roundtrip by using 1942 * uxa_check_poly_fill_rect to initialize the contents. 1943 */ 1944void 1945uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 1946 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 1947 int ntri, xTriangle * tris) 1948{ 1949 ScreenPtr pScreen = pDst->pDrawable->pScreen; 1950 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 1951 PictureScreenPtr ps = GetPictureScreen(pScreen); 1952 BoxRec bounds; 1953 Bool direct; 1954 1955 if (uxa_screen->info->flags & UXA_USE_GLAMOR) { 1956 int ok; 1957 1958 uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW); 1959 uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO); 1960 ok = glamor_triangles_nf(op, 1961 pSrc, pDst, maskFormat, xSrc, 1962 ySrc, ntri, tris); 1963 uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO); 1964 uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW); 1965 1966 if (!ok) 1967 goto fallback; 1968 1969 return; 1970 } 1971 1972 if (uxa_screen->force_fallback) { 1973fallback: 1974 uxa_check_triangles(op, pSrc, pDst, maskFormat, 1975 xSrc, ySrc, ntri, tris); 1976 return; 1977 } 1978 1979 direct = op == PictOpAdd && miIsSolidAlpha(pSrc); 1980 if (maskFormat || direct) { 1981 miTriangleBounds(ntri, tris, &bounds); 1982 1983 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 1984 return; 1985 } 1986 1987 /* 1988 * Check for solid alpha add 1989 */ 1990 if (direct) { 1991 DrawablePtr pDraw = pDst->pDrawable; 1992 if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) { 1993 (*ps->AddTriangles) (pDst, 0, 0, ntri, tris); 1994 uxa_finish_access(pDraw, UXA_ACCESS_RW); 1995 } 1996 } else if (maskFormat) { 1997 PicturePtr pPicture; 1998 INT16 xDst, yDst; 1999 INT16 xRel, yRel; 2000 int width = bounds.x2 - bounds.x1; 2001 int height = bounds.y2 - bounds.y1; 2002 GCPtr pGC; 2003 xRectangle rect; 2004 2005 xDst = tris[0].p1.x >> 16; 2006 yDst = tris[0].p1.y >> 16; 2007 2008 pPicture = uxa_create_alpha_picture(pScreen, pDst, maskFormat, 2009 width, height); 2010 if (!pPicture) 2011 return; 2012 2013 /* Clear the alpha picture to 0. */ 2014 pGC = GetScratchGC(pPicture->pDrawable->depth, pScreen); 2015 if (!pGC) { 2016 FreePicture(pPicture, 0); 2017 return; 2018 } 2019 ValidateGC(pPicture->pDrawable, pGC); 2020 rect.x = 0; 2021 rect.y = 0; 2022 rect.width = width; 2023 rect.height = height; 2024 uxa_check_poly_fill_rect(pPicture->pDrawable, pGC, 1, &rect); 2025 FreeScratchGC(pGC); 2026 2027 if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { 2028 (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, 2029 ntri, tris); 2030 uxa_finish_access(pPicture->pDrawable, UXA_ACCESS_RW); 2031 } 2032 2033 xRel = bounds.x1 + xSrc - xDst; 2034 yRel = bounds.y1 + ySrc - yDst; 2035 CompositePicture(op, pSrc, pPicture, pDst, 2036 xRel, yRel, 0, 0, bounds.x1, bounds.y1, 2037 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); 2038 FreePicture(pPicture, 0); 2039 } else { 2040 if (pDst->polyEdge == PolyEdgeSharp) 2041 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); 2042 else 2043 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); 2044 2045 for (; ntri; ntri--, tris++) 2046 uxa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, 2047 tris); 2048 } 2049} 2050 2051void 2052uxa_add_traps(PicturePtr pPicture, 2053 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) 2054{ 2055 ScreenPtr pScreen = pPicture->pDrawable->pScreen; 2056 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 2057 2058 if (uxa_screen->info->flags & UXA_USE_GLAMOR) { 2059 int ok; 2060 2061 uxa_picture_prepare_access(pPicture, UXA_GLAMOR_ACCESS_RW); 2062 ok = glamor_add_traps_nf(pPicture, 2063 x_off, y_off, ntrap, traps); 2064 uxa_picture_finish_access(pPicture, UXA_GLAMOR_ACCESS_RW); 2065 2066 if (!ok) 2067 goto fallback; 2068 2069 return; 2070 } 2071 2072fallback: 2073 uxa_check_add_traps(pPicture, x_off, y_off, ntrap, traps); 2074} 2075