summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-08-23 18:19:17 -0700
committerIan Romanick <idr@us.ibm.com>2007-08-23 18:19:17 -0700
commit8b6b40b7271acd81a9548f502c18f46f3b640640 (patch)
tree1462cb63501a8bdd8845d7c62e038b6a86b78fd5 /exa
parentab7a6d860d4a275a810a64b1ba7b13726ed10575 (diff)
parent3305d17195e3a0a5555300555bd7703312fa489f (diff)
Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/xserver into pci-reworkpci-rework
Conflicts: hw/xfree86/common/xf86.h hw/xfree86/common/xf86Init.c hw/xfree86/common/xf86pciBus.c hw/xfree86/int10/generic.c hw/xfree86/int10/helper_exec.c hw/xfree86/loader/xf86sym.c hw/xfree86/os-support/bus/Pci.c hw/xfree86/os-support/bus/Pci.h hw/xfree86/os-support/bus/linuxPci.c hw/xfree86/os-support/linux/int10/linux.c
Diffstat (limited to 'exa')
-rw-r--r--exa/exa.c45
-rw-r--r--exa/exa_accel.c27
-rw-r--r--exa/exa_offscreen.c2
-rw-r--r--exa/exa_priv.h6
-rw-r--r--exa/exa_render.c126
-rw-r--r--exa/exa_unaccel.c35
6 files changed, 212 insertions, 29 deletions
diff --git a/exa/exa.c b/exa/exa.c
index c5b5a666a..b2faf2f1c 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -253,7 +253,7 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
pExaScr->info->pixmapPitchAlign);
pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
- if (pExaPixmap->fb_pitch > 32767) {
+ if (pExaPixmap->fb_pitch > 131071) {
fbDestroyPixmap(pPixmap);
return NULL;
}
@@ -526,6 +526,7 @@ exaCloseScreen(int i, ScreenPtr pScreen)
if (ps) {
ps->Composite = pExaScr->SavedComposite;
ps->Glyphs = pExaScr->SavedGlyphs;
+ ps->Trapezoids = pExaScr->SavedTrapezoids;
}
#endif
@@ -569,6 +570,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)
{
@@ -645,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_accel.c b/exa/exa_accel.c
index bf63f2c4f..cc383cca4 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -643,15 +643,13 @@ exaPolyFillRect(DrawablePtr pDrawable,
int n;
ExaMigrationRec pixmaps[2];
RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
- RegionPtr pDamageReg = DamageRegion(ExaGetPixmapPriv(pPixmap)->pDamage);
/* 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)) {
- REGION_DESTROY(pScreen, pReg);
- return;
+ goto out;
}
pixmaps[0].as_dst = TRUE;
@@ -680,7 +678,7 @@ exaPolyFillRect(DrawablePtr pDrawable,
(pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
pGC->planemask, pGC->alu))) {
- goto damage;
+ goto out;
}
}
@@ -709,13 +707,7 @@ fallback:
}
ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
-
-damage:
- REGION_TRANSLATE(pScreen, pReg, xoff, yoff);
- REGION_UNION(pScreen, pDamageReg, pReg, pDamageReg);
- REGION_DESTROY(pScreen, pReg);
-
- return;
+ goto out;
}
xorg = pDrawable->x;
@@ -754,8 +746,6 @@ damage:
(*pExaScr->info->Solid) (pPixmap,
fullX1 + xoff, fullY1 + yoff,
fullX2 + xoff, fullY2 + yoff);
- exaPixmapDirty (pPixmap, fullX1 + xoff, fullY1 + yoff,
- fullX2 + xoff, fullY2 + yoff);
}
else
{
@@ -786,14 +776,15 @@ damage:
(*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
@@ -1329,6 +1320,9 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
int xoff, yoff;
Bool ok;
+ if (pExaScr->swappedOut || (w == 1 && h == 1))
+ goto fallback;
+
if (pExaScr->info->DownloadFromScreen == NULL)
goto migrate_and_fallback;
@@ -1342,9 +1336,6 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
if (pDrawable->bitsPerPixel < 8)
goto migrate_and_fallback;
- if (pExaScr->swappedOut)
- goto fallback;
-
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
if (pPix == NULL)
goto fallback;
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c
index 6fe646a88..c666b001b 100644
--- a/exa/exa_offscreen.c
+++ b/exa/exa_offscreen.c
@@ -429,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 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)
/**
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index 708d1eac6..a94648b47 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -369,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);
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPixmap;
- exaDoMigration (pixmaps, 1, FALSE);
+ fb = pExaPixmap->sys_ptr;
+
+ /* Try to avoid framebuffer readbacks */
+ 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;
+ }
- 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;
}