diff --git a/exa/exa.c b/exa/exa.c index ecdb76139a..145d5b2b04 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -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); } /** diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 07ada153f2..ceb6c7bb56 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 99058f1389..f48e93a786 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); + } - /* 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 */ diff --git a/exa/exa_priv.h b/exa/exa_priv.h index b9e501625f..491d80b8ed 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; /** @@ -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); diff --git a/exa/exa_render.c b/exa/exa_render.c index 738ac15b16..067f88b897 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--)