summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorFredrik Höglund <fredrik@kde.org>2007-08-15 19:19:11 +0200
committerFredrik Höglund <fredrik@kde.org>2007-08-16 23:49:07 +0200
commitdaee59b1703ac07c2def9e9fecc479e59b93f761 (patch)
tree47794ad31caf34c436e3a596e0acc40d30bf62dc /exa
parentbe536b79f2a364399937314cfa6c88bf8188da9c (diff)
EXA: Wrap Trapezoids to prevent excessive migration of the alpha pixmap.
miTrapezoids creates an alpha pixmap and initializes the contents using PolyFillRect, which causes the pixmap to be moved in for acceleration. The subsequent call to RasterizeTrapezoid won't be accelerated by EXA, which causing the pixmap to be moved back out again. By wrapping Trapezoids and using ExaCheckPolyFillRect instead of PolyFillRect to initialize the pixmap, we avoid this roundtrip.
Diffstat (limited to 'exa')
-rw-r--r--exa/exa.c4
-rw-r--r--exa/exa_priv.h6
-rw-r--r--exa/exa_render.c126
3 files changed, 136 insertions, 0 deletions
diff --git a/exa/exa.c b/exa/exa.c
index 8e22b8927..aa42b9266 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -526,6 +526,7 @@ exaCloseScreen(int i, ScreenPtr pScreen)
if (ps) {
ps->Composite = pExaScr->SavedComposite;
ps->Glyphs = pExaScr->SavedGlyphs;
+ ps->Trapezoids = pExaScr->SavedTrapezoids;
}
#endif
@@ -684,6 +685,9 @@ exaDriverInit (ScreenPtr pScreen,
pExaScr->SavedGlyphs = ps->Glyphs;
ps->Glyphs = exaGlyphs;
+
+ pExaScr->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = exaTrapezoids;
}
#endif
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index a6d98cd2d..bab8aa23b 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -108,6 +108,7 @@ typedef struct {
RasterizeTrapezoidProcPtr SavedRasterizeTrapezoid;
AddTrianglesProcPtr SavedAddTriangles;
GlyphsProcPtr SavedGlyphs;
+ TrapezoidsProcPtr SavedTrapezoids;
#endif
Bool swappedOut;
enum ExaMigrationHeuristic migration;
@@ -393,6 +394,11 @@ exaComposite(CARD8 op,
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 --git a/exa/exa_render.c b/exa/exa_render.c
index 5e7c67feb..2dd3fc1ce 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -749,6 +749,132 @@ done:
}
#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)
/**