EXA: Added pitch limitations.
Drivers can now specify the max pitches that the accelerator supports.
This commit is contained in:
parent
988f446fe0
commit
ae8b4f7dcf
53
exa/exa.c
53
exa/exa.c
|
@ -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
|
||||||
|
|
33
exa/exa.h
33
exa/exa.h
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue