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