[PATCH 3/3] damageext: Xineramify (v2)

Adam Jackson ajax at redhat.com
Wed Sep 11 14:26:51 PDT 2013


v2:
Optimize pixmaps by only watching for them on screen 0
Properly translate coordinates for window reports in Xinerama mode

This still has the issue that damage to windows that cross ScreenRec
boundaries will come in multiple pieces.  Technically, for everything
except NonEmpty reports, this is indistinguishable from the drawing
simply having actually happened in multiple pieces, and the client just
being told about them all at once.  Clients expecting NonEmpty to be
like an edge trigger may do excess work in this scenario.

I'm fairly sure Subtract isn't quite right yet.  Regions aren't
xineramified - which is probably correct - so if the repair region is
None you'll end up copying only ScreenRec 0's region contents into it.
Neither am I doing coordinate translation by screen.

DamageAdd is also probably broken for coordinate translation reasons,
but I think DamageAdd really only exists for DRI1 so that'll probably be
the last issue that gets fixed.

Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 Xext/panoramiX.c      |   3 +
 damageext/damageext.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++--
 damageext/damageext.h |   6 +-
 3 files changed, 204 insertions(+), 10 deletions(-)

diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
index 2b3a570..7734309 100644
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@ -54,6 +54,7 @@ Equipment Corporation.
 #include "resource.h"
 #include "picturestr.h"
 #include "xfixesint.h"
+#include "damageext.h"
 #ifdef COMPOSITE
 #include "compint.h"
 #endif
@@ -582,6 +583,7 @@ PanoramiXExtensionInit(void)
 
     PanoramiXRenderInit();
     PanoramiXFixesInit();
+    PanoramiXDamageInit();
 #ifdef COMPOSITE
     PanoramiXCompositeInit();
 #endif
@@ -887,6 +889,7 @@ PanoramiXResetProc(ExtensionEntry * extEntry)
 
     PanoramiXRenderReset();
     PanoramiXFixesReset();
+    PanoramiXDamageReset();
 #ifdef COMPOSITE
     PanoramiXCompositeReset ();
 #endif
diff --git a/damageext/damageext.c b/damageext/damageext.c
index 01b88ef..7ed1a8d 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2002 Keith Packard
+ * Copyright 2013 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -24,10 +25,21 @@
 #include <dix-config.h>
 #endif
 
+#include "damageext.h"
 #include "damageextint.h"
 #include "protocol-versions.h"
 #include "extinit.h"
 
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+
+static RESTYPE XRT_DAMAGE;
+static XID PanoramiXReportDrawable;
+static int (*PanoramiXSaveDamageVector[XDamageNumberRequests]) (ClientPtr);
+
+#endif
+
 static unsigned char DamageReqCode;
 static int DamageEventBase;
 static RESTYPE DamageExtType;
@@ -42,8 +54,16 @@ DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
     ClientPtr pClient = pDamageExt->pClient;
     DamageClientPtr pDamageClient = GetDamageClient(pClient);
     DrawablePtr pDrawable = pDamageExt->pDrawable;
+    ScreenPtr pScreen = pDrawable->pScreen;
     xDamageNotifyEvent ev;
-    int i;
+    int i, dx = 0, dy = 0;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension && pDrawable->type == DRAWABLE_WINDOW) {
+        dx = pScreen->x;
+        dy = pScreen->y;
+    }
+#endif
 
     UpdateCurrentTimeIf();
     ev = (xDamageNotifyEvent) {
@@ -52,8 +72,8 @@ DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
         .drawable = pDamageExt->drawable,
         .damage = pDamageExt->id,
         .timestamp = currentTime.milliseconds,
-        .geometry.x = pDrawable->x,
-        .geometry.y = pDrawable->y,
+        .geometry.x = pDrawable->x + dx,
+        .geometry.y = pDrawable->y + dy,
         .geometry.width = pDrawable->width,
         .geometry.height = pDrawable->height
     };
