[PATCH 1/3] exa: Split out some classic and driver allocated pixmap code into seperate files
Maarten Maathuis
madman2003 at gmail.com
Sun Aug 2 07:47:48 PDT 2009
- Create a few seperate functions and a few private function pointers.
- Replace a few if conditions with a check for pExaPix->pDamage instead.
- This is in preperation of a third scheme that lies somewhere in between.
- Code clarity would have suffered (i started working on it and didn't like the mess).
---
exa/Makefile.am | 5 +-
exa/exa.c | 326 ++++++---------------------------------------------
exa/exa_accel.c | 5 +-
exa/exa_classic.c | 258 ++++++++++++++++++++++++++++++++++++++++
exa/exa_driver.c | 211 +++++++++++++++++++++++++++++++++
exa/exa_migration.c | 7 +-
exa/exa_priv.h | 109 ++++++++++++-----
7 files changed, 590 insertions(+), 331 deletions(-)
create mode 100644 exa/exa_classic.c
create mode 100644 exa/exa_driver.c
diff --git a/exa/Makefile.am b/exa/Makefile.am
index 2b3f1e4..bf2c138 100644
--- a/exa/Makefile.am
+++ b/exa/Makefile.am
@@ -17,11 +17,12 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
libexa_la_SOURCES = \
exa.c \
exa.h \
+ exa_classic.c \
+ exa_migration.c \
+ exa_driver.c \
exa_accel.c \
exa_glyphs.c \
- exa_migration.c \
exa_offscreen.c \
exa_render.c \
exa_priv.h \
exa_unaccel.c
-
diff --git a/exa/exa.c b/exa/exa.c
index daa4a7a..0f37168 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -48,17 +48,6 @@ DevPrivateKey exaGCPrivateKey = &exaGCPrivateKeyIndex;
static ShmFuncs exaShmFuncs = { NULL, NULL };
#endif
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
- return pExaPixmap->fb_ptr;
- else
- return pExaPixmap->sys_ptr;
-}
-
/**
* exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
* the beginning of the given pixmap.
@@ -178,45 +167,6 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
REGION_UNINIT(pScreen, ®ion);
}
-static Bool
-exaDestroyPixmap (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);
- pExaPixmap->driverPriv = NULL;
- }
-
- if (pExaPixmap->area)
- {
- DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
- (void*)pPixmap->drawable.id,
- ExaGetPixmapPriv(pPixmap)->area->offset,
- pPixmap->drawable.width,
- pPixmap->drawable.height));
- /* Free the offscreen area */
- exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- }
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
- }
-
- swap(pExaScr, pScreen, DestroyPixmap);
- ret = pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
-
- return ret;
-}
-
static int
exaLog2(int val)
{
@@ -229,7 +179,7 @@ exaLog2(int val)
return bits - 1;
}
-static void
+void
exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
@@ -253,7 +203,7 @@ exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
}
-static void
+void
exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
@@ -267,227 +217,6 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
}
/**
- * exaCreatePixmap() creates a new pixmap.
- *
- * If width and height are 0, this won't be a full-fledged pixmap and it will
- * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
- * ModifyPixmapHeader() would break migration. These types of pixmaps are used
- * for scratch pixmaps, or to represent the visible screen.
- */
-static PixmapPtr
-exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- BoxRec box;
- int driver_alloc = 0;
- int bpp;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- swap(pExaScr, pScreen, CreatePixmap);
- if (!pExaScr->info->CreatePixmap && !pExaScr->info->CreatePixmap2) {
- pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
- } else {
- driver_alloc = 1;
- 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;
-
- if (driver_alloc) {
- size_t paddedWidth, datasize;
-
- paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || h > 32767)
- return NullPixmap;
-
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
-
- if (paddedWidth < pExaPixmap->fb_pitch)
- paddedWidth = pExaPixmap->fb_pitch;
-
- datasize = h * paddedWidth;
-
- /* Set this before driver hooks, to allow for !offscreen pixmaps.
- * !offscreen pixmaps have a valid pointer at all times.
- */
- pPixmap->devPrivate.ptr = NULL;
-
- if (pExaScr->info->CreatePixmap2)
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp);
- else
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
- if (!pExaPixmap->driverPriv) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->pDamage = NULL;
- pExaPixmap->sys_ptr = NULL;
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
-
- } else {
- pExaPixmap->driverPriv = NULL;
- /* Scratch pixmaps may have w/h equal to zero, and may not be
- * migrated.
- */
- if (!w || !h)
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- else
- pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
-
- pPixmap->devPrivate.ptr = NULL;
- pExaPixmap->offscreen = FALSE;
-
- pExaPixmap->fb_ptr = NULL;
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
- pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
-
- if (pExaPixmap->fb_pitch > 131071) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* Set up damage tracking */
- pExaPixmap->pDamage = DamageCreate (NULL, NULL,
- DamageReportNone, TRUE,
- pScreen, pPixmap);
-
- if (pExaPixmap->pDamage == NULL) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
- /* This ensures that pending damage reflects the current operation. */
- /* This is used by exa to optimize migration. */
- DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
- }
-
- pExaPixmap->area = NULL;
-
- /* We set the initial pixmap as completely valid for a simple reason.
- * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
- * could form single pixel rects as part of a region. Setting the complete region
- * as valid is a natural defragmentation of the region.
- */
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = w;
- box.y2 = h;
- REGION_INIT(pScreen, &pExaPixmap->validSys, &box, 0);
- REGION_INIT(pScreen, &pExaPixmap->validFB, &box, 0);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- return pPixmap;
-}
-
-static Bool
-exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
-{
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret;
-
- if (!pPixmap)
- return FALSE;
-
- pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
-
- if (pExaPixmap) {
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
-
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
-
- /* Classic EXA:
- * - Framebuffer.
- * - Scratch pixmap with offscreen memory.
- */
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
- pExaScr->info->memoryBase && pPixData) {
- if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
- ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
- pExaScr->info->memorySize) {
- pExaPixmap->fb_ptr = pPixData;
- pExaPixmap->fb_pitch = devKind;
- pExaPixmap->offscreen = TRUE;
- }
- }
-
- if (width > 0 && height > 0 && bitsPerPixel > 0) {
- exaSetFbPitch(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- }
-
- /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
- * offscreen memory, so there's no need to track damage.
- */
- if (pExaPixmap->pDamage) {
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
- }
- }
-
- if (pExaScr->info->ModifyPixmapHeader) {
- 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;
- }
- ret = pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
-
-out:
- /* Always NULL this, we don't want lingering pointers. */
- pPixmap->devPrivate.ptr = NULL;
-
- return ret;
-}
-
-/**
* 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
@@ -500,21 +229,15 @@ out:
* @return TRUE if the given drawable is in framebuffer memory.
*/
Bool
-exaPixmapIsOffscreen(PixmapPtr p)
+exaPixmapIsOffscreen(PixmapPtr pPixmap)
{
- ScreenPtr pScreen = p->drawable.pScreen;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv(pScreen);
- ExaPixmapPriv(p);
- Bool ret;
- if (pExaScr->info->PixmapIsOffscreen) {
- p->devPrivate.ptr = ExaGetPixmapAddress(p);
- ret = pExaScr->info->PixmapIsOffscreen(p);
- p->devPrivate.ptr = NULL;
- } else
- ret = (pExaPixmap->offscreen && pExaPixmap->fb_ptr);
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return FALSE;
- return ret;
+ return pExaScr->pixmap_is_offscreen(pPixmap);
}
/**
@@ -1313,10 +1036,19 @@ exaDriverInit (ScreenPtr pScreen,
pScreen->myNum);
return FALSE;
}
- wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap);
- wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap);
-
- wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader);
+ 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;
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_classic);
+ pExaScr->do_migration = exaDoMigration_classic;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic;
+ }
if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
pScreen->myNum,
@@ -1414,3 +1146,21 @@ void exaWaitSync(ScreenPtr pScreen)
pExaScr->info->needsSync = FALSE;
}
}
+
+/**
+ * Performs migration of the pixmaps according to the operation information
+ * provided in pixmaps and can_accel and the migration scheme chosen in the
+ * config file.
+ */
+void
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_migration)
+ pExaScr->do_migration(pixmaps, npixmaps, can_accel);
+}
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index 3aa5578..bc970bb 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -1015,7 +1015,7 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+ if (pExaPixmap->pDamage &&
pDrawable->width == 1 && pDrawable->height == 1 &&
pDrawable->bitsPerPixel != 24) {
ExaPixmapPriv(pPixmap);
@@ -1233,13 +1233,14 @@ 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 (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
+ if (pExaPixmap->pDamage) {
BoxRec Box;
RegionRec Reg;
ExaMigrationRec pixmaps[1];
diff --git a/exa/exa_classic.c b/exa/exa_classic.c
new file mode 100644
index 0000000..1eff570
--- /dev/null
+++ b/exa/exa_classic.c
@@ -0,0 +1,258 @@
+/*
+ * 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 classic exa specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
+ return pExaPixmap->fb_ptr;
+ else
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * If width and height are 0, this won't be a full-fledged pixmap and it will
+ * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
+ * ModifyPixmapHeader() would break migration. These types of pixmaps are used
+ * for scratch pixmaps, or to represent the visible screen.
+ */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ BoxRec box;
+ int bpp;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ pExaPixmap->driverPriv = NULL;
+ /* Scratch pixmaps may have w/h equal to zero, and may not be
+ * migrated.
+ */
+ if (!w || !h)
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ else
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->offscreen = FALSE;
+
+ pExaPixmap->fb_ptr = NULL;
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
+
+ if (pExaPixmap->fb_pitch > 131071) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate (NULL, NULL,
+ DamageReportNone, TRUE,
+ pScreen, pPixmap);
+
+ if (pExaPixmap->pDamage == NULL) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
+
+ pExaPixmap->area = NULL;
+
+ /* We set the initial pixmap as completely valid for a simple reason.
+ * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
+ * could form single pixel rects as part of a region. Setting the complete region
+ * as valid is a natural defragmentation of the region.
+ */
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ REGION_INIT(pScreen, &pExaPixmap->validSys, &box, 0);
+ REGION_INIT(pScreen, &pExaPixmap->validFB, &box, 0);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_classic(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)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ /* Classic EXA:
+ * - Framebuffer.
+ * - Scratch pixmap with offscreen memory.
+ */
+ if (pExaScr->info->memoryBase && pPixData) {
+ if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
+ ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
+ pExaScr->info->memorySize) {
+ pExaPixmap->fb_ptr = pPixData;
+ pExaPixmap->fb_pitch = devKind;
+ pExaPixmap->offscreen = TRUE;
+ }
+ }
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
+ * offscreen memory, so there's no need to track damage.
+ */
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->area)
+ {
+ DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ ExaGetPixmapPriv(pPixmap)->area->offset,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ /* Free the offscreen area */
+ exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_classic(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool ret;
+
+ if (pExaScr->info->PixmapIsOffscreen) {
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = NULL;
+ } else
+ ret = (pExaPixmap->offscreen && pExaPixmap->fb_ptr);
+
+ return ret;
+}
diff --git a/exa/exa_driver.c b/exa/exa_driver.c
new file mode 100644
index 0000000..b4ca426
--- /dev/null
+++ b/exa/exa_driver.c
@@ -0,0 +1,211 @@
+/*
+ * 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 specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * Pixmaps are always marked as pinned, because exa has no control over them.
+ */
+PixmapPtr
+exaCreatePixmap_driver(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;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+
+ datasize = h * paddedWidth;
+
+ /* Set this before driver hooks, to allow for !offscreen pixmaps.
+ * !offscreen pixmaps have a valid pointer at all times.
+ */
+ pPixmap->devPrivate.ptr = NULL;
+
+ if (pExaScr->info->CreatePixmap2)
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp);
+ else
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
+ if (!pExaPixmap->driverPriv) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ pExaPixmap->sys_ptr = NULL;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ pExaPixmap->area = NULL;
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_driver(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)
+ 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);
+ }
+ }
+
+ if (pExaScr->info->ModifyPixmapHeader) {
+ 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_driver (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);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_driver(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
diff --git a/exa/exa_migration.c b/exa/exa_migration.c
index f6805cb..afab9d2 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration.c
@@ -607,17 +607,12 @@ out:
* config file.
*/
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
ExaScreenPriv(pScreen);
int i, j;
- if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
- return;
- if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
- return;
-
/* If this debugging flag is set, check each pixmap for whether it is marked
* as clean, and if so, actually check if that's the case. This should help
* catch issues with failing to mark a drawable as dirty. While it will
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index f67a9cb..3c34513 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -142,6 +142,13 @@ typedef struct {
#define EXA_FALLBACK_COPYWINDOW (1 << 0)
#define EXA_ACCEL_COPYWINDOW (1 << 1)
+typedef struct _ExaMigrationRec {
+ Bool as_dst;
+ Bool as_src;
+ PixmapPtr pPix;
+ RegionPtr pReg;
+} ExaMigrationRec, *ExaMigrationPtr;
+
typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
typedef struct {
ExaDriverPtr info;
@@ -165,7 +172,9 @@ typedef struct {
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
#endif
-
+ void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+ Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap);
+
Bool swappedOut;
enum ExaMigrationHeuristic migration;
Bool checkDirtyCorrectness;
@@ -303,13 +312,6 @@ typedef struct {
GCFuncs *Savedfuncs;
} ExaGCPrivRec, *ExaGCPrivPtr;
-typedef struct _ExaMigrationRec {
- Bool as_dst;
- Bool as_src;
- PixmapPtr pPix;
- RegionPtr pReg;
-} ExaMigrationRec, *ExaMigrationPtr;
-
typedef struct {
PicturePtr pDst;
INT16 xSrc;
@@ -443,6 +445,34 @@ void
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
+RegionPtr
+exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown);
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure);
+
extern const GCOps exaOps;
#ifdef RENDER
@@ -506,36 +536,49 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp);
PixmapPtr
exaGetDrawablePixmap(DrawablePtr pDrawable);
-RegionPtr
-exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
- int srcx, int srcy, int width, int height, int dstx, int dsty);
+void
+exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
-Bool
-exaHWCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown);
+void
+exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure);
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
extern const GCFuncs exaGCFuncs;
+/* exa_classic.c */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_classic(PixmapPtr pPixmap);
+
+/* exa_driver.c */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_driver(PixmapPtr pPixmap);
+
/* exa_render.c */
Bool
exaOpReadsDestination (CARD8 op);
@@ -592,7 +635,7 @@ exaGlyphs (CARD8 op,
/* exa_migration.c */
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
void
exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area);
--
1.6.4
More information about the xorg-devel
mailing list