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