[xserver-commit] xserver/composite Makefile.am,1.1,1.2 compalloc.c,1.1,1.2 compinit.c,1.2,1.3 compint.h,1.1,1.2 compwindow.c,1.2,1.3

Keith Packard xserver-commit@pdx.freedesktop.org
Thu, 06 Nov 2003 20:26:10 -0800


Committed by: keithp

Update of /cvs/xserver/xserver/composite
In directory pdx:/tmp/cvs-serv20575/composite

Modified Files:
	Makefile.am compalloc.c compinit.c compint.h compwindow.c 
Log Message:
	* composite/Makefile.am:
	* composite/compalloc.c: (compRedirectWindow),
	(compFreeClientWindow), (compUnredirectWindow),
	(compRedirectSubwindows), (compFreeClientSubwindows),
	(compUnredirectSubwindows), (compAllocPixmap), (compFreePixmap):
	* composite/compinit.c: (compScreenInit):
	* composite/compint.h:
	* composite/compwindow.c: (compShouldBeRedirected),
	(compCheckRedirect), (compCreateWindow):
	* fb/fbwindow.c: (fbCopyWindow):
	* xfixes/region.c: (XFixesRegionCopy),
	(ProcXFixesCreateRegionFromWindow), (ProcXFixesCreateRegionFromGC),
	(ProcXFixesCreateRegionFromPicture), (ProcXFixesSetGCClipRegion),
	(ProcXFixesSetWindowShapeRegion):
	* xfixes/xfixes.h:
	Finish up preliminary Composite extension implementation.
	Export XFixesRegionCopy from xfixes for Composite.
	Use window pixmap for fbCopyWindow, not root window.


Index: Makefile.am
===================================================================
RCS file: /cvs/xserver/xserver/composite/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Makefile.am	5 Nov 2003 05:45:30 -0000	1.1
+++ Makefile.am	7 Nov 2003 04:26:08 -0000	1.2
@@ -3,12 +3,14 @@
 	-I$(top_srcdir)/Xext			\
 	-I$(top_srcdir)/render			\
 	-I$(top_srcdir)/miext/damage		\
+	-I$(top_srcdir)/xfixes			\
 	@XSERVER_CFLAGS@
 
 noinst_LIBRARIES = libcomposite.a
 
 libcomposite_a_SOURCES = 	\
 	compalloc.c		\
+	compext.c		\
 	compint.h		\
 	compinit.c		\
 	compwindow.c

Index: compalloc.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compalloc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- compalloc.c	5 Nov 2003 05:45:31 -0000	1.1
+++ compalloc.c	7 Nov 2003 04:26:08 -0000	1.2
@@ -46,6 +46,272 @@
     cw->damage = 0;
 }
 
