diff options
author | Michel Dänzer <michel@tungstengraphics.com> | 2006-12-19 16:29:26 +0100 |
---|---|---|
committer | Michel Dänzer <michel@tungstengraphics.com> | 2006-12-19 16:29:26 +0100 |
commit | 4334860e69e7d5b156082bd05c7a86708e5bad4c (patch) | |
tree | 380e4abcbfc8950b000ff72b0347e78fee3bc74a /exa | |
parent | 7e4717683d6c08d1e490a60b7493a94bbc57bf8d (diff) | |
parent | fdcc22ca1704d3519156c66804528c21b04fea65 (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.am | 2 | ||||
-rw-r--r-- | exa/exa.c | 40 | ||||
-rw-r--r-- | exa/exa.h | 9 | ||||
-rw-r--r-- | exa/exa_accel.c | 47 | ||||
-rw-r--r-- | exa/exa_offscreen.c | 5 | ||||
-rw-r--r-- | exa/exa_priv.h | 8 | ||||
-rw-r--r-- | exa/exa_render.c | 123 |
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 \ @@ -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; } @@ -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, ®ion); + 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; } |