[xserver-commit] xserver/composite compalloc.c,1.6,1.7 compext.c,1.3,1.4 compinit.c,1.7,1.8 compint.h,1.6,1.7 compwindow.c,1.8,1.9

Keith Packard xserver-commit@pdx.freedesktop.org
Wed, 19 Nov 2003 19:31:31 -0800


Committed by: keithp

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

Modified Files:
	compalloc.c compext.c compinit.c compint.h compwindow.c 
Log Message:
	* composite/compalloc.c: (compFreePixmap), (compReallocPixmap):
	* composite/compext.c:
	* composite/compinit.c: (compCloseScreen), (compScreenInit):
	* composite/compint.h:
	* composite/compwindow.c: (compCheckRedirect),
	(compPositionWindow), (compMoveWindow), (compResizeWindow),
	(compChangeBorderWidth), (compCopyWindow):
	* dix/window.c:
	(Yes, these are all related changes).  Rework window manipulation
	while Composite is enabled.  The basic problem was when the
	window was resized, the offscreen pixmap would get resized and if
	that shrunk, the eventual CopyWindow call would not be able to get
	bits.  Now, all resizes are managed by allocating a new pixmap
	and hanging on to the old one until after all of the CopyWindow
	calls are done.
	A related change was to reset the borderClip back to the
	parent-limited version when removing redirection from a window
	so that the UnmapWindow operation within that uses the correct
	value


Index: compalloc.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compalloc.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- compalloc.c	18 Nov 2003 03:41:37 -0000	1.6
+++ compalloc.c	20 Nov 2003 03:31:29 -0000	1.7
@@ -455,11 +455,18 @@
     PixmapPtr	    pRedirectPixmap, pParentPixmap;
     CompWindowPtr   cw = GetCompWindow (pWin);
 
-    if (cw && cw->damageRegistered)
+    if (cw->damageRegistered)
     {
 	DamageUnregister (&pWin->drawable, cw->damage);
 	cw->damageRegistered = FALSE;
     }
+    /*
+     * Move the parent-constrained border clip region back into
+     * the window so that ValidateTree will handle the unmap
+     * case correctly.  Unmap adds the window borderClip to the
+     * parent exposed area; regions beyond the parent cause crashes
+     */
+    REGION_COPY (pScreen, &pWin->borderClip, &cw->borderClip);
     pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
     pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
     pWin->redirectDraw = FALSE;
@@ -469,55 +476,61 @@
 
 /*
  * Make sure the pixmap is the right size and offset.  Allocate a new
- * pixmap to change size, adjust origin to change offset
+ * pixmap to change size, adjust origin to change offset, leaving the
+ * old pixmap in cw->pOldPixmap so bits can be recovered
  */
 Bool
-compReallocPixmap (WindowPtr pWin)
+compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
+		   unsigned int w, unsigned int h, int bw)
 {
     ScreenPtr	    pScreen = pWin->drawable.pScreen;
-    PixmapPtr	    pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+    PixmapPtr	    pOld = (*pScreen->GetWindowPixmap) (pWin);
+    PixmapPtr	    pNew;
     CompWindowPtr   cw = GetCompWindow (pWin);
-    int		    bw = (int) pWin->borderWidth;
-    int		    x, y, w, h;
+    int		    pix_x, pix_y;
+    unsigned int    pix_w, pix_h;
 
-    x = pWin->drawable.x - bw;
-    y = pWin->drawable.y - bw;
-    w = pWin->drawable.width + (bw << 1);
-    h = pWin->drawable.height + (bw << 1);
-    if (w != pPixmap->drawable.width ||
-	h != pPixmap->drawable.height)
+    assert (cw && pWin->redirectDraw);
+    pix_x = draw_x - bw;
+    pix_y = draw_y - bw;
+    pix_w = w + (bw << 1);
+    pix_h = h + (bw << 1);
+    cw->oldx = pOld->screen_x;
+    cw->oldy = pOld->screen_y;
+    if (pix_w != pOld->drawable.width ||
+	pix_h != pOld->drawable.height)
     {
-	GCPtr	    pGC;
-	PixmapPtr   pNew;
+	GCPtr	pGC;
 	
-	pPixmap->refcnt++;
-	compFreePixmap (pWin);
-	if (!compAllocPixmap (pWin))
+	pNew = (*pScreen->CreatePixmap) (pScreen, pix_w, pix_h, pWin->drawable.depth);
+	if (!pNew)
 	    return FALSE;
-	cw->oldx = pPixmap->screen_x;
-	cw->oldy = pPixmap->screen_y;
-	pNew = (*pScreen->GetWindowPixmap) (pWin);
+	cw->pOldPixmap = pOld;
+	compSetPixmap (pWin, pNew);
+	/*
+	 * Copy new bits to align at same place on the screen.  CopyWindow
+	 * calls will patch up any differences
+	 */
 	pGC = GetScratchGC (pNew->drawable.depth, pScreen);
 	if (pGC)
 	{
 	    ValidateGC(&pNew->drawable, pGC);
-	    (void) (*pGC->ops->CopyArea) (&pPixmap->drawable,
-					  &pNew->drawable,
-					  pGC,
-					  0, 0,
-					  pNew->drawable.width,
-					  pNew->drawable.height,
-					  0, 0);
+	    (*pGC->ops->CopyArea) (&pOld->drawable,
+				   &pNew->drawable,
+				   pGC,
+				   pWin->drawable.x - draw_x,
+				   pWin->drawable.y - draw_y,
+				   pix_w, pix_h,
+				   0, 0);
 	    FreeScratchGC (pGC);
 	}
-	(*pScreen->DestroyPixmap) (pPixmap);
     }
     else
     {
-	cw->oldx = pPixmap->screen_x;
-	cw->oldy = pPixmap->screen_y;
-	pPixmap->screen_x = x;
-	pPixmap->screen_y = y;
+	pNew = pOld;
+	cw->pOldPixmap = 0;
     }
+    pNew->screen_x = pix_x;
+    pNew->screen_y = pix_y;
     return TRUE;
 }

