EXA: Handle separate alpha maps in Composite fallback.

Michel Dänzer michel at daenzer.net
Mon Feb 23 00:58:10 PST 2009


On Sun, 2009-02-22 at 19:12 +0100, Maarten Maathuis wrote:
> A minor bump is probably nice, the question is, should the new indices
> be used on drivers claiming an older minor version? A major bump would
> avoid this problem, but might be overdone?

I'm afraid there isn't really a choice, I don't see any way to handle
all possible Composite operations with separate alpha maps correctly
without the new indices. So the patch below bumps the major version and
drops the UploadToScratch driver hook and ExaOffscreenSwap*().


>From cd7167f56b1259f92e4c91d398bad9452f7f8ab4 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Michel=20D=C3=A4nzer?= <daenzer at vmware.com>
Date: Mon, 23 Feb 2009 09:52:29 +0100
Subject: EXA: Handle separate alpha maps in Composite fallback.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Fixes https://bugs.freedesktop.org/show_bug.cgi?id=18710 .

As this can't work without new EXA_PREPARE_AUX* indices, this requires a major
version bump, so we can also drop the UploadToScratch driver hook and
ExaOffscreenSwap*().

Moreover, introduce EXA_DRIVER_KNOWN_MAJOR to break compilation of drivers
which can't seem to handle EXA_PREPARE_AUX*, giving instructions how to make
them build again in the #error message.

Signed-off-by: Michel Dänzer <daenzer at vmware.com>
---
 exa/Makefile.am            |    3 +-
 exa/exa.h                  |   46 +++++++++++++---------------------
 exa/exa_offscreen.c        |   59 ++++---------------------------------------
 exa/exa_priv.h             |    6 ----
 exa/exa_render.c           |   19 --------------
 exa/exa_unaccel.c          |   34 ++++++++++++++++++++++++-
 hw/xfree86/exa/Makefile.am |    3 +-
 7 files changed, 61 insertions(+), 109 deletions(-)

diff --git a/exa/Makefile.am b/exa/Makefile.am
index 2b3f1e4..7065e19 100644
--- a/exa/Makefile.am
+++ b/exa/Makefile.am
@@ -12,7 +12,8 @@ INCLUDES = \
 	$(XORG_INCS) \
 	-I$(srcdir)/../miext/cw
 
-AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
+# Use an arbitrary high major version here to satisfy any driver checks in exa.h
+AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) -DEXA_DRIVER_KNOWN_MAJOR=99
 
 libexa_la_SOURCES = \
 	exa.c \
diff --git a/exa/exa.h b/exa/exa.h
index 21a0f1a..b80d0d4 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -38,8 +38,17 @@
 #include "picturestr.h"
 #include "fb.h"
 
-#define EXA_VERSION_MAJOR   2
-#define EXA_VERSION_MINOR   4
+/* If the driver can't seem to handle this major version, abort compilation with
+ * instructions how to fix it.
+ */
+#if !defined(EXA_DRIVER_KNOWN_MAJOR) || EXA_DRIVER_KNOWN_MAJOR < 3
+#error Make sure this EXA driver either does not have Prepare/FinishAccess \
+    hooks or that they can handle EXA_PREPARE_AUX*, and	\
+    #define EXA_DRIVER_KNOWN_MAJOR 3 before including exa.h
+#endif
+
+#define EXA_VERSION_MAJOR   3
+#define EXA_VERSION_MINOR   0
 #define EXA_VERSION_RELEASE 0
 
 typedef struct _ExaOffscreenArea ExaOffscreenArea;
@@ -499,32 +508,6 @@ typedef struct _ExaDriver {
                                    int                  src_pitch);
 
     /**
-     * UploadToScratch() is used to upload a pixmap to a scratch area for
-     * acceleration.
-     *
-     * @param pSrc source pixmap in host memory
-     * @param pDst fake, scratch pixmap to be set up in offscreen memory.
-     *
-     * The UploadToScratch() call was added to support Xati before Xati had
-     * support for hostdata uploads and before exaGlyphs() was written.  It
-     * behaves incorrectly (uses an invalid pixmap as pDst),
-     * and UploadToScreen() should be implemented instead.
-     *
-     * Drivers implementing UploadToScratch() had to set up space (likely in a
-     * statically allocated area) in offscreen memory, copy pSrc to that
-     * scratch area, and adust pDst->devKind for the pitch and
-     * pDst->devPrivate.ptr for the pointer to that scratch area.  The driver
-     * was responsible for syncing (as it was implemented using memcpy() in
-     * Xati), and only the data from the last UploadToScratch() was guaranteed
-     * to be valid at any given time.
-     *
-     * UploadToScratch() should not be implemented by drivers, and will likely
-     * be removed in a future version of EXA.
-     */
-    Bool        (*UploadToScratch) (PixmapPtr           pSrc,
-                                    PixmapPtr           pDst);
-
-    /**
      * DownloadFromScreen() loads a rectangle of data from pSrc into dst
      *
      * @param pSrc source pixmap
@@ -672,6 +655,13 @@ typedef struct _ExaDriver {
 	 * from.
 	 */
 	#define EXA_PREPARE_MASK	2
