summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2006-03-29 22:25:17 +0000
committerEric Anholt <anholt@freebsd.org>2006-03-29 22:25:17 +0000
commite799dd68e2bd0fa8ac3c344111fb12e1f32d4c10 (patch)
treecb5ecf1f28b376fabe832e44cd4e763c6d65d443 /exa
parent4bb5ab0b4453208573b91b334940f190a8f7210a (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.c47
-rw-r--r--exa/exa_priv.h8
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