EXA: Added pitch limitations.

Drivers can now specify the max pitches that the accelerator supports.
This commit is contained in:
Tilman Sauerbeck 2007-09-24 22:06:52 +02:00
parent 988f446fe0
commit ae8b4f7dcf
5 changed files with 139 additions and 35 deletions

View File

@ -278,6 +278,26 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
REGION_NULL(pScreen, &pExaPixmap->validSys); REGION_NULL(pScreen, &pExaPixmap->validSys);
REGION_NULL(pScreen, &pExaPixmap->validFB); 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; return pPixmap;
} }
@ -707,6 +727,39 @@ exaDriverInit (ScreenPtr pScreen,
return FALSE; 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 #ifdef RENDER
ps = GetPictureScreenIfSet(pScreen); ps = GetPictureScreenIfSet(pScreen);
#endif #endif

View File

@ -39,7 +39,7 @@
#include "fb.h" #include "fb.h"
#define EXA_VERSION_MAJOR 2 #define EXA_VERSION_MAJOR 2
#define EXA_VERSION_MINOR 2 #define EXA_VERSION_MINOR 3
#define EXA_VERSION_RELEASE 0 #define EXA_VERSION_RELEASE 0
typedef struct _ExaOffscreenArea ExaOffscreenArea; typedef struct _ExaOffscreenArea ExaOffscreenArea;
@ -671,6 +671,37 @@ typedef struct _ExaDriver {
*/ */
#define EXA_PREPARE_MASK 2 #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; } ExaDriverRec, *ExaDriverPtr;

View File

@ -43,7 +43,8 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
ScreenPtr pScreen = pDrawable->pScreen; ScreenPtr pScreen = pDrawable->pScreen;
ExaScreenPriv (pScreen); ExaScreenPriv (pScreen);
RegionPtr pClip = fbGetCompositeClip(pGC); RegionPtr pClip = fbGetCompositeClip(pGC);
PixmapPtr pPixmap; PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
BoxPtr pextent, pbox; BoxPtr pextent, pbox;
int nbox; int nbox;
int extentX1, extentX2, extentY1, extentY2; int extentX1, extentX2, extentY1, extentY2;
@ -54,13 +55,12 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE; pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); pixmaps[0].pPix = pPixmap;
pixmaps[0].pReg = NULL; pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut || if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid || pGC->fillStyle != FillSolid ||
pPixmap->drawable.width > pExaScr->info->maxX || pExaPixmap->accel_blocked)
pPixmap->drawable.height > pExaScr->info->maxY)
{ {
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return; return;
@ -480,6 +480,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
{ {
ExaScreenPriv (pDstDrawable->pScreen); ExaScreenPriv (pDstDrawable->pScreen);
PixmapPtr pSrcPixmap, pDstPixmap; PixmapPtr pSrcPixmap, pDstPixmap;
ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
int src_off_x, src_off_y; int src_off_x, src_off_y;
int dst_off_x, dst_off_y; int dst_off_x, dst_off_y;
ExaMigrationRec pixmaps[2]; ExaMigrationRec pixmaps[2];
@ -527,14 +528,14 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
pixmaps[1].pPix = pSrcPixmap; pixmaps[1].pPix = pSrcPixmap;
pixmaps[1].pReg = NULL; pixmaps[1].pReg = NULL;
/* Respect maxX/maxY in a trivial way: don't set up drawing when we might pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
* violate the limits. The proper solution would be a temporary pixmap pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
* adjusted so that the drawing happened within limits.
/* 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 || if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked)
pSrcPixmap->drawable.height > pExaScr->info->maxY ||
pDstPixmap->drawable.width > pExaScr->info->maxX ||
pDstPixmap->drawable.height > pExaScr->info->maxY)
{ {
goto fallback; goto fallback;
} else { } else {
@ -760,6 +761,7 @@ exaPolyFillRect(DrawablePtr pDrawable,
ExaScreenPriv (pDrawable->pScreen); ExaScreenPriv (pDrawable->pScreen);
RegionPtr pClip = fbGetCompositeClip(pGC); RegionPtr pClip = fbGetCompositeClip(pGC);
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
ExaPixmapPriv (pPixmap);
register BoxPtr pbox; register BoxPtr pbox;
BoxPtr pextent; BoxPtr pextent;
int extentX1, extentX2, extentY1, extentY2; int extentX1, extentX2, extentY1, extentY2;
@ -786,9 +788,7 @@ exaPolyFillRect(DrawablePtr pDrawable,
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
if (pExaScr->swappedOut || if (pExaScr->swappedOut || pExaPixmap->accel_blocked)
pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{ {
goto fallback; goto fallback;
} }
@ -1102,21 +1102,21 @@ exaFillRegionSolid (DrawablePtr pDrawable,
CARD32 alu) CARD32 alu)
{ {
ExaScreenPriv(pDrawable->pScreen); ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap; PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
int xoff, yoff; int xoff, yoff;
ExaMigrationRec pixmaps[1]; ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE; pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE; pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); pixmaps[0].pPix = pPixmap;
pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
alu) ? NULL : pRegion; alu) ? NULL : pRegion;
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pPixmap->drawable.width > pExaScr->info->maxX || if (pExaPixmap->accel_blocked)
pPixmap->drawable.height > pExaScr->info->maxY)
{ {
goto fallback; goto fallback;
} else { } else {
@ -1193,6 +1193,8 @@ exaFillRegionTiled (DrawablePtr pDrawable,
{ {
ExaScreenPriv(pDrawable->pScreen); ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap; PixmapPtr pPixmap;
ExaPixmapPrivPtr pExaPixmap;
ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
int xoff, yoff, tileXoff, tileYoff; int xoff, yoff, tileXoff, tileYoff;
int tileWidth, tileHeight; int tileWidth, tileHeight;
ExaMigrationRec pixmaps[2]; ExaMigrationRec pixmaps[2];
@ -1223,10 +1225,9 @@ exaFillRegionTiled (DrawablePtr pDrawable,
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pPixmap->drawable.width > pExaScr->info->maxX || pExaPixmap = ExaGetPixmapPriv (pPixmap);
pPixmap->drawable.height > pExaScr->info->maxY ||
tileWidth > pExaScr->info->maxX || if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
tileHeight > pExaScr->info->maxY)
{ {
goto fallback; goto fallback;
} else { } else {

View File

@ -154,6 +154,10 @@ extern int exaPixmapPrivateIndex;
#define ExaSetPixmapPriv(p,a) ((p)->devPrivates[exaPixmapPrivateIndex].ptr = (pointer) (a)) #define ExaSetPixmapPriv(p,a) ((p)->devPrivates[exaPixmapPrivateIndex].ptr = (pointer) (a))
#define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p) #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 { typedef struct {
ExaOffscreenArea *area; ExaOffscreenArea *area;
int score; /**< score for the move-in vs move-out heuristic */ int score; /**< score for the move-in vs move-out heuristic */
@ -166,6 +170,17 @@ typedef struct {
int fb_pitch; /**< pitch of pixmap in framebuffer memory */ int fb_pitch; /**< pitch of pixmap in framebuffer memory */
unsigned int fb_size; /**< size of pixmap in framebuffer memory */ 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 * The damage record contains the areas of the pixmap's current location
* (framebuffer or system) that have been damaged compared to the other * (framebuffer or system) that have been damaged compared to the other

View File

@ -336,24 +336,28 @@ exaTryDriverComposite(CARD8 op,
int nbox; int nbox;
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;
struct _Pixmap scratch; struct _Pixmap scratch;
ExaMigrationRec pixmaps[3]; ExaMigrationRec pixmaps[3];
pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
pDstPix = exaGetDrawablePixmap(pDst->pDrawable); pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
if (pMask)
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
/* Bail if we might exceed coord limits by rendering from/to these. We pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
* should really be making some scratch pixmaps with offsets and coords pDstExaPix = ExaGetPixmapPriv(pDstPix);
* adjusted to deal with this, but it hasn't been done yet.
if (pMask) {
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
}
/* 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 || if (pSrcExaPix->accel_blocked ||
pSrcPix->drawable.height > pExaScr->info->maxY || pDstExaPix->accel_blocked ||
pDstPix->drawable.width > pExaScr->info->maxX || (pMask && (pMaskExaPix->accel_blocked)))
pDstPix->drawable.height > pExaScr->info->maxY ||
(pMask && (pMaskPix->drawable.width > pExaScr->info->maxX ||
pMaskPix->drawable.height > pExaScr->info->maxY)))
{ {
return -1; return -1;
} }