[PATCH 25/36] dix/pixmap: track dirty pixmaps in server. (v3)

Dave Airlie airlied at gmail.com
Thu Jul 5 08:21:26 PDT 2012


From: Dave Airlie <airlied at redhat.com>

This adds two functions for drivers to use directly to keep a
linked list of slave pixmaps to do damage tracking on and keep
updated. It also adds a helper function that drivers may optionally
call to do a simple copy area damage update.

v2: use damage.h not damagestr.h, fixes ephyr build.

v3: address ajax review: use slave_dst, drop unused dst member.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 dix/dispatch.c       |    1 +
 dix/pixmap.c         |  105 ++++++++++++++++++++++++++++++++++++++++++++++----
 include/pixmap.h     |   16 ++++++++
 include/pixmapstr.h  |    8 ++++
 include/scrnintstr.h |    2 +
 5 files changed, 125 insertions(+), 7 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 2eb13db..78afe91 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3742,6 +3742,7 @@ static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
     pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
     pScreen->CreateScreenResources = 0;
 
+    xorg_list_init(&pScreen->pixmap_dirty_list);
     xorg_list_init(&pScreen->unattached_list);
     xorg_list_init(&pScreen->output_slave_list);
 
diff --git a/dix/pixmap.c b/dix/pixmap.c
index 7272098..01e1635 100644
--- a/dix/pixmap.c
+++ b/dix/pixmap.c
@@ -140,21 +140,112 @@ PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
 
     ret = master->SharePixmapBacking(pixmap, slave, &handle);
     if (ret == FALSE)
-	return NULL;
-    
+        return NULL;
+
     spix = slave->CreatePixmap(slave, 0, 0, depth,
-			       CREATE_PIXMAP_USAGE_SHARED);
+                               CREATE_PIXMAP_USAGE_SHARED);
     slave->ModifyPixmapHeader(spix, pixmap->drawable.width,
-			      pixmap->drawable.height, depth, 0,
-			      pixmap->devKind, NULL);
+                              pixmap->drawable.height, depth, 0,
+                              pixmap->devKind, NULL);
 
     spix->master_pixmap = pixmap;
 
     ret = slave->SetSharedPixmapBacking(spix, handle);
     if (ret == FALSE) {
-	slave->DestroyPixmap(spix);
-	return NULL;
+        slave->DestroyPixmap(spix);
+        return NULL;
     }
 
     return spix;
 }
+
+Bool
+PixmapStartDirtyTracking(PixmapPtr src,
+                         PixmapPtr slave_dst,
+                         int x, int y)
+{
+    ScreenPtr screen = src->drawable.pScreen;
+    PixmapDirtyUpdatePtr dirty_update;
+
+    dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec));
+    if (!dirty_update)
+        return FALSE;
+
+    dirty_update->src = src;
+    dirty_update->slave_dst = slave_dst;
+    dirty_update->x = x;
+    dirty_update->y = y;
+
+    dirty_update->damage = DamageCreate(NULL, NULL,
+                                        DamageReportNone,
+                                        TRUE, src->drawable.pScreen,
+                                        src->drawable.pScreen);
+    DamageRegister(&src->drawable, dirty_update->damage);
+    xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list);
+    return TRUE;
+}
+
+Bool
+PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst)
+{
+    ScreenPtr screen = src->drawable.pScreen;
+    PixmapDirtyUpdatePtr ent, safe;
+
+    xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) {
+        if (ent->src == src && ent->slave_dst == slave_dst) {
+            DamageUnregister(&src->drawable, ent->damage);
+            DamageDestroy(ent->damage);
+            xorg_list_del(&ent->ent);
+            free(ent);
+        }
+    }
+    return TRUE;
+}
+
+Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region)
+{
+    ScreenPtr pScreen = dirty->src->drawable.pScreen;
+    int n;
+    BoxPtr b;
+    RegionPtr region = DamageRegion(dirty->damage);
+    GCPtr pGC;
+    PixmapPtr dst;
+    SourceValidateProcPtr SourceValidate;
+
+    SourceValidate = pScreen->SourceValidate;
+    pScreen->SourceValidate = NULL;
+
+    RegionTranslate(dirty_region, dirty->x, dirty->y);
+    RegionIntersect(dirty_region, dirty_region, region);
+
+    if (RegionNil(dirty_region)) {
+        RegionUninit(dirty_region);
+        return FALSE;
+    }
+
+    dst = dirty->slave_dst->master_pixmap;
+
+    RegionTranslate(dirty_region, -dirty->x, -dirty->y);
+    n = RegionNumRects(dirty_region);
+    b = RegionRects(dirty_region);
+
+    pGC = GetScratchGC(dirty->src->drawable.depth, pScreen);
+    ValidateGC(&dst->drawable, pGC);
+
+    while (n--) {
+        BoxRec dst_box;
+        int w, h;
+
+        dst_box = *b;
+        w = dst_box.x2 - dst_box.x1;
+        h = dst_box.y2 - dst_box.y1;
+
+        pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC,
+                           dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1);
+        b++;
+    }
+    FreeScratchGC(pGC);
+
+    pScreen->SourceValidate = SourceValidate;
+    return TRUE;
+}
diff --git a/include/pixmap.h b/include/pixmap.h
index 8c523bd..921a94d 100644
--- a/include/pixmap.h
+++ b/include/pixmap.h
@@ -49,6 +49,7 @@ SOFTWARE.
 
 #include "misc.h"
 #include "screenint.h"
