diff --git a/ChangeLog b/ChangeLog index af80b9dca..aa28f63d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-03-14 Eric Anholt + + * exa/exa.c: (exaDriverInit): + * exa/exa_accel.c: (exaFillSpans), (exaCopyNtoN), + (exaPolyFillRect), (exaSolidBoxClipped), (exaFillRegionSolid), + (exaFillRegionTiled), (exaGetImage), (exaGetSpans): + * exa/exa_migration.c: (exaPixmapIsPinned), (exaMigrateTowardFb), + (exaMigrateTowardSys), (exaDoMigration): + * exa/exa_priv.h: + * exa/exa_render.c: (exaOpReadsDestination), + (exaTryDriverSolidFill), (exaTryDriverComposite), (exaComposite), + (exaGlyphs): + * exa/exa_unaccel.c: (exaGetPixmapFirstPixel): + Move migration logic to a new function, exaDoMigration(). This is + largely a manual conversion to allow for different migration schemes + to be implemented reasonably, but does include some minor improvements + such as accounting for pinned pixmaps not being acceleratable, and for + our current GetImage and GetSpans not being accelerated. + 2006-03-14 Eric Anholt * exa/exa_accel.c: (exaFillRegionTiled): diff --git a/exa/exa.c b/exa/exa.c index ffb80dd37..d987abae3 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -404,10 +404,10 @@ exaDriverInit (ScreenPtr pScreen, pScreen->CreateGC = exaCreateGC; pExaScr->SavedGetImage = pScreen->GetImage; - pScreen->GetImage = ExaCheckGetImage; + pScreen->GetImage = exaGetImage; pExaScr->SavedGetSpans = pScreen->GetSpans; - pScreen->GetSpans = ExaCheckGetSpans; + pScreen->GetSpans = exaGetSpans; pExaScr->SavedCopyWindow = pScreen->CopyWindow; pScreen->CopyWindow = exaCopyWindow; diff --git a/exa/exa_accel.c b/exa/exa_accel.c index ca3afc3ec..7770ef152 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -45,17 +45,25 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, int fullX1, fullX2, fullY1; int partX1, partX2; int off_x, off_y; + ExaMigrationRec pixmaps[1]; + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); - if (pExaScr->swappedOut) { - ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); - return; + if (pExaScr->swappedOut || + pGC->fillStyle != FillSolid || + pDrawable->width > pExaScr->info->maxX || + pDrawable->height > pExaScr->info->maxY) + { + exaDoMigration (pixmaps, 1, FALSE); + ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); + return; + } else { + exaDoMigration (pixmaps, 1, TRUE); } - if (pGC->fillStyle != FillSolid || - pDrawable->width > pExaScr->info->maxX || - pDrawable->height > pExaScr->info->maxY || - !(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || + if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, @@ -263,6 +271,14 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, PixmapPtr pSrcPixmap, pDstPixmap; int src_off_x, src_off_y; int dst_off_x, dst_off_y; + ExaMigrationRec pixmaps[2]; + + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDstDrawable); + pixmaps[1].as_dst = FALSE; + pixmaps[1].as_src = TRUE; + pixmaps[1].pPix = exaGetDrawablePixmap (pSrcDrawable); /* Respect maxX/maxY in a trivial way: don't set up drawing when we might * violate the limits. The proper solution would be a temporary pixmap @@ -273,22 +289,10 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pDstDrawable->width > pExaScr->info->maxX || pDstDrawable->height > pExaScr->info->maxY) { - exaDrawableUseMemory (pSrcDrawable); - exaDrawableUseMemory (pDstDrawable); + exaDoMigration (pixmaps, 2, FALSE); goto fallback; - } - - /* If either drawable is already in framebuffer, try to get both of them - * there. Otherwise, be happy with where they are. - */ - if (exaDrawableIsOffscreen(pDstDrawable) || - exaDrawableIsOffscreen(pSrcDrawable)) - { - exaDrawableUseScreen (pSrcDrawable); - exaDrawableUseScreen (pDstDrawable); } else { - exaDrawableUseMemory (pSrcDrawable); - exaDrawableUseMemory (pDstDrawable); + exaDoMigration (pixmaps, 2, TRUE); } /* Mixed directions must be handled specially if the card is lame */ @@ -367,12 +371,25 @@ exaPolyFillRect(DrawablePtr pDrawable, int xoff, yoff; int xorg, yorg; int n; + ExaMigrationRec pixmaps[1]; + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + if (pExaScr->swappedOut || - pGC->fillStyle != FillSolid || + pGC->fillStyle != FillSolid || pDrawable->width > pExaScr->info->maxX || - pDrawable->height > pExaScr->info->maxY || - !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || + pDrawable->height > pExaScr->info->maxY) + { + exaDoMigration (pixmaps, 1, FALSE); + ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); + return; + } else { + exaDoMigration (pixmaps, 1, TRUE); + } + + if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, @@ -471,13 +488,27 @@ exaSolidBoxClipped (DrawablePtr pDrawable, int nbox; int xoff, yoff; int partX1, partX2, partY1, partY2; + ExaMigrationRec pixmaps[1]; + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + if (pExaScr->swappedOut || pDrawable->width > pExaScr->info->maxX || - pDrawable->height > pExaScr->info->maxY || - !(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || + pDrawable->height > pExaScr->info->maxY) + { + EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); + exaDoMigration (pixmaps, 1, FALSE); + goto fallback; + } else { + exaDoMigration (pixmaps, 1, TRUE); + } + + if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) { +fallback: EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); @@ -724,10 +755,22 @@ exaFillRegionSolid (DrawablePtr pDrawable, ExaScreenPriv(pDrawable->pScreen); PixmapPtr pPixmap; int xoff, yoff; + ExaMigrationRec pixmaps[1]; - if (pDrawable->width <= pExaScr->info->maxX && - pDrawable->height <= pExaScr->info->maxY && - (pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + + if (pDrawable->width > pExaScr->info->maxX || + pDrawable->height > pExaScr->info->maxY) + { + exaDoMigration (pixmaps, 1, FALSE); + goto fallback; + } else { + exaDoMigration (pixmaps, 1, TRUE); + } + + if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel)) { int nbox = REGION_NUM_RECTS (pRegion); @@ -746,6 +789,7 @@ exaFillRegionSolid (DrawablePtr pDrawable, } else { +fallback: EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, @@ -766,18 +810,11 @@ exaFillRegionTiled (DrawablePtr pDrawable, PixmapPtr pPixmap; int xoff, yoff; int tileWidth, tileHeight; + ExaMigrationRec pixmaps[2]; tileWidth = pTile->drawable.width; tileHeight = pTile->drawable.height; - if (pDrawable->width > pExaScr->info->maxX || - pDrawable->height > pExaScr->info->maxY || - tileWidth > pExaScr->info->maxX || - tileHeight > pExaScr->info->maxY) - { - goto fallback; - } - /* If we're filling with a solid color, grab it out and go to * FillRegionSolid, saving numerous copies. */ @@ -786,11 +823,28 @@ exaFillRegionTiled (DrawablePtr pDrawable, return; } + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + pixmaps[1].as_dst = FALSE; + pixmaps[1].as_src = TRUE; + pixmaps[1].pPix = pTile; + + if (pDrawable->width > pExaScr->info->maxX || + pDrawable->height > pExaScr->info->maxY || + tileWidth > pExaScr->info->maxX || + tileHeight > pExaScr->info->maxY) + { + exaDoMigration (pixmaps, 2, FALSE); + goto fallback; + } else { + exaDoMigration (pixmaps, 2, TRUE); + } + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); if (!pPixmap) goto fallback; - exaPixmapUseScreen(pTile); if (!exaPixmapIsOffscreen(pTile)) goto fallback; @@ -891,3 +945,39 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) } ExaCheckPaintWindow (pWin, pRegion, what); } + +/** + * GetImage isn't accelerated yet, but performs migration so that we'll + * hopefully avoid the read-from-framebuffer cost. + */ +void +exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d) +{ + ExaMigrationRec pixmaps[1]; + + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + exaDoMigration (pixmaps, 1, FALSE); + + ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d); +} + +/** + * GetSpans isn't accelerated yet, but performs migration so that we'll + * hopefully avoid the read-from-framebuffer cost. + */ +void +exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart) +{ + ExaMigrationRec pixmaps[1]; + + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + exaDoMigration (pixmaps, 1, FALSE); + + ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); +} diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 720271cb7..d48abf066 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -40,6 +40,20 @@ #define DBG_MIGRATE(a) #endif +/** + * Returns TRUE if the pixmap is not movable. This is the case where it's a + * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch + * pixmap created by some other X Server internals (the score says it's + * pinned). + */ +static Bool +exaPixmapIsPinned (PixmapPtr pPix) +{ + ExaPixmapPriv (pPix); + + return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; +} + static void exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area) { @@ -233,20 +247,8 @@ exaMoveOutPixmap (PixmapPtr pPixmap) } } -void -exaDrawableUseScreen(DrawablePtr pDrawable) -{ - exaPixmapUseScreen (exaGetDrawablePixmap (pDrawable)); -} - -void -exaDrawableUseMemory(DrawablePtr pDrawable) -{ - exaPixmapUseMemory (exaGetDrawablePixmap (pDrawable)); -} - -void -exaPixmapUseScreen (PixmapPtr pPixmap) +static void +exaMigrateTowardFb (PixmapPtr pPixmap) { ExaPixmapPriv (pPixmap); @@ -283,8 +285,8 @@ exaPixmapUseScreen (PixmapPtr pPixmap) ExaOffscreenMarkUsed (pPixmap); } -void -exaPixmapUseMemory (PixmapPtr pPixmap) +static void +exaMigrateTowardSys (PixmapPtr pPixmap) { ExaPixmapPriv (pPixmap); @@ -309,3 +311,60 @@ exaPixmapUseMemory (PixmapPtr pPixmap) if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area) exaMoveOutPixmap (pPixmap); } + +/** + * Performs migration of the pixmaps according to the operation information + * provided in pixmaps and can_accel. In the future, other migration schemes + * may be added, which is facilitated by having this logic all in one place. + */ +void +exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) +{ + ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; + int i, j; + + /* If anything is pinned in system memory, we won't be able to + * accelerate. + */ + for (i = 0; i < npixmaps; i++) { + if (exaPixmapIsPinned (pixmaps[i].pPix) && + !exaPixmapIsOffscreen (pixmaps[i].pPix)) + { + EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix, + pixmaps[i].pPix->drawable.width, + pixmaps[i].pPix->drawable.height)); + can_accel = FALSE; + break; + } + } + + /* If we can't accelerate, either because the driver can't or because one of + * the pixmaps is pinned in system memory, then we migrate everybody toward + * system memory. + * + * We also migrate toward system if all pixmaps involved are currently in + * system memory -- this can mitigate thrashing when there are significantly + * more pixmaps active than would fit in memory. + * + * If not, then we migrate toward FB so that hopefully acceleration can + * happen. + */ + if (!can_accel) { + for (i = 0; i < npixmaps; i++) + exaMigrateTowardSys (pixmaps[i].pPix); + return; + } + + for (i = 0; i < npixmaps; i++) { + if (exaPixmapIsOffscreen(pixmaps[i].pPix)) { + /* Found one in FB, so move all to FB. */ + for (j = 0; j < npixmaps; j++) + exaMigrateTowardFb(pixmaps[j].pPix); + return; + } + } + + /* Nobody's in FB, so move all away from FB. */ + for (i = 0; i < npixmaps; i++) + exaMigrateTowardSys(pixmaps[i].pPix); +} diff --git a/exa/exa_priv.h b/exa/exa_priv.h index d9f0be1a4..036433266 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -140,6 +140,12 @@ typedef struct { Bool dirty; unsigned int size; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; + +typedef struct _ExaMigrationRec { + Bool as_dst; + Bool as_src; + PixmapPtr pPix; +} ExaMigrationRec, *ExaMigrationPtr; /** * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place @@ -256,6 +262,14 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); +void +exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +void +exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart); + extern const GCOps exaOps, exaAsyncPixmapGCOps; #ifdef RENDER @@ -291,18 +305,6 @@ void ExaOffscreenFini (ScreenPtr pScreen); /* exa.c */ -void -exaDrawableUseScreen(DrawablePtr pDrawable); - -void -exaDrawableUseMemory(DrawablePtr pDrawable); - -void -exaPixmapUseScreen (PixmapPtr pPixmap); - -void -exaPixmapUseMemory (PixmapPtr pPixmap); - void exaPrepareAccess(DrawablePtr pDrawable, int index); @@ -324,12 +326,6 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp); PixmapPtr exaGetDrawablePixmap(DrawablePtr pDrawable); -void -exaMoveInPixmap (PixmapPtr pPixmap); - -void -exaMoveOutPixmap (PixmapPtr pPixmap); - RegionPtr exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty); @@ -372,4 +368,14 @@ exaGlyphs (CARD8 op, GlyphListPtr list, GlyphPtr *glyphs); +/* exa_migration.c */ +void +exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); + +void +exaMoveInPixmap (PixmapPtr pPixmap); + +void +exaMoveOutPixmap (PixmapPtr pPixmap); + #endif /* EXAPRIV_H */ diff --git a/exa/exa_render.c b/exa/exa_render.c index 713817095..41fc8ddeb 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -109,7 +109,25 @@ exaPrintCompositeFallback(CARD8 op, " dst %s, \n", sop, srcdesc, maskdesc, dstdesc); } -#endif +#endif /* DEBUG_TRACE_FALL */ + +static Bool +exaOpReadsDestination (CARD8 op) +{ + /* FALSE (does not read destination) is the list of ops in the protocol + * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. + * That's just Clear and Src. ReduceCompositeOp() will already have + * converted con/disjoint clear/src to Clear or Src. + */ + switch (op) { + case PictOpClear: + case PictOpSrc: + return FALSE; + default: + return TRUE; + } +} + static Bool exaGetPixelFromRGBA(CARD32 *pixel, @@ -152,7 +170,6 @@ exaGetPixelFromRGBA(CARD32 *pixel, return TRUE; } - static Bool exaGetRGBAFromPixel(CARD32 pixel, CARD16 *red, @@ -232,6 +249,7 @@ exaTryDriverSolidFill(PicturePtr pSrc, PixmapPtr pSrcPix, pDstPix; CARD32 pixel; CARD16 red, green, blue, alpha; + ExaMigrationRec pixmaps[1]; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; @@ -246,7 +264,10 @@ exaTryDriverSolidFill(PicturePtr pSrc, pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); pixel = exaGetPixmapFirstPixel (pSrcPix); - exaDrawableUseScreen(pDst->pDrawable); + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + exaDoMigration(pixmaps, 1, TRUE); pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); if (!pDstPix) { @@ -309,6 +330,7 @@ exaTryDriverComposite(CARD8 op, int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; struct _Pixmap scratch; + ExaMigrationRec pixmaps[3]; /* Bail if we might exceed coord limits by rendering from/to these. We * should really be making some scratch pixmaps with offsets and coords @@ -347,10 +369,20 @@ exaTryDriverComposite(CARD8 op, return -1; } - exaDrawableUseScreen(pSrc->pDrawable); - if (pMask != NULL) - exaDrawableUseScreen(pMask->pDrawable); - exaDrawableUseScreen(pDst->pDrawable); + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = exaOpReadsDestination(op); + pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + pixmaps[1].as_dst = FALSE; + pixmaps[1].as_src = TRUE; + pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable); + if (pMask) { + pixmaps[2].as_dst = FALSE; + pixmaps[2].as_src = TRUE; + pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable); + exaDoMigration(pixmaps, 3, TRUE); + } else { + exaDoMigration(pixmaps, 2, TRUE); + } pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); if (pMask) @@ -508,13 +540,24 @@ exaComposite(CARD8 op, } if (ret != 0) { + ExaMigrationRec pixmaps[3]; /* failure to accelerate was not due to pixmaps being in the wrong * locations. */ - exaDrawableUseMemory(pSrc->pDrawable); - if (pMask != NULL) - exaDrawableUseMemory(pMask->pDrawable); - exaDrawableUseMemory(pDst->pDrawable); + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = exaOpReadsDestination(op); + pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + pixmaps[1].as_dst = FALSE; + pixmaps[1].as_src = TRUE; + pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable); + if (pMask) { + pixmaps[2].as_dst = FALSE; + pixmaps[2].as_src = TRUE; + pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable); + exaDoMigration(pixmaps, 3, FALSE); + } else { + exaDoMigration(pixmaps, 2, FALSE); + } } #if DEBUG_TRACE_FALL @@ -621,6 +664,7 @@ exaGlyphs (CARD8 op, { GCPtr pGC; int maxwidth = 0, maxheight = 0, i; + ExaMigrationRec pixmaps[1]; x += list->xOff; y += list->yOff; @@ -681,7 +725,10 @@ exaGlyphs (CARD8 op, /* Give the temporary pixmap an initial kick towards the screen, so * it'll stick there. */ - exaPixmapUseScreen (pPixmap); + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = pPixmap; + exaDoMigration (pixmaps, 1, TRUE); while (n--) { diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index 361147cea..1ffecb811 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -279,6 +279,11 @@ ExaCheckRestoreAreas (PixmapPtr pPixmap, exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST); } +/* XXX: Note the lack of a prepare on the tile, if the window has a tiled + * background. This function happens to only be called if pExaScr->swappedOut, + * so we actually end up not having to do it since the tile won't be in fb. + * That doesn't make this not dirty, though. + */ void ExaCheckPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what) { @@ -334,8 +339,12 @@ CARD32 exaGetPixmapFirstPixel (PixmapPtr pPixmap) { CARD32 pixel; + ExaMigrationRec pixmaps[1]; - exaDrawableUseMemory(&pPixmap->drawable); + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = pPixmap; + exaDoMigration (pixmaps, 1, TRUE); exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); switch (pPixmap->drawable.bitsPerPixel) {