[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, &region);
 }
 
-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