exa_accel.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Copyright � 2001 Keith Packard 305b261ecSmrg * 405b261ecSmrg * 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> 2605b261ecSmrg * 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#include "cw.h" 3805b261ecSmrg 3905b261ecSmrgstatic void 4005b261ecSmrgexaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, 4105b261ecSmrg DDXPointPtr ppt, int *pwidth, int fSorted) 4205b261ecSmrg{ 4305b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 4405b261ecSmrg ExaScreenPriv (pScreen); 4505b261ecSmrg RegionPtr pClip = fbGetCompositeClip(pGC); 4605b261ecSmrg PixmapPtr pPixmap; 4705b261ecSmrg BoxPtr pextent, pbox; 4805b261ecSmrg int nbox; 4905b261ecSmrg int extentX1, extentX2, extentY1, extentY2; 5005b261ecSmrg int fullX1, fullX2, fullY1; 5105b261ecSmrg int partX1, partX2; 5205b261ecSmrg int off_x, off_y; 5305b261ecSmrg ExaMigrationRec pixmaps[1]; 5405b261ecSmrg 5505b261ecSmrg pixmaps[0].as_dst = TRUE; 5605b261ecSmrg pixmaps[0].as_src = FALSE; 5705b261ecSmrg pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); 5805b261ecSmrg 5905b261ecSmrg if (pExaScr->swappedOut || 6005b261ecSmrg pGC->fillStyle != FillSolid || 6105b261ecSmrg pPixmap->drawable.width > pExaScr->info->maxX || 6205b261ecSmrg pPixmap->drawable.height > pExaScr->info->maxY) 6305b261ecSmrg { 6405b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 6505b261ecSmrg ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); 6605b261ecSmrg return; 6705b261ecSmrg } else { 6805b261ecSmrg exaDoMigration (pixmaps, 1, TRUE); 6905b261ecSmrg } 7005b261ecSmrg 7105b261ecSmrg if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || 7205b261ecSmrg !(*pExaScr->info->PrepareSolid) (pPixmap, 7305b261ecSmrg pGC->alu, 7405b261ecSmrg pGC->planemask, 7505b261ecSmrg pGC->fgPixel)) 7605b261ecSmrg { 7705b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 7805b261ecSmrg ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); 7905b261ecSmrg return; 8005b261ecSmrg } 8105b261ecSmrg 8205b261ecSmrg pextent = REGION_EXTENTS(pGC->pScreen, pClip); 8305b261ecSmrg extentX1 = pextent->x1; 8405b261ecSmrg extentY1 = pextent->y1; 8505b261ecSmrg extentX2 = pextent->x2; 8605b261ecSmrg extentY2 = pextent->y2; 8705b261ecSmrg while (n--) 8805b261ecSmrg { 8905b261ecSmrg fullX1 = ppt->x; 9005b261ecSmrg fullY1 = ppt->y; 9105b261ecSmrg fullX2 = fullX1 + (int) *pwidth; 9205b261ecSmrg ppt++; 9305b261ecSmrg pwidth++; 9405b261ecSmrg 9505b261ecSmrg if (fullY1 < extentY1 || extentY2 <= fullY1) 9605b261ecSmrg continue; 9705b261ecSmrg 9805b261ecSmrg if (fullX1 < extentX1) 9905b261ecSmrg fullX1 = extentX1; 10005b261ecSmrg 10105b261ecSmrg if (fullX2 > extentX2) 10205b261ecSmrg fullX2 = extentX2; 10305b261ecSmrg 10405b261ecSmrg if (fullX1 >= fullX2) 10505b261ecSmrg continue; 10605b261ecSmrg 10705b261ecSmrg nbox = REGION_NUM_RECTS (pClip); 10805b261ecSmrg if (nbox == 1) 10905b261ecSmrg { 11005b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 11105b261ecSmrg fullX1 + off_x, fullY1 + off_y, 11205b261ecSmrg fullX2 + off_x, fullY1 + 1 + off_y); 11305b261ecSmrg } 11405b261ecSmrg else 11505b261ecSmrg { 11605b261ecSmrg pbox = REGION_RECTS(pClip); 11705b261ecSmrg while(nbox--) 11805b261ecSmrg { 11905b261ecSmrg if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) 12005b261ecSmrg { 12105b261ecSmrg partX1 = pbox->x1; 12205b261ecSmrg if (partX1 < fullX1) 12305b261ecSmrg partX1 = fullX1; 12405b261ecSmrg partX2 = pbox->x2; 12505b261ecSmrg if (partX2 > fullX2) 12605b261ecSmrg partX2 = fullX2; 12705b261ecSmrg if (partX2 > partX1) { 12805b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 12905b261ecSmrg partX1 + off_x, fullY1 + off_y, 13005b261ecSmrg partX2 + off_x, fullY1 + 1 + off_y); 13105b261ecSmrg } 13205b261ecSmrg } 13305b261ecSmrg pbox++; 13405b261ecSmrg } 13505b261ecSmrg } 13605b261ecSmrg } 13705b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 13805b261ecSmrg exaMarkSync(pScreen); 13905b261ecSmrg} 14005b261ecSmrg 14105b261ecSmrgstatic void 14205b261ecSmrgexaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 14305b261ecSmrg int w, int h, int leftPad, int format, char *bits) 14405b261ecSmrg{ 14505b261ecSmrg ExaScreenPriv (pDrawable->pScreen); 14605b261ecSmrg PixmapPtr pPix; 14705b261ecSmrg ExaMigrationRec pixmaps[1]; 14805b261ecSmrg RegionPtr pClip; 14905b261ecSmrg BoxPtr pbox; 15005b261ecSmrg int nbox; 15105b261ecSmrg int xoff, yoff; 15205b261ecSmrg int src_stride, bpp = pDrawable->bitsPerPixel; 15305b261ecSmrg 15405b261ecSmrg pixmaps[0].as_dst = TRUE; 15505b261ecSmrg pixmaps[0].as_src = FALSE; 15605b261ecSmrg pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); 15705b261ecSmrg 15805b261ecSmrg /* Don't bother with under 8bpp, XYPixmaps. */ 15905b261ecSmrg if (format != ZPixmap || bpp < 8) 16005b261ecSmrg goto migrate_and_fallback; 16105b261ecSmrg 16205b261ecSmrg /* Only accelerate copies: no rop or planemask. */ 16305b261ecSmrg if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) 16405b261ecSmrg goto migrate_and_fallback; 16505b261ecSmrg 16605b261ecSmrg if (pExaScr->swappedOut) 16705b261ecSmrg goto fallback; 16805b261ecSmrg 16905b261ecSmrg exaDoMigration (pixmaps, 1, TRUE); 17005b261ecSmrg 17105b261ecSmrg if (pExaScr->info->UploadToScreen == NULL) 17205b261ecSmrg goto fallback; 17305b261ecSmrg 17405b261ecSmrg pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); 17505b261ecSmrg 17605b261ecSmrg if (pPix == NULL) 17705b261ecSmrg goto fallback; 17805b261ecSmrg 17905b261ecSmrg x += pDrawable->x; 18005b261ecSmrg y += pDrawable->y; 18105b261ecSmrg 18205b261ecSmrg pClip = fbGetCompositeClip(pGC); 18305b261ecSmrg src_stride = PixmapBytePad(w, pDrawable->depth); 18405b261ecSmrg for (nbox = REGION_NUM_RECTS(pClip), 18505b261ecSmrg pbox = REGION_RECTS(pClip); 18605b261ecSmrg nbox--; 18705b261ecSmrg pbox++) 18805b261ecSmrg { 18905b261ecSmrg int x1 = x; 19005b261ecSmrg int y1 = y; 19105b261ecSmrg int x2 = x + w; 19205b261ecSmrg int y2 = y + h; 19305b261ecSmrg char *src; 19405b261ecSmrg Bool ok; 19505b261ecSmrg 19605b261ecSmrg if (x1 < pbox->x1) 19705b261ecSmrg x1 = pbox->x1; 19805b261ecSmrg if (y1 < pbox->y1) 19905b261ecSmrg y1 = pbox->y1; 20005b261ecSmrg if (x2 > pbox->x2) 20105b261ecSmrg x2 = pbox->x2; 20205b261ecSmrg if (y2 > pbox->y2) 20305b261ecSmrg y2 = pbox->y2; 20405b261ecSmrg if (x1 >= x2 || y1 >= y2) 20505b261ecSmrg continue; 20605b261ecSmrg 20705b261ecSmrg src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); 20805b261ecSmrg ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, 20905b261ecSmrg x2 - x1, y2 - y1, src, src_stride); 21005b261ecSmrg /* If we fail to accelerate the upload, fall back to using unaccelerated 21105b261ecSmrg * fb calls. 21205b261ecSmrg */ 21305b261ecSmrg if (!ok) { 21405b261ecSmrg FbStip *dst; 21505b261ecSmrg FbStride dst_stride; 21605b261ecSmrg int dstBpp; 21705b261ecSmrg int dstXoff, dstYoff; 21805b261ecSmrg 21905b261ecSmrg exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); 22005b261ecSmrg 22105b261ecSmrg fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, 22205b261ecSmrg dstXoff, dstYoff); 22305b261ecSmrg 22405b261ecSmrg fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), 22505b261ecSmrg src_stride / sizeof(FbStip), 22605b261ecSmrg (x1 - x) * dstBpp, 22705b261ecSmrg dst + (y1 + dstYoff) * dst_stride, 22805b261ecSmrg dst_stride, 22905b261ecSmrg (x1 + dstXoff) * dstBpp, 23005b261ecSmrg (x2 - x1) * dstBpp, 23105b261ecSmrg y2 - y1, 23205b261ecSmrg GXcopy, FB_ALLONES, dstBpp); 23305b261ecSmrg 23405b261ecSmrg exaFinishAccess(pDrawable, EXA_PREPARE_DEST); 23505b261ecSmrg } 23605b261ecSmrg 23705b261ecSmrg exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); 23805b261ecSmrg } 23905b261ecSmrg 24005b261ecSmrg return; 24105b261ecSmrg 24205b261ecSmrgmigrate_and_fallback: 24305b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 24405b261ecSmrg 24505b261ecSmrgfallback: 24605b261ecSmrg ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); 24705b261ecSmrg} 24805b261ecSmrg 24905b261ecSmrgstatic Bool inline 25005b261ecSmrgexaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 25105b261ecSmrg GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) 25205b261ecSmrg{ 25305b261ecSmrg ExaScreenPriv (pDstDrawable->pScreen); 25405b261ecSmrg PixmapPtr pSrcPixmap, pDstPixmap; 25505b261ecSmrg int src_off_x, src_off_y, dst_off_x, dst_off_y; 25605b261ecSmrg int dirsetup; 25705b261ecSmrg 25805b261ecSmrg /* Need to get both pixmaps to call the driver routines */ 25905b261ecSmrg pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y); 26005b261ecSmrg pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y); 26105b261ecSmrg if (!pSrcPixmap || !pDstPixmap) 26205b261ecSmrg return FALSE; 26305b261ecSmrg 26405b261ecSmrg /* 26505b261ecSmrg * Now the case of a chip that only supports xdir = ydir = 1 or 26605b261ecSmrg * xdir = ydir = -1, but we have xdir != ydir. 26705b261ecSmrg */ 26805b261ecSmrg dirsetup = 0; /* No direction set up yet. */ 26905b261ecSmrg for (; nbox; pbox++, nbox--) { 27005b261ecSmrg if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 27105b261ecSmrg /* Do a xdir = ydir = -1 blit instead. */ 27205b261ecSmrg if (dirsetup != -1) { 27305b261ecSmrg if (dirsetup != 0) 27405b261ecSmrg pExaScr->info->DoneCopy(pDstPixmap); 27505b261ecSmrg dirsetup = -1; 27605b261ecSmrg if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, 27705b261ecSmrg pDstPixmap, 27805b261ecSmrg -1, -1, 27905b261ecSmrg pGC ? pGC->alu : GXcopy, 28005b261ecSmrg pGC ? pGC->planemask : 28105b261ecSmrg FB_ALLONES)) 28205b261ecSmrg return FALSE; 28305b261ecSmrg } 28405b261ecSmrg (*pExaScr->info->Copy)(pDstPixmap, 28505b261ecSmrg src_off_x + pbox->x1 + dx, 28605b261ecSmrg src_off_y + pbox->y1 + dy, 28705b261ecSmrg dst_off_x + pbox->x1, 28805b261ecSmrg dst_off_y + pbox->y1, 28905b261ecSmrg pbox->x2 - pbox->x1, 29005b261ecSmrg pbox->y2 - pbox->y1); 29105b261ecSmrg } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 29205b261ecSmrg /* Do a xdir = ydir = 1 blit instead. */ 29305b261ecSmrg if (dirsetup != 1) { 29405b261ecSmrg if (dirsetup != 0) 29505b261ecSmrg pExaScr->info->DoneCopy(pDstPixmap); 29605b261ecSmrg dirsetup = 1; 29705b261ecSmrg if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, 29805b261ecSmrg pDstPixmap, 29905b261ecSmrg 1, 1, 30005b261ecSmrg pGC ? pGC->alu : GXcopy, 30105b261ecSmrg pGC ? pGC->planemask : 30205b261ecSmrg FB_ALLONES)) 30305b261ecSmrg return FALSE; 30405b261ecSmrg } 30505b261ecSmrg (*pExaScr->info->Copy)(pDstPixmap, 30605b261ecSmrg src_off_x + pbox->x1 + dx, 30705b261ecSmrg src_off_y + pbox->y1 + dy, 30805b261ecSmrg dst_off_x + pbox->x1, 30905b261ecSmrg dst_off_y + pbox->y1, 31005b261ecSmrg pbox->x2 - pbox->x1, 31105b261ecSmrg pbox->y2 - pbox->y1); 31205b261ecSmrg } else if (dx >= 0) { 31305b261ecSmrg /* 31405b261ecSmrg * xdir = 1, ydir = -1. 31505b261ecSmrg * Perform line-by-line xdir = ydir = 1 blits, going up. 31605b261ecSmrg */ 31705b261ecSmrg int i; 31805b261ecSmrg if (dirsetup != 1) { 31905b261ecSmrg if (dirsetup != 0) 32005b261ecSmrg pExaScr->info->DoneCopy(pDstPixmap); 32105b261ecSmrg dirsetup = 1; 32205b261ecSmrg if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, 32305b261ecSmrg pDstPixmap, 32405b261ecSmrg 1, 1, 32505b261ecSmrg pGC ? pGC->alu : GXcopy, 32605b261ecSmrg pGC ? pGC->planemask : 32705b261ecSmrg FB_ALLONES)) 32805b261ecSmrg return FALSE; 32905b261ecSmrg } 33005b261ecSmrg for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 33105b261ecSmrg (*pExaScr->info->Copy)(pDstPixmap, 33205b261ecSmrg src_off_x + pbox->x1 + dx, 33305b261ecSmrg src_off_y + pbox->y1 + dy + i, 33405b261ecSmrg dst_off_x + pbox->x1, 33505b261ecSmrg dst_off_y + pbox->y1 + i, 33605b261ecSmrg pbox->x2 - pbox->x1, 1); 33705b261ecSmrg } else { 33805b261ecSmrg /* 33905b261ecSmrg * xdir = -1, ydir = 1. 34005b261ecSmrg * Perform line-by-line xdir = ydir = -1 blits, going down. 34105b261ecSmrg */ 34205b261ecSmrg int i; 34305b261ecSmrg if (dirsetup != -1) { 34405b261ecSmrg if (dirsetup != 0) 34505b261ecSmrg pExaScr->info->DoneCopy(pDstPixmap); 34605b261ecSmrg dirsetup = -1; 34705b261ecSmrg if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, 34805b261ecSmrg pDstPixmap, 34905b261ecSmrg -1, -1, 35005b261ecSmrg pGC ? pGC->alu : GXcopy, 35105b261ecSmrg pGC ? pGC->planemask : 35205b261ecSmrg FB_ALLONES)) 35305b261ecSmrg return FALSE; 35405b261ecSmrg } 35505b261ecSmrg for (i = 0; i < pbox->y2 - pbox->y1; i++) 35605b261ecSmrg (*pExaScr->info->Copy)(pDstPixmap, 35705b261ecSmrg src_off_x + pbox->x1 + dx, 35805b261ecSmrg src_off_y + pbox->y1 + dy + i, 35905b261ecSmrg dst_off_x + pbox->x1, 36005b261ecSmrg dst_off_y + pbox->y1 + i, 36105b261ecSmrg pbox->x2 - pbox->x1, 1); 36205b261ecSmrg } 36305b261ecSmrg exaPixmapDirty(pDstPixmap, dst_off_x + pbox->x1, dst_off_y + pbox->y1, 36405b261ecSmrg dst_off_x + pbox->x2, dst_off_y + pbox->y2); 36505b261ecSmrg } 36605b261ecSmrg if (dirsetup != 0) 36705b261ecSmrg pExaScr->info->DoneCopy(pDstPixmap); 36805b261ecSmrg exaMarkSync(pDstDrawable->pScreen); 36905b261ecSmrg return TRUE; 37005b261ecSmrg} 37105b261ecSmrg 37205b261ecSmrgvoid 37305b261ecSmrgexaCopyNtoN (DrawablePtr pSrcDrawable, 37405b261ecSmrg DrawablePtr pDstDrawable, 37505b261ecSmrg GCPtr pGC, 37605b261ecSmrg BoxPtr pbox, 37705b261ecSmrg int nbox, 37805b261ecSmrg int dx, 37905b261ecSmrg int dy, 38005b261ecSmrg Bool reverse, 38105b261ecSmrg Bool upsidedown, 38205b261ecSmrg Pixel bitplane, 38305b261ecSmrg void *closure) 38405b261ecSmrg{ 38505b261ecSmrg ExaScreenPriv (pDstDrawable->pScreen); 38605b261ecSmrg PixmapPtr pSrcPixmap, pDstPixmap; 38705b261ecSmrg int src_off_x, src_off_y; 38805b261ecSmrg int dst_off_x, dst_off_y; 38905b261ecSmrg ExaMigrationRec pixmaps[2]; 39005b261ecSmrg Bool fallback = FALSE; 39105b261ecSmrg 39205b261ecSmrg pixmaps[0].as_dst = TRUE; 39305b261ecSmrg pixmaps[0].as_src = FALSE; 39405b261ecSmrg pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable); 39505b261ecSmrg pixmaps[1].as_dst = FALSE; 39605b261ecSmrg pixmaps[1].as_src = TRUE; 39705b261ecSmrg pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); 39805b261ecSmrg 39905b261ecSmrg /* Respect maxX/maxY in a trivial way: don't set up drawing when we might 40005b261ecSmrg * violate the limits. The proper solution would be a temporary pixmap 40105b261ecSmrg * adjusted so that the drawing happened within limits. 40205b261ecSmrg */ 40305b261ecSmrg if (pSrcPixmap->drawable.width > pExaScr->info->maxX || 40405b261ecSmrg pSrcPixmap->drawable.height > pExaScr->info->maxY || 40505b261ecSmrg pDstPixmap->drawable.width > pExaScr->info->maxX || 40605b261ecSmrg pDstPixmap->drawable.height > pExaScr->info->maxY) 40705b261ecSmrg { 40805b261ecSmrg fallback = TRUE; 40905b261ecSmrg } else { 41005b261ecSmrg exaDoMigration (pixmaps, 2, TRUE); 41105b261ecSmrg } 41205b261ecSmrg 41305b261ecSmrg /* Mixed directions must be handled specially if the card is lame */ 41405b261ecSmrg if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && 41505b261ecSmrg reverse != upsidedown) { 41605b261ecSmrg if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, 41705b261ecSmrg dx, dy)) 41805b261ecSmrg return; 41905b261ecSmrg fallback = TRUE; 42005b261ecSmrg } 42105b261ecSmrg 42205b261ecSmrg pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); 42305b261ecSmrg pDstPixmap = exaGetDrawablePixmap (pDstDrawable); 42405b261ecSmrg 42505b261ecSmrg exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); 42605b261ecSmrg exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); 42705b261ecSmrg 42805b261ecSmrg if (fallback || !exaPixmapIsOffscreen(pSrcPixmap) || 42905b261ecSmrg !exaPixmapIsOffscreen(pDstPixmap) || 43005b261ecSmrg !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, 43105b261ecSmrg upsidedown ? -1 : 1, 43205b261ecSmrg pGC ? pGC->alu : GXcopy, 43305b261ecSmrg pGC ? pGC->planemask : FB_ALLONES)) { 43405b261ecSmrg fallback = TRUE; 43505b261ecSmrg EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, 43605b261ecSmrg exaDrawableLocation(pSrcDrawable), 43705b261ecSmrg exaDrawableLocation(pDstDrawable))); 43805b261ecSmrg exaDoMigration (pixmaps, 2, FALSE); 43905b261ecSmrg exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); 44005b261ecSmrg exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); 44105b261ecSmrg fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, 44205b261ecSmrg pbox, nbox, dx, dy, reverse, upsidedown, 44305b261ecSmrg bitplane, closure); 44405b261ecSmrg exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); 44505b261ecSmrg exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); 44605b261ecSmrg } 44705b261ecSmrg 44805b261ecSmrg while (nbox--) 44905b261ecSmrg { 45005b261ecSmrg if (!fallback) 45105b261ecSmrg (*pExaScr->info->Copy) (pDstPixmap, 45205b261ecSmrg pbox->x1 + dx + src_off_x, 45305b261ecSmrg pbox->y1 + dy + src_off_y, 45405b261ecSmrg pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, 45505b261ecSmrg pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 45605b261ecSmrg exaPixmapDirty (pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, 45705b261ecSmrg pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); 45805b261ecSmrg pbox++; 45905b261ecSmrg } 46005b261ecSmrg 46105b261ecSmrg if (fallback) 46205b261ecSmrg return; 46305b261ecSmrg 46405b261ecSmrg (*pExaScr->info->DoneCopy) (pDstPixmap); 46505b261ecSmrg exaMarkSync (pDstDrawable->pScreen); 46605b261ecSmrg} 46705b261ecSmrg 46805b261ecSmrgRegionPtr 46905b261ecSmrgexaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, 47005b261ecSmrg int srcx, int srcy, int width, int height, int dstx, int dsty) 47105b261ecSmrg{ 47205b261ecSmrg ExaScreenPriv (pDstDrawable->pScreen); 47305b261ecSmrg 47405b261ecSmrg if (pExaScr->swappedOut) { 47505b261ecSmrg return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, 47605b261ecSmrg srcx, srcy, width, height, dstx, dsty); 47705b261ecSmrg } 47805b261ecSmrg 47905b261ecSmrg return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, 48005b261ecSmrg srcx, srcy, width, height, 48105b261ecSmrg dstx, dsty, exaCopyNtoN, 0, NULL); 48205b261ecSmrg} 48305b261ecSmrg 48405b261ecSmrgstatic void 48505b261ecSmrgexaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 48605b261ecSmrg DDXPointPtr ppt) 48705b261ecSmrg{ 48805b261ecSmrg int i; 48905b261ecSmrg xRectangle *prect; 49005b261ecSmrg 49105b261ecSmrg /* If we can't reuse the current GC as is, don't bother accelerating the 49205b261ecSmrg * points. 49305b261ecSmrg */ 49405b261ecSmrg if (pGC->fillStyle != FillSolid) { 49505b261ecSmrg ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); 49605b261ecSmrg return; 49705b261ecSmrg } 49805b261ecSmrg 49905b261ecSmrg prect = ALLOCATE_LOCAL(sizeof(xRectangle) * npt); 50005b261ecSmrg for (i = 0; i < npt; i++) { 50105b261ecSmrg prect[i].x = ppt[i].x; 50205b261ecSmrg prect[i].y = ppt[i].y; 50305b261ecSmrg if (i > 0 && mode == CoordModePrevious) { 50405b261ecSmrg prect[i].x += prect[i - 1].x; 50505b261ecSmrg prect[i].y += prect[i - 1].y; 50605b261ecSmrg } 50705b261ecSmrg prect[i].width = 1; 50805b261ecSmrg prect[i].height = 1; 50905b261ecSmrg } 51005b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); 51105b261ecSmrg DEALLOCATE_LOCAL(prect); 51205b261ecSmrg} 51305b261ecSmrg 51405b261ecSmrg/** 51505b261ecSmrg * exaPolylines() checks if it can accelerate the lines as a group of 51605b261ecSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 51705b261ecSmrg * acceleration if so. 51805b261ecSmrg */ 51905b261ecSmrgstatic void 52005b261ecSmrgexaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 52105b261ecSmrg DDXPointPtr ppt) 52205b261ecSmrg{ 52305b261ecSmrg xRectangle *prect; 52405b261ecSmrg int x1, x2, y1, y2; 52505b261ecSmrg int i; 52605b261ecSmrg 52705b261ecSmrg /* Don't try to do wide lines or non-solid fill style. */ 52805b261ecSmrg if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 52905b261ecSmrg pGC->fillStyle != FillSolid) { 53005b261ecSmrg ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); 53105b261ecSmrg return; 53205b261ecSmrg } 53305b261ecSmrg 53405b261ecSmrg prect = ALLOCATE_LOCAL(sizeof(xRectangle) * (npt - 1)); 53505b261ecSmrg x1 = ppt[0].x; 53605b261ecSmrg y1 = ppt[0].y; 53705b261ecSmrg /* If we have any non-horizontal/vertical, fall back. */ 53805b261ecSmrg for (i = 0; i < npt - 1; i++) { 53905b261ecSmrg if (mode == CoordModePrevious) { 54005b261ecSmrg x2 = x1 + ppt[i + 1].x; 54105b261ecSmrg y2 = y1 + ppt[i + 1].y; 54205b261ecSmrg } else { 54305b261ecSmrg x2 = ppt[i + 1].x; 54405b261ecSmrg y2 = ppt[i + 1].y; 54505b261ecSmrg } 54605b261ecSmrg 54705b261ecSmrg if (x1 != x2 && y1 != y2) { 54805b261ecSmrg DEALLOCATE_LOCAL(prect); 54905b261ecSmrg ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); 55005b261ecSmrg return; 55105b261ecSmrg } 55205b261ecSmrg 55305b261ecSmrg if (x1 < x2) { 55405b261ecSmrg prect[i].x = x1; 55505b261ecSmrg prect[i].width = x2 - x1 + 1; 55605b261ecSmrg } else { 55705b261ecSmrg prect[i].x = x2; 55805b261ecSmrg prect[i].width = x1 - x2 + 1; 55905b261ecSmrg } 56005b261ecSmrg if (y1 < y2) { 56105b261ecSmrg prect[i].y = y1; 56205b261ecSmrg prect[i].height = y2 - y1 + 1; 56305b261ecSmrg } else { 56405b261ecSmrg prect[i].y = y2; 56505b261ecSmrg prect[i].height = y1 - y2 + 1; 56605b261ecSmrg } 56705b261ecSmrg 56805b261ecSmrg x1 = x2; 56905b261ecSmrg y1 = y2; 57005b261ecSmrg } 57105b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); 57205b261ecSmrg DEALLOCATE_LOCAL(prect); 57305b261ecSmrg} 57405b261ecSmrg 57505b261ecSmrg/** 57605b261ecSmrg * exaPolySegment() checks if it can accelerate the lines as a group of 57705b261ecSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 57805b261ecSmrg * acceleration if so. 57905b261ecSmrg */ 58005b261ecSmrgstatic void 58105b261ecSmrgexaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, 58205b261ecSmrg xSegment *pSeg) 58305b261ecSmrg{ 58405b261ecSmrg xRectangle *prect; 58505b261ecSmrg int i; 58605b261ecSmrg 58705b261ecSmrg /* Don't try to do wide lines or non-solid fill style. */ 58805b261ecSmrg if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 58905b261ecSmrg pGC->fillStyle != FillSolid) 59005b261ecSmrg { 59105b261ecSmrg ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); 59205b261ecSmrg return; 59305b261ecSmrg } 59405b261ecSmrg 59505b261ecSmrg /* If we have any non-horizontal/vertical, fall back. */ 59605b261ecSmrg for (i = 0; i < nseg; i++) { 59705b261ecSmrg if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { 59805b261ecSmrg ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); 59905b261ecSmrg return; 60005b261ecSmrg } 60105b261ecSmrg } 60205b261ecSmrg 60305b261ecSmrg prect = ALLOCATE_LOCAL(sizeof(xRectangle) * nseg); 60405b261ecSmrg for (i = 0; i < nseg; i++) { 60505b261ecSmrg if (pSeg[i].x1 < pSeg[i].x2) { 60605b261ecSmrg prect[i].x = pSeg[i].x1; 60705b261ecSmrg prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; 60805b261ecSmrg } else { 60905b261ecSmrg prect[i].x = pSeg[i].x2; 61005b261ecSmrg prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; 61105b261ecSmrg } 61205b261ecSmrg if (pSeg[i].y1 < pSeg[i].y2) { 61305b261ecSmrg prect[i].y = pSeg[i].y1; 61405b261ecSmrg prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; 61505b261ecSmrg } else { 61605b261ecSmrg prect[i].y = pSeg[i].y2; 61705b261ecSmrg prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; 61805b261ecSmrg } 61905b261ecSmrg } 62005b261ecSmrg pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); 62105b261ecSmrg DEALLOCATE_LOCAL(prect); 62205b261ecSmrg} 62305b261ecSmrg 62405b261ecSmrgstatic Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, 62505b261ecSmrg Pixel pixel, CARD32 planemask, CARD32 alu); 62605b261ecSmrg 62705b261ecSmrgstatic void 62805b261ecSmrgexaPolyFillRect(DrawablePtr pDrawable, 62905b261ecSmrg GCPtr pGC, 63005b261ecSmrg int nrect, 63105b261ecSmrg xRectangle *prect) 63205b261ecSmrg{ 63305b261ecSmrg ExaScreenPriv (pDrawable->pScreen); 63405b261ecSmrg RegionPtr pClip = fbGetCompositeClip(pGC); 63505b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 63605b261ecSmrg register BoxPtr pbox; 63705b261ecSmrg BoxPtr pextent; 63805b261ecSmrg int extentX1, extentX2, extentY1, extentY2; 63905b261ecSmrg int fullX1, fullX2, fullY1, fullY2; 64005b261ecSmrg int partX1, partX2, partY1, partY2; 64105b261ecSmrg int xoff, yoff; 64205b261ecSmrg int xorg, yorg; 64305b261ecSmrg int n; 64405b261ecSmrg ExaMigrationRec pixmaps[2]; 64505b261ecSmrg RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); 64605b261ecSmrg 64705b261ecSmrg /* Compute intersection of rects and clip region */ 64805b261ecSmrg REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); 64905b261ecSmrg REGION_INTERSECT(pScreen, pReg, pClip, pReg); 65005b261ecSmrg 65105b261ecSmrg if (!REGION_NUM_RECTS(pReg)) { 65205b261ecSmrg goto out; 65305b261ecSmrg } 65405b261ecSmrg 65505b261ecSmrg pixmaps[0].as_dst = TRUE; 65605b261ecSmrg pixmaps[0].as_src = FALSE; 65705b261ecSmrg pixmaps[0].pPix = pPixmap; 65805b261ecSmrg 65905b261ecSmrg exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); 66005b261ecSmrg 66105b261ecSmrg if (pExaScr->swappedOut || 66205b261ecSmrg pPixmap->drawable.width > pExaScr->info->maxX || 66305b261ecSmrg pPixmap->drawable.height > pExaScr->info->maxY) 66405b261ecSmrg { 66505b261ecSmrg goto fallback; 66605b261ecSmrg } 66705b261ecSmrg 66805b261ecSmrg /* For ROPs where overlaps don't matter, convert rectangles to region and 66905b261ecSmrg * call exaFillRegion{Solid,Tiled}. 67005b261ecSmrg */ 67105b261ecSmrg if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && 67205b261ecSmrg (pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || 67305b261ecSmrg pGC->alu == GXcopyInverted || pGC->alu == GXset)) { 67405b261ecSmrg if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && 67505b261ecSmrg exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? 67605b261ecSmrg pGC->fgPixel : pGC->tile.pixel, pGC->planemask, 67705b261ecSmrg pGC->alu)) || 67805b261ecSmrg (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && 67905b261ecSmrg exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, 68005b261ecSmrg pGC->planemask, pGC->alu))) { 68105b261ecSmrg goto out; 68205b261ecSmrg } 68305b261ecSmrg } 68405b261ecSmrg 68505b261ecSmrg if (pGC->fillStyle != FillSolid && 68605b261ecSmrg !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) 68705b261ecSmrg { 68805b261ecSmrg goto fallback; 68905b261ecSmrg } 69005b261ecSmrg 69105b261ecSmrg exaDoMigration (pixmaps, 1, TRUE); 69205b261ecSmrg 69305b261ecSmrg if (!exaPixmapIsOffscreen (pPixmap) || 69405b261ecSmrg !(*pExaScr->info->PrepareSolid) (pPixmap, 69505b261ecSmrg pGC->alu, 69605b261ecSmrg pGC->planemask, 69705b261ecSmrg pGC->fgPixel)) 69805b261ecSmrg { 69905b261ecSmrgfallback: 70005b261ecSmrg if (pGC->fillStyle == FillTiled && !pGC->tileIsPixel) { 70105b261ecSmrg pixmaps[1].as_dst = FALSE; 70205b261ecSmrg pixmaps[1].as_src = TRUE; 70305b261ecSmrg pixmaps[1].pPix = pGC->tile.pixmap; 70405b261ecSmrg exaDoMigration (pixmaps, 2, FALSE); 70505b261ecSmrg } else { 70605b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 70705b261ecSmrg } 70805b261ecSmrg 70905b261ecSmrg ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); 71005b261ecSmrg goto out; 71105b261ecSmrg } 71205b261ecSmrg 71305b261ecSmrg xorg = pDrawable->x; 71405b261ecSmrg yorg = pDrawable->y; 71505b261ecSmrg 71605b261ecSmrg pextent = REGION_EXTENTS(pGC->pScreen, pClip); 71705b261ecSmrg extentX1 = pextent->x1; 71805b261ecSmrg extentY1 = pextent->y1; 71905b261ecSmrg extentX2 = pextent->x2; 72005b261ecSmrg extentY2 = pextent->y2; 72105b261ecSmrg while (nrect--) 72205b261ecSmrg { 72305b261ecSmrg fullX1 = prect->x + xorg; 72405b261ecSmrg fullY1 = prect->y + yorg; 72505b261ecSmrg fullX2 = fullX1 + (int) prect->width; 72605b261ecSmrg fullY2 = fullY1 + (int) prect->height; 72705b261ecSmrg prect++; 72805b261ecSmrg 72905b261ecSmrg if (fullX1 < extentX1) 73005b261ecSmrg fullX1 = extentX1; 73105b261ecSmrg 73205b261ecSmrg if (fullY1 < extentY1) 73305b261ecSmrg fullY1 = extentY1; 73405b261ecSmrg 73505b261ecSmrg if (fullX2 > extentX2) 73605b261ecSmrg fullX2 = extentX2; 73705b261ecSmrg 73805b261ecSmrg if (fullY2 > extentY2) 73905b261ecSmrg fullY2 = extentY2; 74005b261ecSmrg 74105b261ecSmrg if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) 74205b261ecSmrg continue; 74305b261ecSmrg n = REGION_NUM_RECTS (pClip); 74405b261ecSmrg if (n == 1) 74505b261ecSmrg { 74605b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 74705b261ecSmrg fullX1 + xoff, fullY1 + yoff, 74805b261ecSmrg fullX2 + xoff, fullY2 + yoff); 74905b261ecSmrg } 75005b261ecSmrg else 75105b261ecSmrg { 75205b261ecSmrg pbox = REGION_RECTS(pClip); 75305b261ecSmrg /* 75405b261ecSmrg * clip the rectangle to each box in the clip region 75505b261ecSmrg * this is logically equivalent to calling Intersect(), 75605b261ecSmrg * but rectangles may overlap each other here. 75705b261ecSmrg */ 75805b261ecSmrg while(n--) 75905b261ecSmrg { 76005b261ecSmrg partX1 = pbox->x1; 76105b261ecSmrg if (partX1 < fullX1) 76205b261ecSmrg partX1 = fullX1; 76305b261ecSmrg partY1 = pbox->y1; 76405b261ecSmrg if (partY1 < fullY1) 76505b261ecSmrg partY1 = fullY1; 76605b261ecSmrg partX2 = pbox->x2; 76705b261ecSmrg if (partX2 > fullX2) 76805b261ecSmrg partX2 = fullX2; 76905b261ecSmrg partY2 = pbox->y2; 77005b261ecSmrg if (partY2 > fullY2) 77105b261ecSmrg partY2 = fullY2; 77205b261ecSmrg 77305b261ecSmrg pbox++; 77405b261ecSmrg 77505b261ecSmrg if (partX1 < partX2 && partY1 < partY2) { 77605b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 77705b261ecSmrg partX1 + xoff, partY1 + yoff, 77805b261ecSmrg partX2 + xoff, partY2 + yoff); 77905b261ecSmrg } 78005b261ecSmrg } 78105b261ecSmrg } 78205b261ecSmrg } 78305b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 78405b261ecSmrg exaMarkSync(pDrawable->pScreen); 78505b261ecSmrg 78605b261ecSmrgout: 78705b261ecSmrg REGION_DESTROY(pScreen, pReg); 78805b261ecSmrg} 78905b261ecSmrg 79005b261ecSmrgstatic void 79105b261ecSmrgexaSolidBoxClipped (DrawablePtr pDrawable, 79205b261ecSmrg RegionPtr pClip, 79305b261ecSmrg FbBits pm, 79405b261ecSmrg FbBits fg, 79505b261ecSmrg int x1, 79605b261ecSmrg int y1, 79705b261ecSmrg int x2, 79805b261ecSmrg int y2) 79905b261ecSmrg{ 80005b261ecSmrg ExaScreenPriv (pDrawable->pScreen); 80105b261ecSmrg PixmapPtr pPixmap; 80205b261ecSmrg BoxPtr pbox; 80305b261ecSmrg int nbox; 80405b261ecSmrg int xoff, yoff; 80505b261ecSmrg int partX1, partX2, partY1, partY2; 80605b261ecSmrg ExaMigrationRec pixmaps[1]; 80705b261ecSmrg Bool fallback = FALSE; 80805b261ecSmrg 80905b261ecSmrg pixmaps[0].as_dst = TRUE; 81005b261ecSmrg pixmaps[0].as_src = FALSE; 81105b261ecSmrg pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); 81205b261ecSmrg 81305b261ecSmrg if (pExaScr->swappedOut || 81405b261ecSmrg pPixmap->drawable.width > pExaScr->info->maxX || 81505b261ecSmrg pPixmap->drawable.height > pExaScr->info->maxY) 81605b261ecSmrg { 81705b261ecSmrg fallback = TRUE; 81805b261ecSmrg } else { 81905b261ecSmrg exaDoMigration (pixmaps, 1, TRUE); 82005b261ecSmrg } 82105b261ecSmrg 82205b261ecSmrg exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff); 82305b261ecSmrg 82405b261ecSmrg if (fallback || !exaPixmapIsOffscreen(pPixmap) || 82505b261ecSmrg !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) 82605b261ecSmrg { 82705b261ecSmrg EXA_FALLBACK(("to %p (%c)\n", pDrawable, 82805b261ecSmrg exaDrawableLocation(pDrawable))); 82905b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 83005b261ecSmrg fallback = TRUE; 83105b261ecSmrg exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 83205b261ecSmrg fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); 83305b261ecSmrg fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, 83405b261ecSmrg fbAnd (GXcopy, fg, pm), 83505b261ecSmrg fbXor (GXcopy, fg, pm)); 83605b261ecSmrg exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 83705b261ecSmrg } 83805b261ecSmrg for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); 83905b261ecSmrg nbox--; 84005b261ecSmrg pbox++) 84105b261ecSmrg { 84205b261ecSmrg partX1 = pbox->x1; 84305b261ecSmrg if (partX1 < x1) 84405b261ecSmrg partX1 = x1; 84505b261ecSmrg 84605b261ecSmrg partX2 = pbox->x2; 84705b261ecSmrg if (partX2 > x2) 84805b261ecSmrg partX2 = x2; 84905b261ecSmrg 85005b261ecSmrg if (partX2 <= partX1) 85105b261ecSmrg continue; 85205b261ecSmrg 85305b261ecSmrg partY1 = pbox->y1; 85405b261ecSmrg if (partY1 < y1) 85505b261ecSmrg partY1 = y1; 85605b261ecSmrg 85705b261ecSmrg partY2 = pbox->y2; 85805b261ecSmrg if (partY2 > y2) 85905b261ecSmrg partY2 = y2; 86005b261ecSmrg 86105b261ecSmrg if (partY2 <= partY1) 86205b261ecSmrg continue; 86305b261ecSmrg 86405b261ecSmrg if (!fallback) { 86505b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 86605b261ecSmrg partX1 + xoff, partY1 + yoff, 86705b261ecSmrg partX2 + xoff, partY2 + yoff); 86805b261ecSmrg } 86905b261ecSmrg 87005b261ecSmrg exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, 87105b261ecSmrg partY2 + yoff); 87205b261ecSmrg } 87305b261ecSmrg 87405b261ecSmrg if (fallback) 87505b261ecSmrg return; 87605b261ecSmrg 87705b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 87805b261ecSmrg exaMarkSync(pDrawable->pScreen); 87905b261ecSmrg} 88005b261ecSmrg 88105b261ecSmrgstatic void 88205b261ecSmrgexaImageGlyphBlt (DrawablePtr pDrawable, 88305b261ecSmrg GCPtr pGC, 88405b261ecSmrg int x, 88505b261ecSmrg int y, 88605b261ecSmrg unsigned int nglyph, 88705b261ecSmrg CharInfoPtr *ppciInit, 88805b261ecSmrg pointer pglyphBase) 88905b261ecSmrg{ 89005b261ecSmrg FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 89105b261ecSmrg CharInfoPtr *ppci; 89205b261ecSmrg CharInfoPtr pci; 89305b261ecSmrg unsigned char *pglyph; /* pointer bits in glyph */ 89405b261ecSmrg int gWidth, gHeight; /* width and height of glyph */ 89505b261ecSmrg FbStride gStride; /* stride of glyph */ 89605b261ecSmrg Bool opaque; 89705b261ecSmrg int n; 89805b261ecSmrg int gx, gy; 89905b261ecSmrg void (*glyph) (FbBits *, 90005b261ecSmrg FbStride, 90105b261ecSmrg int, 90205b261ecSmrg FbStip *, 90305b261ecSmrg FbBits, 90405b261ecSmrg int, 90505b261ecSmrg int); 90605b261ecSmrg FbBits *dst; 90705b261ecSmrg FbStride dstStride; 90805b261ecSmrg int dstBpp; 90905b261ecSmrg int dstXoff, dstYoff; 91005b261ecSmrg FbBits depthMask; 91105b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 91205b261ecSmrg ExaMigrationRec pixmaps[1]; 91305b261ecSmrg int xBack, widthBack, yBack, heightBack; 91405b261ecSmrg 91505b261ecSmrg for (ppci = ppciInit, n = nglyph, widthBack = 0; n; n--) 91605b261ecSmrg widthBack += (*ppci++)->metrics.characterWidth; 91705b261ecSmrg 91805b261ecSmrg xBack = x; 91905b261ecSmrg if (widthBack < 0) 92005b261ecSmrg { 92105b261ecSmrg xBack += widthBack; 92205b261ecSmrg widthBack = -widthBack; 92305b261ecSmrg } 92405b261ecSmrg yBack = y - FONTASCENT(pGC->font); 92505b261ecSmrg heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); 92605b261ecSmrg 92705b261ecSmrg if (xBack >= pDrawable->width || yBack >= pDrawable->height || 92805b261ecSmrg (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0) 92905b261ecSmrg return; 93005b261ecSmrg 93105b261ecSmrg pixmaps[0].as_dst = TRUE; 93205b261ecSmrg pixmaps[0].as_src = TRUE; 93305b261ecSmrg pixmaps[0].pPix = pPixmap; 93405b261ecSmrg 93505b261ecSmrg depthMask = FbFullMask(pDrawable->depth); 93605b261ecSmrg if ((pGC->planemask & depthMask) != depthMask) 93705b261ecSmrg { 93805b261ecSmrg exaDoMigration(pixmaps, 1, FALSE); 93905b261ecSmrg ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); 94005b261ecSmrg goto damage; 94105b261ecSmrg } 94205b261ecSmrg glyph = NULL; 94305b261ecSmrg switch (pDrawable->bitsPerPixel) { 94405b261ecSmrg case 8: glyph = fbGlyph8; break; 94505b261ecSmrg case 16: glyph = fbGlyph16; break; 94605b261ecSmrg case 24: glyph = fbGlyph24; break; 94705b261ecSmrg case 32: glyph = fbGlyph32; break; 94805b261ecSmrg } 94905b261ecSmrg 95005b261ecSmrg x += pDrawable->x; 95105b261ecSmrg y += pDrawable->y; 95205b261ecSmrg xBack += pDrawable->x; 95305b261ecSmrg yBack += pDrawable->y; 95405b261ecSmrg 95505b261ecSmrg if (TERMINALFONT (pGC->font) && !glyph) 95605b261ecSmrg { 95705b261ecSmrg opaque = TRUE; 95805b261ecSmrg } 95905b261ecSmrg else 96005b261ecSmrg { 96105b261ecSmrg exaSolidBoxClipped (pDrawable, 96205b261ecSmrg fbGetCompositeClip(pGC), 96305b261ecSmrg pGC->planemask, 96405b261ecSmrg pGC->bgPixel, 96505b261ecSmrg xBack, 96605b261ecSmrg yBack, 96705b261ecSmrg xBack + widthBack, 96805b261ecSmrg yBack + heightBack); 96905b261ecSmrg opaque = FALSE; 97005b261ecSmrg } 97105b261ecSmrg 97205b261ecSmrg EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 97305b261ecSmrg exaDoMigration(pixmaps, 1, FALSE); 97405b261ecSmrg exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 97505b261ecSmrg exaPrepareAccessGC (pGC); 97605b261ecSmrg 97705b261ecSmrg fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 97805b261ecSmrg 97905b261ecSmrg for (ppci = ppciInit; nglyph; nglyph--, x += pci->metrics.characterWidth) 98005b261ecSmrg { 98105b261ecSmrg pci = *ppci++; 98205b261ecSmrg gWidth = GLYPHWIDTHPIXELS(pci); 98305b261ecSmrg gHeight = GLYPHHEIGHTPIXELS(pci); 98405b261ecSmrg gx = x + pci->metrics.leftSideBearing; 98505b261ecSmrg gy = y - pci->metrics.ascent; 98605b261ecSmrg 98705b261ecSmrg if (!gWidth || !gHeight || (gx + gWidth) <= xBack || 98805b261ecSmrg (gy + gHeight) <= yBack || gx >= (xBack + widthBack) || 98905b261ecSmrg gy >= (yBack + heightBack)) 99005b261ecSmrg continue; 99105b261ecSmrg 99205b261ecSmrg pglyph = FONTGLYPHBITS(pglyphBase, pci); 99305b261ecSmrg 99405b261ecSmrg if (glyph && gWidth <= sizeof (FbStip) * 8 && 99505b261ecSmrg fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) 99605b261ecSmrg { 99705b261ecSmrg (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 99805b261ecSmrg (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); 99905b261ecSmrg } 100005b261ecSmrg else 100105b261ecSmrg { 100205b261ecSmrg RegionPtr pClip = fbGetCompositeClip(pGC); 100305b261ecSmrg 100405b261ecSmrg gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); 100505b261ecSmrg fbPutXYImage (pDrawable, pClip, pPriv->fg, pPriv->bg, pPriv->pm, 100605b261ecSmrg GXcopy, opaque, gx, gy, gWidth, gHeight, 100705b261ecSmrg (FbStip *) pglyph, gStride, 0); 100805b261ecSmrg } 100905b261ecSmrg } 101005b261ecSmrg exaFinishAccessGC (pGC); 101105b261ecSmrg exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 101205b261ecSmrg 101305b261ecSmrgdamage: 101405b261ecSmrg exaGetDrawableDeltas(pDrawable, pPixmap, &dstXoff, &dstYoff); 101505b261ecSmrg exaPixmapDirty(pPixmap, xBack + dstXoff, yBack + dstYoff, 101605b261ecSmrg xBack + dstXoff + widthBack, yBack + dstYoff + heightBack); 101705b261ecSmrg} 101805b261ecSmrg 101905b261ecSmrgconst GCOps exaOps = { 102005b261ecSmrg exaFillSpans, 102105b261ecSmrg ExaCheckSetSpans, 102205b261ecSmrg exaPutImage, 102305b261ecSmrg exaCopyArea, 102405b261ecSmrg ExaCheckCopyPlane, 102505b261ecSmrg exaPolyPoint, 102605b261ecSmrg exaPolylines, 102705b261ecSmrg exaPolySegment, 102805b261ecSmrg miPolyRectangle, 102905b261ecSmrg ExaCheckPolyArc, 103005b261ecSmrg miFillPolygon, 103105b261ecSmrg exaPolyFillRect, 103205b261ecSmrg miPolyFillArc, 103305b261ecSmrg miPolyText8, 103405b261ecSmrg miPolyText16, 103505b261ecSmrg miImageText8, 103605b261ecSmrg miImageText16, 103705b261ecSmrg exaImageGlyphBlt, 103805b261ecSmrg ExaCheckPolyGlyphBlt, 103905b261ecSmrg ExaCheckPushPixels, 104005b261ecSmrg}; 104105b261ecSmrg 104205b261ecSmrgvoid 104305b261ecSmrgexaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 104405b261ecSmrg{ 104505b261ecSmrg RegionRec rgnDst; 104605b261ecSmrg int dx, dy; 104705b261ecSmrg PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); 104805b261ecSmrg 104905b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 105005b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 105105b261ecSmrg REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 105205b261ecSmrg 105305b261ecSmrg REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); 105405b261ecSmrg 105505b261ecSmrg REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 105605b261ecSmrg#ifdef COMPOSITE 105705b261ecSmrg if (pPixmap->screen_x || pPixmap->screen_y) 105805b261ecSmrg REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, 105905b261ecSmrg -pPixmap->screen_x, -pPixmap->screen_y); 106005b261ecSmrg#endif 106105b261ecSmrg 106205b261ecSmrg fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable, 106305b261ecSmrg NULL, 106405b261ecSmrg &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); 106505b261ecSmrg 106605b261ecSmrg REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); 106705b261ecSmrg} 106805b261ecSmrg 106905b261ecSmrgstatic Bool 107005b261ecSmrgexaFillRegionSolid (DrawablePtr pDrawable, 107105b261ecSmrg RegionPtr pRegion, 107205b261ecSmrg Pixel pixel, 107305b261ecSmrg CARD32 planemask, 107405b261ecSmrg CARD32 alu) 107505b261ecSmrg{ 107605b261ecSmrg ExaScreenPriv(pDrawable->pScreen); 107705b261ecSmrg PixmapPtr pPixmap; 107805b261ecSmrg int xoff, yoff; 107905b261ecSmrg ExaMigrationRec pixmaps[1]; 108005b261ecSmrg int nbox = REGION_NUM_RECTS (pRegion); 108105b261ecSmrg BoxPtr pBox = REGION_RECTS (pRegion); 108205b261ecSmrg 108305b261ecSmrg pixmaps[0].as_dst = TRUE; 108405b261ecSmrg pixmaps[0].as_src = FALSE; 108505b261ecSmrg pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); 108605b261ecSmrg 108705b261ecSmrg if (pPixmap->drawable.width > pExaScr->info->maxX || 108805b261ecSmrg pPixmap->drawable.height > pExaScr->info->maxY) 108905b261ecSmrg { 109005b261ecSmrg goto fallback; 109105b261ecSmrg } else { 109205b261ecSmrg exaDoMigration (pixmaps, 1, TRUE); 109305b261ecSmrg } 109405b261ecSmrg 109505b261ecSmrg if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && 109605b261ecSmrg (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) 109705b261ecSmrg { 109805b261ecSmrg while (nbox--) 109905b261ecSmrg { 110005b261ecSmrg (*pExaScr->info->Solid) (pPixmap, 110105b261ecSmrg pBox->x1 + xoff, pBox->y1 + yoff, 110205b261ecSmrg pBox->x2 + xoff, pBox->y2 + yoff); 110305b261ecSmrg pBox++; 110405b261ecSmrg } 110505b261ecSmrg (*pExaScr->info->DoneSolid) (pPixmap); 110605b261ecSmrg exaMarkSync(pDrawable->pScreen); 110705b261ecSmrg } 110805b261ecSmrg else 110905b261ecSmrg { 111005b261ecSmrgfallback: 111105b261ecSmrg if (alu != GXcopy || planemask != FB_ALLONES) 111205b261ecSmrg return FALSE; 111305b261ecSmrg EXA_FALLBACK(("to %p (%c)\n", pDrawable, 111405b261ecSmrg exaDrawableLocation(pDrawable))); 111505b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 111605b261ecSmrg exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 111705b261ecSmrg fbFillRegionSolid (pDrawable, pRegion, 0, 111805b261ecSmrg fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); 111905b261ecSmrg exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 112005b261ecSmrg } 112105b261ecSmrg 112205b261ecSmrg return TRUE; 112305b261ecSmrg} 112405b261ecSmrg 112505b261ecSmrg/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. 112605b261ecSmrg * Based on fbFillRegionTiled(), fbTile(). 112705b261ecSmrg */ 112805b261ecSmrgBool 112905b261ecSmrgexaFillRegionTiled (DrawablePtr pDrawable, 113005b261ecSmrg RegionPtr pRegion, 113105b261ecSmrg PixmapPtr pTile, 113205b261ecSmrg DDXPointPtr pPatOrg, 113305b261ecSmrg CARD32 planemask, 113405b261ecSmrg CARD32 alu) 113505b261ecSmrg{ 113605b261ecSmrg ExaScreenPriv(pDrawable->pScreen); 113705b261ecSmrg PixmapPtr pPixmap; 113805b261ecSmrg int xoff, yoff, tileXoff, tileYoff; 113905b261ecSmrg int tileWidth, tileHeight; 114005b261ecSmrg ExaMigrationRec pixmaps[2]; 114105b261ecSmrg int nbox = REGION_NUM_RECTS (pRegion); 114205b261ecSmrg BoxPtr pBox = REGION_RECTS (pRegion); 114305b261ecSmrg 114405b261ecSmrg tileWidth = pTile->drawable.width; 114505b261ecSmrg tileHeight = pTile->drawable.height; 114605b261ecSmrg 114705b261ecSmrg /* If we're filling with a solid color, grab it out and go to 114805b261ecSmrg * FillRegionSolid, saving numerous copies. 114905b261ecSmrg */ 115005b261ecSmrg if (tileWidth == 1 && tileHeight == 1) 115105b261ecSmrg return exaFillRegionSolid(pDrawable, pRegion, 115205b261ecSmrg exaGetPixmapFirstPixel (pTile), planemask, 115305b261ecSmrg alu); 115405b261ecSmrg 115505b261ecSmrg pixmaps[0].as_dst = TRUE; 115605b261ecSmrg pixmaps[0].as_src = FALSE; 115705b261ecSmrg pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); 115805b261ecSmrg pixmaps[1].as_dst = FALSE; 115905b261ecSmrg pixmaps[1].as_src = TRUE; 116005b261ecSmrg pixmaps[1].pPix = pTile; 116105b261ecSmrg 116205b261ecSmrg if (pPixmap->drawable.width > pExaScr->info->maxX || 116305b261ecSmrg pPixmap->drawable.height > pExaScr->info->maxY || 116405b261ecSmrg tileWidth > pExaScr->info->maxX || 116505b261ecSmrg tileHeight > pExaScr->info->maxY) 116605b261ecSmrg { 116705b261ecSmrg goto fallback; 116805b261ecSmrg } else { 116905b261ecSmrg exaDoMigration (pixmaps, 2, TRUE); 117005b261ecSmrg } 117105b261ecSmrg 117205b261ecSmrg pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); 117305b261ecSmrg 117405b261ecSmrg if (!pPixmap) 117505b261ecSmrg goto fallback; 117605b261ecSmrg 117705b261ecSmrg if (!exaPixmapIsOffscreen(pTile)) 117805b261ecSmrg goto fallback; 117905b261ecSmrg 118005b261ecSmrg if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, 118105b261ecSmrg &tileXoff, &tileYoff), 118205b261ecSmrg pPixmap, 0, 0, alu, planemask)) 118305b261ecSmrg { 118405b261ecSmrg while (nbox--) 118505b261ecSmrg { 118605b261ecSmrg int height = pBox->y2 - pBox->y1; 118705b261ecSmrg int dstY = pBox->y1; 118805b261ecSmrg int tileY; 118905b261ecSmrg 119005b261ecSmrg modulus(dstY - pDrawable->y - pPatOrg->y, tileHeight, tileY); 119105b261ecSmrg 119205b261ecSmrg while (height > 0) { 119305b261ecSmrg int width = pBox->x2 - pBox->x1; 119405b261ecSmrg int dstX = pBox->x1; 119505b261ecSmrg int tileX; 119605b261ecSmrg int h = tileHeight - tileY; 119705b261ecSmrg 119805b261ecSmrg if (h > height) 119905b261ecSmrg h = height; 120005b261ecSmrg height -= h; 120105b261ecSmrg 120205b261ecSmrg modulus(dstX - pDrawable->x - pPatOrg->x, tileWidth, tileX); 120305b261ecSmrg 120405b261ecSmrg while (width > 0) { 120505b261ecSmrg int w = tileWidth - tileX; 120605b261ecSmrg if (w > width) 120705b261ecSmrg w = width; 120805b261ecSmrg width -= w; 120905b261ecSmrg 121005b261ecSmrg (*pExaScr->info->Copy) (pPixmap, 121105b261ecSmrg tileX + tileXoff, tileY + tileYoff, 121205b261ecSmrg dstX + xoff, dstY + yoff, 121305b261ecSmrg w, h); 121405b261ecSmrg dstX += w; 121505b261ecSmrg tileX = 0; 121605b261ecSmrg } 121705b261ecSmrg dstY += h; 121805b261ecSmrg tileY = 0; 121905b261ecSmrg } 122005b261ecSmrg pBox++; 122105b261ecSmrg } 122205b261ecSmrg (*pExaScr->info->DoneCopy) (pPixmap); 122305b261ecSmrg exaMarkSync(pDrawable->pScreen); 122405b261ecSmrg return TRUE; 122505b261ecSmrg } 122605b261ecSmrg 122705b261ecSmrgfallback: 122805b261ecSmrg if (alu != GXcopy || planemask != FB_ALLONES || pPatOrg->x != 0 || 122905b261ecSmrg pPatOrg->y != 0) 123005b261ecSmrg return FALSE; 123105b261ecSmrg EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable, 123205b261ecSmrg exaDrawableLocation(&pTile->drawable), 123305b261ecSmrg exaDrawableLocation(pDrawable))); 123405b261ecSmrg exaDoMigration (pixmaps, 2, FALSE); 123505b261ecSmrg exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 123605b261ecSmrg exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); 123705b261ecSmrg fbFillRegionTiled (pDrawable, pRegion, pTile); 123805b261ecSmrg exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); 123905b261ecSmrg exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 124005b261ecSmrg 124105b261ecSmrg return TRUE; 124205b261ecSmrg} 124305b261ecSmrg 124405b261ecSmrgvoid 124505b261ecSmrgexaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) 124605b261ecSmrg{ 124705b261ecSmrg ExaScreenPriv (pWin->drawable.pScreen); 124805b261ecSmrg PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin); 124905b261ecSmrg int xoff, yoff; 125005b261ecSmrg BoxPtr pBox; 125105b261ecSmrg int nbox = REGION_NUM_RECTS(pRegion); 125205b261ecSmrg 125305b261ecSmrg if (!nbox) 125405b261ecSmrg return; 125505b261ecSmrg 125605b261ecSmrg if (!pExaScr->swappedOut) { 125705b261ecSmrg DDXPointRec zeros = { 0, 0 }; 125805b261ecSmrg 125905b261ecSmrg switch (what) { 126005b261ecSmrg case PW_BACKGROUND: 126105b261ecSmrg switch (pWin->backgroundState) { 126205b261ecSmrg case None: 126305b261ecSmrg return; 126405b261ecSmrg case ParentRelative: 126505b261ecSmrg do { 126605b261ecSmrg pWin = pWin->parent; 126705b261ecSmrg } while (pWin->backgroundState == ParentRelative); 126805b261ecSmrg (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, 126905b261ecSmrg what); 127005b261ecSmrg return; 127105b261ecSmrg case BackgroundPixel: 127205b261ecSmrg exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel, 127305b261ecSmrg FB_ALLONES, GXcopy); 127405b261ecSmrg goto damage; 127505b261ecSmrg case BackgroundPixmap: 127605b261ecSmrg exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap, 127705b261ecSmrg &zeros, FB_ALLONES, GXcopy); 127805b261ecSmrg goto damage; 127905b261ecSmrg } 128005b261ecSmrg break; 128105b261ecSmrg case PW_BORDER: 128205b261ecSmrg if (pWin->borderIsPixel) { 128305b261ecSmrg exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel, 128405b261ecSmrg FB_ALLONES, GXcopy); 128505b261ecSmrg goto damage; 128605b261ecSmrg } else { 128705b261ecSmrg exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap, 128805b261ecSmrg &zeros, FB_ALLONES, GXcopy); 128905b261ecSmrg goto damage; 129005b261ecSmrg } 129105b261ecSmrg break; 129205b261ecSmrg } 129305b261ecSmrg } 129405b261ecSmrg ExaCheckPaintWindow (pWin, pRegion, what); 129505b261ecSmrg 129605b261ecSmrgdamage: 129705b261ecSmrg exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff); 129805b261ecSmrg 129905b261ecSmrg pBox = REGION_RECTS(pRegion); 130005b261ecSmrg 130105b261ecSmrg while (nbox--) 130205b261ecSmrg { 130305b261ecSmrg exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, 130405b261ecSmrg pBox->x2 + xoff, pBox->y2 + yoff); 130505b261ecSmrg pBox++; 130605b261ecSmrg } 130705b261ecSmrg} 130805b261ecSmrg 130905b261ecSmrg/** 131005b261ecSmrg * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. 131105b261ecSmrg * 131205b261ecSmrg * This is probably the only case we actually care about. The rest fall through 131305b261ecSmrg * to migration and ExaCheckGetImage, which hopefully will result in migration 131405b261ecSmrg * pushing the pixmap out of framebuffer. 131505b261ecSmrg */ 131605b261ecSmrgvoid 131705b261ecSmrgexaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, 131805b261ecSmrg unsigned int format, unsigned long planeMask, char *d) 131905b261ecSmrg{ 132005b261ecSmrg ExaScreenPriv (pDrawable->pScreen); 132105b261ecSmrg ExaMigrationRec pixmaps[1]; 132205b261ecSmrg PixmapPtr pPix; 132305b261ecSmrg int xoff, yoff; 132405b261ecSmrg Bool ok; 132505b261ecSmrg 132605b261ecSmrg if (pExaScr->swappedOut || (w == 1 && h == 1)) 132705b261ecSmrg goto fallback; 132805b261ecSmrg 132905b261ecSmrg if (pExaScr->info->DownloadFromScreen == NULL) 133005b261ecSmrg goto migrate_and_fallback; 133105b261ecSmrg 133205b261ecSmrg /* Only cover the ZPixmap, solid copy case. */ 133305b261ecSmrg if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) 133405b261ecSmrg goto migrate_and_fallback; 133505b261ecSmrg 133605b261ecSmrg /* Only try to handle the 8bpp and up cases, since we don't want to think 133705b261ecSmrg * about <8bpp. 133805b261ecSmrg */ 133905b261ecSmrg if (pDrawable->bitsPerPixel < 8) 134005b261ecSmrg goto migrate_and_fallback; 134105b261ecSmrg 134205b261ecSmrg pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); 134305b261ecSmrg if (pPix == NULL) 134405b261ecSmrg goto fallback; 134505b261ecSmrg 134605b261ecSmrg xoff += pDrawable->x; 134705b261ecSmrg yoff += pDrawable->y; 134805b261ecSmrg 134905b261ecSmrg ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d, 135005b261ecSmrg PixmapBytePad(w, pDrawable->depth)); 135105b261ecSmrg if (ok) { 135205b261ecSmrg exaWaitSync(pDrawable->pScreen); 135305b261ecSmrg return; 135405b261ecSmrg } 135505b261ecSmrg 135605b261ecSmrgmigrate_and_fallback: 135705b261ecSmrg pixmaps[0].as_dst = FALSE; 135805b261ecSmrg pixmaps[0].as_src = TRUE; 135905b261ecSmrg pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); 136005b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 136105b261ecSmrgfallback: 136205b261ecSmrg ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d); 136305b261ecSmrg} 136405b261ecSmrg 136505b261ecSmrg/** 136605b261ecSmrg * GetSpans isn't accelerated yet, but performs migration so that we'll 136705b261ecSmrg * hopefully avoid the read-from-framebuffer cost. 136805b261ecSmrg */ 136905b261ecSmrgvoid 137005b261ecSmrgexaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, 137105b261ecSmrg int nspans, char *pdstStart) 137205b261ecSmrg{ 137305b261ecSmrg ExaMigrationRec pixmaps[1]; 137405b261ecSmrg 137505b261ecSmrg pixmaps[0].as_dst = FALSE; 137605b261ecSmrg pixmaps[0].as_src = TRUE; 137705b261ecSmrg pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); 137805b261ecSmrg exaDoMigration (pixmaps, 1, FALSE); 137905b261ecSmrg 138005b261ecSmrg ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 138105b261ecSmrg} 1382