@@ -62,16 +82,16 @@ DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
             ev.level = pDamageExt->level;
             if (i < nBoxes - 1)
                 ev.level |= DamageNotifyMore;
-            ev.area.x = pBoxes[i].x1;
-            ev.area.y = pBoxes[i].y1;
+            ev.area.x = pBoxes[i].x1 + dx;
+            ev.area.y = pBoxes[i].y1 + dy;
             ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
             ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
             WriteEventsToClient(pClient, 1, (xEvent *) &ev);
         }
     }
     else {
-        ev.area.x = 0;
-        ev.area.y = 0;
+        ev.area.x = 0 + dx;
+        ev.area.y = 0 + dy;
         ev.area.width = pDrawable->width;
         ev.area.height = pDrawable->height;
         WriteEventsToClient(pClient, 1, (xEvent *) &ev);
@@ -170,6 +190,7 @@ ProcDamageCreate(ClientPtr client)
     DamageReportLevel level;
     RegionPtr pRegion;
     int rc;
+    XID report;
 
     REQUEST(xDamageCreateReq);
 
@@ -198,11 +219,18 @@ ProcDamageCreate(ClientPtr client)
         return BadValue;
     }
 
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+        report = PanoramiXReportDrawable;
+    else
+#endif
+        report = stuff->drawable;
+
     pDamageExt = malloc(sizeof(DamageExtRec));
     if (!pDamageExt)
         return BadAlloc;
     pDamageExt->id = stuff->damage;
-    pDamageExt->drawable = stuff->drawable;
+    pDamageExt->drawable = report;
     pDamageExt->pDrawable = pDrawable;
     pDamageExt->level = level;
     pDamageExt->pClient = client;
@@ -458,6 +486,162 @@ SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to)
     cpswaps(from->geometry.height, to->geometry.height);
 }
 
