summaryrefslogtreecommitdiff
path: root/exa/exa_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'exa/exa_accel.c')
-rw-r--r--exa/exa_accel.c665
1 files changed, 316 insertions, 349 deletions
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index feedd49a2..2acade263 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -55,13 +55,13 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
- exaDoMigration (pixmaps, 1, FALSE);
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
} else {
@@ -74,7 +74,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
pGC->planemask,
pGC->fgPixel))
{
- exaDoMigration (pixmaps, 1, FALSE);
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
}
@@ -140,10 +139,11 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
static Bool
exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
- int w, int h, int leftPad, int format, char *bits, int src_stride)
+ int w, int h, int format, char *bits, int src_stride)
{
ExaScreenPriv (pDrawable->pScreen);
- PixmapPtr pPix;
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv(pPix);
ExaMigrationRec pixmaps[1];
RegionPtr pClip;
BoxPtr pbox;
@@ -152,25 +152,28 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int bpp = pDrawable->bitsPerPixel;
Bool access_prepared = FALSE;
- 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)
- goto migrate_and_fallback;
+ return FALSE;
/* Only accelerate copies: no rop or planemask. */
if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
- goto migrate_and_fallback;
+ return FALSE;
if (pExaScr->swappedOut)
- goto fallback;
+ return FALSE;
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPix;
+ pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
exaDoMigration (pixmaps, 1, TRUE);
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+ if (!pPix || !pExaScr->info->UploadToScreen)
+ return FALSE;
+
x += pDrawable->x;
y += pDrawable->y;
@@ -199,10 +202,8 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
continue;
src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
- ok = (pPix && pExaScr->info->UploadToScreen) ?
- pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
- x2 - x1, y2 - y1, src, src_stride) :
- FALSE;
+ ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
+ x2 - x1, y2 - y1, src, src_stride);
/* If we fail to accelerate the upload, fall back to using unaccelerated
* fb calls.
*/
@@ -213,7 +214,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int dstXoff, dstYoff;
if (!access_prepared) {
- exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
+ ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST);
access_prepared = TRUE;
}
@@ -231,54 +232,118 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
y2 - y1,
GXcopy, FB_ALLONES, dstBpp);
}
-
- if (access_prepared)
- exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
-
- exaPixmapDirty(pixmaps[0].pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff);
}
- return TRUE;
-
-migrate_and_fallback:
- exaDoMigration (pixmaps, 1, FALSE);
+ if (access_prepared)
+ exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
+ else
+ exaMarkSync(pDrawable->pScreen);
-fallback:
- return FALSE;
+ return TRUE;
}
-static void
-exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
- int w, int h, int leftPad, int format, char *bits)
+#ifdef MITSHM
+
+static Bool
+exaDoShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ unsigned int format, int w, int h, int sx, int sy, int sw,
+ int sh, int dx, int dy, char *data)
{
- if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits,
- PixmapBytePad(w, pDrawable->depth)))
- ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
- bits);
-}
+ int src_stride = PixmapBytePad(w, depth);
-#ifdef MITSHM
+ if (exaDoPutImage(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
+ sy * src_stride + sx * BitsPerPixel(depth) / 8,
+ src_stride))
+ return TRUE;
-static void
+ if (format == ZPixmap)
+ {
+ PixmapPtr pPixmap;
+
+ pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
+ BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
+ if (!pPixmap)
+ return FALSE;
+
+ if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
+ pGC->alu))
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ else
+ ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
+ exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
+
+ FreeScratchPixmapHeader(pPixmap);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
+ * inform any interested parties of the damage incurred to the drawable.
+ *
+ * We also need to set the pending damage to ensure correct migration in all
+ * cases.
+ */
+void
exaShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
char *data)
{
- int src_stride = PixmapBytePad(w, depth);
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaPixmapPriv(pPixmap);
+ BoxRec box = { .x1 = pDrawable->x + dx, .y1 = pDrawable->y + dy,
+ .x2 = pDrawable->x + dx + sw, .y2 = pDrawable->y + dy + sh };
+ RegionRec region;
+ int xoff, yoff;
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
- if (exaDoPutImage(pDrawable, pGC, depth, dx, dy, sw, sh, 0, format, data +
- sy * src_stride + sx * BitsPerPixel(depth) / 8,
- src_stride))
- return;
+ REGION_INIT(pScreen, &region, &box, 1);
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+
+ REGION_TRANSLATE(pScreen, &region, xoff, yoff);
+ REGION_UNION(pScreen, pending_damage, pending_damage, &region);
+
+ if (!exaDoShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
+ dx, dy, data)) {
+ if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
+ pGC->alu))
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ else
+ ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
+ data);
+ exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
+ }
+
+ REGION_TRANSLATE(pScreen, &region, -xoff, -yoff);
+ DamageDamageRegion(pDrawable, &region);
- fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
- data);
+ REGION_UNINIT(pScreen, &region);
}
ShmFuncs exaShmFuncs = { NULL, exaShmPutImage };
#endif
+static void
+exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+#ifdef MITSHM
+ if (!exaDoShmPutImage(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y,
+ bits))
+#else
+ if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits,
+ PixmapBytePad(w, pDrawable->depth)))
+#endif
+ ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+}
+
static Bool inline
exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
@@ -393,8 +458,6 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
dst_off_y + pbox->y1 + i,
pbox->x2 - pbox->x1, 1);
}
- exaPixmapDirty(pDstPixmap, dst_off_x + pbox->x1, dst_off_y + pbox->y1,
- dst_off_x + pbox->x2, dst_off_y + pbox->y2);
}
if (dirsetup != 0)
pExaScr->info->DoneCopy(pDstPixmap);
@@ -420,14 +483,49 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
ExaMigrationRec pixmaps[2];
- Bool fallback = FALSE;
+ RegionPtr region = NULL;
+
+ 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 (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask,
+ pGC->fillStyle, pGC->alu)) {
+ xRectangle *rects = ALLOCATE_LOCAL(nbox * sizeof(xRectangle));
+
+ if (rects) {
+ int i;
+
+ for (i = 0; i < nbox; i++) {
+ rects[i].x = pbox[i].x1 + dst_off_x;
+ rects[i].y = pbox[i].y1 + dst_off_y;
+ rects[i].width = pbox[i].x2 - pbox[i].x1;
+ rects[i].height = pbox[i].y2 - pbox[i].y1;
+ }
+
+ region = RECTS_TO_REGION(pScreen, nbox, rects, CT_YXBANDED);
+ DEALLOCATE_LOCAL(rects);
+
+ if (region) {
+ src_off_x -= dst_off_x;
+ src_off_y -= dst_off_y;
+ dst_off_x = dst_off_y = 0;
+ pbox = REGION_RECTS(region);
+ nbox = REGION_NUM_RECTS(region);
+ }
+ }
+ }
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
+ pixmaps[0].pPix = pDstPixmap;
+ pixmaps[0].pReg = region;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
+ pixmaps[1].pPix = pSrcPixmap;
+ pixmaps[1].pReg = NULL;
/* Respect maxX/maxY in a trivial way: don't set up drawing when we might
* violate the limits. The proper solution would be a temporary pixmap
@@ -438,64 +536,60 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
pDstPixmap->drawable.width > pExaScr->info->maxX ||
pDstPixmap->drawable.height > pExaScr->info->maxY)
{
- fallback = TRUE;
+ goto fallback;
} else {
exaDoMigration (pixmaps, 2, TRUE);
}
/* Mixed directions must be handled specially if the card is lame */
- if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
+ if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
reverse != upsidedown) {
if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
dx, dy))
- return;
- fallback = TRUE;
+ goto out;
+ goto fallback;
}
- 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) ||
+ if (!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);
+ goto fallback;
}
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);
+ (*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);
pbox++;
}
- if (fallback)
- return;
-
(*pExaScr->info->DoneCopy) (pDstPixmap);
exaMarkSync (pDstDrawable->pScreen);
+
+ goto out;
+
+fallback:
+ EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
+ exaDrawableLocation(pSrcDrawable),
+ exaDrawableLocation(pDstDrawable)));
+ exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, region);
+ 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);
+
+out:
+ if (region) {
+ REGION_UNINIT(pScreen, region);
+ REGION_DESTROY(pScreen, region);
+ }
}
RegionPtr
@@ -688,7 +782,8 @@ exaPolyFillRect(DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
-
+ pixmaps[0].pReg = NULL;
+
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
if (pExaScr->swappedOut ||
@@ -731,15 +826,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
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);
goto out;
}
@@ -818,101 +904,11 @@ fallback:
exaMarkSync(pDrawable->pScreen);
out:
+ REGION_UNINIT(pScreen, pReg);
REGION_DESTROY(pScreen, pReg);
}
static void
-exaSolidBoxClipped (DrawablePtr pDrawable,
- RegionPtr pClip,
- FbBits pm,
- FbBits fg,
- int x1,
- int y1,
- int x2,
- int y2)
-{
- ExaScreenPriv (pDrawable->pScreen);
- PixmapPtr pPixmap;
- BoxPtr pbox;
- int nbox;
- int xoff, yoff;
- int partX1, partX2, partY1, partY2;
- ExaMigrationRec pixmaps[1];
- Bool fallback = FALSE;
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
-
- if (pExaScr->swappedOut ||
- pPixmap->drawable.width > pExaScr->info->maxX ||
- pPixmap->drawable.height > pExaScr->info->maxY)
- {
- fallback = TRUE;
- } else {
- exaDoMigration (pixmaps, 1, TRUE);
- }
-
- exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff);
-
- if (fallback || !exaPixmapIsOffscreen(pPixmap) ||
- !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
- {
- 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);
- fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
- fbAnd (GXcopy, fg, pm),
- fbXor (GXcopy, fg, pm));
- exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- }
- for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
- nbox--;
- pbox++)
- {
- partX1 = pbox->x1;
- if (partX1 < x1)
- partX1 = x1;
-
- partX2 = pbox->x2;
- if (partX2 > x2)
- partX2 = x2;
-
- if (partX2 <= partX1)
- continue;
-
- partY1 = pbox->y1;
- if (partY1 < y1)
- partY1 = y1;
-
- partY2 = pbox->y2;
- if (partY2 > y2)
- partY2 = y2;
-
- if (partY2 <= partY1)
- continue;
-
- if (!fallback) {
- (*pExaScr->info->Solid) (pPixmap,
- partX1 + xoff, partY1 + yoff,
- partX2 + xoff, partY2 + yoff);
- }
-
- exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff,
- partY2 + yoff);
- }
-
- if (fallback)
- return;
-
- (*pExaScr->info->DoneSolid) (pPixmap);
- exaMarkSync(pDrawable->pScreen);
-}
-
-static void
exaImageGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x,
@@ -928,7 +924,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
int gWidth, gHeight; /* width and height of glyph */
FbStride gStride; /* stride of glyph */
Bool opaque;
- int n;
int gx, gy;
void (*glyph) (FbBits *,
FbStride,
@@ -942,37 +937,33 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
int dstBpp;
int dstXoff, dstYoff;
FbBits depthMask;
+ Bool fallback;
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaPixmapPriv(pPixmap);
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);
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
+ BoxRec extents = *REGION_EXTENTS(pScreen, pending_damage);
+ int xoff, yoff;
- if (xBack >= pDrawable->width || yBack >= pDrawable->height ||
- (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0)
+ if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
return;
+ depthMask = FbFullMask(pDrawable->depth);
+ fallback = (pGC->planemask & depthMask) != depthMask;
+
pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = TRUE;
+ pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = fallback ? NULL : pending_damage;
- depthMask = FbFullMask(pDrawable->depth);
- if ((pGC->planemask & depthMask) != depthMask)
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ if (fallback)
{
- exaDoMigration(pixmaps, 1, FALSE);
ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
- goto damage;
+ return;
}
+
glyph = NULL;
switch (pDrawable->bitsPerPixel) {
case 8: glyph = fbGlyph8; break;
@@ -983,8 +974,14 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
x += pDrawable->x;
y += pDrawable->y;
- xBack += pDrawable->x;
- yBack += pDrawable->y;
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ extents.x1 -= xoff;
+ extents.x2 -= xoff;
+ extents.y1 -= yoff;
+ extents.y2 -= yoff;
+
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
if (TERMINALFONT (pGC->font) && !glyph)
{
@@ -992,20 +989,22 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
}
else
{
- exaSolidBoxClipped (pDrawable,
- fbGetCompositeClip(pGC),
- pGC->planemask,
- pGC->bgPixel,
- xBack,
- yBack,
- xBack + widthBack,
- yBack + heightBack);
+ FbBits fg = fbReplicatePixel (pGC->bgPixel, pDrawable->bitsPerPixel);
+
+ fbSolidBoxClipped (pDrawable,
+ fbGetCompositeClip(pGC),
+ extents.x1,
+ extents.y1,
+ extents.x2,
+ extents.y2,
+ fbAnd (GXcopy, fg, pGC->planemask),
+ fbXor (GXcopy, fg, pGC->planemask));
+
opaque = FALSE;
}
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);
@@ -1018,9 +1017,9 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
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))
+ if (!gWidth || !gHeight || (gx + gWidth) <= extents.x1 ||
+ (gy + gHeight) <= extents.y1 || gx >= extents.x2 ||
+ gy >= extents.y2)
continue;
pglyph = FONTGLYPHBITS(pglyphBase, pci);
@@ -1043,11 +1042,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable,
}
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 = {
@@ -1111,13 +1105,16 @@ exaFillRegionSolid (DrawablePtr pDrawable,
PixmapPtr pPixmap;
int xoff, yoff;
ExaMigrationRec pixmaps[1];
- int nbox = REGION_NUM_RECTS (pRegion);
- BoxPtr pBox = REGION_RECTS (pRegion);
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
-
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
+ alu) ? NULL : pRegion;
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY)
{
@@ -1129,29 +1126,56 @@ exaFillRegionSolid (DrawablePtr pDrawable,
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
(*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
{
+ int nbox;
+ BoxPtr pBox;
+
+ nbox = REGION_NUM_RECTS (pRegion);
+ pBox = REGION_RECTS (pRegion);
+
while (nbox--)
{
- (*pExaScr->info->Solid) (pPixmap,
- pBox->x1 + xoff, pBox->y1 + yoff,
- pBox->x2 + xoff, pBox->y2 + yoff);
+ (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ pBox->y2);
pBox++;
}
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
+
+ if (pDrawable->width == 1 && pDrawable->height == 1 &&
+ pDrawable->bitsPerPixel != 24) {
+ ExaPixmapPriv(pPixmap);
+
+ switch (pDrawable->bitsPerPixel) {
+ case 32:
+ *(CARD32*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 16:
+ *(CARD16*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 8:
+ *(CARD8*)pExaPixmap->sys_ptr = pixel;
+ }
+
+ REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
+ pRegion);
+ }
+
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+ return TRUE;
}
- 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);
+ if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) {
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+ return FALSE;
}
+ EXA_FALLBACK(("to %p (%c)\n", pDrawable,
+ exaDrawableLocation(pDrawable)));
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+ fbFillRegionSolid (pDrawable, pRegion, 0,
+ fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
+ exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
return TRUE;
}
@@ -1189,9 +1213,15 @@ exaFillRegionTiled (DrawablePtr pDrawable,
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
+ alu) ? NULL : pRegion;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pPixmap->drawable.width > pExaScr->info->maxX ||
pPixmap->drawable.height > pExaScr->info->maxY ||
@@ -1221,7 +1251,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
int dstY = pBox->y1;
int tileY;
- tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight;
+ tileY = (dstY - yoff - pDrawable->y - pPatOrg->y) % tileHeight;
while (height > 0) {
int width = pBox->x2 - pBox->x1;
int dstX = pBox->x1;
@@ -1232,7 +1262,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
h = height;
height -= h;
- tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth;
+ tileX = (dstX - xoff - pDrawable->x - pPatOrg->x) % tileWidth;
while (width > 0) {
int w = tileWidth - tileX;
if (w > width)
@@ -1241,8 +1271,7 @@ exaFillRegionTiled (DrawablePtr pDrawable,
(*pExaScr->info->Copy) (pPixmap,
tileX + tileXoff, tileY + tileYoff,
- dstX + xoff, dstY + yoff,
- w, h);
+ dstX, dstY, w, h);
dstX += w;
tileX = 0;
}
@@ -1253,17 +1282,20 @@ exaFillRegionTiled (DrawablePtr pDrawable,
}
(*pExaScr->info->DoneCopy) (pPixmap);
exaMarkSync(pDrawable->pScreen);
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
return TRUE;
}
fallback:
- if (alu != GXcopy || planemask != FB_ALLONES)
+ if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) {
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
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);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg);
+ REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
fbFillRegionTiled (pDrawable, pRegion, pTile);
exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
@@ -1272,77 +1304,13 @@ fallback:
return TRUE;
}
-void
-exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
-{
- ExaScreenPriv (pWin->drawable.pScreen);
- 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) {
- case None:
- return;
- case ParentRelative:
- do {
- pWin = pWin->parent;
- } while (pWin->backgroundState == ParentRelative);
- (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
- what);
- return;
- case BackgroundPixel:
- exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel,
- FB_ALLONES, GXcopy);
- goto damage;
- case BackgroundPixmap:
- 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,
- FB_ALLONES, GXcopy);
- goto damage;
- } else {
- 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++;
- }
-}
/**
* Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
*
* This is probably the only case we actually care about. The rest fall through
- * to migration and ExaCheckGetImage, which hopefully will result in migration
- * pushing the pixmap out of framebuffer.
+ * to migration and fbGetImage, which hopefully will result in migration pushing
+ * the pixmap out of framebuffer.
*/
void
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
@@ -1350,63 +1318,62 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
{
ExaScreenPriv (pDrawable->pScreen);
ExaMigrationRec pixmaps[1];
+ BoxRec Box;
+ RegionRec Reg;
PixmapPtr pPix;
int xoff, yoff;
Bool ok;
- if (pExaScr->swappedOut || (w == 1 && h == 1))
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable);
+ pixmaps[0].pReg = &Reg;
+
+ exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);
+
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
+
+ REGION_INIT(pScreen, &Reg, &Box, 1);
+
+ if (pExaScr->swappedOut)
goto fallback;
- if (pExaScr->info->DownloadFromScreen == NULL)
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+
+ if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
goto fallback;
/* Only cover the ZPixmap, solid copy case. */
if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
- goto migrate_and_fallback;
+ goto fallback;
/* Only try to handle the 8bpp and up cases, since we don't want to think
* about <8bpp.
*/
if (pDrawable->bitsPerPixel < 8)
- goto migrate_and_fallback;
-
- pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (pPix == NULL)
goto fallback;
- xoff += pDrawable->x;
- yoff += pDrawable->y;
-
- ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d,
+ ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+ pDrawable->y + y + yoff, w, h, d,
PixmapBytePad(w, pDrawable->depth));
if (ok) {
exaWaitSync(pDrawable->pScreen);
- return;
+ goto out;
}
-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);
-}
-
-/**
- * GetSpans isn't accelerated yet, but performs migration so that we'll
- * hopefully avoid the read-from-framebuffer cost.
- */
-void
-exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth,
- int nspans, char *pdstStart)
-{
- ExaMigrationRec pixmaps[1];
+ EXA_FALLBACK(("from %p (%c)\n", pDrawable,
+ exaDrawableLocation(pDrawable)));
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
- exaDoMigration (pixmaps, 1, FALSE);
+ exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg);
+ fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
+ exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
- ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+out:
+ REGION_UNINIT(pScreen, &Reg);
}