+	/**
+	 * EXA_PREPARE_AUX* are additional indices for other purposes, e.g.
+	 * separate alpha maps with Composite operations.
+	 */
+	#define EXA_PREPARE_AUX0	3
+	#define EXA_PREPARE_AUX1	4
+	#define EXA_PREPARE_AUX2	5
 	/** @} */
 
     /**
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c
index 4aaa2c1..c45df67 100644
--- a/exa/exa_offscreen.c
+++ b/exa/exa_offscreen.c
@@ -285,36 +285,6 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
     return area;
 }
 
-/**
- * Ejects all offscreen areas, and uninitializes the offscreen memory manager.
- */
-void
-ExaOffscreenSwapOut (ScreenPtr pScreen)
-{
-    ExaScreenPriv (pScreen);
-
-    ExaOffscreenValidate (pScreen);
-    /* loop until a single free area spans the space */
-    for (;;)
-    {
-	ExaOffscreenArea *area = pExaScr->info->offScreenAreas;
-
-	if (!area)
-	    break;
-	if (area->state == ExaOffscreenAvail)
-	{
-	    area = area->next;
-	    if (!area)
-		break;
-	}
-	assert (area->state != ExaOffscreenAvail);
-	(void) ExaOffscreenKickOut (pScreen, area);
-	ExaOffscreenValidate (pScreen);
-    }
-    ExaOffscreenValidate (pScreen);
-    ExaOffscreenFini (pScreen);
-}
-
 /** Ejects all pixmaps managed by EXA. */
 static void
 ExaOffscreenEjectPixmaps (ScreenPtr pScreen)
@@ -344,26 +314,14 @@ ExaOffscreenEjectPixmaps (ScreenPtr pScreen)
     ExaOffscreenValidate (pScreen);
 }
 
-void
-ExaOffscreenSwapIn (ScreenPtr pScreen)
-{
-    exaOffscreenInit (pScreen);
-}
-
 /**
  * Prepares EXA for disabling of FB access, or restoring it.
  *
- * In version 2.1, the disabling results in pixmaps being ejected, while other
- * allocations remain.  With this plus the prevention of migration while
- * swappedOut is set, EXA by itself should not cause any access of the
- * framebuffer to occur while swapped out.  Any remaining issues are the
- * responsibility of the driver.
- *
- * Prior to version 2.1, all allocations, including locked ones, are ejected
- * when access is disabled, and the allocator is torn down while swappedOut
- * is set.  This is more drastic, and caused implementation difficulties for
- * many drivers that could otherwise handle the lack of FB access while
- * swapped out.
+ * The disabling results in pixmaps being ejected, while other allocations
+ * remain.  With this plus the prevention of migration while swappedOut is
+ * set, EXA by itself should not cause any access of the framebuffer to occur
+ * while swapped out.  Any remaining issues are the responsibility of the
+ * driver.
  */
 void
 exaEnableDisableFBAccess (int index, Bool enable)
