[PATCH xserver 2/2] damage: Support Xinerama in the Damage extension (#17013)

Aaron Plattner aplattner at nvidia.com
Mon Sep 26 15:01:57 PDT 2011


The Damage extension creates a pDamage object on the root window of
screen 0 when a DamageCreate request is received.  However, this
ignores damage events from other screens so only damage that occurs to
the root window in the bounds of screen 0 is reported.

When the server starts, register a RootWindowCreated callback and use
it to install damage listeners on the root windows of screens 1 and
up.  When damage occurs on those screens, translate it based on the
positions of those screens in the Xinerama desktop and deliver it as
damage to screen 0's root window.

When a client damage object is created on the root window, use the
window size from the connection block instead of the actual root
window's dimensions to construct the initial damage box.  Xinerama
overrides the connection block root size but not the size of the
actual root window on screen 0.

Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
---
 damageext/Makefile.am      |    3 +-
 damageext/damageext.c      |   33 ++++++++++++-
 damageext/damageextint.h   |    2 +
 damageext/xineramadamage.c |  106 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+), 4 deletions(-)
 create mode 100644 damageext/xineramadamage.c

diff --git a/damageext/Makefile.am b/damageext/Makefile.am
index 35f7620..13facd5 100644
--- a/damageext/Makefile.am
+++ b/damageext/Makefile.am
@@ -5,4 +5,5 @@ AM_CFLAGS = $(DIX_CFLAGS)
 libdamageext_la_SOURCES = 	\
 	damageext.c		\
 	damageext.h		\
-	damageextint.h
+	damageextint.h		\
+	xineramadamage.c
diff --git a/damageext/damageext.c b/damageext/damageext.c
index 86f880c..1c624e3 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2002 Keith Packard
+ * Copyright © 2011 NVIDIA Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -26,6 +27,9 @@
 
 #include "damageextint.h"
 #include "protocol-versions.h"
+#ifdef PANORAMIX
+#include "panoramiXh.h"
+#endif
 
 static unsigned char	DamageReqCode;
 static int		DamageEventBase;
@@ -164,7 +168,6 @@ ProcDamageCreate (ClientPtr client)
     DrawablePtr		pDrawable;
     DamageExtPtr	pDamageExt;
     DamageReportLevel	level;
-    RegionPtr		pRegion;
     int			rc;
     
     REQUEST(xDamageCreateReq);
@@ -221,8 +224,29 @@ ProcDamageCreate (ClientPtr client)
 
     if (pDrawable->type == DRAWABLE_WINDOW)
     {
-	pRegion = &((WindowPtr) pDrawable)->borderClip;
-	DamageReportDamage(pDamageExt->pDamage, pRegion);
+	WindowPtr pWin = (WindowPtr)pDrawable;
+
+#ifdef PANORAMIX
+	/*
+	 * Special-case the root window, because in Xinerama we need to use the
+	 * connection block root window size rather than the root window size
+	 * for screen 0.
+	 */
+	if (!pWin->parent && !noPanoramiXExtension) {
+	    xWindowRoot *root = (xWindowRoot *)
+				(ConnectionInfo + connBlockScreenStart);
+	    BoxRec box = { 0, 0, root->pixWidth, root->pixHeight };
+	    RegionRec region;
+
+	    RegionInit(&region, &box, 1);
+	    DamageReportDamage(pDamageExt->pDamage, &region);
+	    RegionUninit(&region);
+	} else
+#endif
+	{
+	    RegionPtr pRegion = &pWin->borderClip;
+	    DamageReportDamage(pDamageExt->pDamage, pRegion);
+	}
     }
 
     return Success;
@@ -512,4 +536,7 @@ DamageExtensionInit(void)
 			(EventSwapPtr) SDamageNotifyEvent;
 	SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage);
     }
+
+    if (!XineramaDamageInit())
+	FatalError("Failed to initialize Damage Xinerama support");
 }
diff --git a/damageext/damageextint.h b/damageext/damageextint.h
index a235cb9..992bbb1 100644
--- a/damageext/damageextint.h
+++ b/damageext/damageextint.h
@@ -68,4 +68,6 @@ typedef struct _DamageExt {
 void
 DamageExtSetCritical (ClientPtr pClient, Bool critical);
 
+Bool XineramaDamageInit(void);
+
 #endif /* _DAMAGEEXTINT_H_ */
diff --git a/damageext/xineramadamage.c b/damageext/xineramadamage.c
new file mode 100644
index 0000000..d7d7986
--- /dev/null
+++ b/damageext/xineramadamage.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2011 NVIDIA Corporation
+ *
+ * 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 "damageextint.h"
+#include "damagestr.h"
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+
+static RESTYPE XineramaDamageType;
+
+static void
+XineramaDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+    ScreenPtr pScreen0 = screenInfo.screens[0];
+    ScreenPtr pScreen = screenInfo.screens[pDamage->pScreen->myNum];
+
+    RegionTranslate(pRegion, pScreen->x, pScreen->y);
+    DamageDamageRegion(&pScreen0->root->drawable, pRegion);
+
+    DamageEmpty(pDamage);
+}
+
+
+static void
+XineramaDamageInitDamage(CallbackListPtr *list, void *closure, void *data)
+{
+    WindowPtr pRoot = data;
+    ScreenPtr pScreen = pRoot->drawable.pScreen;
+    DamagePtr pDamage;
+
+    if (pScreen->myNum == 0)
+	return;
+
+    pDamage = DamageCreate(XineramaDamageReport,
+			   NULL,
+			   DamageReportNonEmpty,
+			   TRUE,
+			   pScreen,
+			   NULL);
+
+    DamageRegister(&pRoot->drawable, pDamage);
+
+    /*
+     * Add a resource so that it gets destroyed automatically when the
+     * server shuts down.
+     */
+    AddResource(pRoot->drawable.id, XineramaDamageType, pDamage);
+}
+
+static int
+XineramaDamageDestroy(void *value, XID xid)
+{
+    DamagePtr pDamage = value;
+
+    DamageUnregister(pDamage->pDrawable, pDamage);
+    DamageDestroy(pDamage);
+
+    return Success;
+}
+#endif
+
+Bool XineramaDamageInit(void)
+{
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension) {
+	XineramaDamageType = CreateNewResourceType(XineramaDamageDestroy, "Xinerama Damage");
+	if (!XineramaDamageType)
+	    return FALSE;
+
+	/*
+	 * Install a wakeup handler to create the Damage objects for screens 1 and
+	 * up.  We need to do that after InitRootWindow is called and pScreen->root
+	 * is created.
+	 */
+	if (!AddCallback(&RootWindowCreatedCallback, XineramaDamageInitDamage,
+			 NULL))
+	    return FALSE;
+    }
+#endif
+
+    return TRUE;
+}
-- 
1.7.4.1



More information about the xorg-devel mailing list