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