EXA: Handle separate alpha maps properly in Composite fallback.

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*(). So this also fixes
http://bugs.freedesktop.org/show_bug.cgi?id=20213 .

Moreover, introduce EXA_DRIVER_KNOWN_MAJOR to break compilation of drivers
which may not be able to handle EXA_PREPARE_AUX*, giving instructions how to
make them build again in the #error message.

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
This commit is contained in:
Michel Dänzer 2009-02-24 09:22:09 +01:00
parent d3b355875a
commit 170cf1270d
7 changed files with 47 additions and 109 deletions

View File

@ -12,7 +12,8 @@ INCLUDES = \
$(XORG_INCS) \ $(XORG_INCS) \
-I$(srcdir)/../miext/cw -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 = \ libexa_la_SOURCES = \
exa.c \ exa.c \

View File

@ -38,8 +38,17 @@
#include "picturestr.h" #include "picturestr.h"
#include "fb.h" #include "fb.h"
#define EXA_VERSION_MAJOR 2 /* If the driver can't seem to handle this major version, abort compilation with
#define EXA_VERSION_MINOR 4 * 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 #define EXA_VERSION_RELEASE 0
typedef struct _ExaOffscreenArea ExaOffscreenArea; typedef struct _ExaOffscreenArea ExaOffscreenArea;
@ -498,32 +507,6 @@ typedef struct _ExaDriver {
char *src, char *src,
int src_pitch); 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 * DownloadFromScreen() loads a rectangle of data from pSrc into dst
* *
@ -672,6 +655,13 @@ typedef struct _ExaDriver {
* from. * from.
*/ */
#define EXA_PREPARE_MASK 2 #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
/** @} */ /** @} */
/** /**

View File

@ -285,36 +285,6 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
return area; 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. */ /** Ejects all pixmaps managed by EXA. */
static void static void
ExaOffscreenEjectPixmaps (ScreenPtr pScreen) ExaOffscreenEjectPixmaps (ScreenPtr pScreen)
@ -344,26 +314,14 @@ ExaOffscreenEjectPixmaps (ScreenPtr pScreen)
ExaOffscreenValidate (pScreen); ExaOffscreenValidate (pScreen);
} }
void
ExaOffscreenSwapIn (ScreenPtr pScreen)
{
exaOffscreenInit (pScreen);
}
/** /**
* Prepares EXA for disabling of FB access, or restoring it. * Prepares EXA for disabling of FB access, or restoring it.
* *
* In version 2.1, the disabling results in pixmaps being ejected, while other * The disabling results in pixmaps being ejected, while other allocations
* allocations remain. With this plus the prevention of migration while * remain. With this plus the prevention of migration while swappedOut is
* swappedOut is set, EXA by itself should not cause any access of the * set, EXA by itself should not cause any access of the framebuffer to occur
* framebuffer to occur while swapped out. Any remaining issues are the * while swapped out. Any remaining issues are the responsibility of the
* responsibility of the driver. * 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.
*/ */
void void
exaEnableDisableFBAccess (int index, Bool enable) exaEnableDisableFBAccess (int index, Bool enable)
@ -372,16 +330,11 @@ exaEnableDisableFBAccess (int index, Bool enable)
ExaScreenPriv (pScreen); ExaScreenPriv (pScreen);
if (!enable && pExaScr->disableFbCount++ == 0) { if (!enable && pExaScr->disableFbCount++ == 0) {
if (pExaScr->info->exa_minor < 1) ExaOffscreenEjectPixmaps (pScreen);
ExaOffscreenSwapOut (pScreen);
else
ExaOffscreenEjectPixmaps (pScreen);
pExaScr->swappedOut = TRUE; pExaScr->swappedOut = TRUE;
} }
if (enable && --pExaScr->disableFbCount == 0) { if (enable && --pExaScr->disableFbCount == 0) {
if (pExaScr->info->exa_minor < 1)
ExaOffscreenSwapIn (pScreen);
pExaScr->swappedOut = FALSE; pExaScr->swappedOut = FALSE;
} }
} }

View File

@ -433,12 +433,6 @@ ExaCheckComposite (CARD8 op,
#endif #endif
/* exa_offscreen.c */ /* exa_offscreen.c */
void
ExaOffscreenSwapOut (ScreenPtr pScreen);
void
ExaOffscreenSwapIn (ScreenPtr pScreen);
Bool Bool
exaOffscreenInit(ScreenPtr pScreen); exaOffscreenInit(ScreenPtr pScreen);

View File

@ -342,7 +342,6 @@ exaTryDriverCompositeRects(CARD8 op,
int src_off_x, src_off_y, dst_off_x, dst_off_y; int src_off_x, src_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pDstPix; PixmapPtr pSrcPix, pDstPix;
ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
struct _Pixmap scratch;
ExaMigrationRec pixmaps[2]; ExaMigrationRec pixmaps[2];
if (!pExaScr->info->PrepareComposite) if (!pExaScr->info->PrepareComposite)
@ -386,13 +385,6 @@ exaTryDriverCompositeRects(CARD8 op,
if (!exaPixmapIsOffscreen(pDstPix)) if (!exaPixmapIsOffscreen(pDstPix))
return 0; return 0;
if (!pSrcPix && pExaScr->info->UploadToScratch)
{
pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
pSrcPix = &scratch;
}
if (!pSrcPix) if (!pSrcPix)
return 0; 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; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
struct _Pixmap scratch;
ExaMigrationRec pixmaps[3]; ExaMigrationRec pixmaps[3];
pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
@ -652,16 +643,6 @@ exaTryDriverComposite(CARD8 op,
return 0; 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)) { if (!pSrcPix || (pMask && !pMaskPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region); REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return 0; return 0;

View File

@ -405,16 +405,28 @@ ExaCheckComposite (CARD8 op,
REGION_TRANSLATE(pScreen, &region, xoff, yoff); REGION_TRANSLATE(pScreen, &region, xoff, yoff);
exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region); exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region);
} else
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0,
&region);
} else {
exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST); exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
}
EXA_FALLBACK(("from picts %p/%p to pict %p\n", EXA_FALLBACK(("from picts %p/%p to pict %p\n",
pSrc, pMask, pDst)); pSrc, pMask, pDst));
if (pSrc->pDrawable != NULL) if (pSrc->pDrawable != NULL)
exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC); exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
if (pMask && pMask->pDrawable != NULL) if (pMask && pMask->pDrawable != NULL)
exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK); exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
#ifdef RENDER #ifdef RENDER
swap(pExaScr, ps, Composite); swap(pExaScr, ps, Composite);
ps->Composite (op, ps->Composite (op,
@ -433,9 +445,15 @@ ExaCheckComposite (CARD8 op,
#endif /* RENDER */ #endif /* RENDER */
if (pMask && pMask->pDrawable != NULL) if (pMask && pMask->pDrawable != NULL)
exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK); exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
if (pSrc->pDrawable != NULL) if (pSrc->pDrawable != NULL)
exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC); exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST); exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
REGION_UNINIT(pScreen, &region); REGION_UNINIT(pScreen, &region);
} }

View File

@ -7,7 +7,8 @@ INCLUDES = \
-I$(srcdir)/../../../exa \ -I$(srcdir)/../../../exa \
-I$(srcdir)/../../../miext/cw -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 = \ libexa_la_SOURCES = \
examodule.c examodule.c