@@ -372,16 +330,11 @@ exaEnableDisableFBAccess (int index, Bool enable)
     ExaScreenPriv (pScreen);
 
     if (!enable && pExaScr->disableFbCount++ == 0) {
-	if (pExaScr->info->exa_minor < 1)
-	    ExaOffscreenSwapOut (pScreen);
-	else
-	    ExaOffscreenEjectPixmaps (pScreen);
+	ExaOffscreenEjectPixmaps (pScreen);
 	pExaScr->swappedOut = TRUE;
     }
     
     if (enable && --pExaScr->disableFbCount == 0) {
-	if (pExaScr->info->exa_minor < 1)
-	    ExaOffscreenSwapIn (pScreen);
 	pExaScr->swappedOut = FALSE;
     }
 }
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 461e5e3..ea8c3da 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -433,12 +433,6 @@ ExaCheckComposite (CARD8      op,
 #endif
 
 /* exa_offscreen.c */
-void
-ExaOffscreenSwapOut (ScreenPtr pScreen);
-
-void
-ExaOffscreenSwapIn (ScreenPtr pScreen);
-
 Bool
 exaOffscreenInit(ScreenPtr pScreen);
 
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 1788531..bdc1ed1 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -342,7 +342,6 @@ exaTryDriverCompositeRects(CARD8	       op,
     int src_off_x, src_off_y, dst_off_x, dst_off_y;
     PixmapPtr pSrcPix, pDstPix;
     ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
-    struct _Pixmap scratch;
     ExaMigrationRec pixmaps[2];
 
     if (!pExaScr->info->PrepareComposite)
@@ -386,13 +385,6 @@ exaTryDriverCompositeRects(CARD8	       op,
     if (!exaPixmapIsOffscreen(pDstPix))
 	return 0;
     
-    if (!pSrcPix && pExaScr->info->UploadToScratch)
-    {
-	pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
-	if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
-	    pSrcPix = &scratch;
-    }
-
     if (!pSrcPix)
 	return 0;
 
@@ -573,7 +565,6 @@ exaTryDriverComposite(CARD8		op,
     int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
     PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
     ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
-    struct _Pixmap scratch;
     ExaMigrationRec pixmaps[3];
 
     pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
@@ -652,16 +643,6 @@ exaTryDriverComposite(CARD8		op,
 	return 0;
     }
 
-    if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) {
-	pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
-	if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
-	    pSrcPix = &scratch;
-    } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) {
-	pMaskPix = exaGetDrawablePixmap (pMask->pDrawable);
-	if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch))
-	    pMaskPix = &scratch;
-    }
-
     if (!pSrcPix || (pMask && !pMaskPix)) {
 	REGION_UNINIT(pDst->pDrawable->pScreen, &region);
 	return 0;
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index c821f0d..88d3121 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -387,6 +387,7 @@ ExaCheckComposite (CARD8      op,
     PictureScreenPtr	ps = GetPictureScreen(pScreen);
 #endif /* RENDER */
     ExaScreenPriv(pScreen);
+    ExaPixmapPrivPtr pExaDstAlphaPix = NULL, pExaMaskAlphaPix = NULL, pExaSrcAlphaPix = NULL;
     RegionRec region;
     int xoff, yoff;
 
@@ -405,16 +406,41 @@ ExaCheckComposite (CARD8      op,
 	REGION_TRANSLATE(pScreen, &region, xoff, yoff);
 
 	exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region);
-    } else
+
+	if (pDst->alphaMap && pDst->alphaMap->pDrawable) {
+	    /* The RENDER spec doesn't allow windows for separate alpha maps */
+	    pExaDstAlphaPix =
+		ExaGetPixmapPriv((PixmapPtr)pDst->alphaMap->pDrawable);
+	    exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0,
+				&region);
+	}
+    } else {
 	exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
 
+	if (pDst->alphaMap && pDst->alphaMap->pDrawable) {
+	    pExaDstAlphaPix =
+		ExaGetPixmapPriv((PixmapPtr)pDst->alphaMap->pDrawable);
+	    exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
+	}
+    }
+
     EXA_FALLBACK(("from picts %p/%p to pict %p\n",
 		 pSrc, pMask, pDst));
 
     if (pSrc->pDrawable != NULL)
 	exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
+    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) {
+	pExaSrcAlphaPix =
+	    ExaGetPixmapPriv((PixmapPtr)pSrc->alphaMap->pDrawable);
+	exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
+    }
     if (pMask && pMask->pDrawable != NULL)
 	exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
+    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) {
+	pExaMaskAlphaPix =
+	    ExaGetPixmapPriv((PixmapPtr)pMask->alphaMap->pDrawable);
+	exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
+    }
 #ifdef RENDER
     swap(pExaScr, ps, Composite);
     ps->Composite (op,
@@ -433,9 +459,15 @@ ExaCheckComposite (CARD8      op,
 #endif /* RENDER */
     if (pMask && pMask->pDrawable != NULL)
 	exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
+    if (pExaMaskAlphaPix)
+	exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
     if (pSrc->pDrawable != NULL)
 	exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
+    if (pExaSrcAlphaPix)
+	exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
     exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
+    if (pExaDstAlphaPix)
+	exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
 
     REGION_UNINIT(pScreen, &region);
 }
diff --git a/hw/xfree86/exa/Makefile.am b/hw/xfree86/exa/Makefile.am
index 9eb2e17..9fb5151 100644
--- a/hw/xfree86/exa/Makefile.am
+++ b/hw/xfree86/exa/Makefile.am
@@ -7,7 +7,8 @@ INCLUDES = \
 	-I$(srcdir)/../../../exa \
 	-I$(srcdir)/../../../miext/cw
 
-AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS)
+# Use an arbitrary high major version here to satisfy any driver checks in exa.h
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) -DEXA_DRIVER_KNOWN_MAJOR=99
 
 libexa_la_SOURCES = \
 	examodule.c
-- 
1.6.2.rc1



-- 
Earthling Michel Dänzer           |                http://www.vmware.com
Libre software enthusiast         |          Debian, X and DRI developer


More information about the xorg-devel mailing list