Index: compext.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compext.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- compext.c	11 Nov 2003 09:02:22 -0000	1.3
+++ compext.c	20 Nov 2003 03:31:29 -0000	1.4
@@ -26,8 +26,6 @@
 #include <config.h>
 #endif
 #include "compint.h"
-#undef NDEBUG
-#include <assert.h>
 
 int CompositeClientPrivateIndex;
 

Index: compinit.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compinit.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- compinit.c	13 Nov 2003 09:14:29 -0000	1.7
+++ compinit.c	20 Nov 2003 03:31:29 -0000	1.8
@@ -41,6 +41,10 @@
     pScreen->CloseScreen = cs->CloseScreen;
     pScreen->BlockHandler = cs->BlockHandler;
     pScreen->ReparentWindow = cs->ReparentWindow;
+    pScreen->MoveWindow = cs->MoveWindow;
+    pScreen->ResizeWindow = cs->ResizeWindow;
+    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
+    
     pScreen->PaintWindowBackground = cs->PaintWindowBackground;
     pScreen->UnrealizeWindow = cs->UnrealizeWindow;
     pScreen->RealizeWindow = cs->RealizeWindow;
@@ -269,6 +273,15 @@
     cs->PaintWindowBackground = pScreen->PaintWindowBackground;
     pScreen->PaintWindowBackground = compPaintWindowBackground;
 
+    cs->MoveWindow = pScreen->MoveWindow;
+    pScreen->MoveWindow = compMoveWindow;
+
+    cs->ResizeWindow = pScreen->ResizeWindow;
+    pScreen->ResizeWindow = compResizeWindow;
+
+    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
+    pScreen->ChangeBorderWidth = compChangeBorderWidth;
+
     cs->ReparentWindow = pScreen->ReparentWindow;
     pScreen->ReparentWindow = compReparentWindow;
 

Index: compint.h
===================================================================
RCS file: /cvs/xserver/xserver/composite/compint.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- compint.h	13 Nov 2003 09:14:29 -0000	1.6
+++ compint.h	20 Nov 2003 03:31:29 -0000	1.7
@@ -47,6 +47,7 @@
 #include "damageextint.h"
 #include "xfixes.h"
 #include <X11/extensions/compositeproto.h>
+#include <assert.h>
 
 typedef struct _CompClientWindow {
     struct _CompClientWindow	*next;
@@ -63,6 +64,7 @@
     CompClientWindowPtr	    clients;
     int			    oldx;
     int			    oldy;
+    PixmapPtr		    pOldPixmap;
     int			    borderClipX, borderClipY;
 } CompWindowRec, *CompWindowPtr;
 
@@ -83,7 +85,19 @@
     RealizeWindowProcPtr	RealizeWindow;
     UnrealizeWindowProcPtr	UnrealizeWindow;
     PaintWindowProcPtr		PaintWindowBackground;
