diff options
author | Tilman Sauerbeck <tilman@code-monkey.de> | 2007-09-24 22:06:52 +0200 |
---|---|---|
committer | Tilman Sauerbeck <tilman@code-monkey.de> | 2007-09-25 16:43:06 +0200 |
commit | ae8b4f7dcf1291a2f5a0d0159f3e6089eea0578a (patch) | |
tree | ada82ec180d7f6f5073c5172b8c8eea050e43ee9 | |
parent | 988f446fe00ac2b92c484a4440613dd82191eadd (diff) |
EXA: Added pitch limitations.
Drivers can now specify the max pitches that the accelerator supports.
-rw-r--r-- | exa/exa.c | 53 | ||||
-rw-r--r-- | exa/exa.h | 33 | ||||
-rw-r--r-- | exa/exa_accel.c | 45 | ||||
-rw-r--r-- | exa/exa_priv.h | 15 | ||||
-rw-r--r-- | exa/exa_render.c | 24 |
5 files changed, 137 insertions, 33 deletions
@@ -278,6 +278,26 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) REGION_NULL(pScreen, &pExaPixmap->validSys); REGION_NULL(pScreen, &pExaPixmap->validFB); + /* Check whether this pixmap can be used for acceleration. */ + pExaPixmap->accel_blocked = 0; + + if (pExaScr->info->maxPitchPixels) { + int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8; + + if (pExaPixmap->fb_pitch > max_pitch) + pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; + } + + if (pExaScr->info->maxPitchBytes && + pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) + pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; + + if (w > pExaScr->info->maxX) + pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; + + if (h > pExaScr->info->maxY) + pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; + return pPixmap; } @@ -707,6 +727,39 @@ exaDriverInit (ScreenPtr pScreen, return FALSE; } + /* If the driver doesn't set any max pitch values, we'll just assume + * that there's a limitation by pixels, and that it's the same as + * maxX. + */ + if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) + { + pScreenInfo->maxPitchPixels = pScreenInfo->maxX; + } + + /* If set, maxPitchPixels must not be smaller than maxX. */ + if (pScreenInfo->maxPitchPixels && + pScreenInfo->maxPitchPixels < pScreenInfo->maxX) + { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::maxPitchPixels " + "is smaller than ExaDriverRec::maxX\n", + pScreen->myNum); + return FALSE; + } + + /* If set, maxPitchBytes must not be smaller than maxX * 4. + * This is to ensure that a 32bpp pixmap with the maximum width + * can be handled wrt the pitch. + */ + if (pScreenInfo->maxPitchBytes && + pScreenInfo->maxPitchBytes < (pScreenInfo->maxX * 4)) + { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::maxPitchBytes " + "doesn't allow a 32bpp pixmap with width equal to " + "ExaDriverRec::maxX\n", + pScreen->myNum); + return FALSE; + } + #ifdef RENDER ps = GetPictureScreenIfSet(pScreen); #endif @@ -39,7 +39,7 @@ #include "fb.h" #define EXA_VERSION_MAJOR 2 -#define EXA_VERSION_MINOR 2 +#define EXA_VERSION_MINOR 3 #define EXA_VERSION_RELEASE 0 typedef struct _ExaOffscreenArea ExaOffscreenArea; @@ -671,6 +671,37 @@ typedef struct _ExaDriver { */ #define EXA_PREPARE_MASK 2 /** @} */ + + /** + * maxPitchPixels controls the pitch limitation for rendering from + * the card. + * The driver should never receive a request for rendering a pixmap + * that has a pitch (in pixels) beyond maxPitchPixels. + * + * Setting this field is optional -- if your hardware doesn't have + * a pitch limitation in pixels, don't set this. If neither this value + * nor maxPitchBytes is set, then maxPitchPixels is set to maxX. + * If set, it must not be smaller than maxX. + * + * @sa maxPitchBytes + */ + int maxPitchPixels; + + /** + * maxPitchBytes controls the pitch limitation for rendering from + * the card. + * The driver should never receive a request for rendering a pixmap + * that has a pitch (in bytes) beyond maxPitchBytes. + * + * Setting this field is optional -- if your hardware doesn't have + * a pitch limitation in bytes, don't set this. + * If set, it must not be smaller than maxX * 4. + * There's no default value for maxPitchBytes. + * + * @sa maxPitchPixels + */ + int maxPitchBytes; + /** @} */ } ExaDriverRec, *ExaDriverPtr; diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 2acade263..028d93644 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -43,7 +43,8 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, ScreenPtr pScreen = pDrawable->pScreen; ExaScreenPriv (pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap; + PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); + ExaPixmapPriv (pPixmap); BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; @@ -54,13 +55,12 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = NULL; if (pExaScr->swappedOut || pGC->fillStyle != FillSolid || - pPixmap->drawable.width > pExaScr->info->maxX || - pPixmap->drawable.height > pExaScr->info->maxY) + pExaPixmap->accel_blocked) { ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; @@ -480,6 +480,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, { ExaScreenPriv (pDstDrawable->pScreen); PixmapPtr pSrcPixmap, pDstPixmap; + ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; int src_off_x, src_off_y; int dst_off_x, dst_off_y; ExaMigrationRec pixmaps[2]; @@ -527,14 +528,14 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pixmaps[1].pPix = pSrcPixmap; pixmaps[1].pReg = NULL; - /* 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. + pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap); + pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); + + /* Check whether the accelerator can use this pixmap. + * FIXME: If it cannot, use temporary pixmaps so that the drawing + * happens within limits. */ - 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) + if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { goto fallback; } else { @@ -760,6 +761,7 @@ exaPolyFillRect(DrawablePtr pDrawable, ExaScreenPriv (pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaPixmapPriv (pPixmap); register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; @@ -786,9 +788,7 @@ exaPolyFillRect(DrawablePtr pDrawable, exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - if (pExaScr->swappedOut || - pPixmap->drawable.width > pExaScr->info->maxX || - pPixmap->drawable.height > pExaScr->info->maxY) + if (pExaScr->swappedOut || pExaPixmap->accel_blocked) { goto fallback; } @@ -1102,21 +1102,21 @@ exaFillRegionSolid (DrawablePtr pDrawable, CARD32 alu) { ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPixmap; + PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); + ExaPixmapPriv (pPixmap); int xoff, yoff; ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, alu) ? NULL : pRegion; exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); - if (pPixmap->drawable.width > pExaScr->info->maxX || - pPixmap->drawable.height > pExaScr->info->maxY) + if (pExaPixmap->accel_blocked) { goto fallback; } else { @@ -1193,6 +1193,8 @@ exaFillRegionTiled (DrawablePtr pDrawable, { ExaScreenPriv(pDrawable->pScreen); PixmapPtr pPixmap; + ExaPixmapPrivPtr pExaPixmap; + ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); int xoff, yoff, tileXoff, tileYoff; int tileWidth, tileHeight; ExaMigrationRec pixmaps[2]; @@ -1223,10 +1225,9 @@ exaFillRegionTiled (DrawablePtr pDrawable, exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); - if (pPixmap->drawable.width > pExaScr->info->maxX || - pPixmap->drawable.height > pExaScr->info->maxY || - tileWidth > pExaScr->info->maxX || - tileHeight > pExaScr->info->maxY) + pExaPixmap = ExaGetPixmapPriv (pPixmap); + + if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) { goto fallback; } else { diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 9e4f8bc52..a26933d11 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -154,6 +154,10 @@ extern int exaPixmapPrivateIndex; #define ExaSetPixmapPriv(p,a) ((p)->devPrivates[exaPixmapPrivateIndex].ptr = (pointer) (a)) #define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p) +#define EXA_RANGE_PITCH (1 << 0) +#define EXA_RANGE_WIDTH (1 << 1) +#define EXA_RANGE_HEIGHT (1 << 2) + typedef struct { ExaOffscreenArea *area; int score; /**< score for the move-in vs move-out heuristic */ @@ -167,6 +171,17 @@ typedef struct { unsigned int fb_size; /**< size of pixmap in framebuffer memory */ /** + * Holds information about whether this pixmap can be used for + * acceleration (== 0) or not (> 0). + * + * Contains a OR'ed combination of the following values: + * EXA_RANGE_PITCH - set if the pixmap's pitch is out of range + * EXA_RANGE_WIDTH - set if the pixmap's width is out of range + * EXA_RANGE_HEIGHT - set if the pixmap's height is out of range + */ + unsigned int accel_blocked; + + /** * The damage record contains the areas of the pixmap's current location * (framebuffer or system) that have been damaged compared to the other * location. diff --git a/exa/exa_render.c b/exa/exa_render.c index 943a4c8f6..4c931283e 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -336,24 +336,28 @@ exaTryDriverComposite(CARD8 op, int nbox; 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); + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - if (pMask) + pDstExaPix = ExaGetPixmapPriv(pDstPix); + + if (pMask) { pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); + pMaskExaPix = ExaGetPixmapPriv(pMaskPix); + } - /* 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. + /* Check whether the accelerator can use these pixmaps. + * FIXME: If it cannot, use temporary pixmaps so that the drawing + * happens within limits. */ - 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))) + if (pSrcExaPix->accel_blocked || + pDstExaPix->accel_blocked || + (pMask && (pMaskExaPix->accel_blocked))) { return -1; } |