[PATCH 2/2] EXA: Try to minimize UploadToScreen calls for mixed pixmaps.

Michel Dänzer michel at daenzer.net
Tue Sep 22 10:54:06 PDT 2009


From: Michel Dänzer <daenzer at vmware.com>

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                 |   33 ++++++++++++++++++++++++++-------
 exa/exa_migration_mixed.c |    5 +++++
 exa/exa_mixed.c           |    3 +++
 exa/exa_priv.h            |    1 +
 4 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/exa/exa.c b/exa/exa.c
index 6a1029a..7494406 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -487,7 +487,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
 	if (pExaScr->access[i].pixmap == pPixmap) {
 	    if (--pExaScr->access[i].count > 0)
 		return;
-	    index = i;
 	    break;
 	}
     }
@@ -497,7 +496,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
 	EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
 			     pPixmap));
 
-    pExaScr->access[index].pixmap = NULL;
+    pExaScr->access[i].pixmap = NULL;
 
     /* We always hide the devPrivate.ptr. */
     pPixmap->devPrivate.ptr = NULL;
@@ -511,20 +510,30 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
 	(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
 	(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
 	DamageRegionProcessPending(&pPixmap->drawable);
-	exaMoveInPixmap_mixed(pPixmap);
+	/* Defer moving the destination back into the driver pixmap, to try and
+	 * save overhead on multiple consequent software fallbacks.
+	 */
+	if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+	    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);
     }
 
     if (!is_offscreen || !pExaScr->info->FinishAccess)
 	return;
 
-    if (index >= EXA_PREPARE_AUX_DEST &&
+    if (i >= EXA_PREPARE_AUX_DEST &&
 	!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
 	ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
 	       "unsupported index EXA_PREPARE_AUX*\n");
 	return;
     }
 
-    (*pExaScr->info->FinishAccess) (pPixmap, index);
+    (*pExaScr->info->FinishAccess) (pPixmap, i);
 }
 
 /**
@@ -868,10 +877,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.
      */
@@ -1085,10 +1102,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 a71a5ad..bea18a9 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);
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 11a2e55..e53a1be 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -186,6 +186,7 @@ typedef struct {
     unsigned			 numOffscreenAvailable;
     CARD32			 lastDefragment;
     CARD32			 nextDefragment;
+    PixmapPtr			 deferred_mixed_pixmap;
 
     /* Reference counting for accessed pixmaps */
     struct {
-- 
1.6.4.3



More information about the xorg-devel mailing list