+    /*
+     * Called from ConfigureWindow, these
+     * three track changes to the offscreen storage
+     * geometry
+     */
+    MoveWindowProcPtr		MoveWindow;
+    ResizeWindowProcPtr		ResizeWindow;
+    ChangeBorderWidthProcPtr	ChangeBorderWidth;
+    /*
+     * Reparenting has an effect on Subwindows redirect
+     */
     ReparentWindowProcPtr	ReparentWindow;
+    
     ScreenBlockHandlerProcPtr	BlockHandler;
     CloseScreenProcPtr		CloseScreen;
     Bool			damaged;
@@ -143,7 +157,8 @@
 compFreePixmap (WindowPtr pWin);
 
 Bool
-compReallocPixmap (WindowPtr pWin);
+compReallocPixmap (WindowPtr pWin, int x, int y,
+		   unsigned int w, unsigned int h, int bw);
 
 /*
  * compext.c
@@ -163,8 +178,12 @@
  * compwindow.c
  */
 
+#ifdef NDEBUG
+#define compCheckTree(s)
+#else
 void
 compCheckTree (ScreenPtr pScreen);
+#endif
 
 void
 compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap);
@@ -185,6 +204,16 @@
 compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what);
 
 void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind);
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+		  unsigned int w, unsigned int h, WindowPtr pSib);
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int border_width);
+
+void
 compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent);
 
 Bool

Index: compwindow.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compwindow.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- compwindow.c	18 Nov 2003 03:41:37 -0000	1.8
+++ compwindow.c	20 Nov 2003 03:31:29 -0000	1.9
@@ -26,9 +26,8 @@
 #include <config.h>
 #endif
 #include "compint.h"
-#undef NDEBUG
-#include <assert.h>
 
+#ifndef NDEBUG
 static int
 compCheckWindow (WindowPtr pWin, pointer data)
 {
@@ -63,6 +62,7 @@
 {
     WalkTree (pScreen, compCheckWindow, 0);
 }
+#endif
 
 typedef struct _compPixmapVisit {
     WindowPtr	pWindow;
@@ -112,8 +112,6 @@
 	else
 	    compFreePixmap (pWin);
     }
-    else if (pWin->redirectDraw)
-	return compReallocPixmap (pWin);
     return TRUE;
 }
 
@@ -125,7 +123,14 @@
     Bool	    ret = TRUE;
 
     pScreen->PositionWindow = cs->PositionWindow;
+    /*
+     * "Shouldn't need this as all possible places should be wrapped
+     *
     compCheckRedirect (pWin);
+     */
+    if (pWin->redirectDraw != (pWin->viewable && (GetCompWindow(pWin) != NULL)))
+	abort ();
+
     if (!(*pScreen->PositionWindow) (pWin, x, y))
 	ret = FALSE;
     cs->PositionWindow = pScreen->PositionWindow;
@@ -200,6 +205,132 @@
 }
 
 void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+    ScreenPtr		pScreen = pWin->drawable.pScreen;
