summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Maathuis <madman2003@gmail.com>2009-08-01 19:19:19 +0200
committerMaarten Maathuis <madman2003@gmail.com>2009-08-06 23:48:14 +0200
commit03ecb164f2592c954aa408bf121e0c67b604d854 (patch)
tree98acdd425239b9c8723cea9c537eebca70af8cba
parentac7ac913fd98ea359c05c89968ab53a3223615b4 (diff)
exa: A simple 3rd backend implementation.
- Based on driver pixmaps with some changes (completely transparent to driver). - It helps with the problem of known software fallbacks, such as trapezoids. - exaDoMigration is now called for all cases that provide a do_migration hook. - exa_migration.c is renamed to exa_migration_classic.c
-rw-r--r--exa/Makefile.am4
-rw-r--r--exa/exa.c42
-rw-r--r--exa/exa.h7
-rw-r--r--exa/exa_accel.c34
-rw-r--r--exa/exa_glyphs.c4
-rw-r--r--exa/exa_migration_classic.c (renamed from exa/exa_migration.c)18
-rw-r--r--exa/exa_migration_mixed.c136
-rw-r--r--exa/exa_mixed.c229
-rw-r--r--exa/exa_priv.h27
-rw-r--r--exa/exa_render.c17
10 files changed, 460 insertions, 58 deletions
diff --git a/exa/Makefile.am b/exa/Makefile.am
index bf2c138d8..8b759cd76 100644
--- a/exa/Makefile.am
+++ b/exa/Makefile.am
@@ -18,8 +18,10 @@ libexa_la_SOURCES = \
exa.c \
exa.h \
exa_classic.c \
- exa_migration.c \
+ exa_migration_classic.c \
exa_driver.c \
+ exa_mixed.c \
+ exa_migration_mixed.c \
exa_accel.c \
exa_glyphs.c \
exa_offscreen.c \
diff --git a/exa/exa.c b/exa/exa.c
index 0f3716894..fd9ba9001 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -217,6 +217,22 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
}
/**
+ * Returns TRUE if the pixmap is not movable. This is the case where it's a
+ * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
+ * some X Server internal component (the score says it's pinned).
+ */
+Bool
+exaPixmapIsPinned (PixmapPtr pPix)
+{
+ ExaPixmapPriv (pPix);
+
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
+
+ return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
+}
+
+/**
* exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
@@ -237,7 +253,7 @@ exaPixmapIsOffscreen(PixmapPtr pPixmap)
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
return FALSE;
- return pExaScr->pixmap_is_offscreen(pPixmap);
+ return (*pExaScr->pixmap_is_offscreen)(pPixmap);
}
/**
@@ -348,9 +364,9 @@ void
exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
{
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPriv(pPixmap);
+ ExaScreenPriv(pPixmap->drawable.pScreen);
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
@@ -1037,11 +1053,19 @@ exaDriverInit (ScreenPtr pScreen,
return FALSE;
}
if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) {
- wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
- wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
- wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver);
- pExaScr->do_migration = NULL;
- pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver;
+ if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_mixed);
+ pExaScr->do_migration = exaDoMigration_mixed;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed;
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver);
+ pExaScr->do_migration = NULL;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver;
+ }
} else {
wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
@@ -1162,5 +1186,5 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
return;
if (pExaScr->do_migration)
- pExaScr->do_migration(pixmaps, npixmaps, can_accel);
+ (*pExaScr->do_migration)(pixmaps, npixmaps, can_accel);
}
diff --git a/exa/exa.h b/exa/exa.h
index 1d2c6a9e6..40ac1ddba 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -758,6 +758,13 @@ typedef struct _ExaDriver {
*/
#define EXA_SUPPORTS_OFFSCREEN_OVERLAPS (1 << 5)
+/**
+ * EXA_MIXED_PIXMAPS will hide unacceleratable pixmaps from drivers and manage the
+ * problem known software fallbacks like trapezoids. This only migrates pixmaps one way
+ * into a driver pixmap and then pins it.
+ */
+#define EXA_MIXED_PIXMAPS (1 << 6)
+
/** @} */
/* in exa.c */
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index bc970bbe1..33fbb9843 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -57,7 +57,9 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
{
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
- } else if (pExaPixmap->pDamage) {
+ }
+
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE;
@@ -165,10 +167,10 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (pExaScr->swappedOut)
return FALSE;
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPix;
pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
@@ -455,7 +457,7 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- if (pDstExaPixmap->pDamage || pSrcExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[2];
pixmaps[0].as_dst = TRUE;
@@ -466,6 +468,7 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable,
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pSrcPixmap;
pixmaps[1].pReg = srcregion;
+
exaDoMigration (pixmaps, 2, TRUE);
}
@@ -809,7 +812,7 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto fallback;
}
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE;
@@ -982,17 +985,16 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pExaPixmap->accel_blocked)
- {
goto out;
- } else if (pExaPixmap->pDamage) {
+
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
- alu, clientClipType)
- ? NULL : pRegion;
+ alu, clientClipType) ? NULL : pRegion;
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -1078,17 +1080,16 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
pExaPixmap = ExaGetPixmapPriv (pPixmap);
if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
- {
return FALSE;
- } else if (pExaPixmap->pDamage || pTileExaPixmap->pDamage) {
+
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[2];
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPixmap;
pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
- alu, clientClipType)
- ? NULL : pRegion;
+ alu, clientClipType) ? NULL : pRegion;
pixmaps[1].as_dst = FALSE;
pixmaps[1].as_src = TRUE;
pixmaps[1].pPix = pTile;
@@ -1233,20 +1234,19 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
{
ExaScreenPriv (pDrawable->pScreen);
PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv (pPix);
int xoff, yoff;
Bool ok;
if (pExaScr->swappedOut)
goto fallback;
- if (pExaPixmap->pDamage) {
+ exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);
+
+ if (pExaScr->do_migration) {
BoxRec Box;
RegionRec Reg;
ExaMigrationRec pixmaps[1];
- exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);
-
Box.x1 = pDrawable->y + x + xoff;
Box.y1 = pDrawable->y + y + yoff;
Box.x2 = Box.x1 + w;
diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
index 1855de1b1..d621ccf76 100644
--- a/exa/exa_glyphs.c
+++ b/exa/exa_glyphs.c
@@ -385,10 +385,10 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
goto composite;
- /* cache pixmap must be offscreen. */
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
+ /* cache pixmap must be offscreen. */
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pCachePixmap;
diff --git a/exa/exa_migration.c b/exa/exa_migration_classic.c
index afab9d2f4..83559593f 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration_classic.c
@@ -42,22 +42,6 @@
#endif
/**
- * Returns TRUE if the pixmap is not movable. This is the case where it's a
- * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
- * some X Server internal component (the score says it's pinned).
- */
-static Bool
-exaPixmapIsPinned (PixmapPtr pPix)
-{
- ExaPixmapPriv (pPix);
-
- if (pExaPixmap == NULL)
- EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
-
- return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
-}
-
-/**
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
* and exaCopyDirtyToFb both needed to do this loop.
*/
@@ -77,7 +61,7 @@ exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
dst += dst_pitch;
}
}
-
+
/**
* Returns TRUE if the pixmap is dirty (has been modified in its current
* location compared to the other), or lacks a private for tracking
diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
new file mode 100644
index 000000000..475b76a63
--- /dev/null
+++ b/exa/exa_migration_mixed.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+static void
+exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch,
+ CARD8 *dst, int dst_pitch)
+ {
+ int i;
+
+ for (i = pPixmap->drawable.height; i; i--) {
+ memcpy (dst, src, min(src_pitch, dst_pitch));
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ void *sys_buffer = pExaPixmap->sys_ptr;
+ int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
+ int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
+ int usage_hint = pPixmap->usage_hint;
+ int sys_pitch = pExaPixmap->sys_pitch;
+ int paddedWidth = sys_pitch;
+
+ /* Already done. */
+ if (pExaPixmap->driverPriv)
+ return;
+
+ if (exaPixmapIsPinned(pPixmap))
+ return;
+
+ /* Can't accel 1/4 bpp. */
+ if (pExaPixmap->accel_blocked || bpp < 8)
+ return;
+
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+
+ if (pExaScr->info->CreatePixmap2)
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp);
+ else
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0);
+
+ if (!pExaPixmap->driverPriv)
+ return;
+
+ pExaPixmap->offscreen = TRUE;
+ pExaPixmap->sys_ptr = NULL;
+
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ /* scratch pixmaps */
+ if (!w || !h)
+ goto finish;
+
+ if (!pExaScr->info->UploadToScreen)
+ goto fallback;
+
+ if (pExaScr->info->UploadToScreen(pPixmap, 0, 0, w, h, sys_buffer, sys_pitch))
+ goto finish;
+
+fallback:
+ ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
+ exaUploadFallback(pPixmap, sys_buffer, sys_pitch, pPixmap->devPrivate.ptr,
+ exaGetPixmapPitch(pPixmap));
+ exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
+
+finish:
+ free(sys_buffer);
+}
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ int i;
+
+ /* If anything is pinned in system memory, we won't be able to
+ * accelerate.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapIsPinned (pixmaps[i].pPix) &&
+ !exaPixmapIsOffscreen (pixmaps[i].pPix))
+ {
+ can_accel = FALSE;
+ break;
+ }
+ }
+
+ /* We can do nothing. */
+ if (!can_accel)
+ return;
+
+ for (i = 0; i < npixmaps; i++) {
+ PixmapPtr pPixmap = pixmaps[i].pPix;
+ ExaPixmapPriv(pPixmap);
+ if (!pExaPixmap->driverPriv)
+ exaCreateDriverPixmap_mixed(pPixmap);
+ }
+}
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
new file mode 100644
index 000000000..26406c42f
--- /dev/null
+++ b/exa/exa_mixed.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps + better initial placement code.
+ * A pinned pixmap implies one that is either driver based already or otherwise altered.
+ * Proper care is taken to free the initially allocated buffer.
+ */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * Pixmaps are always marked as pinned, unless the pixmap can still be transfered to a
+ * driver pixmaps.
+ */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth, datasize;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ datasize = h * paddedWidth;
+
+ /* Allocate temporary pixmap. */
+ pExaPixmap->sys_ptr = malloc(datasize);
+ pExaPixmap->sys_pitch = paddedWidth;
+
+ if (!pExaPixmap->sys_ptr) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ pExaPixmap->area = NULL;
+ pExaPixmap->offscreen = FALSE;
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ /* A scratch pixmap will become a driver pixmap right away. */
+ if (!w || !h) {
+ exaCreateDriverPixmap_mixed(pPixmap);
+ } else {
+ /* Avoid freeing sys_ptr. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ /* We want to be able to copy the pixmap to driver memory later on. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+ }
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData) {
+ if (!exaPixmapIsPinned(pPixmap))
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = pPixData;
+ }
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Anything can happen, don't try to predict it all. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ }
+
+ /* Only pass driver pixmaps to the driver. */
+ if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+ * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap.
+ * We need to store the pointer, because PrepareAccess won't be called.
+ */
+ if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+ }
+ if (ret == TRUE)
+ goto out;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ else if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap))
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->driverPriv = NULL;
+ pExaPixmap->sys_ptr = NULL;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool ret;
+
+ if (!pExaPixmap->driverPriv)
+ return FALSE;
+
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 3c3451377..620bc67a4 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -547,6 +547,9 @@ exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
void
exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+Bool
+exaPixmapIsPinned (PixmapPtr pPix);
+
extern const GCFuncs exaGCFuncs;
/* exa_classic.c */
@@ -579,6 +582,28 @@ exaDestroyPixmap_driver (PixmapPtr pPixmap);
Bool
exaPixmapIsOffscreen_driver(PixmapPtr pPixmap);
+/* exa_mixed.c */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_mixed(PixmapPtr pPixmap);
+
+/* exa_migration_mixed.c */
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap);
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+
/* exa_render.c */
Bool
exaOpReadsDestination (CARD8 op);
@@ -633,7 +658,7 @@ exaGlyphs (CARD8 op,
GlyphListPtr list,
GlyphPtr *glyphs);
-/* exa_migration.c */
+/* exa_migration_classic.c */
void
exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 3c822d16b..1ac29f233 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -301,7 +301,7 @@ exaTryDriverSolidFill(PicturePtr pSrc,
pixel = exaGetPixmapFirstPixel (pSrcPix);
- if (pDstExaPix->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
pixmaps[0].as_dst = TRUE;
@@ -395,8 +395,7 @@ exaTryDriverCompositeRects(CARD8 op,
return -1;
}
- if (pSrcExaPix->pDamage || pDstExaPix->pDamage ||
- (pMask && pMaskExaPix->pDamage)) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[3];
pixmaps[0].as_dst = TRUE;
@@ -507,8 +506,6 @@ exaCompositeRects(CARD8 op,
ExaCompositeRectPtr rects)
{
ExaScreenPriv (pDst->pDrawable->pScreen);
- PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
- ExaPixmapPriv(pPixmap);
int n;
ExaCompositeRectPtr r;
int ret;
@@ -516,7 +513,7 @@ exaCompositeRects(CARD8 op,
/* If we get a mask, that means we're rendering to the exaGlyphs
* destination directly, so the damage layer takes care of this.
*/
- if (!pMask && pExaPixmap->pDamage) {
+ if (!pMask) {
RegionRec region;
int x1 = MAXSHORT;
int y1 = MAXSHORT;
@@ -610,7 +607,7 @@ exaCompositeRects(CARD8 op,
/************************************************************/
- if (!pMask && pExaPixmap->pDamage) {
+ if (!pMask) {
/* Now we have to flush the damage out from pendingDamage => damage
* Calling DamageRegionProcessPending has that effect.
*/
@@ -689,8 +686,7 @@ exaTryDriverComposite(CARD8 op,
REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
- if (pSrcExaPix->pDamage || pDstExaPix->pDamage ||
- (pMask && pMaskExaPix->pDamage)) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[3];
pixmaps[0].as_dst = TRUE;
@@ -707,9 +703,8 @@ exaTryDriverComposite(CARD8 op,
pixmaps[2].pPix = pMaskPix;
pixmaps[2].pReg = NULL;
exaDoMigration(pixmaps, 3, TRUE);
- } else {
+ } else
exaDoMigration(pixmaps, 2, TRUE);
- }
}
pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);