summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2006-12-19 16:29:26 +0100
committerMichel Dänzer <michel@tungstengraphics.com>2006-12-19 16:29:26 +0100
commit4334860e69e7d5b156082bd05c7a86708e5bad4c (patch)
tree380e4abcbfc8950b000ff72b0347e78fee3bc74a /exa
parent7e4717683d6c08d1e490a60b7493a94bbc57bf8d (diff)
parentfdcc22ca1704d3519156c66804528c21b04fea65 (diff)
Merge branch 'master' into exa-damagetrack
Conflicts: exa/exa_accel.c exa/exa_migration.c
Diffstat (limited to 'exa')
-rw-r--r--exa/Makefile.am2
-rw-r--r--exa/exa.c40
-rw-r--r--exa/exa.h9
-rw-r--r--exa/exa_accel.c47
-rw-r--r--exa/exa_offscreen.c5
-rw-r--r--exa/exa_priv.h8
-rw-r--r--exa/exa_render.c123
7 files changed, 169 insertions, 65 deletions
diff --git a/exa/Makefile.am b/exa/Makefile.am
index 98db0271f..e2f7ed302 100644
--- a/exa/Makefile.am
+++ b/exa/Makefile.am
@@ -12,7 +12,7 @@ INCLUDES = \
$(XORG_INCS) \
-I$(srcdir)/../miext/cw
-AM_CFLAGS = $(XORG_CFLAGS) @SERVER_DEFINES@ @LOADER_DEFINES@ $(DIX_CFLAGS)
+AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
libexa_la_SOURCES = \
exa.c \
diff --git a/exa/exa.c b/exa/exa.c
index 3e6ac76dc..195457cd5 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -32,6 +32,10 @@
#include <dix-config.h>
#endif
+#ifdef MITSHM
+#include "shmint.h"
+#endif
+
#include <stdlib.h>
#include "exa_priv.h"
@@ -169,7 +173,7 @@ exaLog2(int val)
{
int bits;
- if (!val)
+ if (val <= 0)
return 0;
for (bits = 0; val != 0; bits++)
val >>= 1;
@@ -549,6 +553,9 @@ exaDriverInit (ScreenPtr pScreen,
ExaDriverPtr pScreenInfo)
{
ExaScreenPrivPtr pExaScr;
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
pScreenInfo->exa_minor > EXA_VERSION_MINOR)
@@ -562,7 +569,7 @@ exaDriverInit (ScreenPtr pScreen,
}
#ifdef RENDER
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+ ps = GetPictureScreenIfSet(pScreen);
#endif
if (exaGeneration != serverGeneration)
{
@@ -629,8 +636,17 @@ exaDriverInit (ScreenPtr pScreen,
}
#endif
+#ifdef COMPOSITE
miDisableCompositeWrapper(pScreen);
+#endif
+#ifdef MITSHM
+ /* Re-register with the MI funcs, which don't allow shared pixmaps.
+ * Shared pixmaps are almost always a performance loss for us, but this
+ * still allows for SHM PutImage.
+ */
+ ShmRegisterFuncs(pScreen, NULL);
+#endif
/*
* Hookup offscreen pixmaps
*/
@@ -649,6 +665,10 @@ exaDriverInit (ScreenPtr pScreen,
pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
pScreen->DestroyPixmap = exaDestroyPixmap;
+
+ LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n",
+ pScreen->myNum,
+ pExaScr->info->memorySize - pExaScr->info->offScreenBase);
}
else
{
@@ -667,6 +687,22 @@ exaDriverInit (ScreenPtr pScreen,
}
}
+ LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
+ " operations:\n", pScreen->myNum);
+ assert(pScreenInfo->PrepareSolid != NULL);
+ LogMessage(X_INFO, " Solid\n");
+ assert(pScreenInfo->PrepareCopy != NULL);
+ LogMessage(X_INFO, " Copy\n");
+ if (pScreenInfo->PrepareComposite != NULL) {
+ LogMessage(X_INFO, " Composite (RENDER acceleration)\n");
+ }
+ if (pScreenInfo->UploadToScreen != NULL) {
+ LogMessage(X_INFO, " UploadToScreen\n");
+ }
+ if (pScreenInfo->DownloadFromScreen != NULL) {
+ LogMessage(X_INFO, " DownloadFromScreen\n");
+ }
+
return TRUE;
}
diff --git a/exa/exa.h b/exa/exa.h
index 2cb200854..96465a775 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -36,6 +36,7 @@
#include "windowstr.h"
#include "gcstruct.h"
#include "picturestr.h"
+#include "fb.h"
#define EXA_VERSION_MAJOR 2
#define EXA_VERSION_MINOR 0
@@ -715,4 +716,12 @@ exaGetPixmapSize(PixmapPtr pPix);
void
exaEnableDisableFBAccess (int index, Bool enable);
+/**
+ * Returns TRUE if the given planemask covers all the significant bits in the
+ * pixel values for pDrawable.
+ */
+#define EXA_PM_IS_SOLID(_pDrawable, _pm) \
+ (((_pm) & FbFullMask((_pDrawable)->depth)) == \
+ FbFullMask((_pDrawable)->depth))
+
#endif /* EXA_H */
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index 102973ac6..d2fe2e034 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -54,12 +54,12 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
- pDrawable->width > pExaScr->info->maxX ||
- pDrawable->height > pExaScr->info->maxY)
+ pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY)
{
exaDoMigration (pixmaps, 1, FALSE);
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
@@ -393,19 +393,19 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDstDrawable);
+ pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = exaGetDrawablePixmap (pSrcDrawable);
+ pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
/* Respect maxX/maxY in a trivial way: don't set up drawing when we might
* violate the limits. The proper solution would be a temporary pixmap
* adjusted so that the drawing happened within limits.
*/
- if (pSrcDrawable->width > pExaScr->info->maxX ||
- pSrcDrawable->height > pExaScr->info->maxY ||
- pDstDrawable->width > pExaScr->info->maxX ||
- pDstDrawable->height > pExaScr->info->maxY)
+ if (pSrcPixmap->drawable.width > pExaScr->info->maxX ||
+ pSrcPixmap->drawable.height > pExaScr->info->maxY ||
+ pDstPixmap->drawable.width > pExaScr->info->maxX ||
+ pDstPixmap->drawable.height > pExaScr->info->maxY)
{
exaDoMigration (pixmaps, 2, FALSE);
goto fallback;
@@ -414,7 +414,8 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
}
/* Mixed directions must be handled specially if the card is lame */
- if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS && (dx*dy) < 0) {
+ if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS &&
+ reverse != upsidedown) {
if (!exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
dx, dy))
goto fallback;
@@ -424,7 +425,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
(pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap,
- dx, dy,
+ reverse ? -1 : 1, upsidedown ? -1 : 1,
pGC ? pGC->alu : GXcopy,
pGC ? pGC->planemask : FB_ALLONES))
{
@@ -643,12 +644,12 @@ exaPolyFillRect(DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
- pDrawable->width > pExaScr->info->maxX ||
- pDrawable->height > pExaScr->info->maxY)
+ pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY)
{
exaDoMigration (pixmaps, 1, FALSE);
ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
@@ -767,14 +768,14 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
/* We need to initialize x/yoff for tracking damage in the fallback case */
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
if (pExaScr->swappedOut ||
- pDrawable->width > pExaScr->info->maxX ||
- pDrawable->height > pExaScr->info->maxY)
+ pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY)
{
exaDoMigration (pixmaps, 1, FALSE);
goto fallback;
@@ -1042,10 +1043,10 @@ exaFillRegionSolid (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
- if (pDrawable->width > pExaScr->info->maxX ||
- pDrawable->height > pExaScr->info->maxY)
+ if (pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY)
{
exaDoMigration (pixmaps, 1, FALSE);
goto fallback;
@@ -1117,7 +1118,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pTile;
@@ -1125,8 +1126,8 @@ exaFillRegionTiled (DrawablePtr pDrawable,
/* We need to initialize x/yoff for tracking damage in the fallback case */
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (pDrawable->width > pExaScr->info->maxX ||
- pDrawable->height > pExaScr->info->maxY ||
+ if (pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY ||
tileWidth > pExaScr->info->maxX ||
tileHeight > pExaScr->info->maxY)
{
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c
index d5864dc57..fd3599e8c 100644
--- a/exa/exa_offscreen.c
+++ b/exa/exa_offscreen.c
@@ -414,7 +414,6 @@ exaOffscreenInit (ScreenPtr pScreen)
if (!area)
return FALSE;
-
area->state = ExaOffscreenAvail;
area->base_offset = pExaScr->info->offScreenBase;
area->offset = area->base_offset;
@@ -423,10 +422,6 @@ exaOffscreenInit (ScreenPtr pScreen)
area->next = NULL;
area->score = 0;
-#if DEBUG_OFFSCREEN
- ErrorF("============ initial memory block of %d\n", area->size);
-#endif
-
/* Add it to the free areas */
pExaScr->info->offScreenAreas = area;
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index c725b4da0..80cf60903 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -138,14 +138,6 @@ extern int exaPixmapPrivateIndex;
/** Align an offset to a power-of-two alignment */
#define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
-/**
- * Returns TRUE if the given planemask covers all the significant bits in the
- * pixel values for pDrawable.
- */
-#define EXA_PM_IS_SOLID(_pDrawable, _pm) \
- (((_pm) & FbFullMask((_pDrawable)->depth)) == \
- FbFullMask((_pDrawable)->depth))
-
#define EXA_PIXMAP_SCORE_MOVE_IN 10
#define EXA_PIXMAP_SCORE_MAX 20
#define EXA_PIXMAP_SCORE_MOVE_OUT -10
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 790a359a3..a73582000 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -282,8 +282,12 @@ exaTryDriverSolidFill(PicturePtr pSrc,
return -1;
}
- exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
- pDst->format);
+ if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
+ pDst->format))
+ {
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ return -1;
+ }
if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
{
@@ -333,16 +337,21 @@ exaTryDriverComposite(CARD8 op,
struct _Pixmap scratch;
ExaMigrationRec pixmaps[3];
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
+ if (pMask)
+ pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
+
/* Bail if we might exceed coord limits by rendering from/to these. We
* should really be making some scratch pixmaps with offsets and coords
* adjusted to deal with this, but it hasn't been done yet.
*/
- if (pSrc->pDrawable->width > pExaScr->info->maxX ||
- pSrc->pDrawable->height > pExaScr->info->maxY ||
- pDst->pDrawable->width > pExaScr->info->maxX ||
- pDst->pDrawable->height > pExaScr->info->maxY ||
- (pMask && (pMask->pDrawable->width > pExaScr->info->maxX ||
- pMask->pDrawable->height > pExaScr->info->maxY)))
+ if (pSrcPix->drawable.width > pExaScr->info->maxX ||
+ pSrcPix->drawable.height > pExaScr->info->maxY ||
+ pDstPix->drawable.width > pExaScr->info->maxX ||
+ pDstPix->drawable.height > pExaScr->info->maxY ||
+ (pMask && (pMaskPix->drawable.width > pExaScr->info->maxX ||
+ pMaskPix->drawable.height > pExaScr->info->maxY)))
{
return -1;
}
@@ -450,24 +459,72 @@ exaTryDriverComposite(CARD8 op,
return 1;
}
+/**
+ * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of
+ * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component
+ * alpha and limited 1-tmu cards.
+ *
+ * From http://anholt.livejournal.com/32058.html:
+ *
+ * The trouble is that component-alpha rendering requires two different sources
+ * for blending: one for the source value to the blender, which is the
+ * per-channel multiplication of source and mask, and one for the source alpha
+ * for multiplying with the destination channels, which is the multiplication
+ * of the source channels by the mask alpha. So the equation for Over is:
+ *
+ * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
+ *
+ * But we can do some simpler operations, right? How about PictOpOutReverse,
+ * which has a source factor of 0 and dest factor of (1 - source alpha). We
+ * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
+ * blenders pretty easily. So we can do a component-alpha OutReverse, which
+ * gets us:
+ *
+ * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
+ *
+ * OK. And if an op doesn't use the source alpha value for the destination
+ * factor, then we can do the channel multiplication in the texture blenders
+ * to get the source value, and ignore the source alpha that we wouldn't use.
+ * We've supported this in the Radeon driver for a long time. An example would
+ * be PictOpAdd, which does:
+ *
+ * dst.A = src.A * mask.A + dst.A
+ * dst.R = src.R * mask.R + dst.R
+ * dst.G = src.G * mask.G + dst.G
+ * dst.B = src.B * mask.B + dst.B
+ *
+ * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
+ * after it, we get:
+ *
+ * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
+ * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
+ * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
+ * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
+ */
+
static int
-exaTryComponentAlphaHelper(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
+exaTryMagicTwoPassCompositeHelper(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
{
ExaScreenPriv (pDst->pDrawable->pScreen);
assert(op == PictOpOver);
- assert(pMask->componentAlpha == TRUE);
if (pExaScr->info->CheckComposite &&
(!(*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
@@ -533,7 +590,8 @@ exaComposite(CARD8 op,
if (op == PictOpSrc)
{
if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 && pSrc->repeat)
+ pSrc->pDrawable->height == 1 && pSrc->repeat &&
+ pSrc->repeatType == RepeatNormal)
{
ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
width, height);
@@ -573,21 +631,34 @@ exaComposite(CARD8 op,
pMask->repeat = 0;
if (pExaScr->info->PrepareComposite &&
+ (!pSrc->repeat || pSrc->repeat == RepeatNormal) &&
+ (!pMask || !pMask->repeat || pMask->repeat == RepeatNormal) &&
!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
{
+ Bool isSrcSolid;
+
ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask,
yMask, xDst, yDst, width, height);
if (ret == 1)
goto done;
+ /* For generic masks and solid src pictures, mach64 can do Over in two
+ * passes, similar to the component-alpha case.
+ */
+ isSrcSolid = pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat;
+
/* If we couldn't do the Composite in a single pass, and it was a
* component-alpha Over, see if we can do it in two passes with
* an OutReverse and then an Add.
*/
- if (ret == -1 && pMask && pMask->componentAlpha && op == PictOpOver) {
- ret = exaTryComponentAlphaHelper(op, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst,
- width, height);
+ if (ret == -1 && op == PictOpOver && pMask &&
+ (pMask->componentAlpha || isSrcSolid)) {
+ ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst,
+ xSrc, ySrc,
+ xMask, yMask, xDst, yDst,
+ width, height);
if (ret == 1)
goto done;
}