+#include "regionstr.h"
 
 /* types for Drawable */
 #define DRAWABLE_WINDOW 0
@@ -73,6 +74,8 @@ SOFTWARE.
 typedef struct _Drawable *DrawablePtr;
 typedef struct _Pixmap *PixmapPtr;
 
+typedef struct _PixmapDirtyUpdate *PixmapDirtyUpdatePtr;
+
 typedef union _PixUnion {
     PixmapPtr pixmap;
     unsigned long pixel;
@@ -112,4 +115,17 @@ extern _X_EXPORT void FreePixmap(PixmapPtr /*pPixmap */ );
 extern _X_EXPORT PixmapPtr
 PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave);
 
+extern _X_EXPORT Bool
+PixmapStartDirtyTracking(PixmapPtr src,
+                         PixmapPtr slave_dst,
+                         int x, int y);
+
+extern _X_EXPORT Bool
+PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst);
+
+/* helper function, drivers can do this themselves if they can do it more
+   efficently */
+extern _X_EXPORT Bool
+PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region);
+
 #endif                          /* PIXMAP_H */
diff --git a/include/pixmapstr.h b/include/pixmapstr.h
index 40af5c4..2a1ef9b 100644
--- a/include/pixmapstr.h
+++ b/include/pixmapstr.h
@@ -50,6 +50,7 @@ SOFTWARE.
 #include "screenint.h"
 #include "regionstr.h"
 #include "privates.h"
+#include "damage.h"
 
 typedef struct _Drawable {
     unsigned char type;         /* DRAWABLE_<type> */
@@ -84,6 +85,13 @@ typedef struct _Pixmap {
     PixmapPtr master_pixmap;    /* pointer to master copy of pixmap for pixmap sharing */
 } PixmapRec;
 
+typedef struct _PixmapDirtyUpdate {
+    PixmapPtr src, slave_dst;
+    int x, y;
+    DamagePtr damage;
+    struct xorg_list ent;
+} PixmapDirtyUpdateRec;
+
 static inline void
 PixmapBox(BoxPtr box, PixmapPtr pixmap)
 {
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 3a738d3..5ef37ed 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -505,6 +505,8 @@ typedef struct _Screen {
 
     StartPixmapTrackingProcPtr StartPixmapTracking;
     StopPixmapTrackingProcPtr StopPixmapTracking;
+
+    struct xorg_list pixmap_dirty_list;
 } ScreenRec;
 
 static inline RegionPtr
-- 
1.7.10.2



More information about the xorg-devel mailing list