+/*
+ * Redirect one window for one client
+ */
+int
+compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+    CompWindowPtr	cw = GetCompWindow (pWin);
+    CompClientWindowPtr	ccw;
+
+    /*
+     * Only one Manual update is allowed
+     */
+    if (cw && update == CompositeRedirectManual)
+	for (ccw = cw->clients; ccw; ccw = ccw->next)
+	    if (ccw->update == CompositeRedirectManual)
+		return BadAccess;
+    
+    /*
+     * Allocate per-client per-window structure 
+     * The client *could* allocate multiple, but while supported,
+     * it is not expected to be common
+     */
+    ccw = xalloc (sizeof (CompClientWindowRec));
+    if (!ccw)
+	return BadAlloc;
+    ccw->id = FakeClientID (pClient->index);
+    ccw->update = update;
+    /*
+     * Now make sure there's a per-window structure to hang this from
+     */
+    if (!cw)
+    {
+	cw = xalloc (sizeof (CompWindowRec));
+	if (!cw)
+	{
+	    xfree (ccw);
+	    return BadAlloc;
+	}
+	cw->damage = DamageCreate (compReportDamage,
+				   compDestroyDamage,
+				   DamageReportRawRegion,
+				   FALSE,
+				   pWin);
+	if (!cw->damage)
+	{
+	    xfree (ccw);
+	    xfree (cw);
+	    return BadAlloc;
+	}
+	cw->update = CompositeRedirectAutomatic;
+	cw->clients = 0;
+	pWin->devPrivates[CompWindowPrivateIndex].ptr = cw;
+    }
+    ccw->next = cw->clients;
+    cw->clients = ccw;
+    if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
+	return BadAlloc;
+    if (ccw->update == CompositeRedirectManual)
+	cw->update = CompositeRedirectManual;
+
+    if (!compCheckRedirect (pWin))
+    {
+	FreeResource (ccw->id, RT_NONE);
+	return BadAlloc;
+    }
+    
+    return Success;
+}
+
+/*
+ * Free one of the per-client per-window resources, clearing
+ * redirect and the per-window pointer as appropriate
+ */
+void
+compFreeClientWindow (WindowPtr pWin, XID id)
+{
+    CompWindowPtr	cw = GetCompWindow (pWin);
+    CompClientWindowPtr	ccw, *prev;
+
+    if (!cw)
+	return;
+    for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
+    {
+	if (ccw->id == id)
+	{
+	    *prev = ccw->next;
+	    if (ccw->update == CompositeRedirectManual)
+		cw->update = CompositeRedirectAutomatic;
+	    xfree (ccw);
+	    break;
+	}
+    }
+    if (!cw->clients)
+    {
+	pWin->devPrivates[CompWindowPrivateIndex].ptr = 0;
+	
+	(void) compCheckRedirect (pWin);
+	
+	if (cw->damage)
+	    DamageDestroy (cw->damage);
+	REGION_UNINIT (pScreen, &cw->borderClip);
+	xfree (cw);
+    }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+    CompWindowPtr	cw = GetCompWindow (pWin);
+    CompClientWindowPtr	ccw;
+
+    if (!cw)
+	return BadValue;
+
+    for (ccw = cw->clients; ccw; ccw = ccw->next)
+	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+	{
+	    FreeResource (ccw->id, RT_NONE);
+	    return Success;
+	}
+    return BadValue;
+}
+	
+/*
+ * Redirect all subwindows for one client
+ */
+
+int
+compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
+    CompClientWindowPtr	ccw;
+    WindowPtr		pChild;
+
+    /*
+     * Only one Manual update is allowed
+     */
+    if (csw && update == CompositeRedirectManual)
+	for (ccw = csw->clients; ccw; ccw = ccw->next)
+	    if (ccw->update == CompositeRedirectManual)
+		return BadAccess;
+    /*
+     * Allocate per-client per-window structure 
+     * The client *could* allocate multiple, but while supported,
+     * it is not expected to be common
+     */
+    ccw = xalloc (sizeof (CompClientWindowRec));
+    if (!ccw)
+	return BadAlloc;
+    ccw->id = FakeClientID (pClient->index);
+    ccw->update = update;
+    /*
+     * Now make sure there's a per-window structure to hang this from
+     */
+    if (!csw)
+    {
+	csw = xalloc (sizeof (CompSubwindowsRec));
+	if (!csw)
+	{
+	    xfree (ccw);
+	    return BadAlloc;
+	}
+	csw->update = CompositeRedirectAutomatic;
+	csw->clients = 0;
+	pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = csw;
+    }
+    /*
+     * Redirect all existing windows
+     */
+    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+    {
+	int ret = compRedirectWindow (pClient, pChild, update);
+	if (ret != Success)
+	{
+	    for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
+		(void) compUnredirectWindow (pClient, pChild, update);
+	    if (!csw->clients)
+	    {
+		xfree (csw);
+		pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0;
+	    }
+	    xfree (ccw);
+	    return ret;
+	}
+    }
+    /*
+     * Hook into subwindows list
+     */
+    ccw->next = csw->clients;
+    csw->clients = ccw;
+    if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
+	return BadAlloc;
+    if (ccw->update == CompositeRedirectManual)
+	csw->update = CompositeRedirectManual;
+    return Success;
+}
+
+/*
+ * Free one of the per-client per-subwindows resources,
+ * which frees one redirect per subwindow
+ */
+void
+compFreeClientSubwindows (WindowPtr pWin, XID id)
+{
+    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
+    CompClientWindowPtr	ccw, *prev;
+    WindowPtr		pChild;
+
+    if (!csw)
+	return;
+    for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
+    {
+	if (ccw->id == id)
+	{
+	    ClientPtr	pClient = clients[CLIENT_ID(id)];
+	    
+	    *prev = ccw->next;
+	    if (ccw->update == CompositeRedirectManual)
+		csw->update = CompositeRedirectAutomatic;
+
+	    /*
+	     * Unredirect all existing subwindows
+	     */
+	    for (pChild = pWin->lastChild; pWin; pWin = pWin->prevSib)
+		(void) compUnredirectWindow (pClient, pChild, ccw->update);
+
+	    xfree (ccw);
+	    break;
+	}
+    }
+
+    /*
+     * Check if all of the per-client records are gone
+     */
+    if (!csw->clients)
+    {
+	pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0;
+	xfree (csw);
+    }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+    CompSubwindowsPtr	csw = GetCompSubwindows (pWin);
+    CompClientWindowPtr	ccw;
+    
+    if (!csw)
+	return BadValue;
+    for (ccw = csw->clients; ccw; ccw = ccw->next)
+	if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+	{
+	    FreeResource (ccw->id, RT_NONE);
+	    return Success;
+	}
+    return BadValue;
+}
+
 Bool
 compAllocPixmap (WindowPtr pWin)
 {
@@ -53,39 +319,20 @@
     PixmapPtr	    pPixmap;
     int		    bw = (int) pWin->borderWidth;
     int		    x, y, w, h;
-    CompWindowPtr   cw;
+    CompWindowPtr   cw = GetCompWindow (pWin);
 
-    cw = xalloc (sizeof (CompWindowRec));
-    if (!cw)
-	return FALSE;
-    cw->damage = DamageCreate (compReportDamage,
-			       compDestroyDamage,
-			       DamageReportRawRegion,
-			       FALSE,
-			       pWin);
-    if (!cw->damage)
-    {
-	xfree (cw);
-	return FALSE;
-    }
     x = pWin->drawable.x - bw;
     y = pWin->drawable.y - bw;
     w = pWin->drawable.width + (bw << 1);
     h = pWin->drawable.height + (bw << 1);
     pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth);
     if (!pPixmap)
-    {
-	DamageDestroy (cw->damage);
-	xfree (cw);
 	return FALSE;
-    }
     pPixmap->drawable.x = -x;
     pPixmap->drawable.y = -y;
     pWin->redirectDraw = TRUE;
     compSetPixmap (pWin, pPixmap);
     REGION_INIT (pScreen, &cw->borderClip, NullBox, 0);
-    cw->update = CompositeRedirectAutomatic;
-    pWin->devPrivates[CompWindowPrivateIndex].ptr = cw;
     DamageRegister (&pWin->drawable, cw->damage);
     return TRUE;
 }
@@ -95,16 +342,7 @@
 {
     ScreenPtr	    pScreen = pWin->drawable.pScreen;
     PixmapPtr	    pRedirectPixmap, pParentPixmap;
-    CompWindowPtr   cw = GetCompWindow (pWin);
 
-    REGION_UNINIT (pScreen, &cw->borderClip);
-    if (cw->damage)
-    {
-	DamageUnregister (&pWin->drawable, cw->damage);
-	DamageDestroy (cw->damage);
-    }
-    xfree (cw);
-    pWin->devPrivates[CompWindowPrivateIndex].ptr = 0;
     pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
     pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
     pWin->redirectDraw = FALSE;

Index: compinit.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compinit.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- compinit.c	5 Nov 2003 06:46:13 -0000	1.2
+++ compinit.c	7 Nov 2003 04:26:08 -0000	1.3
@@ -29,6 +29,7 @@
 
 int	CompScreenPrivateIndex;
 int	CompWindowPrivateIndex;
+int	CompSubwindowsPrivateIndex;
 int	CompGeneration;
 
 static Bool
@@ -81,7 +82,7 @@
     pScreen->BlockHandler = compBlockHandler;
 }
 
