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.
This commit is contained in:
Michel Dänzer 2007-08-29 19:55:22 +02:00
parent f27931bdd2
commit 962eddd7a2
5 changed files with 196 additions and 104 deletions

View File

@ -363,6 +363,21 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
}
}
void
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);
ExaDoPrepareAccess(pDrawable, index);
}
/**
* exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
*
@ -372,15 +387,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
void
exaPrepareAccess(DrawablePtr pDrawable, int index)
{
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = index == EXA_PREPARE_DEST;
pixmaps[0].as_src = index != EXA_PREPARE_DEST;
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
exaDoMigration(pixmaps, 1, FALSE);
ExaDoPrepareAccess(pDrawable, index);
exaPrepareAccessReg(pDrawable, index, NULL);
}
/**

View File

@ -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);

View File

@ -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);
}
/* Copy bits valid in ssource but not in destination */
REGION_EMPTY(pScreen, damage);
/* 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,50 +249,18 @@ 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
@ -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 */

View File

@ -185,6 +185,7 @@ typedef struct _ExaMigrationRec {
Bool as_dst;
Bool as_src;
PixmapPtr pPix;
RegionPtr pReg;
} ExaMigrationRec, *ExaMigrationPtr;
/**
@ -337,6 +338,9 @@ ExaOffscreenFini (ScreenPtr pScreen);
void
ExaDoPrepareAccess(DrawablePtr pDrawable, int index);
void
exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg);
void
exaPrepareAccess(DrawablePtr pDrawable, int index);

View File

@ -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--)