xorg-x11-server/xserver-1.3.0-exaupgrade.patch
Dave Airlie 5d4276c96a * Mon Aug 13 2007 Dave Airlie <airlied@redhat.com> 1.3.0.0-18
- xserver-1.3.0-mesa7.patch: Add support for building against mesa 7.0.1
  along with DRI zero-copy TFP hopefully
- xserver-1.3.0-exaupgrade.patch: Add updated EXA support
- dropped xserver-1.2.99.901-xephyr-crash-at-exit.patch - upstream
- rebase xorg-x11-server-1.1.1-offscreen-pixmaps.patch to xserver-1.3.0-newglx-offscreen-pixmaps.patch
- dropped xorg-x11-server-1.1.1-glcore-visual-matching.patch - fixed upstream
2007-08-14 06:16:44 +00:00

1614 lines
50 KiB
Diff

diff --git a/exa/exa.c b/exa/exa.c
index e9f42df..8e22b89 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -126,7 +126,7 @@ exaGetDrawablePixmap(DrawablePtr pDrawable)
* the backing drawable. These coordinates are nonzero only for redirected
* windows.
*/
-static void
+void
exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp)
{
@@ -172,29 +172,6 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
REGION_UNINIT(pScreen, &region);
}
-/**
- * exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for
- * optimizations in pixmap migration when no changes have occurred.
- */
-void
-exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2)
-{
- PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
- int xoff, yoff;
-
- x1 = max(x1, pDrawable->x);
- y1 = max(y1, pDrawable->y);
- x2 = min(x2, pDrawable->x + pDrawable->width);
- y2 = min(y2, pDrawable->y + pDrawable->height);
-
- if (x1 >= x2 || y1 >= y2)
- return;
-
- exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
-
- exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
-}
-
static Bool
exaDestroyPixmap (PixmapPtr pPixmap)
{
@@ -322,6 +299,9 @@ exaPixmapIsOffscreen(PixmapPtr p)
if (p->devPrivate.ptr == NULL)
return TRUE;
+ if (pExaScr->info->PixmapIsOffscreen)
+ return pExaScr->info->PixmapIsOffscreen(p);
+
return ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
(CARD8 *) pExaScr->info->memoryBase) <
pExaScr->info->memorySize);
@@ -589,6 +569,45 @@ exaDriverInit (ScreenPtr pScreen,
PictureScreenPtr ps;
#endif
+ if (!pScreenInfo)
+ return FALSE;
+
+ if (!pScreenInfo->memoryBase) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase must be "
+ "non-zero\n", pScreen->myNum);
+ return FALSE;
+ }
+
+ if (!pScreenInfo->memorySize) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
+ "non-zero\n", pScreen->myNum);
+ return FALSE;
+ }
+
+ if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must be <= "
+ "ExaDriverRec::memorySize\n", pScreen->myNum);
+ return FALSE;
+ }
+
+ if (!pScreenInfo->PrepareSolid) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
+ "non-NULL\n", pScreen->myNum);
+ return FALSE;
+ }
+
+ if (!pScreenInfo->PrepareCopy) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
+ "non-NULL\n", pScreen->myNum);
+ return FALSE;
+ }
+
+ if (!pScreenInfo->WaitMarker) {
+ LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
+ "non-NULL\n", pScreen->myNum);
+ return FALSE;
+ }
+
if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
pScreenInfo->exa_minor > EXA_VERSION_MINOR)
{
@@ -668,10 +687,6 @@ 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
diff --git a/exa/exa.h b/exa/exa.h
index bf723f7..9ea5933 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -39,7 +39,7 @@
#include "fb.h"
#define EXA_VERSION_MAJOR 2
-#define EXA_VERSION_MINOR 1
+#define EXA_VERSION_MINOR 2
#define EXA_VERSION_RELEASE 0
typedef struct _ExaOffscreenArea ExaOffscreenArea;
@@ -229,7 +229,7 @@ typedef struct _ExaDriver {
* @{
*/
/**
- * PrepareCopy() sets up the driver for doing a copy within offscreen
+ * PrepareCopy() sets up the driver for doing a copy within video
* memory.
*
* @param pSrcPixmap source pixmap
@@ -636,6 +636,23 @@ typedef struct _ExaDriver {
*/
void (*FinishAccess)(PixmapPtr pPix, int index);
+ /**
+ * PixmapIsOffscreen() is an optional driver replacement to
+ * exaPixmapIsOffscreen(). Set to NULL if you want the standard behaviour
+ * of exaPixmapIsOffscreen().
+ *
+ * @param pPix the pixmap
+ * @return TRUE if the given drawable is in framebuffer memory.
+ *
+ * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
+ * memory, meaning that acceleration could probably be done to it, and that it
+ * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * with the CPU.
+ *
+ *
+ */
+ Bool (*PixmapIsOffscreen)(PixmapPtr pPix);
+
/** @name PrepareAccess() and FinishAccess() indices
* @{
*/
@@ -704,6 +721,9 @@ exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
ExaOffscreenArea *
exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea *area);
+void
+ExaOffscreenMarkUsed (PixmapPtr pPixmap);
+
unsigned long
exaGetPixmapOffset(PixmapPtr pPix);
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index e633d80..cc383cc 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -74,6 +74,7 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pGC->planemask,
pGC->fgPixel))
{
+ exaDoMigration (pixmaps, 1, FALSE);
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
}
@@ -109,8 +110,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
(*pExaScr->info->Solid) (pPixmap,
fullX1 + off_x, fullY1 + off_y,
fullX2 + off_x, fullY1 + 1 + off_y);
- exaPixmapDirty (pPixmap, fullX1 + off_x, fullY1 + off_y,
- fullX2 + off_x, fullY1 + 1 + off_y);
}
else
{
@@ -129,8 +128,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
(*pExaScr->info->Solid) (pPixmap,
partX1 + off_x, fullY1 + off_y,
partX2 + off_x, fullY1 + 1 + off_y);
- exaPixmapDirty (pPixmap, partX1 + off_x, fullY1 + off_y,
- partX2 + off_x, fullY1 + 1 + off_y);
}
}
pbox++;
@@ -154,8 +151,9 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int xoff, yoff;
int src_stride, bpp = pDrawable->bitsPerPixel;
- if (pExaScr->swappedOut || pExaScr->info->UploadToScreen == NULL)
- goto migrate_and_fallback;
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
/* Don't bother with under 8bpp, XYPixmaps. */
if (format != ZPixmap || bpp < 8)
@@ -165,10 +163,14 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
goto migrate_and_fallback;
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
+ if (pExaScr->swappedOut)
+ goto fallback;
+
exaDoMigration (pixmaps, 1, TRUE);
+
+ if (pExaScr->info->UploadToScreen == NULL)
+ goto fallback;
+
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
if (pPix == NULL)
@@ -221,25 +223,23 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
src_stride / sizeof(FbStip),
- (x1 - x) * bpp,
- dst + (y1 + yoff) * dst_stride,
+ (x1 - x) * dstBpp,
+ dst + (y1 + dstYoff) * dst_stride,
dst_stride,
- (x1 + xoff) * bpp,
- (x2 - x1) * bpp,
+ (x1 + dstXoff) * dstBpp,
+ (x2 - x1) * dstBpp,
y2 - y1,
- GXcopy, FB_ALLONES, bpp);
+ GXcopy, FB_ALLONES, dstBpp);
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
}
+
exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
}
return;
migrate_and_fallback:
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
exaDoMigration (pixmaps, 1, FALSE);
fallback:
@@ -387,6 +387,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
ExaMigrationRec pixmaps[2];
+ Bool fallback = FALSE;
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
@@ -404,62 +405,64 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
pDstPixmap->drawable.width > pExaScr->info->maxX ||
pDstPixmap->drawable.height > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 2, FALSE);
- goto fallback;
+ fallback = TRUE;
} else {
exaDoMigration (pixmaps, 2, TRUE);
}
/* Mixed directions must be handled specially if the card is lame */
- if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS &&
+ if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
reverse != upsidedown) {
- if (!exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+ if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
dx, dy))
- goto fallback;
- return;
+ return;
+ fallback = TRUE;
+ }
+
+ pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
+ pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
+
+ exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
+ exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
+
+ if (fallback || !exaPixmapIsOffscreen(pSrcPixmap) ||
+ !exaPixmapIsOffscreen(pDstPixmap) ||
+ !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ upsidedown ? -1 : 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES)) {
+ fallback = TRUE;
+ EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
+ exaDrawableLocation(pSrcDrawable),
+ exaDrawableLocation(pDstDrawable)));
+ exaDoMigration (pixmaps, 2, FALSE);
+ exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
+ fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
+ pbox, nbox, dx, dy, reverse, upsidedown,
+ bitplane, closure);
+ exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
+ exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
}
- if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
- (pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
- (*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap,
- reverse ? -1 : 1, upsidedown ? -1 : 1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask : FB_ALLONES))
+ while (nbox--)
{
- while (nbox--)
- {
+ if (!fallback)
(*pExaScr->info->Copy) (pDstPixmap,
pbox->x1 + dx + src_off_x,
pbox->y1 + dy + src_off_y,
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
- exaPixmapDirty (pDstPixmap,
- pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
- pbox++;
- }
- (*pExaScr->info->DoneCopy) (pDstPixmap);
- exaMarkSync(pDstDrawable->pScreen);
- return;
- }
-
-fallback:
- EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
- exaDrawableLocation(pSrcDrawable),
- exaDrawableLocation(pDstDrawable)));
- exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
- exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
- fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
- pbox, nbox, dx, dy, reverse, upsidedown,
- bitplane, closure);
- exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
- exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
- while (nbox--)
- {
- exaDrawableDirty (pDstDrawable, pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ exaPixmapDirty (pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+ pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
pbox++;
}
+
+ if (fallback)
+ return;
+
+ (*pExaScr->info->DoneCopy) (pDstPixmap);
+ exaMarkSync (pDstDrawable->pScreen);
}
RegionPtr
@@ -618,6 +621,9 @@ exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
DEALLOCATE_LOCAL(prect);
}
+static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion,
+ Pixel pixel, CARD32 planemask, CARD32 alu);
+
static void
exaPolyFillRect(DrawablePtr pDrawable,
GCPtr pGC,
@@ -626,7 +632,7 @@ exaPolyFillRect(DrawablePtr pDrawable,
{
ExaScreenPriv (pDrawable->pScreen);
RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap;
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
register BoxPtr pbox;
BoxPtr pextent;
int extentX1, extentX2, extentY1, extentY2;
@@ -635,40 +641,73 @@ exaPolyFillRect(DrawablePtr pDrawable,
int xoff, yoff;
int xorg, yorg;
int n;
- ExaMigrationRec pixmaps[1];
+ ExaMigrationRec pixmaps[2];
+ RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
+
+ /* Compute intersection of rects and clip region */
+ REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
+ REGION_INTERSECT(pScreen, pReg, pClip, pReg);
+
+ if (!REGION_NUM_RECTS(pReg)) {
+ goto out;
+ }
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pPix = pPixmap;
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+
if (pExaScr->swappedOut ||
- pGC->fillStyle != FillSolid ||
pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 1, FALSE);
- ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
- while (nrect-- >= 0) {
- exaDrawableDirty(pDrawable,
- pDrawable->x + prect->x,
- pDrawable->y + prect->y,
- pDrawable->x + prect->x + prect->width,
- pDrawable->y + prect->y + prect->height);
- prect++;
+ goto fallback;
+ }
+
+ /* For ROPs where overlaps don't matter, convert rectangles to region and
+ * call exaFillRegion{Solid,Tiled}.
+ */
+ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
+ (pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop ||
+ pGC->alu == GXcopyInverted || pGC->alu == GXset)) {
+ if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
+ exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
+ pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
+ pGC->alu)) ||
+ (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
+ exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
+ pGC->planemask, pGC->alu))) {
+ goto out;
}
- return;
- } else {
- exaDoMigration (pixmaps, 1, TRUE);
}
- if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
+ if (pGC->fillStyle != FillSolid &&
+ !(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
+ {
+ goto fallback;
+ }
+
+ exaDoMigration (pixmaps, 1, TRUE);
+
+ if (!exaPixmapIsOffscreen (pPixmap) ||
!(*pExaScr->info->PrepareSolid) (pPixmap,
pGC->alu,
pGC->planemask,
pGC->fgPixel))
{
+fallback:
+ if (pGC->fillStyle == FillTiled && !pGC->tileIsPixel) {
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pGC->tile.pixmap;
+ exaDoMigration (pixmaps, 2, FALSE);
+ } else {
+ exaDoMigration (pixmaps, 1, FALSE);
+ }
+
ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
- return;
+ goto out;
}
xorg = pDrawable->x;
@@ -707,15 +746,14 @@ exaPolyFillRect(DrawablePtr pDrawable,
(*pExaScr->info->Solid) (pPixmap,
fullX1 + xoff, fullY1 + yoff,
fullX2 + xoff, fullY2 + yoff);
- exaPixmapDirty (pPixmap, fullX1 + xoff, fullY1 + yoff,
- fullX2 + xoff, fullY2 + yoff);
}
else
{
pbox = REGION_RECTS(pClip);
/*
* clip the rectangle to each box in the clip region
- * this is logically equivalent to calling Intersect()
+ * this is logically equivalent to calling Intersect(),
+ * but rectangles may overlap each other here.
*/
while(n--)
{
@@ -738,14 +776,15 @@ exaPolyFillRect(DrawablePtr pDrawable,
(*pExaScr->info->Solid) (pPixmap,
partX1 + xoff, partY1 + yoff,
partX2 + xoff, partY2 + yoff);
- exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff,
- partX2 + xoff, partY2 + yoff);
}
}
}
}
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
+
+out:
+ REGION_DESTROY(pScreen, pReg);
}
static void
@@ -775,20 +814,19 @@ exaSolidBoxClipped (DrawablePtr pDrawable,
pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 1, FALSE);
- goto fallback;
+ fallback = TRUE;
} else {
exaDoMigration (pixmaps, 1, TRUE);
}
- pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+ exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff);
- if (!pPixmap ||
+ if (fallback || !exaPixmapIsOffscreen(pPixmap) ||
!(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
{
-fallback:
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable)));
+ exaDoMigration (pixmaps, 1, FALSE);
fallback = TRUE;
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
@@ -827,10 +865,10 @@ fallback:
(*pExaScr->info->Solid) (pPixmap,
partX1 + xoff, partY1 + yoff,
partX2 + xoff, partY2 + yoff);
- exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff,
- partX2 + xoff, partY2 + yoff);
- } else
- exaDrawableDirty (pDrawable, partX1, partY1, partX2, partY2);
+ }
+
+ exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff,
+ partY2 + yoff);
}
if (fallback)
@@ -870,12 +908,36 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
int dstBpp;
int dstXoff, dstYoff;
FbBits depthMask;
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaMigrationRec pixmaps[1];
+ int xBack, widthBack, yBack, heightBack;
+
+ for (ppci = ppciInit, n = nglyph, widthBack = 0; n; n--)
+ widthBack += (*ppci++)->metrics.characterWidth;
+
+ xBack = x;
+ if (widthBack < 0)
+ {
+ xBack += widthBack;
+ widthBack = -widthBack;
+ }
+ yBack = y - FONTASCENT(pGC->font);
+ heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
+
+ if (xBack >= pDrawable->width || yBack >= pDrawable->height ||
+ (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0)
+ return;
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
depthMask = FbFullMask(pDrawable->depth);
if ((pGC->planemask & depthMask) != depthMask)
{
+ exaDoMigration(pixmaps, 1, FALSE);
ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
- return;
+ goto damage;
}
glyph = NULL;
switch (pDrawable->bitsPerPixel) {
@@ -887,6 +949,8 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
x += pDrawable->x;
y += pDrawable->y;
+ xBack += pDrawable->x;
+ yBack += pDrawable->y;
if (TERMINALFONT (pGC->font) && !glyph)
{
@@ -894,23 +958,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
}
else
{
- int xBack, widthBack;
- int yBack, heightBack;
-
- ppci = ppciInit;
- n = nglyph;
- widthBack = 0;
- while (n--)
- widthBack += (*ppci++)->metrics.characterWidth;
-
- xBack = x;
- if (widthBack < 0)
- {
- xBack += widthBack;
- widthBack = -widthBack;
- }
- yBack = y - FONTASCENT(pGC->font);
- heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
exaSolidBoxClipped (pDrawable,
fbGetCompositeClip(pGC),
pGC->planemask,
@@ -923,74 +970,50 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
}
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
+ exaDoMigration(pixmaps, 1, FALSE);
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccessGC (pGC);
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- ppci = ppciInit;
- while (nglyph--)
+ for (ppci = ppciInit; nglyph; nglyph--, x += pci->metrics.characterWidth)
{
pci = *ppci++;
- pglyph = FONTGLYPHBITS(pglyphBase, pci);
gWidth = GLYPHWIDTHPIXELS(pci);
gHeight = GLYPHHEIGHTPIXELS(pci);
- if (gWidth && gHeight)
+ gx = x + pci->metrics.leftSideBearing;
+ gy = y - pci->metrics.ascent;
+
+ if (!gWidth || !gHeight || (gx + gWidth) <= xBack ||
+ (gy + gHeight) <= yBack || gx >= (xBack + widthBack) ||
+ gy >= (yBack + heightBack))
+ continue;
+
+ pglyph = FONTGLYPHBITS(pglyphBase, pci);
+
+ if (glyph && gWidth <= sizeof (FbStip) * 8 &&
+ fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
{
- gx = x + pci->metrics.leftSideBearing;
- gy = y - pci->metrics.ascent;
- if (glyph && gWidth <= sizeof (FbStip) * 8 &&
- fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
- {
- (*glyph) (dst + (gy + dstYoff) * dstStride,
- dstStride,
- dstBpp,
- (FbStip *) pglyph,
- pPriv->fg,
- gx + dstXoff,
- gHeight);
- exaDrawableDirty (pDrawable, gx, gy, gx + gWidth, gy + gHeight);
- }
- else
- {
- RegionPtr pClip = fbGetCompositeClip(pGC);
- int nbox;
- BoxPtr pbox;
-
- gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
- fbPutXYImage (pDrawable,
- pClip,
- pPriv->fg,
- pPriv->bg,
- pPriv->pm,
- GXcopy,
- opaque,
-
- gx,
- gy,
- gWidth, gHeight,
-
- (FbStip *) pglyph,
- gStride,
- 0);
-
- for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
- nbox--; pbox++) {
- int x1 = max(gx, pbox->x1), x2 = min(gx + gWidth, pbox->x2);
- int y1 = max(gy, pbox->y1), y2 = min(gy + gHeight, pbox->y2);
-
- if (x1 >= x2 || y1 >= y2)
- continue;
-
- exaDrawableDirty (pDrawable, gx, gy, gx + gWidth,
- gy + gHeight);
- }
- }
+ (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
+ (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight);
+ }
+ else
+ {
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+
+ gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
+ fbPutXYImage (pDrawable, pClip, pPriv->fg, pPriv->bg, pPriv->pm,
+ GXcopy, opaque, gx, gy, gWidth, gHeight,
+ (FbStip *) pglyph, gStride, 0);
}
- x += pci->metrics.characterWidth;
}
exaFinishAccessGC (pGC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+
+damage:
+ exaGetDrawableDeltas(pDrawable, pPixmap, &dstXoff, &dstYoff);
+ exaPixmapDirty(pPixmap, xBack + dstXoff, yBack + dstYoff,
+ xBack + dstXoff + widthBack, yBack + dstYoff + heightBack);
}
const GCOps exaOps = {
@@ -1043,10 +1066,12 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
}
-static void
+static Bool
exaFillRegionSolid (DrawablePtr pDrawable,
RegionPtr pRegion,
- Pixel pixel)
+ Pixel pixel,
+ CARD32 planemask,
+ CARD32 alu)
{
ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap;
@@ -1062,22 +1087,19 @@ exaFillRegionSolid (DrawablePtr pDrawable,
if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 1, FALSE);
goto fallback;
} else {
exaDoMigration (pixmaps, 1, TRUE);
}
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
- (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
+ (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
{
while (nbox--)
{
(*pExaScr->info->Solid) (pPixmap,
pBox->x1 + xoff, pBox->y1 + yoff,
pBox->x2 + xoff, pBox->y2 + yoff);
- exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
- pBox->x2 + xoff, pBox->y2 + yoff);
pBox++;
}
(*pExaScr->info->DoneSolid) (pPixmap);
@@ -1086,27 +1108,30 @@ exaFillRegionSolid (DrawablePtr pDrawable,
else
{
fallback:
+ if (alu != GXcopy || planemask != FB_ALLONES)
+ return FALSE;
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable)));
+ exaDoMigration (pixmaps, 1, FALSE);
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
fbFillRegionSolid (pDrawable, pRegion, 0,
fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- while (nbox--)
- {
- exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- pBox++;
- }
}
+
+ return TRUE;
}
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
* Based on fbFillRegionTiled(), fbTile().
*/
-static void
+Bool
exaFillRegionTiled (DrawablePtr pDrawable,
RegionPtr pRegion,
- PixmapPtr pTile)
+ PixmapPtr pTile,
+ DDXPointPtr pPatOrg,
+ CARD32 planemask,
+ CARD32 alu)
{
ExaScreenPriv(pDrawable->pScreen);
PixmapPtr pPixmap;
@@ -1122,10 +1147,10 @@ exaFillRegionTiled (DrawablePtr pDrawable,
/* If we're filling with a solid color, grab it out and go to
* FillRegionSolid, saving numerous copies.
*/
- if (tileWidth == 1 && tileHeight == 1) {
- exaFillRegionSolid(pDrawable, pRegion, exaGetPixmapFirstPixel (pTile));
- return;
- }
+ if (tileWidth == 1 && tileHeight == 1)
+ return exaFillRegionSolid(pDrawable, pRegion,
+ exaGetPixmapFirstPixel (pTile), planemask,
+ alu);
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
@@ -1139,7 +1164,6 @@ exaFillRegionTiled (DrawablePtr pDrawable,
tileWidth > pExaScr->info->maxX ||
tileHeight > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 2, FALSE);
goto fallback;
} else {
exaDoMigration (pixmaps, 2, TRUE);
@@ -1153,8 +1177,9 @@ exaFillRegionTiled (DrawablePtr pDrawable,
if (!exaPixmapIsOffscreen(pTile))
goto fallback;
- if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, &tileXoff, &tileYoff), pPixmap, 0, 0, GXcopy,
- FB_ALLONES))
+ if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile,
+ &tileXoff, &tileYoff),
+ pPixmap, 0, 0, alu, planemask))
{
while (nbox--)
{
@@ -1162,7 +1187,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
int dstY = pBox->y1;
int tileY;
- tileY = (dstY - pDrawable->y) % tileHeight;
+ tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
while (height > 0) {
int width = pBox->x2 - pBox->x1;
int dstX = pBox->x1;
@@ -1173,7 +1198,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
h = height;
height -= h;
- tileX = (dstX - pDrawable->x) % tileWidth;
+ tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
while (width > 0) {
int w = tileWidth - tileX;
if (w > width)
@@ -1190,38 +1215,44 @@ exaFillRegionTiled (DrawablePtr pDrawable,
dstY += h;
tileY = 0;
}
- exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
- pBox->x2 + xoff, pBox->y2 + yoff);
pBox++;
}
(*pExaScr->info->DoneCopy) (pPixmap);
exaMarkSync(pDrawable->pScreen);
- return;
+ return TRUE;
}
fallback:
+ if (alu != GXcopy || planemask != FB_ALLONES)
+ return FALSE;
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
exaDrawableLocation(&pTile->drawable),
exaDrawableLocation(pDrawable)));
+ exaDoMigration (pixmaps, 2, FALSE);
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
fbFillRegionTiled (pDrawable, pRegion, pTile);
exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- while (nbox--)
- {
- exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- pBox++;
- }
+
+ return TRUE;
}
void
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
{
ExaScreenPriv (pWin->drawable.pScreen);
- if (!REGION_NUM_RECTS(pRegion))
+ PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin);
+ int xoff, yoff;
+ BoxPtr pBox;
+ int nbox = REGION_NUM_RECTS(pRegion);
+
+ if (!nbox)
return;
+
if (!pExaScr->swappedOut) {
+ DDXPointRec zeros = { 0, 0 };
+
switch (what) {
case PW_BACKGROUND:
switch (pWin->backgroundState) {
@@ -1235,25 +1266,41 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
what);
return;
case BackgroundPixel:
- exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel);
- return;
+ exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel,
+ FB_ALLONES, GXcopy);
+ goto damage;
case BackgroundPixmap:
- exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap);
- return;
+ exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap,
+ &zeros, FB_ALLONES, GXcopy);
+ goto damage;
}
break;
case PW_BORDER:
if (pWin->borderIsPixel) {
- exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel);
- return;
+ exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel,
+ FB_ALLONES, GXcopy);
+ goto damage;
} else {
- exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap);
- return;
+ exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap,
+ &zeros, FB_ALLONES, GXcopy);
+ goto damage;
}
break;
}
}
ExaCheckPaintWindow (pWin, pRegion, what);
+
+damage:
+ exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff);
+
+ pBox = REGION_RECTS(pRegion);
+
+ while (nbox--)
+ {
+ exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff,
+ pBox->x2 + xoff, pBox->y2 + yoff);
+ pBox++;
+ }
}
/**
@@ -1273,27 +1320,22 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
int xoff, yoff;
Bool ok;
- if (pExaScr->swappedOut || pExaScr->info->DownloadFromScreen == NULL)
+ if (pExaScr->swappedOut || (w == 1 && h == 1))
goto fallback;
+ if (pExaScr->info->DownloadFromScreen == NULL)
+ goto migrate_and_fallback;
+
/* Only cover the ZPixmap, solid copy case. */
if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
- goto fallback;
+ goto migrate_and_fallback;
/* Only try to handle the 8bpp and up cases, since we don't want to think
* about <8bpp.
*/
if (pDrawable->bitsPerPixel < 8)
- goto fallback;
+ goto migrate_and_fallback;
- /* Migrate, but assume that we could accelerate the download. It is up to
- * the migration scheme to ensure that this case doesn't result in bad
- * moving of pixmaps.
- */
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
- exaDoMigration (pixmaps, 1, TRUE);
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
if (pPix == NULL)
goto fallback;
@@ -1308,12 +1350,12 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
return;
}
-fallback:
+migrate_and_fallback:
pixmaps[0].as_dst = FALSE;
pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
exaDoMigration (pixmaps, 1, FALSE);
-
+fallback:
ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d);
}
diff --git a/exa/exa_migration.c b/exa/exa_migration.c
index eedc5fd..70d8e12 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration.c
@@ -464,12 +464,10 @@ exaAssertNotDirty (PixmapPtr pPixmap)
BoxPtr pBox = REGION_RECTS(pValidReg);
Bool ret = TRUE;
- if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL)
+ if (!nbox || exaPixmapIsPinned(pPixmap) || pExaPixmap->fb_ptr == NULL)
return ret;
- dst = pExaPixmap->sys_ptr;
dst_pitch = pExaPixmap->sys_pitch;
- src = pExaPixmap->fb_ptr;
src_pitch = pExaPixmap->fb_pitch;
cpp = pPixmap->drawable.bitsPerPixel / 8;
@@ -486,21 +484,18 @@ exaAssertNotDirty (PixmapPtr pPixmap)
continue;
rowbytes = (pBox->x2 - pBox->x1) * cpp;
- src += pBox->y1 * src_pitch + pBox->x1 * cpp;
- dst += pBox->y1 * dst_pitch + pBox->x1 * cpp;
+ src = pExaPixmap->fb_ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
+ dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
- for (y = pBox->y2 - pBox->y1; y; y--) {
- if (memcmp(dst + pBox->y1 * dst_pitch + pBox->x1 * cpp,
- src + pBox->y1 * src_pitch + pBox->x1 * cpp,
- (pBox->x2 - pBox->x1) * cpp) != 0) {
+ for (y = pBox->y1; y < pBox->y2;
+ y++, src += src_pitch, dst += dst_pitch) {
+ if (memcmp(dst, src, rowbytes) != 0) {
ret = FALSE;
+ exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ pBox->y2);
break;
}
- src += src_pitch;
- dst += dst_pitch;
}
- src -= pBox->y1 * src_pitch + pBox->x1 * cpp;
- dst -= pBox->y1 * dst_pitch + pBox->x1 * cpp;
}
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c
index 7708dd7..c666b00 100644
--- a/exa/exa_offscreen.c
+++ b/exa/exa_offscreen.c
@@ -54,7 +54,7 @@ ExaOffscreenValidate (ScreenPtr pScreen)
assert (area->offset >= area->base_offset &&
area->offset < (area->base_offset + area->size));
if (prev)
- assert (prev->base_offset + prev->area.size == area->base_offset);
+ assert (prev->base_offset + prev->size == area->base_offset);
prev = area;
}
assert (prev->base_offset + prev->size == pExaScr->info->memorySize);
@@ -341,13 +341,15 @@ exaEnableDisableFBAccess (int index, Bool enable)
ScreenPtr pScreen = screenInfo.screens[index];
ExaScreenPriv (pScreen);
- if (!enable) {
+ if (!enable && pExaScr->disableFbCount++ == 0) {
if (pExaScr->info->exa_minor < 1)
ExaOffscreenSwapOut (pScreen);
else
ExaOffscreenEjectPixmaps (pScreen);
pExaScr->swappedOut = TRUE;
- } else {
+ }
+
+ if (enable && --pExaScr->disableFbCount == 0) {
if (pExaScr->info->exa_minor < 1)
ExaOffscreenSwapIn (pScreen);
pExaScr->swappedOut = FALSE;
@@ -427,7 +429,7 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap)
ExaScreenPriv (pPixmap->drawable.pScreen);
static int iter = 0;
- if (!pExaPixmap->area)
+ if (!pExaPixmap || !pExaPixmap->area)
return;
/* The numbers here are arbitrary. We may want to tune these. */
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 984cb66..a6d98cd 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -113,6 +113,7 @@ typedef struct {
enum ExaMigrationHeuristic migration;
Bool hideOffscreenPixmapData;
Bool checkDirtyCorrectness;
+ unsigned disableFbCount;
} ExaScreenPrivRec, *ExaScreenPrivPtr;
/*
@@ -287,6 +288,10 @@ exaGetPixmapFirstPixel (PixmapPtr pPixmap);
void
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+Bool
+exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
+ DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
+
void
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
@@ -318,9 +323,6 @@ ExaCheckComposite (CARD8 op,
/* exa_offscreen.c */
void
-ExaOffscreenMarkUsed (PixmapPtr pPixmap);
-
-void
ExaOffscreenSwapOut (ScreenPtr pScreen);
void
@@ -343,7 +345,8 @@ void
exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2);
void
-exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2);
+exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
+ int *xp, int *yp);
Bool
exaDrawableIsOffscreen (DrawablePtr pDrawable);
diff --git a/exa/exa_render.c b/exa/exa_render.c
index b78d728..5e7c67f 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -297,15 +297,15 @@ exaTryDriverSolidFill(PicturePtr pSrc,
nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region);
+
while (nbox--)
{
(*pExaScr->info->Solid) (pDstPix,
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
- exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
pbox++;
}
+
(*pExaScr->info->DoneSolid) (pDstPix);
exaMarkSync(pDst->pDrawable->pScreen);
@@ -446,8 +446,6 @@ exaTryDriverComposite(CARD8 op,
pbox->y1 + dst_off_y,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
- exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 + dst_off_x, pbox->y2 + dst_off_y);
pbox++;
}
(*pExaScr->info->DoneComposite) (pDstPix);
@@ -521,6 +519,9 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op,
CARD16 height)
{
ExaScreenPriv (pDst->pDrawable->pScreen);
+ DrawablePtr pDstDraw = pDst->pDrawable;
+ PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDstDraw);
+ int xoff, yoff;
assert(op == PictOpOver);
@@ -539,6 +540,12 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op,
exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
xDst, yDst, width, height);
+ exaGetDrawableDeltas(pDstDraw, pDstPixmap, &xoff, &yoff);
+ xoff += pDstDraw->x;
+ yoff += pDstDraw->y;
+ exaPixmapDirty(pDstPixmap, xDst + xoff, yDst + yoff, xDst + xoff + width,
+ yDst + yoff + height);
+
/* Then, add in the source value times the destination alpha factors (1.0).
*/
exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
@@ -565,6 +572,28 @@ exaComposite(CARD8 op,
int ret = -1;
Bool saveSrcRepeat = pSrc->repeat;
Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
+ ExaMigrationRec pixmaps[3];
+ int npixmaps = 1;
+ PixmapPtr pSrcPixmap = NULL;
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = exaOpReadsDestination(op);
+ pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
+
+ if (pSrc->pDrawable) {
+ pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable);
+ pixmaps[npixmaps].as_dst = FALSE;
+ pixmaps[npixmaps].as_src = TRUE;
+ pixmaps[npixmaps].pPix = pSrcPixmap;
+ npixmaps++;
+ }
+
+ if (pMask && pMask->pDrawable) {
+ pixmaps[npixmaps].as_dst = FALSE;
+ pixmaps[npixmaps].as_src = TRUE;
+ pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable);
+ npixmaps++;
+ }
/* We currently don't support acceleration of gradients, or other pictures
* with a NULL pDrawable.
@@ -583,19 +612,24 @@ exaComposite(CARD8 op,
if (!pMask)
{
- if (op == PictOpSrc)
+ if ((op == PictOpSrc &&
+ ((pSrc->format == pDst->format) ||
+ (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
+ (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
+ (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
+ pSrc->format == pDst->format &&
+ (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
{
if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 && pSrc->repeat &&
- pSrc->repeatType == RepeatNormal)
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat)
{
ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
width, height);
if (ret == 1)
goto done;
}
- else if (!pSrc->repeat && !pSrc->transform &&
- pSrc->format == pDst->format)
+ else if (pSrcPixmap && !pSrc->repeat && !pSrc->transform)
{
RegionRec region;
@@ -617,6 +651,45 @@ exaComposite(CARD8 op,
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
goto done;
}
+ else if (pSrcPixmap && !pSrc->transform &&
+ pSrc->repeatType == RepeatNormal)
+ {
+ RegionRec region;
+ DDXPointRec srcOrg;
+
+ /* Let's see if the driver can do the repeat in one go */
+ if (pExaScr->info->PrepareComposite && !pSrc->alphaMap &&
+ !pDst->alphaMap)
+ {
+ ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc,
+ ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
+
+ /* Now see if we can use exaFillRegionTiled() */
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+
+ if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, xSrc,
+ ySrc, xMask, yMask, xDst, yDst,
+ width, height))
+ goto done;
+
+ srcOrg.x = (xSrc - xDst) % pSrcPixmap->drawable.width;
+ srcOrg.y = (ySrc - yDst) % pSrcPixmap->drawable.height;
+
+ ret = exaFillRegionTiled(pDst->pDrawable, &region, pSrcPixmap,
+ &srcOrg, FB_ALLONES, GXcopy);
+
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+ if (ret)
+ goto done;
+ }
}
}
@@ -627,8 +700,8 @@ exaComposite(CARD8 op,
pMask->repeat = 0;
if (pExaScr->info->PrepareComposite &&
- (!pSrc->repeat || pSrc->repeat == RepeatNormal) &&
- (!pMask || !pMask->repeat || pMask->repeat == RepeatNormal) &&
+ (!pSrc->repeat || pSrc->repeatType == RepeatNormal) &&
+ (!pMask || !pMask->repeat || pMask->repeatType == RepeatNormal) &&
!pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
{
Bool isSrcSolid;
@@ -660,39 +733,14 @@ exaComposite(CARD8 op,
}
}
- if (ret != 0) {
- ExaMigrationRec pixmaps[3];
- /* failure to accelerate was not due to pixmaps being in the wrong
- * locations.
- */
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = exaOpReadsDestination(op);
- pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable);
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable);
- if (pMask) {
- pixmaps[2].as_dst = FALSE;
- pixmaps[2].as_src = TRUE;
- pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable);
- exaDoMigration(pixmaps, 3, FALSE);
- } else {
- exaDoMigration(pixmaps, 2, FALSE);
- }
- }
-
fallback:
#if DEBUG_TRACE_FALL
exaPrintCompositeFallback (op, pSrc, pMask, pDst);
#endif
+ exaDoMigration(pixmaps, npixmaps, FALSE);
ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc,
xMask, yMask, xDst, yDst, width, height);
- exaDrawableDirty(pDst->pDrawable,
- pDst->pDrawable->x + xDst,
- pDst->pDrawable->y + yDst,
- pDst->pDrawable->x + xDst + width,
- pDst->pDrawable->y + yDst + height);
done:
pSrc->repeat = saveSrcRepeat;
@@ -716,6 +764,7 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap,
{
DrawablePtr pDraw = pPicture->pDrawable;
ExaMigrationRec pixmaps[1];
+ int xoff, yoff;
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE;
@@ -724,8 +773,10 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap,
exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
fbRasterizeTrapezoid(pPicture, trap, x_off, y_off);
- exaDrawableDirty(pDraw, pDraw->x, pDraw->y,
- pDraw->x + pDraw->width, pDraw->y + pDraw->height);
+ exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff);
+ exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff,
+ pDraw->x + xoff + pDraw->width,
+ pDraw->y + yoff + pDraw->height);
exaFinishAccess(pDraw, EXA_PREPARE_DEST);
}
@@ -739,6 +790,7 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri,
{
DrawablePtr pDraw = pPicture->pDrawable;
ExaMigrationRec pixmaps[1];
+ int xoff, yoff;
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE;
@@ -747,8 +799,10 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri,
exaPrepareAccess(pDraw, EXA_PREPARE_DEST);
fbAddTriangles(pPicture, x_off, y_off, ntri, tris);
- exaDrawableDirty(pDraw, pDraw->x, pDraw->y,
- pDraw->x + pDraw->width, pDraw->y + pDraw->height);
+ exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff);
+ exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff,
+ pDraw->x + xoff + pDraw->width,
+ pDraw->y + yoff + pDraw->height);
exaFinishAccess(pDraw, EXA_PREPARE_DEST);
}
@@ -845,10 +899,11 @@ exaGlyphs (CARD8 op,
PixmapPtr pPixmap = NULL;
PicturePtr pPicture;
PixmapPtr pMaskPixmap = NULL;
+ PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDst->pDrawable);
PicturePtr pMask;
ScreenPtr pScreen = pDst->pDrawable->pScreen;
int width = 0, height = 0;
- int x, y;
+ int x, y, x1, y1, xoff, yoff;
int xDst = list->xOff, yDst = list->yOff;
int n;
int error;
@@ -892,7 +947,12 @@ exaGlyphs (CARD8 op,
xRectangle rect;
miGlyphExtents (nlist, list, glyphs, &extents);
-
+
+ extents.x1 = max(extents.x1, 0);
+ extents.y1 = max(extents.y1, 0);
+ extents.x2 = min(extents.x2, pDst->pDrawable->width);
+ extents.y2 = min(extents.y2, pDst->pDrawable->height);
+
if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
return;
width = extents.x2 - extents.x1;
@@ -918,6 +978,7 @@ exaGlyphs (CARD8 op,
rect.width = width;
rect.height = height;
(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
+ exaPixmapDirty(pMaskPixmap, 0, 0, width, height);
FreeScratchGC (pGC);
x = -extents.x1;
y = -extents.y1;
@@ -929,6 +990,8 @@ exaGlyphs (CARD8 op,
y = 0;
}
+ exaGetDrawableDeltas(pDst->pDrawable, pDstPixmap, &xoff, &yoff);
+
while (nlist--)
{
GCPtr pGC = NULL;
@@ -983,13 +1046,21 @@ exaGlyphs (CARD8 op,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = pPixmap;
- exaDoMigration (pixmaps, 1, TRUE);
+ exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL);
while (n--)
{
GlyphPtr glyph = *glyphs++;
pointer glyphdata = (pointer) (glyph + 1);
-
+ DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable;
+
+ x1 = x - glyph->info.x;
+ y1 = y - glyph->info.y;
+
+ if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height ||
+ (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0)
+ goto nextglyph;
+
(*pScreen->ModifyPixmapHeader) (pScratchPixmap,
glyph->info.width,
glyph->info.height,
@@ -1048,17 +1119,22 @@ exaGlyphs (CARD8 op,
if (maskFormat)
{
exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0,
- x - glyph->info.x, y - glyph->info.y,
- glyph->info.width, glyph->info.height);
+ x1, y1, glyph->info.width, glyph->info.height);
+ exaPixmapDirty(pMaskPixmap, x1, y1, x1 + glyph->info.width,
+ y1 + glyph->info.height);
}
else
{
exaComposite (op, pSrc, pPicture, pDst,
- xSrc + (x - glyph->info.x) - xDst,
- ySrc + (y - glyph->info.y) - yDst,
- 0, 0, x - glyph->info.x, y - glyph->info.y,
- glyph->info.width, glyph->info.height);
+ xSrc + x1 - xDst, ySrc + y1 - yDst,
+ 0, 0, x1, y1, glyph->info.width,
+ glyph->info.height);
+ x1 += pDst->pDrawable->x + xoff;
+ y1 += pDst->pDrawable->y + yoff;
+ exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width,
+ y1 + glyph->info.height);
}
+nextglyph:
x += glyph->info.xOff;
y += glyph->info.yOff;
}
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index 7713a08..b67ea63 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -88,10 +88,15 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits)
{
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ int xoff, yoff;
+
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ exaPixmapDirty(pPixmap, x + xoff, y + yoff, x + xoff + w, y + yoff + h);
}
RegionPtr
@@ -201,32 +206,11 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
{
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
- if (nrect) {
- int x1 = max(prect->x, 0), y1 = max(prect->y, 0);
- int x2 = min(prect->x + prect->width, pDrawable->width);
- int y2 = min(prect->y + prect->height, pDrawable->height);
-
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- exaPrepareAccessGC (pGC);
- fbPolyFillRect (pDrawable, pGC, nrect, prect);
- exaFinishAccessGC (pGC);
- exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
-
- /* Only track bounding box of damage, as this path can degenerate to
- * zillions of damage boxes
- */
- while (--nrect)
- {
- prect++;
- x1 = min(x1, prect->x);
- x2 = max(x2, prect->x + prect->width);
- y1 = min(y1, prect->y);
- y2 = max(y2, prect->y + prect->height);
- }
-
- exaDrawableDirty (pDrawable, pDrawable->x + x1, pDrawable->y + y1,
- pDrawable->x + x2, pDrawable->y + y2);
- }
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessGC (pGC);
+ fbPolyFillRect (pDrawable, pGC, nrect, prect);
+ exaFinishAccessGC (pGC);
+ exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
}
void
@@ -385,31 +369,48 @@ ExaCheckComposite (CARD8 op,
/**
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
* that happen to be 1x1. Pixmap must be at least 8bpp.
+ *
+ * XXX This really belongs in fb, so it can be aware of tiling and etc.
*/
CARD32
exaGetPixmapFirstPixel (PixmapPtr pPixmap)
{
CARD32 pixel;
+ void *fb;
+ Bool need_finish = FALSE;
+ BoxRec box;
ExaMigrationRec pixmaps[1];
+ ExaPixmapPriv (pPixmap);
+
+ /* Try to avoid framebuffer readbacks */
+ if (exaPixmapIsOffscreen(pPixmap)) {
+ if (!miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box)) {
+ fb = pExaPixmap->sys_ptr;
+ } else {
+ need_finish = TRUE;
+ fb = pPixmap->devPrivate.ptr;
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
+ exaDoMigration (pixmaps, 1, FALSE);
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+ }
+ }
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPixmap;
- exaDoMigration (pixmaps, 1, FALSE);
-
- exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
switch (pPixmap->drawable.bitsPerPixel) {
case 32:
- pixel = *(CARD32 *)(pPixmap->devPrivate.ptr);
+ pixel = *(CARD32 *)fb;
break;
case 16:
- pixel = *(CARD16 *)(pPixmap->devPrivate.ptr);
+ pixel = *(CARD16 *)fb;
break;
default:
- pixel = *(CARD8 *)(pPixmap->devPrivate.ptr);
+ pixel = *(CARD8 *)fb;
break;
}
- exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+
+ if (need_finish)
+ exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
return pixel;
}