-static Bool
+Bool
 compScreenInit (ScreenPtr pScreen)
 {
     CompScreenPtr   cs;
@@ -94,11 +95,17 @@
 	CompWindowPrivateIndex = AllocateWindowPrivateIndex ();
 	if (CompWindowPrivateIndex == -1)
 	    return FALSE;
+	CompSubwindowsPrivateIndex = AllocateWindowPrivateIndex ();
+	if (CompSubwindowsPrivateIndex == -1)
+	    return FALSE;
 	CompGeneration = serverGeneration;
     }
     if (!AllocateWindowPrivate (pScreen, CompWindowPrivateIndex, 0))
 	return FALSE;
 
+    if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivateIndex, 0))
+	return FALSE;
+
     if (GetCompScreen (pScreen))
 	return TRUE;
     cs = (CompScreenPtr) xalloc (sizeof (CompScreenRec));
@@ -135,16 +142,3 @@
     pScreen->devPrivates[CompScreenPrivateIndex].ptr = (pointer) cs;
     return TRUE;
 }
-
-void
-CompositeExtensionInit (void)
-{
-    int	    s;
-
-    if (!getenv ("XCOMPOSITE"))
-	return;
-    for (s = 0; s < screenInfo.numScreens; s++)
-	if (!compScreenInit (screenInfo.screens[s]))
-	    return;
-    miRegisterRedirectBorderClipProc (compRedirectBorderClip);
-}

Index: compint.h
===================================================================
RCS file: /cvs/xserver/xserver/composite/compint.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- compint.h	5 Nov 2003 05:45:31 -0000	1.1
+++ compint.h	7 Nov 2003 04:26:08 -0000	1.2
@@ -40,16 +40,31 @@
 #include "servermd.h"
 #include "dixevents.h"
 #include "globals.h"
+#include "picturestr.h"
+#include "extnsionst.h"
 #include "mi.h"
 #include "damage.h"
+#include "xfixes.h"
 #include <X11/extensions/compositeproto.h>
 
+typedef struct _CompClientWindow {
+    struct _CompClientWindow	*next;
+    XID				id;
+    int				update;
+}  CompClientWindowRec, *CompClientWindowPtr;
+
 typedef struct _CompWindow {
     RegionRec		    borderClip;
-    DamagePtr		    damage;
+    DamagePtr		    damage;	/* for automatic update mode */
     int			    update;
+    CompClientWindowPtr	    clients;
 } CompWindowRec, *CompWindowPtr;
 
+typedef struct _CompSubwindows {
+    int			    update;
+    CompClientWindowPtr	    clients;
+} CompSubwindowsRec, *CompSubwindowsPtr;
+
 extern int  CompPixmapPrivateIndex;
 
 typedef struct _CompScreen {
@@ -71,27 +86,75 @@
 
 extern int  CompScreenPrivateIndex;
 extern int  CompWindowPrivateIndex;
+extern int  CompSubwindowsPrivateIndex;
 
 #define GetCompScreen(s) ((CompScreenPtr) ((s)->devPrivates[CompScreenPrivateIndex].ptr))
 #define GetCompWindow(w) ((CompWindowPtr) ((w)->devPrivates[CompWindowPrivateIndex].ptr))
+#define GetCompSubwindows(w) ((CompSubwindowsPtr) ((w)->devPrivates[CompSubwindowsPrivateIndex].ptr))
+
+extern RESTYPE		CompositeClientWindowType;
+extern RESTYPE		CompositeClientSubwindowsType;
+
+/*
+ * compalloc.c
+ */
+
+Bool
+compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update);
 
 void
-compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap);
+compFreeClientWindow (WindowPtr pWin, XID id);
+
+int
+compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update);
+
+int
+compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update);
 
 void
-compCheckTree (ScreenPtr pScreen);
+compFreeClientSubwindows (WindowPtr pWin, XID id);
+
+int
+compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update);
 
 Bool
-compPositionWindow (WindowPtr pWin, int x, int y);
+compAllocPixmap (WindowPtr pWin);
 
 void
-compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+compFreePixmap (WindowPtr pWin);
 
 Bool
-compCreateWindow (WindowPtr pWin);
+compReallocPixmap (WindowPtr pWin);
+
+/*
+ * compext.c
+ */
+
+void
+CompositeExtensionInit (void);
+
+/*
+ * compinit.c
+ */
 
 Bool
-compDestroyWindow (WindowPtr pWin);
+compScreenInit (ScreenPtr pScreen);
+
+/*
+ * compwindow.c
+ */
+
+void
+compCheckTree (ScreenPtr pScreen);
+
+void
+compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap);
+
+Bool
+compCheckRedirect (WindowPtr pWin);
+
+Bool
+compPositionWindow (WindowPtr pWin, int x, int y);
 
 Bool
 compRealizeWindow (WindowPtr pWin);
@@ -102,22 +165,19 @@
 void
 compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent);
 
-void
-compWindowUpdate (WindowPtr pWin);
-
-void
-compRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion);
-
 Bool
-compReallocPixmap (WindowPtr pWin);
+compCreateWindow (WindowPtr pWin);
 
 Bool
-compAllocPixmap (WindowPtr pWin);
+compDestroyWindow (WindowPtr pWin);
 
 void
-compFreePixmap (WindowPtr pWin);
+compRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion);
 
 void
-CompositeExtensionInit (void);
+compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+void
+compWindowUpdate (WindowPtr pWin);
 
 #endif /* _COMPINT_H_ */

Index: compwindow.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compwindow.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- compwindow.c	5 Nov 2003 06:46:13 -0000	1.2
+++ compwindow.c	7 Nov 2003 04:26:08 -0000	1.3
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 #include "compint.h"
-#include "picturestr.h"
 #undef NDEBUG
 #include <assert.h>
 
@@ -85,14 +84,13 @@
 static Bool
 compShouldBeRedirected (WindowPtr pWin)
 {
-    /* XXX static policy during development - redirect children of root */
-    return pWin->viewable && pWin->parent && !pWin->parent->parent;
+    return pWin->viewable && GetCompWindow (pWin);
 }
 
-static Bool
+Bool
 compCheckRedirect (WindowPtr pWin)
 {
-    Bool	    should = compShouldBeRedirected (pWin);
+    Bool	should = compShouldBeRedirected (pWin);
     
     if (should != pWin->redirectDraw)
     {
@@ -194,14 +192,23 @@
 Bool
 compCreateWindow (WindowPtr pWin)
 {
-    ScreenPtr	    pScreen = pWin->drawable.pScreen;
-    CompScreenPtr   cs = GetCompScreen (pScreen);
-    Bool	    ret;
+    ScreenPtr		pScreen = pWin->drawable.pScreen;
+    CompScreenPtr	cs = GetCompScreen (pScreen);
+    Bool		ret;
 
     pScreen->CreateWindow = cs->CreateWindow;
     ret = (*pScreen->CreateWindow) (pWin);
     if (pWin->parent && ret)
+    {
+	CompSubwindowsPtr	csw = GetCompSubwindows (pWin->parent);
+        CompClientWindowPtr	ccw;
+
 	(*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
+	if (csw)
+	    for (ccw = csw->clients; ccw; ccw = ccw->next)
+		compRedirectWindow (clients[CLIENT_ID(ccw->id)],
+				    pWin, ccw->update);
+    }
     cs->CreateWindow = pScreen->CreateWindow;
     pScreen->CreateWindow = compCreateWindow;
     compCheckTree (pWin->drawable.pScreen);