diff options
author | Eric Anholt <anholt@freebsd.org> | 2006-03-29 22:25:17 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2006-03-29 22:25:17 +0000 |
commit | e799dd68e2bd0fa8ac3c344111fb12e1f32d4c10 (patch) | |
tree | cb5ecf1f28b376fabe832e44cd4e763c6d65d443 /exa | |
parent | 4bb5ab0b4453208573b91b334940f190a8f7210a (diff) |
Bug #2986: Add acceleration of GetImage using DownloadFromScreen for the
ZPixmap, planeMask ~= FB_ALLONES, bitsPerPixel >= 8 case. I'm pretty
convinced that this is the only case that we care about at all. Tested
with xwd -root and xwd on a gnome-terminal, in a composited environment
or not.
Diffstat (limited to 'exa')
-rw-r--r-- | exa/exa_accel.c | 47 | ||||
-rw-r--r-- | exa/exa_priv.h | 8 |
2 files changed, 53 insertions, 2 deletions
diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 7770ef152..6ab3a3cc4 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -947,15 +947,58 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) } /** - * GetImage isn't accelerated yet, but performs migration so that we'll - * hopefully avoid the read-from-framebuffer cost. + * 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. */ void exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { + ExaScreenPriv (pDrawable->pScreen); ExaMigrationRec pixmaps[1]; + PixmapPtr pPix; + int xoff, yoff; + Bool ok; + + if (pExaScr->swappedOut || pExaScr->info->DownloadFromScreen == NULL) + goto fallback; + + /* Only cover the ZPixmap, solid copy case. */ + if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) + 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 fallback; + /* Migrate, but assume that we could accelerate the download. It is up to + * the migration scheme to ensure that this case doesn't result in bad + * moving of pixmaps. + */ + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + exaDoMigration (pixmaps, 1, TRUE); + 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, + PixmapBytePad(pDrawable, w)); + if (ok) { + exaWaitSync(pDrawable->pScreen); + return; + } + +fallback: pixmaps[0].as_dst = FALSE; pixmaps[0].as_src = TRUE; pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); diff --git a/exa/exa_priv.h b/exa/exa_priv.h index c52ee8c44..8a1b27710 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -129,6 +129,14 @@ extern int exaPixmapPrivateIndex; /** Align an offset to a power-of-two alignment */ #define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1)) +/** + * Returns TRUE if the given planemask covers all the significant bits in the + * pixel values for pDrawable. + */ +#define EXA_PM_IS_SOLID(_pDrawable, _pm) \ + (((_pm) & ((1 << (_pDrawable)->bitsPerPixel) - 1)) == \ + ((1 << (_pDrawable)->bitsPerPixel) - 1)) + #define EXA_PIXMAP_SCORE_MOVE_IN 10 #define EXA_PIXMAP_SCORE_MAX 20 #define EXA_PIXMAP_SCORE_MOVE_OUT -10 |