5d4276c96a
- 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
1614 lines
50 KiB
Diff
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, ®ion);
|
|
}
|
|
|
|
-/**
|
|
- * 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(®ion);
|
|
pbox = REGION_RECTS(®ion);
|
|
+
|
|
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, ®ion);
|
|
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 (®ion, 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, ®ion, pSrcPixmap,
|
|
+ &srcOrg, FB_ALLONES, GXcopy);
|
|
+
|
|
+ REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
|
|
+
|
|
+ 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;
|
|
}
|