summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2007-08-29 19:55:22 +0200
committerMichel Dänzer <michel@tungstengraphics.com>2007-09-07 17:58:49 +0200
commit320777ddecbe9f5933eb759678204d2cdd8fe289 (patch)
treef41967333e00ee79360e8e6b3781f31224f74a36
parent19ca0ab22f9bd5a29716259ac230fee62c1afc10 (diff)
EXA: Support partial migration of pixmap contents between Sys and FB.
The initiator of migration can pass in a region that defines the relevant area of each source pixmap or the irrelevant area of the destination pixmap. By default, the pending damage region is assumed relevant for the destination pixmap, and everything for source pixmaps. Thanks to Jarno Manninen for reassuring me that my own ideas for this were feasible and for providing additional ideas.
-rw-r--r--exa/exa.c21
-rw-r--r--exa/exa_accel.c29
-rw-r--r--exa/exa_migration.c232
-rw-r--r--exa/exa_priv.h4
-rw-r--r--exa/exa_render.c10
5 files changed, 194 insertions, 102 deletions
diff --git a/exa/exa.c b/exa/exa.c
index ecdb76139..145d5b2b0 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -363,20 +363,15 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
}
}
-/**
- * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
- *
- * It deals with waiting for synchronization with the card, determining if
- * PrepareAccess() is necessary, and working around PrepareAccess() failure.
- */
void
-exaPrepareAccess(DrawablePtr pDrawable, int index)
+exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
{
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = index == EXA_PREPARE_DEST;
pixmaps[0].as_src = index != EXA_PREPARE_DEST;
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = pReg;
exaDoMigration(pixmaps, 1, FALSE);
@@ -384,6 +379,18 @@ exaPrepareAccess(DrawablePtr pDrawable, int index)
}
/**
+ * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
+ *
+ * It deals with waiting for synchronization with the card, determining if
+ * PrepareAccess() is necessary, and working around PrepareAccess() failure.
+ */
+void
+exaPrepareAccess(DrawablePtr pDrawable, int index)
+{
+ exaPrepareAccessReg(pDrawable, index, NULL);
+}
+
+/**
* exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
*
* It deals with calling the driver's FinishAccess() only if necessary.
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index 07ada153f..ceb6c7bb5 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -55,6 +55,7 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
@@ -153,6 +154,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = NULL;
/* Don't bother with under 8bpp, XYPixmaps. */
if (format != ZPixmap || bpp < 8)
@@ -211,7 +213,8 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int dstXoff, dstYoff;
if (!access_prepared) {
- exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg(pDrawable, EXA_PREPARE_DEST,
+ pixmaps[0].pReg);
access_prepared = TRUE;
}
@@ -232,6 +235,8 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (access_prepared)
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
+ else
+ exaMarkSync(pDrawable->pScreen);
exaPixmapDirty(pixmaps[0].pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
}
@@ -420,9 +425,11 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
+ pixmaps[0].pReg = NULL;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
+ pixmaps[1].pReg = NULL;
/* 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
@@ -463,7 +470,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
exaDrawableLocation(pSrcDrawable),
exaDrawableLocation(pDstDrawable)));
- exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
pbox, nbox, dx, dy, reverse, upsidedown,
@@ -682,7 +689,8 @@ exaPolyFillRect(DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
-
+ pixmaps[0].pReg = NULL;
+
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
if (pExaScr->swappedOut ||
@@ -828,6 +836,7 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut ||
pPixmap->drawable.width > pExaScr->info->maxX ||
@@ -846,7 +855,7 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable)));
fallback = TRUE;
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
fbAnd (GXcopy, fg, pm),
@@ -949,6 +958,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
depthMask = FbFullMask(pDrawable->depth);
if ((pGC->planemask & depthMask) != depthMask)
@@ -987,7 +997,7 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
}
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
exaPrepareAccessGC (pGC);
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
@@ -1099,7 +1109,8 @@ exaFillRegionSolid (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
-
+ pixmaps[0].pReg = NULL;
+
if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
@@ -1128,7 +1139,7 @@ fallback:
return FALSE;
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable)));
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
fbFillRegionSolid (pDrawable, pRegion, 0,
fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
@@ -1170,9 +1181,11 @@ exaFillRegionTiled (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = NULL;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY ||
@@ -1243,7 +1256,7 @@ fallback:
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
exaDrawableLocation(&pTile->drawable),
exaDrawableLocation(pDrawable)));
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
fbFillRegionTiled (pDrawable, pRegion, pTile);
exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
diff --git a/exa/exa_migration.c b/exa/exa_migration.c
index 99058f138..f48e93a78 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration.c
@@ -117,28 +117,62 @@ exaPixmapShouldBeInFB (PixmapPtr pPix)
* FB to system or vice versa. Both areas must be allocated.
*/
static _X_INLINE void
-exaCopyDirty(PixmapPtr pPixmap, RegionPtr pValidDst, RegionPtr pValidSrc,
+exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
char *sys, int sys_pitch), CARD8 *fallback_src,
CARD8 *fallback_dst, int fallback_srcpitch, int fallback_dstpitch,
int fallback_index, void (*sync) (ScreenPtr pScreen))
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
- RegionPtr pDamageReg = DamageRegion (pExaPixmap->pDamage);
+ RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
RegionRec CopyReg;
CARD8 *save_ptr;
int save_pitch;
BoxPtr pBox;
int nbox;
- Bool do_sync = FALSE;
+ Bool access_prepared = FALSE;
- /* Damaged bits are valid in source but invalid in destination */
- REGION_UNION(pScreen, pValidSrc, pValidSrc, pDamageReg);
- REGION_SUBTRACT(pScreen, pValidDst, pValidDst, pDamageReg);
+ /* Damaged bits are valid in current copy but invalid in other one */
+ if (exaPixmapIsOffscreen(pPixmap)) {
+ REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
+ damage);
+ REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
+ damage);
+ } else {
+ REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
+ damage);
+ REGION_SUBTRACT(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
+ damage);
+ }
+
+ REGION_EMPTY(pScreen, damage);
- /* Copy bits valid in ssource but not in destination */
+ /* Copy bits valid in source but not in destination */
REGION_NULL(pScreen, &CopyReg);
REGION_SUBTRACT(pScreen, &CopyReg, pValidSrc, pValidDst);
+
+ if (migrate->as_dst) {
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
+
+ if (REGION_NIL(pending_damage)) {
+ static Bool firsttime = TRUE;
+
+ if (firsttime) {
+ ErrorF("%s: Pending damage region empty!\n", __func__);
+ firsttime = FALSE;
+ }
+ }
+
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage);
+
+ if (migrate->pReg)
+ REGION_SUBTRACT(pScreen, &CopyReg, &CopyReg, migrate->pReg);
+ } else {
+ if (migrate->pReg)
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, migrate->pReg);
+ }
+
pBox = REGION_RECTS(&CopyReg);
nbox = REGION_NUM_RECTS(&CopyReg);
@@ -165,29 +199,30 @@ exaCopyDirty(PixmapPtr pPixmap, RegionPtr pValidDst, RegionPtr pValidSrc,
+ pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
pExaPixmap->sys_pitch))
{
- ExaDoPrepareAccess(&pPixmap->drawable, fallback_index);
+ if (!access_prepared) {
+ ExaDoPrepareAccess(&pPixmap->drawable, fallback_index);
+ access_prepared = TRUE;
+ }
exaMemcpyBox (pPixmap, pBox,
fallback_src, fallback_srcpitch,
fallback_dst, fallback_dstpitch);
- exaFinishAccess(&pPixmap->drawable, fallback_index);
}
- else
- do_sync = TRUE;
pBox++;
}
- if (do_sync)
+ if (access_prepared)
+ exaFinishAccess(&pPixmap->drawable, fallback_index);
+ else
sync (pPixmap->drawable.pScreen);
pPixmap->devPrivate.ptr = save_ptr;
pPixmap->devKind = save_pitch;
- /* The copied bits are now no longer damaged but valid in destination */
+ /* The copied bits are now valid in destination */
REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg);
- REGION_SUBTRACT(pScreen, pDamageReg, pDamageReg, &CopyReg);
- REGION_NULL(pScreen, &CopyReg);
+ REGION_UNINIT(pScreen, &CopyReg);
}
/**
@@ -196,12 +231,13 @@ exaCopyDirty(PixmapPtr pPixmap, RegionPtr pValidDst, RegionPtr pValidSrc,
* allocated.
*/
static void
-exaCopyDirtyToSys (PixmapPtr pPixmap)
+exaCopyDirtyToSys (ExaMigrationPtr migrate)
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaScreenPriv (pPixmap->drawable.pScreen);
ExaPixmapPriv (pPixmap);
- exaCopyDirty(pPixmap, &pExaPixmap->validSys, &pExaPixmap->validFB,
+ exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
pExaScr->info->DownloadFromScreen, pExaPixmap->fb_ptr,
pExaPixmap->sys_ptr, pExaPixmap->fb_pitch,
pExaPixmap->sys_pitch, EXA_PREPARE_SRC, exaWaitSync);
@@ -213,51 +249,19 @@ exaCopyDirtyToSys (PixmapPtr pPixmap)
* allocated.
*/
static void
-exaCopyDirtyToFb (PixmapPtr pPixmap)
+exaCopyDirtyToFb (ExaMigrationPtr migrate)
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaScreenPriv (pPixmap->drawable.pScreen);
ExaPixmapPriv (pPixmap);
- exaCopyDirty(pPixmap, &pExaPixmap->validFB, &pExaPixmap->validSys,
+ exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
pExaScr->info->UploadToScreen, pExaPixmap->sys_ptr,
pExaPixmap->fb_ptr, pExaPixmap->sys_pitch,
pExaPixmap->fb_pitch, EXA_PREPARE_DEST, exaMarkSync);
}
/**
- * Copies out important pixmap data and removes references to framebuffer area.
- * Called when the memory manager decides it's time to kick the pixmap out of
- * framebuffer entirely.
- */
-void
-exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
-{
- PixmapPtr pPixmap = area->privData;
- ExaPixmapPriv(pPixmap);
-
- DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap,
- (void*)(ExaGetPixmapPriv(pPixmap)->area ?
- ExaGetPixmapPriv(pPixmap)->area->offset : 0),
- pPixmap->drawable.width,
- pPixmap->drawable.height,
- exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
-
- if (exaPixmapIsOffscreen(pPixmap)) {
- exaCopyDirtyToSys (pPixmap);
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- }
-
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->area = NULL;
-
- /* Mark all FB bits as invalid, so all valid system bits get copied to FB
- * next time */
- REGION_NULL(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
-}
-
-/**
* Allocates a framebuffer copy of the pixmap if necessary, and then copies
* any necessary pixmap data into the framebuffer copy and points the pixmap at
* it.
@@ -272,10 +276,11 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
* we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
* all the data, since it's almost surely all valid now.
*/
-void
-exaMoveInPixmap (PixmapPtr pPixmap)
+static void
+exaDoMoveInPixmap (ExaMigrationPtr migrate)
{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ PixmapPtr pPixmap = migrate->pPix;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv (pScreen);
ExaPixmapPriv (pPixmap);
@@ -283,10 +288,6 @@ exaMoveInPixmap (PixmapPtr pPixmap)
if (pExaScr->swappedOut)
return;
- /* If we're already in FB, our work is done. */
- if (exaPixmapIsOffscreen(pPixmap))
- return;
-
/* If we're not allowed to move, then fail. */
if (exaPixmapIsPinned(pPixmap))
return;
@@ -310,6 +311,11 @@ exaMoveInPixmap (PixmapPtr pPixmap)
pExaPixmap->area->offset;
}
+ exaCopyDirtyToFb (migrate);
+
+ if (exaPixmapIsOffscreen(pPixmap))
+ return;
+
DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
(ExaGetPixmapPriv(pPixmap)->area ?
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
@@ -317,8 +323,6 @@ exaMoveInPixmap (PixmapPtr pPixmap)
pPixmap->drawable.height,
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
- exaCopyDirtyToFb (pPixmap);
-
if (pExaScr->hideOffscreenPixmapData)
pPixmap->devPrivate.ptr = NULL;
else
@@ -327,18 +331,31 @@ exaMoveInPixmap (PixmapPtr pPixmap)
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
+void
+exaMoveInPixmap (PixmapPtr pPixmap)
+{
+ static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
+ .pReg = NULL };
+
+ migrate.pPix = pPixmap;
+ exaDoMoveInPixmap (&migrate);
+}
+
/**
* Switches the current active location of the pixmap to system memory, copying
* updated data out if necessary.
*/
-void
-exaMoveOutPixmap (PixmapPtr pPixmap)
+static void
+exaDoMoveOutPixmap (ExaMigrationPtr migrate)
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
- if (exaPixmapIsPinned(pPixmap))
+ if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
return;
+ exaCopyDirtyToSys (migrate);
+
if (exaPixmapIsOffscreen(pPixmap)) {
DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
@@ -348,21 +365,52 @@ exaMoveOutPixmap (PixmapPtr pPixmap)
pPixmap->drawable.height,
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
- exaCopyDirtyToSys (pPixmap);
-
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
pPixmap->devKind = pExaPixmap->sys_pitch;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
}
+void
+exaMoveOutPixmap (PixmapPtr pPixmap)
+{
+ static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
+ .pReg = NULL };
+
+ migrate.pPix = pPixmap;
+ exaDoMoveOutPixmap (&migrate);
+}
+
+
+/**
+ * Copies out important pixmap data and removes references to framebuffer area.
+ * Called when the memory manager decides it's time to kick the pixmap out of
+ * framebuffer entirely.
+ */
+void
+exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
+{
+ PixmapPtr pPixmap = area->privData;
+ ExaPixmapPriv(pPixmap);
+
+ exaMoveOutPixmap(pPixmap);
+
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->area = NULL;
+
+ /* Mark all FB bits as invalid, so all valid system bits get copied to FB
+ * next time */
+ REGION_EMPTY(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
+}
+
/**
* For the "greedy" migration scheme, pushes the pixmap toward being located in
* framebuffer memory.
*/
static void
-exaMigrateTowardFb (PixmapPtr pPixmap)
+exaMigrateTowardFb (ExaMigrationPtr migrate)
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
if (pExaPixmap == NULL) {
@@ -382,7 +430,7 @@ exaMigrateTowardFb (PixmapPtr pPixmap)
(pointer)pPixmap, pExaPixmap->score));
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
- exaMoveInPixmap(pPixmap);
+ exaDoMoveInPixmap(migrate);
pExaPixmap->score = 0;
}
@@ -392,7 +440,7 @@ exaMigrateTowardFb (PixmapPtr pPixmap)
if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
!exaPixmapIsOffscreen(pPixmap))
{
- exaMoveInPixmap (pPixmap);
+ exaDoMoveInPixmap(migrate);
}
ExaOffscreenMarkUsed (pPixmap);
@@ -403,8 +451,9 @@ exaMigrateTowardFb (PixmapPtr pPixmap)
* system memory.
*/
static void
-exaMigrateTowardSys (PixmapPtr pPixmap)
+exaMigrateTowardSys (ExaMigrationPtr migrate)
{
+ PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
if (pExaPixmap == NULL) {
@@ -426,7 +475,7 @@ exaMigrateTowardSys (PixmapPtr pPixmap)
pExaPixmap->score--;
if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
- exaMoveOutPixmap (pPixmap);
+ exaDoMoveOutPixmap(migrate);
}
/**
@@ -438,15 +487,24 @@ exaAssertNotDirty (PixmapPtr pPixmap)
{
ExaPixmapPriv (pPixmap);
CARD8 *dst, *src;
- RegionPtr pValidReg = exaPixmapIsOffscreen(pPixmap) ? &pExaPixmap->validFB :
- &pExaPixmap->validSys;
- int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg);
- BoxPtr pBox = REGION_RECTS(pValidReg);
+ RegionRec ValidReg;
+ int dst_pitch, src_pitch, cpp, y, nbox;
+ BoxPtr pBox;
Bool ret = TRUE;
- if (!nbox || exaPixmapIsPinned(pPixmap) || pExaPixmap->fb_ptr == NULL)
+ if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
return ret;
+ REGION_NULL(pScreen, &ValidReg);
+ REGION_INTERSECT(pScreen, &ValidReg, &pExaPixmap->validFB,
+ &pExaPixmap->validSys);
+ nbox = REGION_NUM_RECTS(&ValidReg);
+
+ if (!nbox)
+ goto out;
+
+ pBox = REGION_RECTS(&ValidReg);
+
dst_pitch = pExaPixmap->sys_pitch;
src_pitch = pExaPixmap->fb_pitch;
cpp = pPixmap->drawable.bitsPerPixel / 8;
@@ -479,6 +537,8 @@ exaAssertNotDirty (PixmapPtr pPixmap)
}
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+out:
+ REGION_UNINIT(pScreen, &ValidReg);
return ret;
}
@@ -533,7 +593,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
for (i = 0; i < npixmaps; i++) {
if (!exaPixmapIsDirty (pixmaps[i].pPix))
- exaMoveOutPixmap (pixmaps[i].pPix);
+ exaDoMoveOutPixmap (pixmaps + i);
}
return;
}
@@ -544,17 +604,17 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
*/
if (!can_accel) {
for (i = 0; i < npixmaps; i++) {
- exaMigrateTowardSys (pixmaps[i].pPix);
+ exaMigrateTowardSys (pixmaps + i);
if (!exaPixmapIsDirty (pixmaps[i].pPix))
- exaMoveOutPixmap (pixmaps[i].pPix);
+ exaDoMoveOutPixmap (pixmaps + i);
}
return;
}
/* Finally, the acceleration path. Move them all in. */
for (i = 0; i < npixmaps; i++) {
- exaMigrateTowardFb(pixmaps[i].pPix);
- exaMoveInPixmap(pixmaps[i].pPix);
+ exaMigrateTowardFb(pixmaps + i);
+ exaDoMoveInPixmap(pixmaps + i);
}
} else if (pExaScr->migration == ExaMigrationGreedy) {
/* If we can't accelerate, either because the driver can't or because one of
@@ -570,7 +630,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
*/
if (!can_accel) {
for (i = 0; i < npixmaps; i++)
- exaMigrateTowardSys (pixmaps[i].pPix);
+ exaMigrateTowardSys (pixmaps + i);
return;
}
@@ -578,14 +638,14 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
if (exaPixmapIsOffscreen(pixmaps[i].pPix)) {
/* Found one in FB, so move all to FB. */
for (j = 0; j < npixmaps; j++)
- exaMigrateTowardFb(pixmaps[j].pPix);
+ exaMigrateTowardFb(pixmaps + i);
return;
}
}
/* Nobody's in FB, so move all away from FB. */
for (i = 0; i < npixmaps; i++)
- exaMigrateTowardSys(pixmaps[i].pPix);
+ exaMigrateTowardSys(pixmaps + i);
} else if (pExaScr->migration == ExaMigrationAlways) {
/* Always move the pixmaps out if we can't accelerate. If we can
* accelerate, try to move them all in. If that fails, then move them
@@ -593,13 +653,13 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
*/
if (!can_accel) {
for (i = 0; i < npixmaps; i++)
- exaMoveOutPixmap(pixmaps[i].pPix);
+ exaDoMoveOutPixmap(pixmaps + i);
return;
}
/* Now, try to move them all into FB */
for (i = 0; i < npixmaps; i++) {
- exaMoveInPixmap(pixmaps[i].pPix);
+ exaDoMoveInPixmap(pixmaps + i);
}
/* If we couldn't fit everything in, abort */
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index b9e501625..491d80b8e 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -185,6 +185,7 @@ typedef struct _ExaMigrationRec {
Bool as_dst;
Bool as_src;
PixmapPtr pPix;
+ RegionPtr pReg;
} ExaMigrationRec, *ExaMigrationPtr;
/**
@@ -338,6 +339,9 @@ void
ExaDoPrepareAccess(DrawablePtr pDrawable, int index);
void
+exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg);
+
+void
exaPrepareAccess(DrawablePtr pDrawable, int index);
void
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 738ac15b1..067f88b89 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -267,6 +267,7 @@ exaTryDriverSolidFill(PicturePtr pSrc,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
+ pixmaps[0].pReg = NULL;
exaDoMigration(pixmaps, 1, TRUE);
pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
@@ -381,13 +382,16 @@ exaTryDriverComposite(CARD8 op,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = exaOpReadsDestination(op);
pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
+ pixmaps[0].pReg = NULL;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable);
+ pixmaps[1].pReg = NULL;
if (pMask) {
pixmaps[2].as_dst = FALSE;
pixmaps[2].as_src = TRUE;
pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable);
+ pixmaps[2].pReg = NULL;
exaDoMigration(pixmaps, 3, TRUE);
} else {
exaDoMigration(pixmaps, 2, TRUE);
@@ -579,12 +583,14 @@ exaComposite(CARD8 op,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = exaOpReadsDestination(op);
pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
+ pixmaps[0].pReg = NULL;
if (pSrc->pDrawable) {
pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable);
pixmaps[npixmaps].as_dst = FALSE;
pixmaps[npixmaps].as_src = TRUE;
pixmaps[npixmaps].pPix = pSrcPixmap;
+ pixmaps[npixmaps].pReg = NULL;
npixmaps++;
}
@@ -592,6 +598,7 @@ exaComposite(CARD8 op,
pixmaps[npixmaps].as_dst = FALSE;
pixmaps[npixmaps].as_src = TRUE;
pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable);
+ pixmaps[npixmaps].pReg = NULL;
npixmaps++;
}
@@ -1159,8 +1166,9 @@ exaGlyphs (CARD8 op,
* it'll stick there.
*/
pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = TRUE;
+ pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL);
while (n--)