From: Michel Dänzer <[email protected]>

If there are several software fallbacks affecting to the system memory copy of
the same pixmap, only copy the results back to the driver pixmap when it's used
for acceleration again, or in the BlockHandler, whichever happens first.
---
 exa/exa.c                 |   14 ++++++++++++--
 exa/exa_migration_mixed.c |   20 +++++++++++++++++++-
 exa/exa_mixed.c           |    3 +++
 exa/exa_priv.h            |    1 +
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/exa/exa.c b/exa/exa.c
index e264d44..46e9182 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 f42c9c2..6065d75 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 167ffa9..bc393c7 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 1aec8e9..5b056da 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 {
-- 
1.6.4.3

_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to