From be922b30486abce3a8c13996d579b211a7b56f0e Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 30 Aug 2007 13:59:07 +0200 Subject: EXA: exa(Shm)PutImage improvements. Improve exaShmPutImage performance and reuse its core in exaPutImage as it seems faster than the previous code when the driver doesn't provide an UploadToScreen hook. Make sure all damage records are notified of the damage incurred by actual ShmPutImage calls. Remove superfluous manual damage tracking for actual PutImage calls. --- exa/exa_accel.c | 138 +++++++++++++++++++++++++++++++++++++++--------------- exa/exa_priv.h | 10 ++++ exa/exa_unaccel.c | 10 ++-- 3 files changed, 116 insertions(+), 42 deletions(-) (limited to 'exa') diff --git a/exa/exa_accel.c b/exa/exa_accel.c index df6a62d68..136fca22d 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -139,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; @@ -151,26 +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); - pixmaps[0].pReg = NULL; - /* Don't bother with under 8bpp, XYPixmaps. */ if (format != ZPixmap || bpp < 8) - goto fallback; + return FALSE; /* Only accelerate copies: no rop or planemask. */ if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) - goto 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. */ @@ -231,8 +232,6 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, y2 - y1, GXcopy, FB_ALLONES, dstBpp); } - - exaPixmapDirty(pixmaps[0].pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } if (access_prepared) @@ -241,45 +240,110 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, exaMarkSync(pDrawable->pScreen); return TRUE; - -fallback: - return FALSE; } -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; + + 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. + */ static 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, ®ion, &box, 1); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, - data); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + + REGION_TRANSLATE(pScreen, ®ion, xoff, yoff); + REGION_UNION(pScreen, pending_damage, pending_damage, ®ion); + + 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, ®ion, -xoff, -yoff); + DamageDamageRegion(pDrawable, ®ion); + + REGION_UNINIT(pScreen, ®ion); } 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) diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 8e51f5d72..a6ac92106 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -279,6 +279,16 @@ CARD32 exaGetPixmapFirstPixel (PixmapPtr pPixmap); /* exa_accel.c */ + +static _X_INLINE Bool +exaGCReadsDestination(DrawablePtr pDrawable, unsigned long planemask, + unsigned int fillStyle, unsigned char alu) +{ + return ((alu != GXcopy && alu != GXclear &&alu != GXset && + alu != GXcopyInverted) || fillStyle == FillStippled || + !EXA_PM_IS_SOLID(pDrawable, planemask)); +} + void exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index 8fb7b526e..f4d453eaa 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -97,14 +97,14 @@ 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); + if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, + pGC->alu)) + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + else + ExaDoPrepareAccess (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); } RegionPtr -- cgit v1.2.3