diff -ur ./exa_accel.c /home/airlied/devel/xorg/xserver/exa/exa_accel.c
--- ./exa_accel.c 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_accel.c 2008-03-03 13:41:24.000000000 +1000
@@ -1187,7 +1187,8 @@
int dstY = pBox->y1;
int tileY;
- tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
+ modulus(dstY - pDrawable->y - pPatOrg->y, tileHeight, tileY);
+
while (height > 0) {
int width = pBox->x2 - pBox->x1;
int dstX = pBox->x1;
@@ -1198,7 +1199,8 @@
h = height;
height -= h;
- tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
+ modulus(dstX - pDrawable->x - pPatOrg->x, tileWidth, tileX);
+
while (width > 0) {
int w = tileWidth - tileX;
if (w > width)
@@ -1223,7 +1225,8 @@
}
fallback:
- if (alu != GXcopy || planemask != FB_ALLONES)
+ if (alu != GXcopy || planemask != FB_ALLONES || pPatOrg->x != 0 ||
+ pPatOrg->y != 0)
return FALSE;
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable,
exaDrawableLocation(&pTile->drawable),
diff -ur ./exa.c /home/airlied/devel/xorg/xserver/exa/exa.c
--- ./exa.c 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa.c 2008-03-03 13:41:24.000000000 +1000
@@ -526,6 +526,7 @@
if (ps) {
ps->Composite = pExaScr->SavedComposite;
ps->Glyphs = pExaScr->SavedGlyphs;
+ ps->Trapezoids = pExaScr->SavedTrapezoids;
}
#endif
@@ -684,6 +685,9 @@
pExaScr->SavedGlyphs = ps->Glyphs;
ps->Glyphs = exaGlyphs;
+
+ pExaScr->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = exaTrapezoids;
}
#endif
diff -ur ./exa_migration.c /home/airlied/devel/xorg/xserver/exa/exa_migration.c
--- ./exa_migration.c 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_migration.c 2008-03-03 13:41:24.000000000 +1000
@@ -319,6 +319,10 @@
if (pPixmap->drawable.bitsPerPixel < 8)
return;
+ if (pPixmap->drawable.width > pExaScr->info->maxX ||
+ pPixmap->drawable.height > pExaScr->info->maxY)
+ return;
+
if (pExaPixmap->area == NULL) {
pExaPixmap->area =
exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
diff -ur ./exa_priv.h /home/airlied/devel/xorg/xserver/exa/exa_priv.h
--- ./exa_priv.h 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_priv.h 2008-03-03 13:41:24.000000000 +1000
@@ -108,6 +108,7 @@
RasterizeTrapezoidProcPtr SavedRasterizeTrapezoid;
AddTrianglesProcPtr SavedAddTriangles;
GlyphsProcPtr SavedGlyphs;
+ TrapezoidsProcPtr SavedTrapezoids;
#endif
Bool swappedOut;
enum ExaMigrationHeuristic migration;
@@ -393,6 +394,11 @@
CARD16 height);
void
+exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps);
+
+void
exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap,
int x_off, int y_off);
diff -ur ./exa_render.c /home/airlied/devel/xorg/xserver/exa/exa_render.c
--- ./exa_render.c 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_render.c 2008-03-03 13:41:24.000000000 +1000
@@ -749,6 +749,132 @@
}
#endif
+/**
+ * Same as miCreateAlphaPicture, except it uses ExaCheckPolyFillRect instead
+ * of PolyFillRect to initialize the pixmap after creating it, to prevent
+ * the pixmap from being migrated.
+ *
+ * See the comments about exaTrapezoids.
+ */
+static PicturePtr
+exaCreateAlphaPicture (ScreenPtr pScreen,
+ PicturePtr pDst,
+ PictFormatPtr pPictFormat,
+ CARD16 width,
+ CARD16 height)
+{
+ PixmapPtr pPixmap;
+ PicturePtr pPicture;
+ GCPtr pGC;
+ int error;
+ xRectangle rect;
+
+ if (width > 32767 || height > 32767)
+ return 0;
+
+ if (!pPictFormat)
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+ if (!pPictFormat)
+ return 0;
+ }
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+ pPictFormat->depth);
+ if (!pPixmap)
+ return 0;
+ pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+ if (!pGC)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ return 0;
+ }
+ ValidateGC (&pPixmap->drawable, pGC);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ ExaCheckPolyFillRect (&pPixmap->drawable, pGC, 1, &rect);
+ exaPixmapDirty (pPixmap, 0, 0, width, height);
+ FreeScratchGC (pGC);
+ pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat,
+ 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ return pPicture;
+}
+
+/**
+ * exaTrapezoids is essentially a copy of miTrapezoids that uses
+ * exaCreateAlphaPicture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to RasterizeTrapezoid won't be accelerated however, which
+ * forces the pixmap to be moved out again.
+ *
+ * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect
+ * to initialize the contents.
+ */
+void
+exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ /*
+ * Check for solid alpha add
+ */
+ if (op == PictOpAdd && miIsSolidAlpha (pSrc))
+ {
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+ }
+ else if (maskFormat)
+ {
+ PicturePtr pPicture;
+ BoxRec bounds;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+
+ xDst = traps[0].left.p1.x >> 16;
+ yDst = traps[0].left.p1.y >> 16;
+
+ miTrapezoidBounds (ntrap, traps, &bounds);
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+ pPicture = exaCreateAlphaPicture (pScreen, pDst, maskFormat,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ if (!pPicture)
+ return;
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pPicture, traps,
+ -bounds.x1, -bounds.y1);
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture (op, pSrc, pPicture, pDst,
+ xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ FreePicture (pPicture, 0);
+ }
+ else
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+ for (; ntrap; ntrap--, traps++)
+ exaTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
+ }
+}
+
#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
/**
diff -ur ./exa_unaccel.c /home/airlied/devel/xorg/xserver/exa/exa_unaccel.c
--- ./exa_unaccel.c 2008-03-03 12:55:32.000000000 +1000
+++ xserver/exa/exa_unaccel.c 2008-03-03 13:41:24.000000000 +1000
@@ -382,19 +382,19 @@
ExaMigrationRec pixmaps[1];
ExaPixmapPriv (pPixmap);
+ fb = pExaPixmap->sys_ptr;
+
/* 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);
- }
+ if (exaPixmapIsOffscreen(pPixmap) &&
+ miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box))
+ {
+ need_finish = TRUE;
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
+ exaDoMigration (pixmaps, 1, FALSE);
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+ fb = pPixmap->devPrivate.ptr;
}
switch (pPixmap->drawable.bitsPerPixel) {