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