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 * Authors: 25 * Eric Anholt <eric@anholt.net> 26 * Michel Dänzer <michel@tungstengraphics.com> 27 * 28 */ 29 30#ifdef HAVE_DIX_CONFIG_H 31#include <dix-config.h> 32#endif 33#include "uxa-priv.h" 34#include "uxa.h" 35#include "mipict.h" 36 37static CARD32 38format_for_depth(int depth) 39{ 40 switch (depth) { 41 case 1: return PICT_a1; 42 case 4: return PICT_a4; 43 case 8: return PICT_a8; 44 case 15: return PICT_x1r5g5b5; 45 case 16: return PICT_r5g6b5; 46 default: 47 case 24: return PICT_x8r8g8b8; 48 case 32: return PICT_a8r8g8b8; 49 } 50} 51 52static void 53uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, 54 DDXPointPtr ppt, int *pwidth, int fSorted) 55{ 56 ScreenPtr screen = pDrawable->pScreen; 57 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 58 RegionPtr pClip = fbGetCompositeClip(pGC); 59 PixmapPtr dst_pixmap, src_pixmap = NULL; 60 BoxPtr pextent, pbox; 61 int nbox; 62 int extentX1, extentX2, extentY1, extentY2; 63 int fullX1, fullX2, fullY1; 64 int partX1, partX2; 65 int off_x, off_y; 66 xRenderColor color; 67 PictFormatPtr format; 68 PicturePtr dst, src; 69 int error; 70 71 if (uxa_screen->swappedOut || uxa_screen->force_fallback) 72 goto fallback; 73 74 if (pGC->fillStyle != FillSolid) 75 goto fallback; 76 77 dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y); 78 if (!dst_pixmap) 79 goto fallback; 80 81 if (pGC->alu != GXcopy || pGC->planemask != FB_ALLONES) 82 goto solid; 83 84 format = PictureMatchFormat(screen, 85 dst_pixmap->drawable.depth, 86 format_for_depth(dst_pixmap->drawable.depth)); 87 dst = CreatePicture(0, &dst_pixmap->drawable, format, 0, 0, serverClient, &error); 88 if (!dst) 89 goto solid; 90 91 ValidatePicture(dst); 92 93 uxa_get_rgba_from_pixel(pGC->fgPixel, 94 &color.red, 95 &color.green, 96 &color.blue, 97 &color.alpha, 98 format_for_depth(dst_pixmap->drawable.depth)); 99 src = CreateSolidPicture(0, &color, &error); 100 if (!src) { 101 FreePicture(dst, 0); 102 goto solid; 103 } 104 105 if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) { 106 FreePicture(src, 0); 107 FreePicture(dst, 0); 108 goto solid; 109 } 110 111 if (!uxa_screen->info->check_composite_texture || 112 !uxa_screen->info->check_composite_texture(screen, src)) { 113 PicturePtr solid; 114 int src_off_x, src_off_y; 115 116 solid = uxa_acquire_solid(screen, src->pSourcePict); 117 FreePicture(src, 0); 118 119 src = solid; 120 src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, 121 &src_off_x, &src_off_y); 122 if (!src_pixmap) { 123 FreePicture(src, 0); 124 FreePicture(dst, 0); 125 goto solid; 126 } 127 } 128 129 if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) { 130 FreePicture(src, 0); 131 FreePicture(dst, 0); 132 goto solid; 133 } 134 135 pextent = REGION_EXTENTS(pGC->screen, pClip); 136 extentX1 = pextent->x1; 137 extentY1 = pextent->y1; 138 extentX2 = pextent->x2; 139 extentY2 = pextent->y2; 140 while (n--) { 141 fullX1 = ppt->x; 142 fullY1 = ppt->y; 143 fullX2 = fullX1 + (int)*pwidth; 144 ppt++; 145 pwidth++; 146 147 if (fullY1 < extentY1 || extentY2 <= fullY1) 148 continue; 149 150 if (fullX1 < extentX1) 151 fullX1 = extentX1; 152 153 if (fullX2 > extentX2) 154 fullX2 = extentX2; 155 156 if (fullX1 >= fullX2) 157 continue; 158 159 nbox = REGION_NUM_RECTS(pClip); 160 if (nbox == 1) { 161 uxa_screen->info->composite(dst_pixmap, 162 0, 0, 0, 0, 163 fullX1 + off_x, 164 fullY1 + off_y, 165 fullX2 - fullX1, 1); 166 } else { 167 pbox = REGION_RECTS(pClip); 168 while (nbox--) { 169 if (pbox->y1 > fullY1) 170 break; 171 172 if (pbox->y1 <= fullY1) { 173 partX1 = pbox->x1; 174 if (partX1 < fullX1) 175 partX1 = fullX1; 176 177 partX2 = pbox->x2; 178 if (partX2 > fullX2) 179 partX2 = fullX2; 180 181 if (partX2 > partX1) { 182 uxa_screen->info->composite(dst_pixmap, 183 0, 0, 0, 0, 184 partX1 + off_x, 185 fullY1 + off_y, 186 partX2 - partX1, 1); 187 } 188 } 189 pbox++; 190 } 191 } 192 } 193 194 uxa_screen->info->done_composite(dst_pixmap); 195 FreePicture(src, 0); 196 FreePicture(dst, 0); 197 return; 198 199solid: 200 if (uxa_screen->info->check_solid && 201 !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) 202 goto fallback; 203 204 if (!(*uxa_screen->info->prepare_solid) (dst_pixmap, 205 pGC->alu, 206 pGC->planemask, 207 pGC->fgPixel)) 208 goto fallback; 209 210 pextent = REGION_EXTENTS(pGC->screen, pClip); 211 extentX1 = pextent->x1; 212 extentY1 = pextent->y1; 213 extentX2 = pextent->x2; 214 extentY2 = pextent->y2; 215 while (n--) { 216 fullX1 = ppt->x; 217 fullY1 = ppt->y; 218 fullX2 = fullX1 + (int)*pwidth; 219 ppt++; 220 pwidth++; 221 222 if (fullY1 < extentY1 || extentY2 <= fullY1) 223 continue; 224 225 if (fullX1 < extentX1) 226 fullX1 = extentX1; 227 228 if (fullX2 > extentX2) 229 fullX2 = extentX2; 230 231 if (fullX1 >= fullX2) 232 continue; 233 234 nbox = REGION_NUM_RECTS(pClip); 235 if (nbox == 1) { 236 (*uxa_screen->info->solid) (dst_pixmap, 237 fullX1 + off_x, 238 fullY1 + off_y, 239 fullX2 + off_x, 240 fullY1 + 1 + off_y); 241 } else { 242 pbox = REGION_RECTS(pClip); 243 while (nbox--) { 244 if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { 245 partX1 = pbox->x1; 246 if (partX1 < fullX1) 247 partX1 = fullX1; 248 partX2 = pbox->x2; 249 if (partX2 > fullX2) 250 partX2 = fullX2; 251 if (partX2 > partX1) { 252 (*uxa_screen->info-> 253 solid) (dst_pixmap, 254 partX1 + off_x, 255 fullY1 + off_y, 256 partX2 + off_x, 257 fullY1 + 1 + off_y); 258 } 259 } 260 pbox++; 261 } 262 } 263 } 264 (*uxa_screen->info->done_solid) (dst_pixmap); 265 266 return; 267 268fallback: 269 uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); 270} 271 272static Bool 273uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 274 int w, int h, int format, char *bits, int src_stride) 275{ 276 uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 277 PixmapPtr pPix; 278 RegionPtr pClip; 279 BoxPtr pbox; 280 int nbox; 281 int xoff, yoff; 282 int bpp = pDrawable->bitsPerPixel; 283 284 /* Don't bother with under 8bpp, XYPixmaps. */ 285 if (format != ZPixmap || bpp < 8) 286 return FALSE; 287 288 if (uxa_screen->swappedOut || uxa_screen->force_fallback) 289 return FALSE; 290 291 if (!uxa_screen->info->put_image) 292 return FALSE; 293 294 /* Only accelerate copies: no rop or planemask. */ 295 if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) 296 return FALSE; 297 298 pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 299 if (!pPix) 300 return FALSE; 301 302 x += pDrawable->x; 303 y += pDrawable->y; 304 305 pClip = fbGetCompositeClip(pGC); 306 for (nbox = REGION_NUM_RECTS(pClip), 307 pbox = REGION_RECTS(pClip); nbox--; pbox++) { 308 int x1 = x; 309 int y1 = y; 310 int x2 = x + w; 311 int y2 = y + h; 312 char *src; 313 Bool ok; 314 315 if (x1 < pbox->x1) 316 x1 = pbox->x1; 317 if (y1 < pbox->y1) 318 y1 = pbox->y1; 319 if (x2 > pbox->x2) 320 x2 = pbox->x2; 321 if (y2 > pbox->y2) 322 y2 = pbox->y2; 323 if (x1 >= x2 || y1 >= y2) 324 continue; 325 326 src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); 327 ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff, 328 x2 - x1, y2 - y1, src, 329 src_stride); 330 /* If we fail to accelerate the upload, fall back to using 331 * unaccelerated fb calls. 332 */ 333 if (!ok) { 334 FbStip *dst; 335 FbStride dst_stride; 336 int dstBpp; 337 int dstXoff, dstYoff; 338 339 if (!uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) 340 return FALSE; 341 342 fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, 343 dstXoff, dstYoff); 344 345 fbBltStip((FbStip *) bits + 346 (y1 - y) * (src_stride / sizeof(FbStip)), 347 src_stride / sizeof(FbStip), 348 (x1 - x) * dstBpp, 349 dst + (y1 + dstYoff) * dst_stride, dst_stride, 350 (x1 + dstXoff) * dstBpp, (x2 - x1) * dstBpp, 351 y2 - y1, GXcopy, FB_ALLONES, dstBpp); 352 353 uxa_finish_access(pDrawable); 354 } 355 } 356 357 358 return TRUE; 359} 360 361static void 362uxa_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 363 int w, int h, int leftPad, int format, char *bits) 364{ 365 if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits, 366 PixmapBytePad(w, pDrawable->depth))) { 367 uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, 368 format, bits); 369 } 370} 371 372static Bool inline 373uxa_copy_n_to_n_two_dir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 374 GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) 375{ 376 uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 377 PixmapPtr pSrcPixmap, pDstPixmap; 378 int src_off_x, src_off_y, dst_off_x, dst_off_y; 379 int dirsetup; 380 381 /* Need to get both pixmaps to call the driver routines */ 382 pSrcPixmap = 383 uxa_get_offscreen_pixmap(pSrcDrawable, &src_off_x, &src_off_y); 384 pDstPixmap = 385 uxa_get_offscreen_pixmap(pDstDrawable, &dst_off_x, &dst_off_y); 386 if (!pSrcPixmap || !pDstPixmap) 387 return FALSE; 388 389 /* 390 * Now the case of a chip that only supports xdir = ydir = 1 or 391 * xdir = ydir = -1, but we have xdir != ydir. 392 */ 393 dirsetup = 0; /* No direction set up yet. */ 394 for (; nbox; pbox++, nbox--) { 395 if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 396 /* Do a xdir = ydir = -1 blit instead. */ 397 if (dirsetup != -1) { 398 if (dirsetup != 0) 399 uxa_screen->info->done_copy(pDstPixmap); 400 dirsetup = -1; 401 if (!(*uxa_screen->info->prepare_copy) 402 (pSrcPixmap, pDstPixmap, -1, -1, 403 pGC ? pGC->alu : GXcopy, 404 pGC ? pGC->planemask : FB_ALLONES)) 405 return FALSE; 406 } 407 (*uxa_screen->info->copy) (pDstPixmap, 408 src_off_x + pbox->x1 + dx, 409 src_off_y + pbox->y1 + dy, 410 dst_off_x + pbox->x1, 411 dst_off_y + pbox->y1, 412 pbox->x2 - pbox->x1, 413 pbox->y2 - pbox->y1); 414 } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 415 /* Do a xdir = ydir = 1 blit instead. */ 416 if (dirsetup != 1) { 417 if (dirsetup != 0) 418 uxa_screen->info->done_copy(pDstPixmap); 419 dirsetup = 1; 420 if (!(*uxa_screen->info->prepare_copy) 421 (pSrcPixmap, pDstPixmap, 1, 1, 422 pGC ? pGC->alu : GXcopy, 423 pGC ? pGC->planemask : FB_ALLONES)) 424 return FALSE; 425 } 426 (*uxa_screen->info->copy) (pDstPixmap, 427 src_off_x + pbox->x1 + dx, 428 src_off_y + pbox->y1 + dy, 429 dst_off_x + pbox->x1, 430 dst_off_y + pbox->y1, 431 pbox->x2 - pbox->x1, 432 pbox->y2 - pbox->y1); 433 } else if (dx >= 0) { 434 /* 435 * xdir = 1, ydir = -1. 436 * Perform line-by-line xdir = ydir = 1 blits, going up. 437 */ 438 int i; 439 if (dirsetup != 1) { 440 if (dirsetup != 0) 441 uxa_screen->info->done_copy(pDstPixmap); 442 dirsetup = 1; 443 if (!(*uxa_screen->info->prepare_copy) 444 (pSrcPixmap, pDstPixmap, 1, 1, 445 pGC ? pGC->alu : GXcopy, 446 pGC ? pGC->planemask : FB_ALLONES)) 447 return FALSE; 448 } 449 for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 450 (*uxa_screen->info->copy) (pDstPixmap, 451 src_off_x + 452 pbox->x1 + dx, 453 src_off_y + 454 pbox->y1 + dy + i, 455 dst_off_x + pbox->x1, 456 dst_off_y + 457 pbox->y1 + i, 458 pbox->x2 - pbox->x1, 459 1); 460 } else { 461 /* 462 * xdir = -1, ydir = 1. 463 * Perform line-by-line xdir = ydir = -1 blits, 464 * going down. 465 */ 466 int i; 467 if (dirsetup != -1) { 468 if (dirsetup != 0) 469 uxa_screen->info->done_copy(pDstPixmap); 470 dirsetup = -1; 471 if (!(*uxa_screen->info->prepare_copy) 472 (pSrcPixmap, pDstPixmap, -1, -1, 473 pGC ? pGC->alu : GXcopy, 474 pGC ? pGC->planemask : FB_ALLONES)) 475 return FALSE; 476 } 477 for (i = 0; i < pbox->y2 - pbox->y1; i++) 478 (*uxa_screen->info->copy) (pDstPixmap, 479 src_off_x + 480 pbox->x1 + dx, 481 src_off_y + 482 pbox->y1 + dy + i, 483 dst_off_x + pbox->x1, 484 dst_off_y + 485 pbox->y1 + i, 486 pbox->x2 - pbox->x1, 487 1); 488 } 489 } 490 if (dirsetup != 0) 491 uxa_screen->info->done_copy(pDstPixmap); 492 return TRUE; 493} 494 495void 496uxa_copy_n_to_n(DrawablePtr pSrcDrawable, 497 DrawablePtr pDstDrawable, 498 GCPtr pGC, 499 BoxPtr pbox, 500 int nbox, 501 int dx, 502 int dy, 503 Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) 504{ 505 ScreenPtr screen = pDstDrawable->pScreen; 506 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 507 int src_off_x, src_off_y; 508 int dst_off_x, dst_off_y; 509 PixmapPtr pSrcPixmap, pDstPixmap; 510 RegionRec src_region; 511 RegionRec dst_region; 512 513 pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); 514 pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); 515 if (!pSrcPixmap || !pDstPixmap) 516 goto fallback; 517 518 if (uxa_screen->info->check_copy && 519 !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, 520 pGC ? pGC->alu : GXcopy, 521 pGC ? pGC->planemask : FB_ALLONES)) 522 goto fallback; 523 524 uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, 525 &src_off_y); 526 uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x, 527 &dst_off_y); 528 529 /* Mixed directions must be handled specially if the card is lame */ 530 if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) && 531 reverse != upsidedown) { 532 if (uxa_copy_n_to_n_two_dir 533 (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) 534 return; 535 goto fallback; 536 } 537 538 if (!uxa_pixmap_is_offscreen(pDstPixmap)) 539 goto fallback; 540 541 if (uxa_pixmap_is_offscreen(pSrcPixmap)) { 542 if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, 543 reverse ? -1 : 1, 544 upsidedown ? -1 : 1, 545 pGC ? pGC->alu : GXcopy, 546 pGC ? pGC-> 547 planemask : FB_ALLONES)) 548 goto fallback; 549 550 while (nbox--) { 551 (*uxa_screen->info->copy) (pDstPixmap, 552 pbox->x1 + dx + src_off_x, 553 pbox->y1 + dy + src_off_y, 554 pbox->x1 + dst_off_x, 555 pbox->y1 + dst_off_y, 556 pbox->x2 - pbox->x1, 557 pbox->y2 - pbox->y1); 558 pbox++; 559 } 560 561 (*uxa_screen->info->done_copy) (pDstPixmap); 562 } else { 563 int stride, bpp; 564 char *src; 565 566 if (!uxa_screen->info->put_image) 567 goto fallback; 568 569 /* Don't bother with under 8bpp, XYPixmaps. */ 570 bpp = pSrcPixmap->drawable.bitsPerPixel; 571 if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) 572 goto fallback; 573 574 /* Only accelerate copies: no rop or planemask. */ 575 if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) 576 goto fallback; 577 578 src = pSrcPixmap->devPrivate.ptr; 579 stride = pSrcPixmap->devKind; 580 bpp /= 8; 581 while (nbox--) { 582 if (!uxa_screen->info->put_image(pDstPixmap, 583 pbox->x1 + dst_off_x, 584 pbox->y1 + dst_off_y, 585 pbox->x2 - pbox->x1, 586 pbox->y2 - pbox->y1, 587 (char *) src + 588 (pbox->y1 + dy + src_off_y) * stride + 589 (pbox->x1 + dx + src_off_x) * bpp, 590 stride)) 591 goto fallback; 592 593 pbox++; 594 } 595 } 596 597 return; 598 599fallback: 600#if 0 601 ErrorF ("falling back: %d boxes\n", nbox); 602#endif 603 604 pixman_region_init_rects (&dst_region, pbox, nbox); 605 REGION_INIT (NULL, &src_region, (BoxPtr)NULL, 0); 606 REGION_COPY (NULL, &src_region, &dst_region); 607 REGION_TRANSLATE (NULL, &src_region, dx, dy); 608 609 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, 610 uxa_drawable_location(pSrcDrawable), 611 uxa_drawable_location(pDstDrawable))); 612 if (uxa_prepare_access(pDstDrawable, &dst_region, UXA_ACCESS_RW)) 613 { 614 if (uxa_prepare_access(pSrcDrawable, &src_region, UXA_ACCESS_RO)) 615 { 616 fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, 617 dx, dy, reverse, upsidedown, bitplane, 618 closure); 619 620 uxa_finish_access(pSrcDrawable); 621 } 622 623 uxa_finish_access(pDstDrawable); 624 } 625 626 REGION_UNINIT (NULL, &src_region); 627 REGION_UNINIT (NULL, &dst_region); 628} 629 630RegionPtr 631uxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, 632 int srcx, int srcy, int width, int height, int dstx, int dsty) 633{ 634 uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 635 636 if (uxa_screen->swappedOut || uxa_screen->force_fallback) { 637 return uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC, 638 srcx, srcy, width, height, dstx, 639 dsty); 640 } 641 642 return miDoCopy(pSrcDrawable, pDstDrawable, pGC, 643 srcx, srcy, width, height, 644 dstx, dsty, uxa_copy_n_to_n, 0, NULL); 645} 646 647static void 648uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 649 DDXPointPtr ppt) 650{ 651 int i; 652 xRectangle *prect; 653 654 /* If we can't reuse the current GC as is, don't bother accelerating the 655 * points. 656 */ 657 if (pGC->fillStyle != FillSolid) { 658 uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt); 659 return; 660 } 661 662 prect = malloc(sizeof(xRectangle) * npt); 663 if (!prect) 664 return; 665 for (i = 0; i < npt; i++) { 666 prect[i].x = ppt[i].x; 667 prect[i].y = ppt[i].y; 668 if (i > 0 && mode == CoordModePrevious) { 669 prect[i].x += prect[i - 1].x; 670 prect[i].y += prect[i - 1].y; 671 } 672 prect[i].width = 1; 673 prect[i].height = 1; 674 } 675 pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); 676 free(prect); 677} 678 679/** 680 * uxa_poly_lines() checks if it can accelerate the lines as a group of 681 * horizontal or vertical lines (rectangles), and uses existing rectangle fill 682 * acceleration if so. 683 */ 684static void 685uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 686 DDXPointPtr ppt) 687{ 688 xRectangle *prect; 689 int x1, x2, y1, y2; 690 int i; 691 692 /* Don't try to do wide lines or non-solid fill style. */ 693 if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 694 pGC->fillStyle != FillSolid) { 695 uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 696 return; 697 } 698 699 prect = malloc(sizeof(xRectangle) * (npt - 1)); 700 if (!prect) 701 return; 702 x1 = ppt[0].x; 703 y1 = ppt[0].y; 704 /* If we have any non-horizontal/vertical, fall back. */ 705 for (i = 0; i < npt - 1; i++) { 706 if (mode == CoordModePrevious) { 707 x2 = x1 + ppt[i + 1].x; 708 y2 = y1 + ppt[i + 1].y; 709 } else { 710 x2 = ppt[i + 1].x; 711 y2 = ppt[i + 1].y; 712 } 713 714 if (x1 != x2 && y1 != y2) { 715 free(prect); 716 uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 717 return; 718 } 719 720 if (x1 < x2) { 721 prect[i].x = x1; 722 prect[i].width = x2 - x1 + 1; 723 } else { 724 prect[i].x = x2; 725 prect[i].width = x1 - x2 + 1; 726 } 727 if (y1 < y2) { 728 prect[i].y = y1; 729 prect[i].height = y2 - y1 + 1; 730 } else { 731 prect[i].y = y2; 732 prect[i].height = y1 - y2 + 1; 733 } 734 735 x1 = x2; 736 y1 = y2; 737 } 738 pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); 739 free(prect); 740} 741 742/** 743 * uxa_poly_segment() checks if it can accelerate the lines as a group of 744 * horizontal or vertical lines (rectangles), and uses existing rectangle fill 745 * acceleration if so. 746 */ 747static void 748uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) 749{ 750 xRectangle *prect; 751 int i; 752 753 /* Don't try to do wide lines or non-solid fill style. */ 754 if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 755 pGC->fillStyle != FillSolid) { 756 uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 757 return; 758 } 759 760 /* If we have any non-horizontal/vertical, fall back. */ 761 for (i = 0; i < nseg; i++) { 762 if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { 763 uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 764 return; 765 } 766 } 767 768 prect = malloc(sizeof(xRectangle) * nseg); 769 if (!prect) 770 return; 771 for (i = 0; i < nseg; i++) { 772 if (pSeg[i].x1 < pSeg[i].x2) { 773 prect[i].x = pSeg[i].x1; 774 prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; 775 } else { 776 prect[i].x = pSeg[i].x2; 777 prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; 778 } 779 if (pSeg[i].y1 < pSeg[i].y2) { 780 prect[i].y = pSeg[i].y1; 781 prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; 782 } else { 783 prect[i].y = pSeg[i].y2; 784 prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; 785 } 786 787 /* don't paint last pixel */ 788 if (pGC->capStyle == CapNotLast) { 789 if (prect[i].width == 1) 790 prect[i].height--; 791 else 792 prect[i].width--; 793 } 794 } 795 pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); 796 free(prect); 797} 798 799static Bool uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion, 800 Pixel pixel, CARD32 planemask, CARD32 alu); 801 802static void 803uxa_poly_fill_rect(DrawablePtr pDrawable, 804 GCPtr pGC, int nrect, xRectangle * prect) 805{ 806 uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 807 RegionPtr pClip = fbGetCompositeClip(pGC); 808 PixmapPtr pPixmap; 809 register BoxPtr pbox; 810 BoxPtr pextent; 811 int extentX1, extentX2, extentY1, extentY2; 812 int fullX1, fullX2, fullY1, fullY2; 813 int partX1, partX2, partY1, partY2; 814 int xoff, yoff; 815 int xorg, yorg; 816 int n; 817 RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); 818 819 /* Compute intersection of rects and clip region */ 820 REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); 821 REGION_INTERSECT(pScreen, pReg, pClip, pReg); 822 823 if (!REGION_NUM_RECTS(pReg)) 824 goto out; 825 826 if (uxa_screen->swappedOut || uxa_screen->force_fallback) 827 goto fallback; 828 829 pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); 830 if (!pPixmap) 831 goto fallback; 832 833 /* For ROPs where overlaps don't matter, convert rectangles to region 834 * and call uxa_fill_region_{solid,tiled}. 835 */ 836 if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && 837 (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || 838 pGC->alu == GXnoop || pGC->alu == GXcopyInverted || 839 pGC->alu == GXset)) { 840 if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && 841 uxa_fill_region_solid(pDrawable, pReg, 842 pGC->fillStyle == 843 FillSolid ? pGC->fgPixel : pGC->tile. 844 pixel, pGC->planemask, pGC->alu)) 845 || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel 846 && uxa_fill_region_tiled(pDrawable, pReg, 847 pGC->tile.pixmap, &pGC->patOrg, 848 pGC->planemask, pGC->alu))) { 849 goto out; 850 } 851 } 852 853 if (pGC->fillStyle != FillSolid && 854 !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { 855 goto fallback; 856 } 857 858 if (uxa_screen->info->check_solid && 859 !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) { 860 goto fallback; 861 } 862 863 if (!(*uxa_screen->info->prepare_solid) (pPixmap, 864 pGC->alu, 865 pGC->planemask, 866 pGC->fgPixel)) { 867fallback: 868 uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); 869 goto out; 870 } 871 872 xorg = pDrawable->x; 873 yorg = pDrawable->y; 874 875 pextent = REGION_EXTENTS(pGC->pScreen, pClip); 876 extentX1 = pextent->x1; 877 extentY1 = pextent->y1; 878 extentX2 = pextent->x2; 879 extentY2 = pextent->y2; 880 while (nrect--) { 881 fullX1 = prect->x + xorg; 882 fullY1 = prect->y + yorg; 883 fullX2 = fullX1 + (int)prect->width; 884 fullY2 = fullY1 + (int)prect->height; 885 prect++; 886 887 if (fullX1 < extentX1) 888 fullX1 = extentX1; 889 890 if (fullY1 < extentY1) 891 fullY1 = extentY1; 892 893 if (fullX2 > extentX2) 894 fullX2 = extentX2; 895 896 if (fullY2 > extentY2) 897 fullY2 = extentY2; 898 899 if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) 900 continue; 901 n = REGION_NUM_RECTS(pClip); 902 if (n == 1) { 903 (*uxa_screen->info->solid) (pPixmap, 904 fullX1 + xoff, 905 fullY1 + yoff, 906 fullX2 + xoff, 907 fullY2 + yoff); 908 } else { 909 pbox = REGION_RECTS(pClip); 910 /* 911 * clip the rectangle to each box in the clip region 912 * this is logically equivalent to calling Intersect(), 913 * but rectangles may overlap each other here. 914 */ 915 while (n--) { 916 partX1 = pbox->x1; 917 if (partX1 < fullX1) 918 partX1 = fullX1; 919 partY1 = pbox->y1; 920 if (partY1 < fullY1) 921 partY1 = fullY1; 922 partX2 = pbox->x2; 923 if (partX2 > fullX2) 924 partX2 = fullX2; 925 partY2 = pbox->y2; 926 if (partY2 > fullY2) 927 partY2 = fullY2; 928 929 pbox++; 930 931 if (partX1 < partX2 && partY1 < partY2) { 932 (*uxa_screen->info->solid) (pPixmap, 933 partX1 + 934 xoff, 935 partY1 + 936 yoff, 937 partX2 + 938 xoff, 939 partY2 + 940 yoff); 941 } 942 } 943 } 944 } 945 (*uxa_screen->info->done_solid) (pPixmap); 946 947out: 948 REGION_UNINIT(pScreen, pReg); 949 REGION_DESTROY(pScreen, pReg); 950} 951 952GCOps uxa_ops = { 953 uxa_fill_spans, 954 uxa_check_set_spans, 955 uxa_put_image, 956 uxa_copy_area, 957 uxa_check_copy_plane, 958 uxa_poly_point, 959 uxa_poly_lines, 960 uxa_poly_segment, 961 miPolyRectangle, 962 uxa_check_poly_arc, 963 miFillPolygon, 964 uxa_poly_fill_rect, 965 miPolyFillArc, 966 miPolyText8, 967 miPolyText16, 968 miImageText8, 969 miImageText16, 970 uxa_check_image_glyph_blt, 971 uxa_check_poly_glyph_blt, 972 uxa_check_push_pixels, 973}; 974 975void uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 976{ 977 RegionRec rgnDst; 978 int dx, dy; 979 PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); 980 981 dx = ptOldOrg.x - pWin->drawable.x; 982 dy = ptOldOrg.y - pWin->drawable.y; 983 REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 984 985 REGION_INIT(pWin->drawable.pScreen, &rgnDst, NullBox, 0); 986 987 REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, 988 prgnSrc); 989#ifdef COMPOSITE 990 if (pPixmap->screen_x || pPixmap->screen_y) 991 REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst, 992 -pPixmap->screen_x, -pPixmap->screen_y); 993#endif 994 995 miCopyRegion(&pPixmap->drawable, &pPixmap->drawable, 996 NULL, &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL); 997 998 REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); 999} 1000 1001static Bool 1002uxa_fill_region_solid(DrawablePtr pDrawable, 1003 RegionPtr pRegion, 1004 Pixel pixel, CARD32 planemask, CARD32 alu) 1005{ 1006 ScreenPtr screen = pDrawable->pScreen; 1007 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1008 PixmapPtr pixmap; 1009 int xoff, yoff; 1010 int nbox; 1011 BoxPtr pBox, extents; 1012 Bool ret = FALSE; 1013 1014 pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 1015 if (!pixmap) 1016 return FALSE; 1017 1018 REGION_TRANSLATE(screen, pRegion, xoff, yoff); 1019 1020 nbox = REGION_NUM_RECTS(pRegion); 1021 pBox = REGION_RECTS(pRegion); 1022 extents = REGION_EXTENTS(screen, pRegion); 1023 1024 /* Using GEM, the relocation costs outweigh the advantages of the blitter */ 1025 if (nbox == 1 || (alu != GXcopy && alu != GXclear) || planemask != FB_ALLONES) { 1026try_solid: 1027 if (uxa_screen->info->check_solid && 1028 !uxa_screen->info->check_solid(&pixmap->drawable, alu, planemask)) 1029 goto err; 1030 1031 if (!uxa_screen->info->prepare_solid(pixmap, alu, planemask, pixel)) 1032 goto err; 1033 1034 while (nbox--) { 1035 uxa_screen->info->solid(pixmap, 1036 pBox->x1, pBox->y1, 1037 pBox->x2, pBox->y2); 1038 pBox++; 1039 } 1040 1041 uxa_screen->info->done_solid(pixmap); 1042 } else { 1043 PicturePtr dst, src; 1044 PixmapPtr src_pixmap = NULL; 1045 xRenderColor color; 1046 int error; 1047 1048 dst = CreatePicture(0, &pixmap->drawable, 1049 PictureMatchFormat(screen, 1050 pixmap->drawable.depth, 1051 format_for_depth(pixmap->drawable.depth)), 1052 0, 0, serverClient, &error); 1053 if (!dst) 1054 goto err; 1055 1056 ValidatePicture(dst); 1057 1058 uxa_get_rgba_from_pixel(pixel, 1059 &color.red, 1060 &color.green, 1061 &color.blue, 1062 &color.alpha, 1063 format_for_depth(pixmap->drawable.depth)); 1064 src = CreateSolidPicture(0, &color, &error); 1065 if (!src) { 1066 FreePicture(dst, 0); 1067 goto err; 1068 } 1069 1070 if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 1071 extents->x2 - extents->x1, 1072 extents->y2 - extents->y1)) { 1073 FreePicture(src, 0); 1074 FreePicture(dst, 0); 1075 goto try_solid; 1076 } 1077 1078 if (!uxa_screen->info->check_composite_texture || 1079 !uxa_screen->info->check_composite_texture(screen, src)) { 1080 PicturePtr solid; 1081 int src_off_x, src_off_y; 1082 1083 solid = uxa_acquire_solid(screen, src->pSourcePict); 1084 FreePicture(src, 0); 1085 1086 src = solid; 1087 src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable, 1088 &src_off_x, &src_off_y); 1089 if (!src_pixmap) { 1090 FreePicture(src, 0); 1091 FreePicture(dst, 0); 1092 goto err; 1093 } 1094 } 1095 1096 if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, pixmap)) { 1097 FreePicture(src, 0); 1098 FreePicture(dst, 0); 1099 goto err; 1100 } 1101 1102 while (nbox--) { 1103 uxa_screen->info->composite(pixmap, 1104 0, 0, 0, 0, 1105 pBox->x1, 1106 pBox->y1, 1107 pBox->x2 - pBox->x1, 1108 pBox->y2 - pBox->y1); 1109 pBox++; 1110 } 1111 1112 uxa_screen->info->done_composite(pixmap); 1113 FreePicture(src, 0); 1114 FreePicture(dst, 0); 1115 } 1116 1117 ret = TRUE; 1118 1119err: 1120 REGION_TRANSLATE(screen, pRegion, -xoff, -yoff); 1121 return ret; 1122} 1123 1124/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. 1125 * Based on fbFillRegionTiled(), fbTile(). 1126 */ 1127Bool 1128uxa_fill_region_tiled(DrawablePtr pDrawable, 1129 RegionPtr pRegion, 1130 PixmapPtr pTile, 1131 DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu) 1132{ 1133 uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 1134 PixmapPtr pPixmap; 1135 int xoff, yoff; 1136 int tileWidth, tileHeight; 1137 int nbox = REGION_NUM_RECTS(pRegion); 1138 BoxPtr pBox = REGION_RECTS(pRegion); 1139 Bool ret = FALSE; 1140 int i; 1141 tileWidth = pTile->drawable.width; 1142 tileHeight = pTile->drawable.height; 1143 1144 /* If we're filling with a solid color, grab it out and go to 1145 * FillRegionsolid, saving numerous copies. 1146 */ 1147 if (tileWidth == 1 && tileHeight == 1) 1148 return uxa_fill_region_solid(pDrawable, pRegion, 1149 uxa_get_pixmap_first_pixel(pTile), 1150 planemask, alu); 1151 1152 pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 1153 if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) 1154 goto out; 1155 1156 if (uxa_screen->info->check_copy && 1157 !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask)) 1158 return FALSE; 1159 1160 1161 if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, 1162 planemask)) { 1163 if (xoff || yoff) 1164 REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); 1165 1166 for (i = 0; i < nbox; i++) { 1167 int height = pBox[i].y2 - pBox[i].y1; 1168 int dstY = pBox[i].y1; 1169 int tileY; 1170 1171 if (alu == GXcopy) 1172 height = min(height, tileHeight); 1173 1174 modulus(dstY - yoff - pDrawable->y - pPatOrg->y, 1175 tileHeight, tileY); 1176 1177 while (height > 0) { 1178 int width = pBox[i].x2 - pBox[i].x1; 1179 int dstX = pBox[i].x1; 1180 int tileX; 1181 int h = tileHeight - tileY; 1182 1183 if (alu == GXcopy) 1184 width = min(width, tileWidth); 1185 if (h > height) 1186 h = height; 1187 height -= h; 1188 1189 modulus(dstX - xoff - pDrawable->x - pPatOrg->x, 1190 tileWidth, tileX); 1191 1192 while (width > 0) { 1193 int w = tileWidth - tileX; 1194 if (w > width) 1195 w = width; 1196 width -= w; 1197 1198 (*uxa_screen->info->copy) (pPixmap, 1199 tileX, tileY, 1200 dstX, dstY, 1201 w, h); 1202 dstX += w; 1203 tileX = 0; 1204 } 1205 dstY += h; 1206 tileY = 0; 1207 } 1208 } 1209 (*uxa_screen->info->done_copy) (pPixmap); 1210 1211 if (alu != GXcopy) 1212 ret = TRUE; 1213 else { 1214 Bool more_copy = FALSE; 1215 1216 for (i = 0; i < nbox; i++) { 1217 int dstX = pBox[i].x1 + tileWidth; 1218 int dstY = pBox[i].y1 + tileHeight; 1219 1220 if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) { 1221 more_copy = TRUE; 1222 break; 1223 } 1224 } 1225 1226 if (more_copy == FALSE) 1227 ret = TRUE; 1228 1229 if (more_copy && (*uxa_screen->info->prepare_copy) (pPixmap, pPixmap, 1, 1, alu, planemask)) { 1230 for (i = 0; i < nbox; i++) { 1231 int dstX = pBox[i].x1 + tileWidth; 1232 int dstY = pBox[i].y1 + tileHeight; 1233 int width = min(pBox[i].x2 - dstX, tileWidth); 1234 int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); 1235 1236 while (dstX < pBox[i].x2) { 1237 (*uxa_screen->info->copy) (pPixmap, 1238 pBox[i].x1, pBox[i].y1, 1239 dstX, pBox[i].y1, 1240 width, height); 1241 dstX += width; 1242 width = min(pBox[i].x2 - dstX, width * 2); 1243 } 1244 1245 width = pBox[i].x2 - pBox[i].x1; 1246 height = min(pBox[i].y2 - dstY, tileHeight); 1247 1248 while (dstY < pBox[i].y2) { 1249 (*uxa_screen->info->copy) (pPixmap, 1250 pBox[i].x1, pBox[i].y1, 1251 pBox[i].x1, dstY, 1252 width, height); 1253 dstY += height; 1254 height = min(pBox[i].y2 - dstY, height * 2); 1255 } 1256 } 1257 (*uxa_screen->info->done_copy) (pPixmap); 1258 ret = TRUE; 1259 } 1260 } 1261 1262 if (xoff || yoff) 1263 REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); 1264 1265 } 1266 1267out: 1268 1269 return ret; 1270} 1271 1272/** 1273 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. 1274 * 1275 * This is probably the only case we actually care about. The rest fall through 1276 * to migration and fbGetImage, which hopefully will result in migration pushing 1277 * the pixmap out of framebuffer. 1278 */ 1279void 1280uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, 1281 unsigned int format, unsigned long planeMask, char *d) 1282{ 1283 ScreenPtr screen = pDrawable->pScreen; 1284 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1285 BoxRec Box; 1286 PixmapPtr pPix = uxa_get_drawable_pixmap(pDrawable); 1287 int xoff, yoff; 1288 Bool ok; 1289 RegionRec region; 1290 1291 uxa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff); 1292 1293 Box.x1 = pDrawable->y + x + xoff; 1294 Box.y1 = pDrawable->y + y + yoff; 1295 Box.x2 = Box.x1 + w; 1296 Box.y2 = Box.y1 + h; 1297 1298 if (uxa_screen->swappedOut || uxa_screen->force_fallback) 1299 goto fallback; 1300 1301 pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 1302 1303 if (pPix == NULL || uxa_screen->info->get_image == NULL) 1304 goto fallback; 1305 1306 /* Only cover the ZPixmap, solid copy case. */ 1307 if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask)) 1308 goto fallback; 1309 1310 /* Only try to handle the 8bpp and up cases, since we don't want to 1311 * think about <8bpp. 1312 */ 1313 if (pDrawable->bitsPerPixel < 8) 1314 goto fallback; 1315 1316 ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff, 1317 pDrawable->y + y + yoff, w, h, d, 1318 PixmapBytePad(w, pDrawable->depth)); 1319 if (ok) 1320 return; 1321 1322fallback: 1323 UXA_FALLBACK(("from %p (%c)\n", pDrawable, 1324 uxa_drawable_location(pDrawable))); 1325 1326 REGION_INIT(screen, ®ion, &Box, 1); 1327 1328 if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RO)) { 1329 fbGetImage(pDrawable, x, y, w, h, format, planeMask, d); 1330 uxa_finish_access(pDrawable); 1331 } 1332 1333 REGION_UNINIT(screen, ®ion); 1334 1335 return; 1336} 1337