[RFC][PATCH] dix/composite: Update windows with automatically redirected children on demand

ville.syrjala at nokia.com ville.syrjala at nokia.com
Mon Dec 27 05:27:10 PST 2010


From: Ville Syrjälä <ville.syrjala at nokia.com>

If a window has automatically redirected children, the contents of
said children is copied to the parent window by compBlockHandler().
Block handlers may not get executed between every request. That may
cause following GetImage, graphics ops with IncludeInferiors
subwindow mode, etc. requests on the parent to use stale data for the
areas covered by automatically redirected children.

The composite protocol seems to allow this:
"Automatic shadow update. When a hierarchy is rendered off-screen,
the X server provides an automatic mechanism for presenting those
contents within the parent window. The implementation is free to
make this update lag behind actual rendering operations by an
unspecified amount of time. This automatic update mechanism may
be disabled so that the parent window contents can be completely
determined by an external application."

Presumably that means that the client should unredirect the window
before the parent window contents need to be determined. That
doesn't really work if multiple clients have requested the window
to be redirected. But the current behaviour still seems to be OK
according to the spec.

Implicit redirection also suffers from the same problem since it
can't be disabled at all. However the parent window contents under
children of different depth is undefined in most cases, so one
could say that the current implementation is still OK.

Backing store however seems to be the real problem case. AFAICS
nothing allows such stale data to appear in the parent window
contents under a child which has backing store enabled.

So every time that the parent window's contents are expected to be
up to date, the contents of the children should be copied immediately
to the parent.

Instead of trying to identify all parts of the code that have that
requirement, add a simple hook into NotClippedByChildren(), which can
perform the update process. Hopefully that should cover most of the
cases, if not all of them.

Signed-off-by: Ville Syrjälä <ville.syrjala at nokia.com>
---
 composite/compinit.c   |   17 +++--------------
 composite/compint.h    |    3 +++
 composite/compwindow.c |   26 ++++++++++++++++++++++++++
 dix/window.c           |   15 +++++++++++++++
 include/window.h       |    4 ++++
 5 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/composite/compinit.c b/composite/compinit.c
index 5db9f02..29293c5 100644
--- a/composite/compinit.c
+++ b/composite/compinit.c
@@ -131,19 +131,6 @@ compChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
 }
 
 static void
-compScreenUpdate (ScreenPtr pScreen)
-{
-    CompScreenPtr   cs = GetCompScreen (pScreen);
-
-    compCheckTree (pScreen);
-    if (cs->damaged)
-    {
-	compWindowUpdate (pScreen->root);
-	cs->damaged = FALSE;
-    }
-}
-
-static void
 compBlockHandler (int	    i,
 		  pointer   blockData,
 		  pointer   pTimeout,
@@ -153,7 +140,7 @@ compBlockHandler (int	    i,
     CompScreenPtr   cs = GetCompScreen (pScreen);
 
     pScreen->BlockHandler = cs->BlockHandler;
-    compScreenUpdate (pScreen);
+    CompositeUpdateWindow (pScreen->root);
     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
     cs->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = compBlockHandler;
@@ -397,5 +384,7 @@ compScreenInit (ScreenPtr pScreen)
 
     RegisterRealChildHeadProc(CompositeRealChildHead);
 
+    RegisterUpdateWindowProc(CompositeUpdateWindow);
+
     return TRUE;
 }
diff --git a/composite/compint.h b/composite/compint.h
index b2fc541..a975922 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -319,6 +319,9 @@ compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
 void
 compWindowUpdate (WindowPtr pWin);
 
+void
+CompositeUpdateWindow (WindowPtr pWin);
+
 WindowPtr
 CompositeRealChildHead (WindowPtr pWin);
 
diff --git a/composite/compwindow.c b/composite/compwindow.c
index b84c437..7383a29 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -733,6 +733,32 @@ compWindowUpdate (WindowPtr pWin)
     }
 }
 
+void
+CompositeUpdateWindow (WindowPtr pWin)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    CompScreenPtr cs = GetCompScreen (pScreen);
+    static Bool updating;
+
+    /* Prevent recursion */
+    if (updating)
+	return;
+    updating = TRUE;
+
+    compCheckTree (pScreen);
+    if (cs->damaged) {
+	WindowPtr pChild;
+
+	for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+	    compWindowUpdate (pChild);
+
+	if (pWin == pScreen->root)
+	    cs->damaged = FALSE;
+    }
+
+    updating = FALSE;
+}
+
 WindowPtr
 CompositeRealChildHead (WindowPtr pWin)
 {
diff --git a/dix/window.c b/dix/window.c
index 0362dce..7962bc0 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3005,6 +3005,20 @@ PointInWindowIsVisible(WindowPtr pWin, int x, int y)
     return FALSE;
 }
 
+static UpdateWindowProc updateWindowProc = NULL;
+
+void
+RegisterUpdateWindowProc (UpdateWindowProc proc)
+{
+    updateWindowProc = proc;
+}
+
+static void
+UpdateWindow (WindowPtr pWin)
+{
+    if (updateWindowProc)
+	updateWindowProc (pWin);
+}
 
 RegionPtr
 NotClippedByChildren(WindowPtr pWin)
@@ -3015,6 +3029,7 @@ NotClippedByChildren(WindowPtr pWin)
 	!HasSaverWindow (pWin->drawable.pScreen))
     {
 	RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
+	UpdateWindow(pWin);
     }
     return pReg;
 }
diff --git a/include/window.h b/include/window.h
index 6fb2f8c..072a782 100644
--- a/include/window.h
+++ b/include/window.h
@@ -100,6 +100,10 @@ extern _X_EXPORT void RegisterRealChildHeadProc (RealChildHeadProc proc);
 extern _X_EXPORT WindowPtr RealChildHead(
     WindowPtr /*pWin*/);
 
+typedef void (* UpdateWindowProc) (WindowPtr pWin);
+
+extern _X_EXPORT void RegisterUpdateWindowProc (UpdateWindowProc proc);
+
 extern _X_EXPORT WindowPtr CreateWindow(
     Window /*wid*/,
     WindowPtr /*pParent*/,
-- 
1.7.2.2



More information about the xorg-devel mailing list