diff --git a/exa/exa.c b/exa/exa.c index e264d440c..46e91820b 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -774,10 +774,18 @@ ExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout, ScreenPtr pScreen = screenInfo.screens[screenNum]; ExaScreenPriv(pScreen); + /* Move any deferred results from a software fallback to the driver pixmap */ + if (pExaScr->deferred_mixed_pixmap) + exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); + unwrap(pExaScr, pScreen, BlockHandler); (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); + /* The rest only applies to classic EXA */ + if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) + return; + /* Try and keep the offscreen memory area tidy every now and then (at most * once per second) when the server has been idle for at least 100ms. */ @@ -991,10 +999,12 @@ exaDriverInit (ScreenPtr pScreen, * Replace various fb screen functions */ if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && - !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { + (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) || + (pExaScr->info->flags & EXA_MIXED_PIXMAPS))) wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); + if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && + !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); - } wrap(pExaScr, pScreen, CreateGC, exaCreateGC); wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen); wrap(pExaScr, pScreen, GetImage, exaGetImage); diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c index f42c9c233..6065d7577 100644 --- a/exa/exa_migration_mixed.c +++ b/exa/exa_migration_mixed.c @@ -99,8 +99,13 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) exaCreateDriverPixmap_mixed(pPixmap); if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) { + ExaScreenPriv(pPixmap->drawable.pScreen); + pPixmap->devKind = pExaPixmap->fb_pitch; exaCopyDirtyToFb(pixmaps + i); + + if (pExaScr->deferred_mixed_pixmap == pPixmap) + pExaScr->deferred_mixed_pixmap = NULL; } pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap); @@ -197,6 +202,9 @@ exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) /* Move back results of software rendering on system memory copy of mixed driver * pixmap (see exaPrepareAccessReg_mixed). + * + * Defer moving the destination back into the driver pixmap, to try and save + * overhead on multiple consequent software fallbacks. */ void exaFinishAccess_mixed(PixmapPtr pPixmap, int index) { @@ -204,6 +212,16 @@ void exaFinishAccess_mixed(PixmapPtr pPixmap, int index) if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) { DamageRegionProcessPending(&pPixmap->drawable); - exaMoveInPixmap_mixed(pPixmap); + + if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) { + ExaScreenPriv(pPixmap->drawable.pScreen); + + if (pExaScr->deferred_mixed_pixmap && + pExaScr->deferred_mixed_pixmap != pPixmap) + exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); + pExaScr->deferred_mixed_pixmap = pPixmap; + pPixmap->devKind = pExaPixmap->fb_pitch; + } else + exaMoveInPixmap_mixed(pPixmap); } } diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c index 167ffa9d5..bc393c772 100644 --- a/exa/exa_mixed.c +++ b/exa/exa_mixed.c @@ -192,6 +192,9 @@ exaDestroyPixmap_mixed(PixmapPtr pPixmap) { ExaPixmapPriv (pPixmap); + if (pExaScr->deferred_mixed_pixmap == pPixmap) + pExaScr->deferred_mixed_pixmap = NULL; + if (pExaPixmap->driverPriv) pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); pExaPixmap->driverPriv = NULL; diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 1aec8e966..5b056dab9 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -188,6 +188,7 @@ typedef struct { unsigned numOffscreenAvailable; CARD32 lastDefragment; CARD32 nextDefragment; + PixmapPtr deferred_mixed_pixmap; /* Reference counting for accessed pixmaps */ struct {