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