105b261ecSmrg/* 2f7df2e56Smrg * Copyright © 2001 Keith Packard 305b261ecSmrg * 4f7df2e56Smrg * Partly based on code that is Copyright © The XFree86 Project Inc. 505b261ecSmrg * 605b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 705b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 805b261ecSmrg * the above copyright notice appear in all copies and that both that 905b261ecSmrg * copyright notice and this permission notice appear in supporting 1005b261ecSmrg * documentation, and that the name of Keith Packard not be used in 1105b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1205b261ecSmrg * specific, written prior permission. Keith Packard makes no 1305b261ecSmrg * representations about the suitability of this software for any purpose. It 1405b261ecSmrg * is provided "as is" without express or implied warranty. 1505b261ecSmrg * 1605b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1705b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1805b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1905b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2005b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2105b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2205b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2305b261ecSmrg * 2405b261ecSmrg * Authors: 2505b261ecSmrg * Eric Anholt <eric@anholt.net> 26f7df2e56Smrg * Michel Dänzer <michel@tungstengraphics.com> 2705b261ecSmrg * 2805b261ecSmrg */ 2905b261ecSmrg 3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3105b261ecSmrg#include <dix-config.h> 3205b261ecSmrg#endif 3305b261ecSmrg#include "exa_priv.h" 3405b261ecSmrg#include <X11/fonts/fontstruct.h> 3505b261ecSmrg#include "dixfontstr.h" 3605b261ecSmrg#include "exa.h" 3705b261ecSmrg 3805b261ecSmrgstatic void 3905b261ecSmrgexaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, 40f7df2e56Smrg DDXPointPtr ppt, int *pwidth, int fSorted) 4105b261ecSmrg{ 42f7df2e56Smrg ScreenPtr pScreen = pDrawable->pScreen; 43f7df2e56Smrg 44f7df2e56Smrg ExaScreenPriv(pScreen); 45f7df2e56Smrg RegionPtr pClip = fbGetCompositeClip(pGC); 46f7df2e56Smrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 47f7df2e56Smrg 48f7df2e56Smrg ExaPixmapPriv(pPixmap); 49f7df2e56Smrg BoxPtr pextent, pbox; 50f7df2e56Smrg int nbox; 51f7df2e56Smrg int extentX1, extentX2, extentY1, extentY2; 52f7df2e56Smrg int fullX1, fullX2, fullY1; 53f7df2e56Smrg int partX1, partX2; 54f7df2e56Smrg int off_x, off_y; 5505b261ecSmrg 564202a189Smrg if (pExaScr->fallback_counter || 57f7df2e56Smrg pExaScr->swappedOut || 58f7df2e56Smrg pGC->fillStyle != FillSolid || pExaPixmap->accel_blocked) { 59f7df2e56Smrg ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); 60f7df2e56Smrg return; 614202a189Smrg } 624202a189Smrg 634202a189Smrg if (pExaScr->do_migration) { 64f7df2e56Smrg ExaMigrationRec pixmaps[1]; 654202a189Smrg 66f7df2e56Smrg pixmaps[0].as_dst = TRUE; 67f7df2e56Smrg pixmaps[0].as_src = FALSE; 68f7df2e56Smrg pixmaps[0].pPix = pPixmap; 69f7df2e56Smrg pixmaps[0].pReg = NULL; 704202a189Smrg 71f7df2e56Smrg exaDoMigration(pixmaps, 1, TRUE); 7205b261ecSmrg } 7305b261ecSmrg 74f7df2e56Smrg if (!(pPixmap = exaGetOffscreenPixmap(pDrawable, &off_x, &off_y)) || 75f7df2e56Smrg !(*pExaScr->info->PrepareSolid) (pPixmap, 76f7df2e56Smrg pGC->alu, 77f7df2e56Smrg pGC->planemask, pGC->fgPixel)) { 78f7df2e56Smrg ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); 79f7df2e56Smrg return; 8005b261ecSmrg } 8105b261ecSmrg 824202a189Smrg pextent = RegionExtents(pClip); 8305b261ecSmrg extentX1 = pextent->x1; 8405b261ecSmrg extentY1 = pextent->y1; 8505b261ecSmrg extentX2 = pextent->x2; 8605b261ecSmrg extentY2 = pextent->y2; 87f7df2e56Smrg while (n--) { 88f7df2e56Smrg fullX1 = ppt->x; 89f7df2e56Smrg fullY1 = ppt->y; 90f7df2e56Smrg fullX2 = fullX1 + (int) *pwidth; 91f7df2e56Smrg ppt++; 92f7df2e56Smrg pwidth++; 93f7df2e56Smrg 94f7df2e56Smrg if (fullY1 < extentY1 || extentY2 <= fullY1) 95f7df2e56Smrg continue; 96f7df2e56Smrg 97f7df2e56Smrg if (fullX1 < extentX1) 98f7df2e56Smrg fullX1 = extentX1; 99f7df2e56Smrg 100f7df2e56Smrg if (fullX2 > extentX2) 101f7df2e56Smrg fullX2 = extentX2; 102f7df2e56Smrg 103f7df2e56Smrg if (fullX1 >= fullX2) 104f7df2e56Smrg continue; 105f7df2e56Smrg 106f7df2e56Smrg nbox = RegionNumRects(pClip); 107f7df2e56Smrg if (nbox == 1) { 108f7df2e56Smrg (*pExaScr->info->Solid) (pPixmap, 109f7df2e56Smrg fullX1 + off_x, fullY1 + off_y, 110f7df2e56Smrg fullX2 + off_x, fullY1 + 1 + off_y); 111f7df2e56Smrg } 112f7df2e56Smrg else { 113f7df2e56Smrg pbox = RegionRects(pClip); 114f7df2e56Smrg while (nbox--) { 115f7df2e56Smrg if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { 116f7df2e56Smrg partX1 = pbox->x1; 117f7df2e56Smrg if (partX1 < fullX1) 118f7df2e56Smrg partX1 = fullX1; 119f7df2e56Smrg partX2 = pbox->x2; 120f7df2e56Smrg if (partX2 > fullX2) 121f7df2e56Smrg partX2 = fullX2; 122f7df2e56Smrg if (partX2 > partX1) { 123f7df2e56Smrg (*pExaScr->info->Solid) (pPixmap, 124f7df2e56Smrg partX1 + off_x, fullY1 + off_y, 125f7df2e56Smrg partX2 + off_x, 126f7df2e56Smrg fullY1 + 1 + off_y); 127f7df2e56Smrg } 128f7df2e56Smrg } 129f7df2e56Smrg pbox++; 130f7df2e56Smrg } 131f7df2e56Smrg } 13205b261ecSmrg } 13305b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 13405b261ecSmrg exaMarkSync(pScreen); 13505b261ecSmrg} 13605b261ecSmrg 1374642e01fSmrgstatic Bool 138f7df2e56SmrgexaDoPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 139f7df2e56Smrg int w, int h, int format, char *bits, int src_stride) 14005b261ecSmrg{ 141f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 142f7df2e56Smrg PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); 143f7df2e56Smrg 1444642e01fSmrg ExaPixmapPriv(pPix); 14505b261ecSmrg RegionPtr pClip; 14605b261ecSmrg BoxPtr pbox; 14705b261ecSmrg int nbox; 14805b261ecSmrg int xoff, yoff; 1494642e01fSmrg int bpp = pDrawable->bitsPerPixel; 1504202a189Smrg Bool ret = TRUE; 15105b261ecSmrg 152f7df2e56Smrg if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || 153f7df2e56Smrg !pExaScr->info->UploadToScreen) 154f7df2e56Smrg return FALSE; 1554202a189Smrg 1564202a189Smrg /* If there's a system copy, we want to save the result there */ 1574202a189Smrg if (pExaPixmap->pDamage) 158f7df2e56Smrg return FALSE; 15905b261ecSmrg 16005b261ecSmrg /* Don't bother with under 8bpp, XYPixmaps. */ 16105b261ecSmrg if (format != ZPixmap || bpp < 8) 162f7df2e56Smrg return FALSE; 16305b261ecSmrg 16405b261ecSmrg /* Only accelerate copies: no rop or planemask. */ 16505b261ecSmrg if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) 166f7df2e56Smrg return FALSE; 16705b261ecSmrg 16805b261ecSmrg if (pExaScr->swappedOut) 169f7df2e56Smrg return FALSE; 17005b261ecSmrg 1714202a189Smrg if (pExaScr->do_migration) { 172f7df2e56Smrg ExaMigrationRec pixmaps[1]; 17305b261ecSmrg 174f7df2e56Smrg pixmaps[0].as_dst = TRUE; 175f7df2e56Smrg pixmaps[0].as_src = FALSE; 176f7df2e56Smrg pixmaps[0].pPix = pPix; 177f7df2e56Smrg pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); 1784642e01fSmrg 179f7df2e56Smrg exaDoMigration(pixmaps, 1, TRUE); 1804642e01fSmrg } 18105b261ecSmrg 182f7df2e56Smrg pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); 18305b261ecSmrg 1844202a189Smrg if (!pPix) 185f7df2e56Smrg return FALSE; 18605b261ecSmrg 18705b261ecSmrg x += pDrawable->x; 18805b261ecSmrg y += pDrawable->y; 18905b261ecSmrg 19005b261ecSmrg pClip = fbGetCompositeClip(pGC); 1914202a189Smrg for (nbox = RegionNumRects(pClip), 192f7df2e56Smrg pbox = RegionRects(pClip); nbox--; pbox++) { 193f7df2e56Smrg int x1 = x; 194f7df2e56Smrg int y1 = y; 195f7df2e56Smrg int x2 = x + w; 196f7df2e56Smrg int y2 = y + h; 197f7df2e56Smrg char *src; 198f7df2e56Smrg Bool ok; 199f7df2e56Smrg 200f7df2e56Smrg if (x1 < pbox->x1) 201f7df2e56Smrg x1 = pbox->x1; 202f7df2e56Smrg if (y1 < pbox->y1) 203f7df2e56Smrg y1 = pbox->y1; 204f7df2e56Smrg if (x2 > pbox->x2) 205f7df2e56Smrg x2 = pbox->x2; 206f7df2e56Smrg if (y2 > pbox->y2) 207f7df2e56Smrg y2 = pbox->y2; 208f7df2e56Smrg if (x1 >= x2 || y1 >= y2) 209f7df2e56Smrg continue; 210f7df2e56Smrg 211f7df2e56Smrg src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); 212f7df2e56Smrg ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, 213f7df2e56Smrg x2 - x1, y2 - y1, src, src_stride); 214f7df2e56Smrg /* We have to fall back completely, and ignore what has already been completed. 215f7df2e56Smrg * Messing with the fb layer directly like we used to is completely unacceptable. 216f7df2e56Smrg */ 217f7df2e56Smrg if (!ok) { 218f7df2e56Smrg ret = FALSE; 219f7df2e56Smrg break; 220f7df2e56Smrg } 22105b261ecSmrg } 22205b261ecSmrg 2234202a189Smrg if (ret) 224f7df2e56Smrg exaMarkSync(pDrawable->pScreen); 22505b261ecSmrg 2264202a189Smrg return ret; 2274642e01fSmrg} 22805b261ecSmrg 2294642e01fSmrgstatic void 230f7df2e56SmrgexaPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 231f7df2e56Smrg int w, int h, int leftPad, int format, char *bits) 2324642e01fSmrg{ 2334642e01fSmrg if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits, 234f7df2e56Smrg PixmapBytePad(w, pDrawable->depth))) 235f7df2e56Smrg ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, 236f7df2e56Smrg bits); 23705b261ecSmrg} 23805b261ecSmrg 23905b261ecSmrgstatic Bool inline 240f7df2e56SmrgexaCopyNtoNTwoDir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 241f7df2e56Smrg GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) 24205b261ecSmrg{ 243f7df2e56Smrg ExaScreenPriv(pDstDrawable->pScreen); 24405b261ecSmrg PixmapPtr pSrcPixmap, pDstPixmap; 24505b261ecSmrg int src_off_x, src_off_y, dst_off_x, dst_off_y; 24605b261ecSmrg int dirsetup; 24705b261ecSmrg 24805b261ecSmrg /* Need to get both pixmaps to call the driver routines */ 249f7df2e56Smrg pSrcPixmap = exaGetOffscreenPixmap(pSrcDrawable, &src_off_x, &src_off_y); 250f7df2e56Smrg pDstPixmap = exaGetOffscreenPixmap(pDstDrawable, &dst_off_x, &dst_off_y); 25105b261ecSmrg if (!pSrcPixmap || !pDstPixmap) 252f7df2e56Smrg return FALSE; 25305b261ecSmrg 25405b261ecSmrg /* 25505b261ecSmrg * Now the case of a chip that only supports xdir = ydir = 1 or 25605b261ecSmrg * xdir = ydir = -1, but we have xdir != ydir. 25705b261ecSmrg */ 258f7df2e56Smrg dirsetup = 0; /* No direction set up yet. */ 25905b261ecSmrg for (; nbox; pbox++, nbox--) { 260f7df2e56Smrg if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 261f7df2e56Smrg /* Do a xdir = ydir = -1 blit instead. */ 262f7df2e56Smrg if (dirsetup != -1) { 263f7df2e56Smrg if (dirsetup != 0) 264f7df2e56Smrg pExaScr->info->DoneCopy(pDstPixmap); 265f7df2e56Smrg dirsetup = -1; 266f7df2e56Smrg if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, 267f7df2e56Smrg pDstPixmap, 268f7df2e56Smrg -1, -1, 269f7df2e56Smrg pGC ? pGC->alu : GXcopy, 270f7df2e56Smrg pGC ? pGC->planemask : 271f7df2e56Smrg FB_ALLONES)) 272f7df2e56Smrg return FALSE; 273f7df2e56Smrg } 274f7df2e56Smrg (*pExaScr->info->Copy) (pDstPixmap, 275f7df2e56Smrg src_off_x + pbox->x1 + dx, 276f7df2e56Smrg src_off_y + pbox->y1 + dy, 277f7df2e56Smrg dst_off_x + pbox->x1, 278f7df2e56Smrg dst_off_y + pbox->y1, 279f7df2e56Smrg pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 280f7df2e56Smrg } 281f7df2e56Smrg else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 282f7df2e56Smrg /* Do a xdir = ydir = 1 blit instead. */ 283f7df2e56Smrg if (dirsetup != 1) { 284f7df2e56Smrg if (dirsetup != 0) 285f7df2e56Smrg pExaScr->info->DoneCopy(pDstPixmap); 286f7df2e56Smrg dirsetup = 1; 287f7df2e56Smrg if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, 288f7df2e56Smrg pDstPixmap, 289f7df2e56Smrg 1, 1, 290f7df2e56Smrg pGC ? pGC->alu : GXcopy, 291f7df2e56Smrg pGC ? pGC->planemask : 292f7df2e56Smrg FB_ALLONES)) 293f7df2e56Smrg return FALSE; 294f7df2e56Smrg } 295f7df2e56Smrg (*pExaScr->info->Copy) (pDstPixmap, 296f7df2e56Smrg src_off_x + pbox->x1 + dx, 297f7df2e56Smrg src_off_y + pbox->y1 + dy, 298f7df2e56Smrg dst_off_x + pbox->x1, 299f7df2e56Smrg dst_off_y + pbox->y1, 300f7df2e56Smrg pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 301f7df2e56Smrg } 302f7df2e56Smrg else if (dx >= 0) { 303f7df2e56Smrg /* 304f7df2e56Smrg * xdir = 1, ydir = -1. 305f7df2e56Smrg * Perform line-by-line xdir = ydir = 1 blits, going up. 306f7df2e56Smrg */ 307f7df2e56Smrg int i; 308f7df2e56Smrg 309f7df2e56Smrg if (dirsetup != 1) { 310f7df2e56Smrg if (dirsetup != 0) 311f7df2e56Smrg pExaScr->info->DoneCopy(pDstPixmap); 312f7df2e56Smrg dirsetup = 1; 313f7df2e56Smrg if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, 314f7df2e56Smrg pDstPixmap, 315f7df2e56Smrg 1, 1, 316f7df2e56Smrg pGC ? pGC->alu : GXcopy, 317f7df2e56Smrg pGC ? pGC->planemask : 318f7df2e56Smrg FB_ALLONES)) 319f7df2e56Smrg return FALSE; 320f7df2e56Smrg } 321f7df2e56Smrg for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 322f7df2e56Smrg (*pExaScr->info->Copy) (pDstPixmap, 323f7df2e56Smrg src_off_x + pbox->x1 + dx, 324f7df2e56Smrg src_off_y + pbox->y1 + dy + i, 325f7df2e56Smrg dst_off_x + pbox->x1, 326f7df2e56Smrg dst_off_y + pbox->y1 + i, 327f7df2e56Smrg pbox->x2 - pbox->x1, 1); 328f7df2e56Smrg } 329f7df2e56Smrg else { 330f7df2e56Smrg /* 331f7df2e56Smrg * xdir = -1, ydir = 1. 332f7df2e56Smrg * Perform line-by-line xdir = ydir = -1 blits, going down. 333f7df2e56Smrg */ 334f7df2e56Smrg int i; 335f7df2e56Smrg 336f7df2e56Smrg if (dirsetup != -1) { 337f7df2e56Smrg if (dirsetup != 0) 338f7df2e56Smrg pExaScr->info->DoneCopy(pDstPixmap); 339f7df2e56Smrg dirsetup = -1; 340f7df2e56Smrg if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, 341f7df2e56Smrg pDstPixmap, 342f7df2e56Smrg -1, -1, 343f7df2e56Smrg pGC ? pGC->alu : GXcopy, 344f7df2e56Smrg pGC ? pGC->planemask : 345f7df2e56Smrg FB_ALLONES)) 346f7df2e56Smrg return FALSE; 347f7df2e56Smrg } 348f7df2e56Smrg for (i = 0; i < pbox->y2 - pbox->y1; i++) 349f7df2e56Smrg (*pExaScr->info->Copy) (pDstPixmap, 350f7df2e56Smrg src_off_x + pbox->x1 + dx, 351f7df2e56Smrg src_off_y + pbox->y1 + dy + i, 352f7df2e56Smrg dst_off_x + pbox->x1, 353f7df2e56Smrg dst_off_y + pbox->y1 + i, 354f7df2e56Smrg pbox->x2 - pbox->x1, 1); 355f7df2e56Smrg } 35605b261ecSmrg } 35705b261ecSmrg if (dirsetup != 0) 358f7df2e56Smrg pExaScr->info->DoneCopy(pDstPixmap); 35905b261ecSmrg exaMarkSync(pDstDrawable->pScreen); 36005b261ecSmrg return TRUE; 36105b261ecSmrg} 36205b261ecSmrg 3634202a189SmrgBool 364f7df2e56SmrgexaHWCopyNtoN(DrawablePtr pSrcDrawable, 365f7df2e56Smrg DrawablePtr pDstDrawable, 366f7df2e56Smrg GCPtr pGC, 367f7df2e56Smrg BoxPtr pbox, 368f7df2e56Smrg int nbox, int dx, int dy, Bool reverse, Bool upsidedown) 36905b261ecSmrg{ 370f7df2e56Smrg ExaScreenPriv(pDstDrawable->pScreen); 37105b261ecSmrg PixmapPtr pSrcPixmap, pDstPixmap; 3724642e01fSmrg ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; 373f7df2e56Smrg int src_off_x, src_off_y; 374f7df2e56Smrg int dst_off_x, dst_off_y; 3754642e01fSmrg RegionPtr srcregion = NULL, dstregion = NULL; 3764642e01fSmrg xRectangle *rects; 3774202a189Smrg Bool ret = TRUE; 3784642e01fSmrg 3794642e01fSmrg /* avoid doing copy operations if no boxes */ 3804642e01fSmrg if (nbox == 0) 381f7df2e56Smrg return TRUE; 3824642e01fSmrg 383f7df2e56Smrg pSrcPixmap = exaGetDrawablePixmap(pSrcDrawable); 384f7df2e56Smrg pDstPixmap = exaGetDrawablePixmap(pDstDrawable); 3854642e01fSmrg 386f7df2e56Smrg exaGetDrawableDeltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); 387f7df2e56Smrg exaGetDrawableDeltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); 3884642e01fSmrg 389f7df2e56Smrg rects = xallocarray(nbox, sizeof(xRectangle)); 3904642e01fSmrg 3914642e01fSmrg if (rects) { 392f7df2e56Smrg int i; 393f7df2e56Smrg int ordering; 394f7df2e56Smrg 395f7df2e56Smrg for (i = 0; i < nbox; i++) { 396f7df2e56Smrg rects[i].x = pbox[i].x1 + dx + src_off_x; 397f7df2e56Smrg rects[i].y = pbox[i].y1 + dy + src_off_y; 398f7df2e56Smrg rects[i].width = pbox[i].x2 - pbox[i].x1; 399f7df2e56Smrg rects[i].height = pbox[i].y2 - pbox[i].y1; 400f7df2e56Smrg } 40105b261ecSmrg 402f7df2e56Smrg /* This must match the RegionCopy() logic for reversing rect order */ 403f7df2e56Smrg if (nbox == 1 || (dx > 0 && dy > 0) || 404f7df2e56Smrg (pDstDrawable != pSrcDrawable && 405f7df2e56Smrg (pDstDrawable->type != DRAWABLE_WINDOW || 406f7df2e56Smrg pSrcDrawable->type != DRAWABLE_WINDOW))) 407f7df2e56Smrg ordering = CT_YXBANDED; 408f7df2e56Smrg else 409f7df2e56Smrg ordering = CT_UNSORTED; 410f7df2e56Smrg 411f7df2e56Smrg srcregion = RegionFromRects(nbox, rects, ordering); 412f7df2e56Smrg free(rects); 413f7df2e56Smrg 414f7df2e56Smrg if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, 415f7df2e56Smrg pGC->fillStyle, pGC->alu, 416f7df2e56Smrg pGC->clientClip != NULL)) { 417f7df2e56Smrg dstregion = RegionCreate(NullBox, 0); 418f7df2e56Smrg RegionCopy(dstregion, srcregion); 419f7df2e56Smrg RegionTranslate(dstregion, dst_off_x - dx - src_off_x, 420f7df2e56Smrg dst_off_y - dy - src_off_y); 421f7df2e56Smrg } 422f7df2e56Smrg } 42305b261ecSmrg 424f7df2e56Smrg pSrcExaPixmap = ExaGetPixmapPriv(pSrcPixmap); 425f7df2e56Smrg pDstExaPixmap = ExaGetPixmapPriv(pDstPixmap); 4264642e01fSmrg 4274642e01fSmrg /* Check whether the accelerator can use this pixmap. 4284642e01fSmrg * If the pitch of the pixmaps is out of range, there's nothing 4294642e01fSmrg * we can do but fall back to software rendering. 43005b261ecSmrg */ 4314642e01fSmrg if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || 4324642e01fSmrg pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) 433f7df2e56Smrg goto fallback; 4344642e01fSmrg 4354642e01fSmrg /* If the width or the height of either of the pixmaps 4364642e01fSmrg * is out of range, check whether the boxes are actually out of the 4374642e01fSmrg * addressable range as well. If they aren't, we can still do 4384642e01fSmrg * the copying in hardware. 4394642e01fSmrg */ 4404642e01fSmrg if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { 4414642e01fSmrg int i; 4424642e01fSmrg 4434642e01fSmrg for (i = 0; i < nbox; i++) { 4444642e01fSmrg /* src */ 4454642e01fSmrg if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || 4464642e01fSmrg (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) 4474642e01fSmrg goto fallback; 4484642e01fSmrg 4494642e01fSmrg /* dst */ 4504642e01fSmrg if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || 4514642e01fSmrg (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) 4524642e01fSmrg goto fallback; 4534642e01fSmrg } 45405b261ecSmrg } 45505b261ecSmrg 4564202a189Smrg if (pExaScr->do_migration) { 457f7df2e56Smrg ExaMigrationRec pixmaps[2]; 458f7df2e56Smrg 459f7df2e56Smrg pixmaps[0].as_dst = TRUE; 460f7df2e56Smrg pixmaps[0].as_src = FALSE; 461f7df2e56Smrg pixmaps[0].pPix = pDstPixmap; 462f7df2e56Smrg pixmaps[0].pReg = dstregion; 463f7df2e56Smrg pixmaps[1].as_dst = FALSE; 464f7df2e56Smrg pixmaps[1].as_src = TRUE; 465f7df2e56Smrg pixmaps[1].pPix = pSrcPixmap; 466f7df2e56Smrg pixmaps[1].pReg = srcregion; 467f7df2e56Smrg 468f7df2e56Smrg exaDoMigration(pixmaps, 2, TRUE); 4694202a189Smrg } 4704642e01fSmrg 47105b261ecSmrg /* Mixed directions must be handled specially if the card is lame */ 4724642e01fSmrg if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && 473f7df2e56Smrg reverse != upsidedown) { 474f7df2e56Smrg if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, 475f7df2e56Smrg dx, dy)) 476f7df2e56Smrg goto out; 477f7df2e56Smrg goto fallback; 47805b261ecSmrg } 47905b261ecSmrg 4804202a189Smrg if (exaPixmapHasGpuCopy(pDstPixmap)) { 481f7df2e56Smrg /* Normal blitting. */ 482f7df2e56Smrg if (exaPixmapHasGpuCopy(pSrcPixmap)) { 483f7df2e56Smrg if (!(*pExaScr->info->PrepareCopy) 484f7df2e56Smrg (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, 485f7df2e56Smrg pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) { 486f7df2e56Smrg goto fallback; 487f7df2e56Smrg } 488f7df2e56Smrg 489f7df2e56Smrg while (nbox--) { 490f7df2e56Smrg (*pExaScr->info->Copy) (pDstPixmap, 491f7df2e56Smrg pbox->x1 + dx + src_off_x, 492f7df2e56Smrg pbox->y1 + dy + src_off_y, 493f7df2e56Smrg pbox->x1 + dst_off_x, 494f7df2e56Smrg pbox->y1 + dst_off_y, 495f7df2e56Smrg pbox->x2 - pbox->x1, 496f7df2e56Smrg pbox->y2 - pbox->y1); 497f7df2e56Smrg pbox++; 498f7df2e56Smrg } 499f7df2e56Smrg 500f7df2e56Smrg (*pExaScr->info->DoneCopy) (pDstPixmap); 501f7df2e56Smrg exaMarkSync(pDstDrawable->pScreen); 502f7df2e56Smrg /* UTS: mainly for SHM PutImage's secondary path. 503f7df2e56Smrg * 504f7df2e56Smrg * Only taking this path for directly accessible pixmaps. 505f7df2e56Smrg */ 506f7df2e56Smrg } 507f7df2e56Smrg else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) { 508f7df2e56Smrg int bpp = pSrcDrawable->bitsPerPixel; 509f7df2e56Smrg int src_stride = exaGetPixmapPitch(pSrcPixmap); 510f7df2e56Smrg CARD8 *src = NULL; 511f7df2e56Smrg 512f7df2e56Smrg if (!pExaScr->info->UploadToScreen) 513f7df2e56Smrg goto fallback; 514f7df2e56Smrg 515f7df2e56Smrg if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) 516f7df2e56Smrg goto fallback; 517f7df2e56Smrg 518f7df2e56Smrg if (pSrcDrawable->bitsPerPixel < 8) 519f7df2e56Smrg goto fallback; 520f7df2e56Smrg 521f7df2e56Smrg if (pGC && 522f7df2e56Smrg !(pGC->alu == GXcopy && 523f7df2e56Smrg EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask))) 524f7df2e56Smrg goto fallback; 525f7df2e56Smrg 526f7df2e56Smrg while (nbox--) { 527f7df2e56Smrg src = 528f7df2e56Smrg pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + 529f7df2e56Smrg src_off_y) * src_stride + 530f7df2e56Smrg (pbox->x1 + dx + src_off_x) * (bpp / 8); 531f7df2e56Smrg if (!pExaScr->info-> 532f7df2e56Smrg UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x, 533f7df2e56Smrg pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, 534f7df2e56Smrg pbox->y2 - pbox->y1, (char *) src, 535f7df2e56Smrg src_stride)) 536f7df2e56Smrg goto fallback; 537f7df2e56Smrg 538f7df2e56Smrg pbox++; 539f7df2e56Smrg } 540f7df2e56Smrg } 541f7df2e56Smrg else 542f7df2e56Smrg goto fallback; 543f7df2e56Smrg } 544f7df2e56Smrg else 545f7df2e56Smrg goto fallback; 5464642e01fSmrg 5474642e01fSmrg goto out; 5484642e01fSmrg 549f7df2e56Smrg fallback: 5504202a189Smrg ret = FALSE; 5514642e01fSmrg 552f7df2e56Smrg out: 5534642e01fSmrg if (dstregion) { 554f7df2e56Smrg RegionUninit(dstregion); 555f7df2e56Smrg RegionDestroy(dstregion); 5564642e01fSmrg } 5574642e01fSmrg if (srcregion) { 558f7df2e56Smrg RegionUninit(srcregion); 559f7df2e56Smrg RegionDestroy(srcregion); 5604642e01fSmrg } 5614202a189Smrg 5624202a189Smrg return ret; 5634202a189Smrg} 5644202a189Smrg 5654202a189Smrgvoid 566f7df2e56SmrgexaCopyNtoN(DrawablePtr pSrcDrawable, 567f7df2e56Smrg DrawablePtr pDstDrawable, 568f7df2e56Smrg GCPtr pGC, 569f7df2e56Smrg BoxPtr pbox, 570f7df2e56Smrg int nbox, 571f7df2e56Smrg int dx, 572f7df2e56Smrg int dy, 573f7df2e56Smrg Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) 5744202a189Smrg{ 5754202a189Smrg ExaScreenPriv(pDstDrawable->pScreen); 5764202a189Smrg 5774202a189Smrg if (pExaScr->fallback_counter || 578f7df2e56Smrg (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW)) 579f7df2e56Smrg return; 5804202a189Smrg 581f7df2e56Smrg if (exaHWCopyNtoN 582f7df2e56Smrg (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, 583f7df2e56Smrg upsidedown)) 584f7df2e56Smrg return; 5854202a189Smrg 5864202a189Smrg /* This is a CopyWindow, it's cleaner to fallback at the original call. */ 5874202a189Smrg if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) { 588f7df2e56Smrg pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW; 589f7df2e56Smrg return; 5904202a189Smrg } 5914202a189Smrg 5924202a189Smrg /* fallback */ 593f7df2e56Smrg ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, 594f7df2e56Smrg reverse, upsidedown, bitplane, closure); 59505b261ecSmrg} 59605b261ecSmrg 59705b261ecSmrgRegionPtr 59805b261ecSmrgexaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, 599f7df2e56Smrg int srcx, int srcy, int width, int height, int dstx, int dsty) 60005b261ecSmrg{ 601f7df2e56Smrg ExaScreenPriv(pDstDrawable->pScreen); 60205b261ecSmrg 6034202a189Smrg if (pExaScr->fallback_counter || pExaScr->swappedOut) { 604f7df2e56Smrg return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, 605f7df2e56Smrg srcx, srcy, width, height, dstx, dsty); 60605b261ecSmrg } 60705b261ecSmrg 608f7df2e56Smrg return miDoCopy(pSrcDrawable, pDstDrawable, pGC, 609f7df2e56Smrg srcx, srcy, width, height, 610f7df2e56Smrg dstx, dsty, exaCopyNtoN, 0, NULL); 61105b261ecSmrg} 61205b261ecSmrg 61305b261ecSmrgstatic void 61405b261ecSmrgexaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 615f7df2e56Smrg DDXPointPtr ppt) 61605b261ecSmrg{ 617f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 61805b261ecSmrg int i; 61905b261ecSmrg xRectangle *prect; 62005b261ecSmrg 62105b261ecSmrg /* If we can't reuse the current GC as is, don't bother accelerating the 62205b261ecSmrg * points. 62305b261ecSmrg */ 6244202a189Smrg if (pExaScr->fallback_counter || pGC->fillStyle != FillSolid) { 625f7df2e56Smrg ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); 626f7df2e56Smrg return; 62705b261ecSmrg } 62805b261ecSmrg 629f7df2e56Smrg prect = xallocarray(npt, sizeof(xRectangle)); 63005b261ecSmrg for (i = 0; i < npt; i++) { 631f7df2e56Smrg prect[i].x = ppt[i].x; 632f7df2e56Smrg prect[i].y = ppt[i].y; 633f7df2e56Smrg if (i > 0 && mode == CoordModePrevious) { 634f7df2e56Smrg prect[i].x += prect[i - 1].x; 635f7df2e56Smrg prect[i].y += prect[i - 1].y; 636f7df2e56Smrg } 637f7df2e56Smrg prect[i].width = 1; 638f7df2e56Smrg prect[i].height = 1; 63905b261ecSmrg } 64005b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); 6414202a189Smrg free(prect); 64205b261ecSmrg} 64305b261ecSmrg 64405b261ecSmrg/** 64505b261ecSmrg * exaPolylines() checks if it can accelerate the lines as a group of 64605b261ecSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 64705b261ecSmrg * acceleration if so. 64805b261ecSmrg */ 64905b261ecSmrgstatic void 65005b261ecSmrgexaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 651f7df2e56Smrg DDXPointPtr ppt) 65205b261ecSmrg{ 653f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 65405b261ecSmrg xRectangle *prect; 65505b261ecSmrg int x1, x2, y1, y2; 65605b261ecSmrg int i; 65705b261ecSmrg 6584202a189Smrg if (pExaScr->fallback_counter) { 659f7df2e56Smrg ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); 660f7df2e56Smrg return; 6614202a189Smrg } 6624202a189Smrg 66305b261ecSmrg /* Don't try to do wide lines or non-solid fill style. */ 66405b261ecSmrg if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 665f7df2e56Smrg pGC->fillStyle != FillSolid) { 666f7df2e56Smrg ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); 667f7df2e56Smrg return; 66805b261ecSmrg } 66905b261ecSmrg 670f7df2e56Smrg prect = xallocarray(npt - 1, sizeof(xRectangle)); 67105b261ecSmrg x1 = ppt[0].x; 67205b261ecSmrg y1 = ppt[0].y; 67305b261ecSmrg /* If we have any non-horizontal/vertical, fall back. */ 67405b261ecSmrg for (i = 0; i < npt - 1; i++) { 675f7df2e56Smrg if (mode == CoordModePrevious) { 676f7df2e56Smrg x2 = x1 + ppt[i + 1].x; 677f7df2e56Smrg y2 = y1 + ppt[i + 1].y; 678f7df2e56Smrg } 679f7df2e56Smrg else { 680f7df2e56Smrg x2 = ppt[i + 1].x; 681f7df2e56Smrg y2 = ppt[i + 1].y; 682f7df2e56Smrg } 683f7df2e56Smrg 684f7df2e56Smrg if (x1 != x2 && y1 != y2) { 685f7df2e56Smrg free(prect); 686f7df2e56Smrg ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); 687f7df2e56Smrg return; 688f7df2e56Smrg } 689f7df2e56Smrg 690f7df2e56Smrg if (x1 < x2) { 691f7df2e56Smrg prect[i].x = x1; 692f7df2e56Smrg prect[i].width = x2 - x1 + 1; 693f7df2e56Smrg } 694f7df2e56Smrg else { 695f7df2e56Smrg prect[i].x = x2; 696f7df2e56Smrg prect[i].width = x1 - x2 + 1; 697f7df2e56Smrg } 698f7df2e56Smrg if (y1 < y2) { 699f7df2e56Smrg prect[i].y = y1; 700f7df2e56Smrg prect[i].height = y2 - y1 + 1; 701f7df2e56Smrg } 702f7df2e56Smrg else { 703f7df2e56Smrg prect[i].y = y2; 704f7df2e56Smrg prect[i].height = y1 - y2 + 1; 705f7df2e56Smrg } 706f7df2e56Smrg 707f7df2e56Smrg x1 = x2; 708f7df2e56Smrg y1 = y2; 70905b261ecSmrg } 71005b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); 7114202a189Smrg free(prect); 71205b261ecSmrg} 71305b261ecSmrg 71405b261ecSmrg/** 71505b261ecSmrg * exaPolySegment() checks if it can accelerate the lines as a group of 71605b261ecSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 71705b261ecSmrg * acceleration if so. 71805b261ecSmrg */ 71905b261ecSmrgstatic void 720f7df2e56SmrgexaPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) 72105b261ecSmrg{ 722f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 72305b261ecSmrg xRectangle *prect; 72405b261ecSmrg int i; 72505b261ecSmrg 72605b261ecSmrg /* Don't try to do wide lines or non-solid fill style. */ 7274202a189Smrg if (pExaScr->fallback_counter || pGC->lineWidth != 0 || 728f7df2e56Smrg pGC->lineStyle != LineSolid || pGC->fillStyle != FillSolid) { 729f7df2e56Smrg ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); 730f7df2e56Smrg return; 73105b261ecSmrg } 73205b261ecSmrg 73305b261ecSmrg /* If we have any non-horizontal/vertical, fall back. */ 73405b261ecSmrg for (i = 0; i < nseg; i++) { 735f7df2e56Smrg if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { 736f7df2e56Smrg ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); 737f7df2e56Smrg return; 738f7df2e56Smrg } 73905b261ecSmrg } 74005b261ecSmrg 7415a112b11Smrg prect = xallocarray((unsigned int)nseg, sizeof(xRectangle)); 74205b261ecSmrg for (i = 0; i < nseg; i++) { 743f7df2e56Smrg if (pSeg[i].x1 < pSeg[i].x2) { 744f7df2e56Smrg prect[i].x = pSeg[i].x1; 745f7df2e56Smrg prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; 746f7df2e56Smrg } 747f7df2e56Smrg else { 748f7df2e56Smrg prect[i].x = pSeg[i].x2; 749f7df2e56Smrg prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; 750f7df2e56Smrg } 751f7df2e56Smrg if (pSeg[i].y1 < pSeg[i].y2) { 752f7df2e56Smrg prect[i].y = pSeg[i].y1; 753f7df2e56Smrg prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; 754f7df2e56Smrg } 755f7df2e56Smrg else { 756f7df2e56Smrg prect[i].y = pSeg[i].y2; 757f7df2e56Smrg prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; 758f7df2e56Smrg } 759f7df2e56Smrg 760f7df2e56Smrg /* don't paint last pixel */ 761f7df2e56Smrg if (pGC->capStyle == CapNotLast) { 762f7df2e56Smrg if (prect[i].width == 1) 763f7df2e56Smrg prect[i].height--; 764f7df2e56Smrg else 765f7df2e56Smrg prect[i].width--; 766f7df2e56Smrg } 76705b261ecSmrg } 76805b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); 7694202a189Smrg free(prect); 77005b261ecSmrg} 77105b261ecSmrg 772f7df2e56Smrgstatic Bool exaFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, 773f7df2e56Smrg Pixel pixel, CARD32 planemask, CARD32 alu, 774f7df2e56Smrg Bool hasClientClip); 77505b261ecSmrg 77605b261ecSmrgstatic void 777f7df2e56SmrgexaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) 77805b261ecSmrg{ 779f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 780f7df2e56Smrg RegionPtr pClip = fbGetCompositeClip(pGC); 781f7df2e56Smrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 782f7df2e56Smrg 783f7df2e56Smrg ExaPixmapPriv(pPixmap); 78405b261ecSmrg register BoxPtr pbox; 785f7df2e56Smrg BoxPtr pextent; 786f7df2e56Smrg int extentX1, extentX2, extentY1, extentY2; 787f7df2e56Smrg int fullX1, fullX2, fullY1, fullY2; 788f7df2e56Smrg int partX1, partX2, partY1, partY2; 789f7df2e56Smrg int xoff, yoff; 790f7df2e56Smrg int xorg, yorg; 791f7df2e56Smrg int n; 7924202a189Smrg RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED); 79305b261ecSmrg 79405b261ecSmrg /* Compute intersection of rects and clip region */ 7954202a189Smrg RegionTranslate(pReg, pDrawable->x, pDrawable->y); 7964202a189Smrg RegionIntersect(pReg, pClip, pReg); 79705b261ecSmrg 7984202a189Smrg if (!RegionNumRects(pReg)) { 799f7df2e56Smrg goto out; 80005b261ecSmrg } 80105b261ecSmrg 80205b261ecSmrg exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); 80305b261ecSmrg 8044202a189Smrg if (pExaScr->fallback_counter || pExaScr->swappedOut || 805f7df2e56Smrg pExaPixmap->accel_blocked) { 806f7df2e56Smrg goto fallback; 80705b261ecSmrg } 80805b261ecSmrg 80905b261ecSmrg /* For ROPs where overlaps don't matter, convert rectangles to region and 81005b261ecSmrg * call exaFillRegion{Solid,Tiled}. 81105b261ecSmrg */ 81205b261ecSmrg if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && 813f7df2e56Smrg (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || 814f7df2e56Smrg pGC->alu == GXnoop || pGC->alu == GXcopyInverted || 815f7df2e56Smrg pGC->alu == GXset)) { 816f7df2e56Smrg if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && 817f7df2e56Smrg exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? 818f7df2e56Smrg pGC->fgPixel : pGC->tile.pixel, pGC->planemask, 819f7df2e56Smrg pGC->alu, pGC->clientClip != NULL)) || 820f7df2e56Smrg (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && 821f7df2e56Smrg exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, 822f7df2e56Smrg pGC->planemask, pGC->alu, 823f7df2e56Smrg pGC->clientClip != NULL))) { 824f7df2e56Smrg goto out; 825f7df2e56Smrg } 82605b261ecSmrg } 82705b261ecSmrg 82805b261ecSmrg if (pGC->fillStyle != FillSolid && 829f7df2e56Smrg !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { 830f7df2e56Smrg goto fallback; 83105b261ecSmrg } 83205b261ecSmrg 8334202a189Smrg if (pExaScr->do_migration) { 834f7df2e56Smrg ExaMigrationRec pixmaps[1]; 8354202a189Smrg 836f7df2e56Smrg pixmaps[0].as_dst = TRUE; 837f7df2e56Smrg pixmaps[0].as_src = FALSE; 838f7df2e56Smrg pixmaps[0].pPix = pPixmap; 839f7df2e56Smrg pixmaps[0].pReg = NULL; 84005b261ecSmrg 841f7df2e56Smrg exaDoMigration(pixmaps, 1, TRUE); 8424202a189Smrg } 8434202a189Smrg 844f7df2e56Smrg if (!exaPixmapHasGpuCopy(pPixmap) || 845f7df2e56Smrg !(*pExaScr->info->PrepareSolid) (pPixmap, 846f7df2e56Smrg pGC->alu, 847f7df2e56Smrg pGC->planemask, pGC->fgPixel)) { 848f7df2e56Smrg fallback: 849f7df2e56Smrg ExaCheckPolyFillRect(pDrawable, pGC, nrect, prect); 850f7df2e56Smrg goto out; 85105b261ecSmrg } 85205b261ecSmrg 85305b261ecSmrg xorg = pDrawable->x; 85405b261ecSmrg yorg = pDrawable->y; 85505b261ecSmrg 8564202a189Smrg pextent = RegionExtents(pClip); 85705b261ecSmrg extentX1 = pextent->x1; 85805b261ecSmrg extentY1 = pextent->y1; 85905b261ecSmrg extentX2 = pextent->x2; 86005b261ecSmrg extentY2 = pextent->y2; 861f7df2e56Smrg while (nrect--) { 862f7df2e56Smrg fullX1 = prect->x + xorg; 863f7df2e56Smrg fullY1 = prect->y + yorg; 864f7df2e56Smrg fullX2 = fullX1 + (int) prect->width; 865f7df2e56Smrg fullY2 = fullY1 + (int) prect->height; 866f7df2e56Smrg prect++; 867f7df2e56Smrg 868f7df2e56Smrg if (fullX1 < extentX1) 869f7df2e56Smrg fullX1 = extentX1; 870f7df2e56Smrg 871f7df2e56Smrg if (fullY1 < extentY1) 872f7df2e56Smrg fullY1 = extentY1; 873f7df2e56Smrg 874f7df2e56Smrg if (fullX2 > extentX2) 875f7df2e56Smrg fullX2 = extentX2; 876f7df2e56Smrg 877f7df2e56Smrg if (fullY2 > extentY2) 878f7df2e56Smrg fullY2 = extentY2; 879f7df2e56Smrg 880f7df2e56Smrg if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) 881f7df2e56Smrg continue; 882f7df2e56Smrg n = RegionNumRects(pClip); 883f7df2e56Smrg if (n == 1) { 884f7df2e56Smrg (*pExaScr->info->Solid) (pPixmap, 885f7df2e56Smrg fullX1 + xoff, fullY1 + yoff, 886f7df2e56Smrg fullX2 + xoff, fullY2 + yoff); 887f7df2e56Smrg } 888f7df2e56Smrg else { 889f7df2e56Smrg pbox = RegionRects(pClip); 890f7df2e56Smrg /* 891f7df2e56Smrg * clip the rectangle to each box in the clip region 892f7df2e56Smrg * this is logically equivalent to calling Intersect(), 893f7df2e56Smrg * but rectangles may overlap each other here. 894f7df2e56Smrg */ 895f7df2e56Smrg while (n--) { 896f7df2e56Smrg partX1 = pbox->x1; 897f7df2e56Smrg if (partX1 < fullX1) 898f7df2e56Smrg partX1 = fullX1; 899f7df2e56Smrg partY1 = pbox->y1; 900f7df2e56Smrg if (partY1 < fullY1) 901f7df2e56Smrg partY1 = fullY1; 902f7df2e56Smrg partX2 = pbox->x2; 903f7df2e56Smrg if (partX2 > fullX2) 904f7df2e56Smrg partX2 = fullX2; 905f7df2e56Smrg partY2 = pbox->y2; 906f7df2e56Smrg if (partY2 > fullY2) 907f7df2e56Smrg partY2 = fullY2; 908f7df2e56Smrg 909f7df2e56Smrg pbox++; 910f7df2e56Smrg 911f7df2e56Smrg if (partX1 < partX2 && partY1 < partY2) { 912f7df2e56Smrg (*pExaScr->info->Solid) (pPixmap, 913f7df2e56Smrg partX1 + xoff, partY1 + yoff, 914f7df2e56Smrg partX2 + xoff, partY2 + yoff); 915f7df2e56Smrg } 916f7df2e56Smrg } 917f7df2e56Smrg } 91805b261ecSmrg } 91905b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 92005b261ecSmrg exaMarkSync(pDrawable->pScreen); 92105b261ecSmrg 922f7df2e56Smrg out: 9234202a189Smrg RegionUninit(pReg); 9244202a189Smrg RegionDestroy(pReg); 92505b261ecSmrg} 92605b261ecSmrg 92705b261ecSmrgconst GCOps exaOps = { 92805b261ecSmrg exaFillSpans, 92905b261ecSmrg ExaCheckSetSpans, 93005b261ecSmrg exaPutImage, 93105b261ecSmrg exaCopyArea, 93205b261ecSmrg ExaCheckCopyPlane, 93305b261ecSmrg exaPolyPoint, 93405b261ecSmrg exaPolylines, 93505b261ecSmrg exaPolySegment, 93605b261ecSmrg miPolyRectangle, 93705b261ecSmrg ExaCheckPolyArc, 93805b261ecSmrg miFillPolygon, 93905b261ecSmrg exaPolyFillRect, 94005b261ecSmrg miPolyFillArc, 94105b261ecSmrg miPolyText8, 94205b261ecSmrg miPolyText16, 94305b261ecSmrg miImageText8, 94405b261ecSmrg miImageText16, 9454642e01fSmrg ExaCheckImageGlyphBlt, 94605b261ecSmrg ExaCheckPolyGlyphBlt, 94705b261ecSmrg ExaCheckPushPixels, 94805b261ecSmrg}; 94905b261ecSmrg 95005b261ecSmrgvoid 95105b261ecSmrgexaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 95205b261ecSmrg{ 953f7df2e56Smrg RegionRec rgnDst; 954f7df2e56Smrg int dx, dy; 955f7df2e56Smrg PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); 956f7df2e56Smrg 9574202a189Smrg ExaScreenPriv(pWin->drawable.pScreen); 95805b261ecSmrg 95905b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 96005b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 9614202a189Smrg RegionTranslate(prgnSrc, -dx, -dy); 96205b261ecSmrg 9634202a189Smrg RegionInit(&rgnDst, NullBox, 0); 96405b261ecSmrg 9654202a189Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 96605b261ecSmrg#ifdef COMPOSITE 96705b261ecSmrg if (pPixmap->screen_x || pPixmap->screen_y) 968f7df2e56Smrg RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y); 96905b261ecSmrg#endif 97005b261ecSmrg 9714202a189Smrg if (pExaScr->fallback_counter) { 972f7df2e56Smrg pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW; 973f7df2e56Smrg goto fallback; 9744202a189Smrg } 9754202a189Smrg 9764202a189Smrg pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW; 977f7df2e56Smrg miCopyRegion(&pPixmap->drawable, &pPixmap->drawable, 978f7df2e56Smrg NULL, &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); 9794202a189Smrg pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW; 98005b261ecSmrg 981f7df2e56Smrg fallback: 9824202a189Smrg RegionUninit(&rgnDst); 9834202a189Smrg 9844202a189Smrg if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) { 985f7df2e56Smrg pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW; 986f7df2e56Smrg RegionTranslate(prgnSrc, dx, dy); 987f7df2e56Smrg ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc); 9884202a189Smrg } 98905b261ecSmrg} 99005b261ecSmrg 99105b261ecSmrgstatic Bool 992f7df2e56SmrgexaFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, 993f7df2e56Smrg CARD32 planemask, CARD32 alu, Bool hasClientClip) 99405b261ecSmrg{ 99505b261ecSmrg ExaScreenPriv(pDrawable->pScreen); 996f7df2e56Smrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 997f7df2e56Smrg 998f7df2e56Smrg ExaPixmapPriv(pPixmap); 99905b261ecSmrg int xoff, yoff; 10004642e01fSmrg Bool ret = FALSE; 100105b261ecSmrg 10024642e01fSmrg exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); 10034202a189Smrg RegionTranslate(pRegion, xoff, yoff); 10044642e01fSmrg 10054202a189Smrg if (pExaScr->fallback_counter || pExaPixmap->accel_blocked) 1006f7df2e56Smrg goto out; 10074202a189Smrg 10084202a189Smrg if (pExaScr->do_migration) { 1009f7df2e56Smrg ExaMigrationRec pixmaps[1]; 10104202a189Smrg 1011f7df2e56Smrg pixmaps[0].as_dst = TRUE; 1012f7df2e56Smrg pixmaps[0].as_src = FALSE; 1013f7df2e56Smrg pixmaps[0].pPix = pPixmap; 1014f7df2e56Smrg pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, 1015f7df2e56Smrg alu, 1016f7df2e56Smrg hasClientClip) ? NULL : pRegion; 10174202a189Smrg 1018f7df2e56Smrg exaDoMigration(pixmaps, 1, TRUE); 101905b261ecSmrg } 102005b261ecSmrg 1021f7df2e56Smrg if (exaPixmapHasGpuCopy(pPixmap) && 1022f7df2e56Smrg (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) { 1023f7df2e56Smrg int nbox; 1024f7df2e56Smrg BoxPtr pBox; 1025f7df2e56Smrg 1026f7df2e56Smrg nbox = RegionNumRects(pRegion); 1027f7df2e56Smrg pBox = RegionRects(pRegion); 1028f7df2e56Smrg 1029f7df2e56Smrg while (nbox--) { 1030f7df2e56Smrg (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, 1031f7df2e56Smrg pBox->y2); 1032f7df2e56Smrg pBox++; 1033f7df2e56Smrg } 1034f7df2e56Smrg (*pExaScr->info->DoneSolid) (pPixmap); 1035f7df2e56Smrg exaMarkSync(pDrawable->pScreen); 1036f7df2e56Smrg 1037f7df2e56Smrg if (pExaPixmap->pDamage && 1038f7df2e56Smrg pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP && 1039f7df2e56Smrg pDrawable->width == 1 && pDrawable->height == 1 && 1040806e81e9Smrg pDrawable->bitsPerPixel != 24 && alu == GXcopy) { 1041f7df2e56Smrg RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); 1042f7df2e56Smrg 1043f7df2e56Smrg switch (pDrawable->bitsPerPixel) { 1044f7df2e56Smrg case 32: 1045f7df2e56Smrg *(CARD32 *) pExaPixmap->sys_ptr = pixel; 1046f7df2e56Smrg break; 1047f7df2e56Smrg case 16: 1048f7df2e56Smrg *(CARD16 *) pExaPixmap->sys_ptr = pixel; 1049f7df2e56Smrg break; 1050f7df2e56Smrg case 8: 1051f7df2e56Smrg case 4: 1052f7df2e56Smrg case 1: 1053f7df2e56Smrg *(CARD8 *) pExaPixmap->sys_ptr = pixel; 1054f7df2e56Smrg } 1055f7df2e56Smrg 1056f7df2e56Smrg RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, pRegion); 1057f7df2e56Smrg RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, pRegion); 1058f7df2e56Smrg RegionSubtract(pending_damage, pending_damage, pRegion); 1059f7df2e56Smrg } 1060f7df2e56Smrg 1061f7df2e56Smrg ret = TRUE; 106205b261ecSmrg } 106305b261ecSmrg 1064f7df2e56Smrg out: 10654202a189Smrg RegionTranslate(pRegion, -xoff, -yoff); 10664642e01fSmrg 10674642e01fSmrg return ret; 106805b261ecSmrg} 106905b261ecSmrg 107005b261ecSmrg/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. 107105b261ecSmrg * Based on fbFillRegionTiled(), fbTile(). 107205b261ecSmrg */ 107305b261ecSmrgBool 1074f7df2e56SmrgexaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, 1075f7df2e56Smrg DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu, 1076f7df2e56Smrg Bool hasClientClip) 107705b261ecSmrg{ 107805b261ecSmrg ExaScreenPriv(pDrawable->pScreen); 107905b261ecSmrg PixmapPtr pPixmap; 10804642e01fSmrg ExaPixmapPrivPtr pExaPixmap; 10814642e01fSmrg ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); 10824642e01fSmrg int xoff, yoff; 108305b261ecSmrg int tileWidth, tileHeight; 1084f7df2e56Smrg int nbox = RegionNumRects(pRegion); 1085f7df2e56Smrg BoxPtr pBox = RegionRects(pRegion); 10864642e01fSmrg Bool ret = FALSE; 10874642e01fSmrg int i; 108805b261ecSmrg 108905b261ecSmrg tileWidth = pTile->drawable.width; 109005b261ecSmrg tileHeight = pTile->drawable.height; 109105b261ecSmrg 109205b261ecSmrg /* If we're filling with a solid color, grab it out and go to 109305b261ecSmrg * FillRegionSolid, saving numerous copies. 109405b261ecSmrg */ 109505b261ecSmrg if (tileWidth == 1 && tileHeight == 1) 1096f7df2e56Smrg return exaFillRegionSolid(pDrawable, pRegion, 1097f7df2e56Smrg exaGetPixmapFirstPixel(pTile), planemask, 1098f7df2e56Smrg alu, hasClientClip); 109905b261ecSmrg 1100f7df2e56Smrg pPixmap = exaGetDrawablePixmap(pDrawable); 1101f7df2e56Smrg pExaPixmap = ExaGetPixmapPriv(pPixmap); 11024642e01fSmrg 11034202a189Smrg if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || 1104f7df2e56Smrg pTileExaPixmap->accel_blocked) 1105f7df2e56Smrg return FALSE; 11064202a189Smrg 11074202a189Smrg if (pExaScr->do_migration) { 1108f7df2e56Smrg ExaMigrationRec pixmaps[2]; 1109f7df2e56Smrg 1110f7df2e56Smrg pixmaps[0].as_dst = TRUE; 1111f7df2e56Smrg pixmaps[0].as_src = FALSE; 1112f7df2e56Smrg pixmaps[0].pPix = pPixmap; 1113f7df2e56Smrg pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled, 1114f7df2e56Smrg alu, 1115f7df2e56Smrg hasClientClip) ? NULL : pRegion; 1116f7df2e56Smrg pixmaps[1].as_dst = FALSE; 1117f7df2e56Smrg pixmaps[1].as_src = TRUE; 1118f7df2e56Smrg pixmaps[1].pPix = pTile; 1119f7df2e56Smrg pixmaps[1].pReg = NULL; 1120f7df2e56Smrg 1121f7df2e56Smrg exaDoMigration(pixmaps, 2, TRUE); 112205b261ecSmrg } 112305b261ecSmrg 1124f7df2e56Smrg pPixmap = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); 112505b261ecSmrg 11264202a189Smrg if (!pPixmap || !exaPixmapHasGpuCopy(pTile)) 1127f7df2e56Smrg return FALSE; 1128f7df2e56Smrg 1129f7df2e56Smrg if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) { 1130f7df2e56Smrg if (xoff || yoff) 1131f7df2e56Smrg RegionTranslate(pRegion, xoff, yoff); 1132f7df2e56Smrg 1133f7df2e56Smrg for (i = 0; i < nbox; i++) { 1134f7df2e56Smrg int height = pBox[i].y2 - pBox[i].y1; 1135f7df2e56Smrg int dstY = pBox[i].y1; 1136f7df2e56Smrg int tileY; 1137f7df2e56Smrg 1138f7df2e56Smrg if (alu == GXcopy) 1139f7df2e56Smrg height = min(height, tileHeight); 1140f7df2e56Smrg 1141f7df2e56Smrg modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); 1142f7df2e56Smrg 1143f7df2e56Smrg while (height > 0) { 1144f7df2e56Smrg int width = pBox[i].x2 - pBox[i].x1; 1145f7df2e56Smrg int dstX = pBox[i].x1; 1146f7df2e56Smrg int tileX; 1147f7df2e56Smrg int h = tileHeight - tileY; 1148f7df2e56Smrg 1149f7df2e56Smrg if (alu == GXcopy) 1150f7df2e56Smrg width = min(width, tileWidth); 1151f7df2e56Smrg 1152f7df2e56Smrg if (h > height) 1153f7df2e56Smrg h = height; 1154f7df2e56Smrg height -= h; 1155f7df2e56Smrg 1156f7df2e56Smrg modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, 1157f7df2e56Smrg tileX); 1158f7df2e56Smrg 1159f7df2e56Smrg while (width > 0) { 1160f7df2e56Smrg int w = tileWidth - tileX; 1161f7df2e56Smrg 1162f7df2e56Smrg if (w > width) 1163f7df2e56Smrg w = width; 1164f7df2e56Smrg width -= w; 1165f7df2e56Smrg 1166f7df2e56Smrg (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY, 1167f7df2e56Smrg w, h); 1168f7df2e56Smrg dstX += w; 1169f7df2e56Smrg tileX = 0; 1170f7df2e56Smrg } 1171f7df2e56Smrg dstY += h; 1172f7df2e56Smrg tileY = 0; 1173f7df2e56Smrg } 1174f7df2e56Smrg } 1175f7df2e56Smrg (*pExaScr->info->DoneCopy) (pPixmap); 1176f7df2e56Smrg 1177f7df2e56Smrg /* With GXcopy, we only need to do the basic algorithm up to the tile 1178f7df2e56Smrg * size; then, we can just keep doubling the destination in each 1179f7df2e56Smrg * direction until it fills the box. This way, the number of copy 1180f7df2e56Smrg * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where 1181f7df2e56Smrg * rx/ry is the ratio between box and tile width/height. This can make 1182f7df2e56Smrg * a big difference if each driver copy incurs a significant constant 1183f7df2e56Smrg * overhead. 1184f7df2e56Smrg */ 1185f7df2e56Smrg if (alu != GXcopy) 1186f7df2e56Smrg ret = TRUE; 1187f7df2e56Smrg else { 1188f7df2e56Smrg Bool more_copy = FALSE; 1189f7df2e56Smrg 1190f7df2e56Smrg for (i = 0; i < nbox; i++) { 1191f7df2e56Smrg int dstX = pBox[i].x1 + tileWidth; 1192f7df2e56Smrg int dstY = pBox[i].y1 + tileHeight; 1193f7df2e56Smrg 1194f7df2e56Smrg if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) { 1195f7df2e56Smrg more_copy = TRUE; 1196f7df2e56Smrg break; 1197f7df2e56Smrg } 1198f7df2e56Smrg } 1199f7df2e56Smrg 1200f7df2e56Smrg if (more_copy == FALSE) 1201f7df2e56Smrg ret = TRUE; 1202f7df2e56Smrg 1203f7df2e56Smrg if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, 1204f7df2e56Smrg 1, 1, alu, 1205f7df2e56Smrg planemask)) { 1206f7df2e56Smrg for (i = 0; i < nbox; i++) { 1207f7df2e56Smrg int dstX = pBox[i].x1 + tileWidth; 1208f7df2e56Smrg int dstY = pBox[i].y1 + tileHeight; 1209f7df2e56Smrg int width = min(pBox[i].x2 - dstX, tileWidth); 1210f7df2e56Smrg int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); 1211f7df2e56Smrg 1212f7df2e56Smrg while (dstX < pBox[i].x2) { 1213f7df2e56Smrg (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, 1214f7df2e56Smrg dstX, pBox[i].y1, width, 1215f7df2e56Smrg height); 1216f7df2e56Smrg dstX += width; 1217f7df2e56Smrg width = min(pBox[i].x2 - dstX, width * 2); 1218f7df2e56Smrg } 1219f7df2e56Smrg 1220f7df2e56Smrg width = pBox[i].x2 - pBox[i].x1; 1221f7df2e56Smrg height = min(pBox[i].y2 - dstY, tileHeight); 1222f7df2e56Smrg 1223f7df2e56Smrg while (dstY < pBox[i].y2) { 1224f7df2e56Smrg (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, 1225f7df2e56Smrg pBox[i].x1, dstY, width, 1226f7df2e56Smrg height); 1227f7df2e56Smrg dstY += height; 1228f7df2e56Smrg height = min(pBox[i].y2 - dstY, height * 2); 1229f7df2e56Smrg } 1230f7df2e56Smrg } 1231f7df2e56Smrg 1232f7df2e56Smrg (*pExaScr->info->DoneCopy) (pPixmap); 1233f7df2e56Smrg 1234f7df2e56Smrg ret = TRUE; 1235f7df2e56Smrg } 1236f7df2e56Smrg } 1237f7df2e56Smrg 1238f7df2e56Smrg exaMarkSync(pDrawable->pScreen); 1239f7df2e56Smrg 1240f7df2e56Smrg if (xoff || yoff) 1241f7df2e56Smrg RegionTranslate(pRegion, -xoff, -yoff); 124205b261ecSmrg } 12434642e01fSmrg 12444642e01fSmrg return ret; 124505b261ecSmrg} 124605b261ecSmrg 124705b261ecSmrg/** 124805b261ecSmrg * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. 124905b261ecSmrg * 125005b261ecSmrg * This is probably the only case we actually care about. The rest fall through 12514642e01fSmrg * to migration and fbGetImage, which hopefully will result in migration pushing 12524642e01fSmrg * the pixmap out of framebuffer. 125305b261ecSmrg */ 125405b261ecSmrgvoid 1255f7df2e56SmrgexaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, 1256f7df2e56Smrg unsigned int format, unsigned long planeMask, char *d) 125705b261ecSmrg{ 1258f7df2e56Smrg ExaScreenPriv(pDrawable->pScreen); 1259f7df2e56Smrg PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); 1260f7df2e56Smrg 12614202a189Smrg ExaPixmapPriv(pPix); 126205b261ecSmrg int xoff, yoff; 126305b261ecSmrg Bool ok; 126405b261ecSmrg 12654202a189Smrg if (pExaScr->fallback_counter || pExaScr->swappedOut) 1266f7df2e56Smrg goto fallback; 126705b261ecSmrg 12684202a189Smrg /* If there's a system copy, we want to save the result there */ 12694202a189Smrg if (pExaPixmap->pDamage) 1270f7df2e56Smrg goto fallback; 12714642e01fSmrg 1272f7df2e56Smrg pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); 12734642e01fSmrg 12744642e01fSmrg if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL) 1275f7df2e56Smrg goto fallback; 127605b261ecSmrg 127705b261ecSmrg /* Only cover the ZPixmap, solid copy case. */ 127805b261ecSmrg if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) 1279f7df2e56Smrg goto fallback; 128005b261ecSmrg 128105b261ecSmrg /* Only try to handle the 8bpp and up cases, since we don't want to think 128205b261ecSmrg * about <8bpp. 128305b261ecSmrg */ 128405b261ecSmrg if (pDrawable->bitsPerPixel < 8) 1285f7df2e56Smrg goto fallback; 128605b261ecSmrg 12874642e01fSmrg ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff, 1288f7df2e56Smrg pDrawable->y + y + yoff, w, h, d, 1289f7df2e56Smrg PixmapBytePad(w, pDrawable->depth)); 129005b261ecSmrg if (ok) { 1291f7df2e56Smrg exaWaitSync(pDrawable->pScreen); 1292f7df2e56Smrg return; 129305b261ecSmrg } 129405b261ecSmrg 1295f7df2e56Smrg fallback: 12964202a189Smrg ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d); 129705b261ecSmrg} 1298