+#ifdef PANORAMIX
+
+#define VERIFY_XIN_DAMAGE(damage, did, client, mode) do { \
+    int rc = dixLookupResourceByType((void **)&damage, did, XRT_DAMAGE, client, mode); \
+    if (rc != Success) \
+        return rc; \
+} while (0)
+
+static int
+PanoramiXDamageCreate(ClientPtr client)
+{
+    PanoramiXRes *draw, *damage;
+    int i, rc;
+
+    REQUEST(xDamageCreateReq);
+
+    REQUEST_SIZE_MATCH(xDamageCreateReq);
+    LEGAL_NEW_RESOURCE(stuff->damage, client);
+    rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE,
+                                  client, DixGetAttrAccess | DixReadAccess);
+    if (rc != Success)
+        return rc;
+
+    if (!(damage = calloc(1, sizeof(PanoramiXRes))))
+        return BadAlloc;
+
+    damage->type = XRT_DAMAGE;
+
+    /*
+     * This is a break from the usual panoramix pattern.  Refer to the
+     * panoramix conditional section in ProcDamageCreate for the other
+     * half of the story, we're doing this in order to get the drawable
+     * ID right in the reported event.
+     */
+
+    PanoramiXReportDrawable = stuff->drawable;
+
+    /*
+     * pixmaps exist on all backend screens, so just watching screen 0 works
+     */
+    if (draw->type == RT_PIXMAP) {
+        damage->info[0].id = stuff->damage;
+
+        rc = PanoramiXSaveDamageVector[X_DamageCreate](client);
+    } else {
+        panoramix_setup_ids(damage, client, stuff->damage);
+
+        FOR_NSCREENS_BACKWARD(i) {
+            stuff->damage = damage->info[i].id;
+            stuff->drawable = draw->info[i].id;
+            rc = PanoramiXSaveDamageVector[X_DamageCreate](client);
+            if (rc != Success)
+                break;
+        }
+    }
+
+    if (rc == Success)
+        AddResource(damage->info[0].id, XRT_DAMAGE, damage);
+    else
+        free(damage);
+
+    return rc;
+}
+
+static int
+PanoramiXDamageDestroy(ClientPtr client)
+{
+    REQUEST(xDamageDestroyReq);
+    PanoramiXRes *damage;
+    int i, rc = Success;
+
+    REQUEST_SIZE_MATCH(xDamageDestroyReq);
+    VERIFY_XIN_DAMAGE(damage, stuff->damage, client, DixWriteAccess);
+
+    FOR_NSCREENS_BACKWARD(i) {
+        if ((stuff->damage = damage->info[i].id)) {
+            rc = PanoramiXSaveDamageVector[X_DamageDestroy](client);
+            if (rc != Success)
+                break;
+        }
+    }
+
+    return rc;
+}
+
+static int
+PanoramiXDamageSubtract(ClientPtr client)
+{
+    REQUEST(xDamageSubtractReq);
+    PanoramiXRes *damage;
+    int i, rc = Success;
+
+    REQUEST_SIZE_MATCH(xDamageSubtractReq);
+    VERIFY_XIN_DAMAGE(damage, stuff->damage, client, DixWriteAccess);
+
+    FOR_NSCREENS_BACKWARD(i) {
+        if ((stuff->damage = damage->info[i].id)) {
+            rc = PanoramiXSaveDamageVector[X_DamageSubtract](client);
+            if (rc != Success)
+                break;
+        }
+    }
+
+    return rc;
+}
+
+static int
+PanoramiXDamageAdd(ClientPtr client)
+{
+    REQUEST(xDamageAddReq);
+    PanoramiXRes *draw;
+    RegionPtr pRegion;
+    int i, rc;
+
+    REQUEST_SIZE_MATCH(xDamageAddReq);
+    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
+    rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE,
+                                  client, DixWriteAccess);
+    if (rc != Success)
+        return rc;
+
+    FOR_NSCREENS_BACKWARD(i) {
+        if ((stuff->drawable = draw->info[i].id)) {
+            rc = PanoramiXSaveDamageVector[X_DamageAdd](client);
+            if (rc != Success)
+                break;
+        }
+    }
+
+    return rc;
+}
+
+void
+PanoramiXDamageInit(void)
+{
+    XRT_DAMAGE = CreateNewResourceType(XineramaDeleteResource,
+                                       "XineramaDamage");
+
+    memcpy(PanoramiXSaveDamageVector, ProcDamageVector,
+           sizeof(ProcDamageVector));
+
+    ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate;
+    ProcDamageVector[X_DamageDestroy] = PanoramiXDamageDestroy;
+    ProcDamageVector[X_DamageSubtract] = PanoramiXDamageSubtract;
+    ProcDamageVector[X_DamageAdd] = PanoramiXDamageAdd;
+}
+
+void
+PanoramiXDamageReset(void)
+{
+    memcpy(ProcDamageVector, PanoramiXSaveDamageVector,
+           sizeof(ProcDamageVector));
+}
+
+#endif /* PANORAMIX */
+
 void
 DamageExtensionInit(void)
 {
@@ -488,5 +672,10 @@ DamageExtensionInit(void)
             (EventSwapPtr) SDamageNotifyEvent;
         SetResourceTypeErrorValue(DamageExtType,
                                   extEntry->errorBase + BadDamage);
+#ifdef PANORAMIX
+        if (XRT_DAMAGE)
+            SetResourceTypeErrorValue(XRT_DAMAGE,
+                                      extEntry->errorBase + BadDamage);
+#endif
     }
 }
diff --git a/damageext/damageext.h b/damageext/damageext.h
index bd99635..3898cc5 100644
--- a/damageext/damageext.h
+++ b/damageext/damageext.h
@@ -27,7 +27,9 @@
 #ifndef _DAMAGEEXT_H_
 #define _DAMAGEEXT_H_
 
-void
- DamageExtensionInit(void);
+#ifdef PANORAMIX
+void PanoramiXDamageInit(void);
+void PanoramiXDamageReset(void);
+#endif
 
 #endif                          /* _DAMAGEEXT_H_ */
-- 
1.8.3.1



More information about the xorg-devel mailing list