+    CompScreenPtr	cs = GetCompScreen (pScreen);
+
+    compCheckTree (pScreen);
+    if (pWin->redirectDraw)
+    {
+	WindowPtr		pParent;
+	int			draw_x, draw_y;
+	unsigned int		w, h, bw;
+	
+	/* if this is a root window, can't be moved */
+	if (!(pParent = pWin->parent))
+	   return;
+	
+	bw = wBorderWidth (pWin);
+	draw_x = pParent->drawable.x + x + (int)bw;
+	draw_y = pParent->drawable.y + y + (int)bw;
+	w = pWin->drawable.width;
+	h = pWin->drawable.height;
+	compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+    }
+    compCheckTree (pScreen);
+
+    pScreen->MoveWindow = cs->MoveWindow;
+    (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
+    cs->MoveWindow = pScreen->MoveWindow;
+    pScreen->MoveWindow = compMoveWindow;
+
+    if (pWin->redirectDraw)
+    {
+	CompWindowPtr	cw = GetCompWindow (pWin);
+	if (cw->pOldPixmap)
+	{
+	    (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+	    cw->pOldPixmap = NullPixmap;
+	}
+    }
+
+    compCheckTree (pScreen);
+}
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+		  unsigned int w, unsigned int h, WindowPtr pSib)
+{
+    ScreenPtr		pScreen = pWin->drawable.pScreen;
+    CompScreenPtr	cs = GetCompScreen (pScreen);
+
+    compCheckTree (pScreen);
+    if (pWin->redirectDraw)
+    {
+	WindowPtr		pParent;
+	int			draw_x, draw_y;
+	unsigned int		bw;
+	
+	/* if this is a root window, can't be moved */
+	if (!(pParent = pWin->parent))
+	   return;
+	
+	bw = wBorderWidth (pWin);
+	draw_x = pParent->drawable.x + x + (int)bw;
+	draw_y = pParent->drawable.y + y + (int)bw;
+	compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+    }
+    compCheckTree (pScreen);
+    
+    pScreen->ResizeWindow = cs->ResizeWindow;
+    (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
+    cs->ResizeWindow = pScreen->ResizeWindow;
+    pScreen->ResizeWindow = compResizeWindow;
+    if (pWin->redirectDraw)
+    {
+	CompWindowPtr	cw = GetCompWindow (pWin);
+	if (cw->pOldPixmap)
+	{
+	    (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+	    cw->pOldPixmap = NullPixmap;
+	}
+    }
+    compCheckTree (pWin->drawable.pScreen);
+}
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int bw)
+{
+    ScreenPtr		pScreen = pWin->drawable.pScreen;
+    CompScreenPtr	cs = GetCompScreen (pScreen);
+
+    compCheckTree (pScreen);
+    if (pWin->redirectDraw)
+    {
+	WindowPtr		pParent;
+	int			draw_x, draw_y;
+	unsigned int		w, h;
+	
+	/* if this is a root window, can't be moved */
+	if (!(pParent = pWin->parent))
+	   return;
+	
+	draw_x = pWin->drawable.x;
+	draw_y = pWin->drawable.y;
+	w = pWin->drawable.width;
+	h = pWin->drawable.height;
+	compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+    }
+    compCheckTree (pScreen);
+
+    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
+    (*pScreen->ChangeBorderWidth) (pWin, bw);
+    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
+    pScreen->ChangeBorderWidth = compChangeBorderWidth;
+    if (pWin->redirectDraw)
+    {
+	CompWindowPtr	cw = GetCompWindow (pWin);
+	if (cw->pOldPixmap)
+	{
+	    (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+	    cw->pOldPixmap = NullPixmap;
+	}
+    }
+    compCheckTree (pWin->drawable.pScreen);
+}
+
+void
 compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
 {
     ScreenPtr		pScreen = pWin->drawable.pScreen;
@@ -250,7 +381,6 @@
     CompScreenPtr   cs = GetCompScreen (pScreen);
     int		    dx = 0, dy = 0;
 
-    pScreen->CopyWindow = cs->CopyWindow;
     if (pWin->redirectDraw)
     {
 	PixmapPtr	pPixmap = (*pScreen->GetWindowPixmap) (pWin);
@@ -258,11 +388,57 @@
 	
 	assert (cw->oldx != COMP_ORIGIN_INVALID);
 	assert (cw->oldy != COMP_ORIGIN_INVALID);
+	if (cw->pOldPixmap)
+	{
+	    /*
+	     * Ok, the old bits are available in pOldPixmap and
+	     * need to be copied to pNewPixmap.
+	     */
+	    RegionRec	rgnDst;
+	    PixmapPtr	pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+	    GCPtr	pGC;
+	    
+	    dx = ptOldOrg.x - pWin->drawable.x;
+	    dy = ptOldOrg.y - pWin->drawable.y;
+	    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+	    REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+	    REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst,
+			     &pWin->borderClip, prgnSrc);
+	    if (pPixmap->screen_x || pPixmap->screen_y)
+		REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, 
+				  -pPixmap->screen_x, -pPixmap->screen_y);
+	    
+	    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+	    if (pGC)
+	    {
+		BoxPtr	pBox = REGION_RECTS (&rgnDst);
+		int	nBox = REGION_NUM_RECTS (&rgnDst);
+		
+		ValidateGC(&pPixmap->drawable, pGC);
+		while (nBox--)
+		{
+		    (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
+						  &pPixmap->drawable,
+						  pGC,
+						  pBox->x1 + dx, pBox->y1 + dy,
+						  pBox->x2 - pBox->x1,
+						  pBox->y2 - pBox->y1,
+						  pBox->x1, pBox->y1);
+		    pBox++;
+		}
+		FreeScratchGC (pGC);
+	    }
+	    return;
+	}
 	dx = pPixmap->screen_x - cw->oldx;
 	dy = pPixmap->screen_y - cw->oldy;
 	ptOldOrg.x += dx;
 	ptOldOrg.y += dy;
     }
+    
+    pScreen->CopyWindow = cs->CopyWindow;
     if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y)
     {
 	if (dx || dy)