648 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			648 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XFree86: xc/programs/Xserver/Xext/mbufpx.c,v 3.3 2001/07/23 13:15:44 dawes Exp $ */
 | |
| /************************************************************
 | |
| 
 | |
| Copyright 1989, 1998  The Open Group
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| the above copyright notice appear in all copies and that both that
 | |
| copyright notice and this permission notice appear in supporting
 | |
| documentation.
 | |
| 
 | |
| The above copyright notice and this permission notice 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
 | |
| OPEN GROUP 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.
 | |
| 
 | |
| Except as contained in this notice, the name of The Open Group shall not be
 | |
| used in advertising or otherwise to promote the sale, use or other dealings
 | |
| in this Software without prior written authorization from The Open Group.
 | |
| 
 | |
| ********************************************************/
 | |
| 
 | |
| /* $Xorg: mbufpx.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include <stdio.h>
 | |
| #include "X.h"
 | |
| #include "Xproto.h"
 | |
| #include "misc.h"
 | |
| #include "os.h"
 | |
| #include "windowstr.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "extnsionst.h"
 | |
| #include "dixstruct.h"
 | |
| #include "resource.h"
 | |
| #include "opaque.h"
 | |
| #include "regionstr.h"
 | |
| #include "gcstruct.h"
 | |
| #include "inputstr.h"
 | |
| #include <sys/time.h>
 | |
| 
 | |
| #define _MULTIBUF_SERVER_	/* don't want Xlib structures */
 | |
| #define _MULTIBUF_PIXMAP_
 | |
| #include "multibufst.h"
 | |
| 
 | |
| 
 | |
| static Bool NoopDDA_True() { return TRUE; }
 | |
| 
 | |
| static Bool pixPositionWindow();
 | |
| static int  pixCreateImageBuffers();
 | |
| static void pixDisplayImageBuffers();
 | |
| static void pixClearImageBufferArea();
 | |
| static void pixDeleteBufferDrawable();
 | |
| static void pixWrapScreenFuncs();
 | |
| static void pixResetProc();
 | |
| 
 | |
| Bool
 | |
| pixMultibufferInit(pScreen, pMBScreen)
 | |
|     ScreenPtr pScreen;
 | |
|     mbufScreenPtr pMBScreen;
 | |
| {
 | |
|     int			i, j, k;
 | |
|     xMbufBufferInfo	*pInfo;
 | |
|     int			nInfo;
 | |
|     DepthPtr		pDepth;
 | |
|     mbufPixmapPrivPtr	pMBPriv;
 | |
| 
 | |
|     pMBScreen->CreateImageBuffers = pixCreateImageBuffers;
 | |
|     pMBScreen->DestroyImageBuffers = (void (*)())NoopDDA;
 | |
|     pMBScreen->DisplayImageBuffers = pixDisplayImageBuffers;
 | |
|     pMBScreen->ClearImageBufferArea = pixClearImageBufferArea;
 | |
|     pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
 | |
|     pMBScreen->ChangeBufferAttributes = NoopDDA_True;
 | |
|     pMBScreen->DeleteBufferDrawable = pixDeleteBufferDrawable;
 | |
|     pMBScreen->WrapScreenFuncs = pixWrapScreenFuncs;
 | |
|     pMBScreen->ResetProc = pixResetProc;
 | |
| 
 | |
|     /* Support every depth and visual combination that the screen does */
 | |
| 
 | |
|     nInfo = 0;
 | |
|     for (i = 0; i < pScreen->numDepths; i++)
 | |
|     {
 | |
| 	pDepth = &pScreen->allowedDepths[i];
 | |
| 	nInfo += pDepth->numVids;
 | |
|     }
 | |
| 
 | |
|     pInfo = (xMbufBufferInfo *) xalloc (nInfo * sizeof (xMbufBufferInfo));
 | |
|     if (!pInfo)
 | |
| 	return FALSE;
 | |
| 
 | |
|     k = 0;
 | |
|     for (i = 0; i < pScreen->numDepths; i++)
 | |
|     {
 | |
| 	pDepth = &pScreen->allowedDepths[i];
 | |
| 	for (j = 0; j < pDepth->numVids; j++)
 | |
| 	{
 | |
| 	    pInfo[k].visualID = pDepth->vids[j];
 | |
| 	    pInfo[k].maxBuffers = 0;
 | |
| 	    pInfo[k].depth = pDepth->depth;
 | |
| 	    k++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     pMBScreen->nInfo = nInfo;
 | |
|     pMBScreen->pInfo = pInfo;
 | |
| 
 | |
|     /*
 | |
|      * Setup the devPrivate to mbufScreenRec
 | |
|      */
 | |
| 
 | |
|     pMBPriv = (mbufPixmapPrivPtr) xalloc(sizeof(* pMBPriv));
 | |
|     if (!pMBPriv)
 | |
|     {
 | |
| 	xfree(pInfo);
 | |
| 	return (FALSE);
 | |
|     }
 | |
|     pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
 | |
|     pMBPriv->PositionWindow = NULL;
 | |
|     pMBPriv->funcsWrapped = 0;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static int
 | |
| pixCreateImageBuffers (pWin, nbuf, ids, action, hint)
 | |
|     WindowPtr	pWin;
 | |
|     int		nbuf;
 | |
|     XID		*ids;
 | |
|     int		action;
 | |
|     int		hint;
 | |
| {
 | |
|     mbufWindowPtr	pMBWindow;
 | |
|     mbufBufferPtr	pMBBuffer;
 | |
|     ScreenPtr		pScreen;
 | |
|     int			width, height, depth;
 | |
|     int			i;
 | |
| 
 | |
|     pMBWindow = MB_WINDOW_PRIV(pWin);
 | |
| 
 | |
|     width = pWin->drawable.width;
 | |
|     height = pWin->drawable.height;
 | |
|     depth = pWin->drawable.depth;
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
| 
 | |
|     for (i = 0; i < nbuf; i++)
 | |
|     {
 | |
| 	pMBBuffer = &pMBWindow->buffers[i];
 | |
| 	pMBBuffer->pDrawable = (DrawablePtr)
 | |
| 	    (*pScreen->CreatePixmap) (pScreen, width, height, depth);
 | |
| 	if (!pMBBuffer->pDrawable)
 | |
| 	    break;
 | |
| 
 | |
| 	if (!AddResource (ids[i], MultibufferDrawableResType,
 | |
| 			  (pointer) pMBBuffer->pDrawable))
 | |
| 	{
 | |
| 	    (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable);
 | |
| 	    break;
 | |
| 	}
 | |
| 	pMBBuffer->pDrawable->id = ids[i];
 | |
| 
 | |
| 	/*
 | |
| 	 * In the description of the CreateImageBuffers request:
 | |
|          * "If the window is mapped, or if these image buffers have
 | |
|          *  backing store, their contents will be tiled with the window
 | |
|          *  background, and zero or more expose events will be generated
 | |
|          *  for each of these buffers."
 | |
| 	 */
 | |
| 
 | |
| 	(* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
 | |
| 	    (pMBBuffer, 0,0, 0,0, TRUE);
 | |
|     }
 | |
| 
 | |
|     return i;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * set up the gc to clear the pixmaps;
 | |
|  */
 | |
| static Bool
 | |
| SetupBackgroundPainter (pWin, pGC)
 | |
|     WindowPtr	pWin;
 | |
|     GCPtr	pGC;
 | |
| {
 | |
|     XID		    gcvalues[4];
 | |
|     int		    ts_x_origin, ts_y_origin;
 | |
|     PixUnion	    background;
 | |
|     int		    backgroundState;
 | |
|     Mask	    gcmask;
 | |
| 
 | |
|     /*
 | |
|      * First take care of any ParentRelative stuff by altering the
 | |
|      * tile/stipple origin to match the coordinates of the upper-left
 | |
|      * corner of the first ancestor without a ParentRelative background.
 | |
|      * This coordinate is, of course, negative.
 | |
|      */
 | |
| 
 | |
|     ts_x_origin = ts_y_origin = 0;
 | |
|     while (pWin->backgroundState == ParentRelative) {
 | |
| 	ts_x_origin -= pWin->origin.x;
 | |
| 	ts_y_origin -= pWin->origin.y;
 | |
| 	pWin = pWin->parent;
 | |
|     }
 | |
|     backgroundState = pWin->backgroundState;
 | |
|     background = pWin->background;
 | |
| 
 | |
|     switch (backgroundState)
 | |
|     {
 | |
|     case BackgroundPixel:
 | |
| 	gcvalues[0] = (XID) background.pixel;
 | |
| 	gcvalues[1] = FillSolid;
 | |
| 	gcmask = GCForeground|GCFillStyle;
 | |
| 	break;
 | |
| 
 | |
|     case BackgroundPixmap:
 | |
| 	gcvalues[0] = FillTiled;
 | |
| 	gcvalues[1] = (XID) background.pixmap;
 | |
| 	gcvalues[2] = ts_x_origin;
 | |
| 	gcvalues[3] = ts_y_origin;
 | |
| 	gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
 | |
| 	break;
 | |
| 
 | |
|     default:
 | |
| 	return FALSE;
 | |
|     }
 | |
|     DoChangeGC(pGC, gcmask, gcvalues, TRUE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects)
 | |
|     WindowPtr pWin;
 | |
|     DrawablePtr pDrawable;
 | |
|     int nrects;
 | |
|     xRectangle *pRects;
 | |
| {
 | |
|     GCPtr      pGC;
 | |
| 
 | |
|     pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
 | |
|     if (SetupBackgroundPainter(pWin, pGC))
 | |
|     {
 | |
| 	ValidateGC(pDrawable, pGC);
 | |
| 	(*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, pRects);
 | |
|     }
 | |
|     FreeScratchGC(pGC);
 | |
| }
 | |
| 
 | |
| static void
 | |
| MultibufferPaintBackgroundRegion(pWin, pDrawable, pRegion)
 | |
|     WindowPtr pWin;
 | |
|     DrawablePtr pDrawable;
 | |
|     RegionPtr pRegion;
 | |
| {
 | |
|     xRectangle *pRects;
 | |
|     int nrects  = REGION_NUM_RECTS(pRegion);
 | |
|     BoxPtr pbox = REGION_RECTS(pRegion);
 | |
| 
 | |
|     pRects = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle));
 | |
|     if (pRects)
 | |
|     {
 | |
| 	int i;
 | |
| 	for (i = 0; i < nrects; i++)
 | |
| 	{
 | |
| 	    pRects[i].x = pbox->x1;
 | |
| 	    pRects[i].y = pbox->y1;
 | |
| 	    pRects[i].width  = pbox->x2 - pbox->x1;
 | |
| 	    pRects[i].height = pbox->y2 - pbox->y1;
 | |
| 	}
 | |
| 	MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects);
 | |
| 	DEALLOCATE_LOCAL(pRects);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| pixDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
 | |
|     mbufBufferPtr	    *ppMBBuffer;
 | |
|     mbufWindowPtr	    *ppMBWindow;
 | |
|     int		    nbuf;
 | |
| {
 | |
|     GCPtr	    pGC = NULL;
 | |
|     PixmapPtr	    pPrevPixmap, pNewPixmap;
 | |
|     WindowPtr	    pWin;
 | |
|     RegionPtr	    pExposed;
 | |
|     int		    i;
 | |
|     mbufBufferPtr  pPrevMBBuffer;
 | |
|     XID		    bool;
 | |
|     xRectangle      r;
 | |
| 
 | |
|     UpdateCurrentTime ();
 | |
|     for (i = 0; i < nbuf; i++)
 | |
|     {
 | |
| 	pWin = ppMBWindow[i]->pWindow;
 | |
| 
 | |
| 	/* Time to get a different scratch GC? */
 | |
| 
 | |
| 	if (!pGC
 | |
| 	    || pGC->depth   != pWin->drawable.depth
 | |
| 	    || pGC->pScreen != pWin->drawable.pScreen)
 | |
| 	{
 | |
| 	    if (pGC) FreeScratchGC(pGC);
 | |
| 	    pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
 | |
| 	}
 | |
| 	pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
 | |
| 	pPrevPixmap = (PixmapPtr) pPrevMBBuffer->pDrawable;
 | |
| 	pNewPixmap = (PixmapPtr) ppMBBuffer[i]->pDrawable;
 | |
| 
 | |
| 	if (pPrevPixmap == pNewPixmap)
 | |
| 	{
 | |
| 	  /* "If a specified buffer is already displayed, any delays and
 | |
| 	   *  update action will still be performed for that buffer."
 | |
| 	   *
 | |
| 	   *  We special-case this because applications do occasionally
 | |
| 	   *  request a redundant DisplayImageBuffers, and we can save
 | |
| 	   *  strokes by recognizing that the only update action that will
 | |
| 	   *  change the buffer contents in this case is Background.
 | |
| 	   */
 | |
| 	    if (ppMBWindow[i]->updateAction == MultibufferUpdateActionBackground)
 | |
| 	    {
 | |
| 		r.x = r.y = 0;
 | |
| 		r.width  = pWin->drawable.width;
 | |
| 		r.height = pWin->drawable.height;
 | |
| 		MultibufferPaintBackgroundRectangles(pWin, (DrawablePtr)pWin,
 | |
| 						     1, &r);
 | |
| 	    }
 | |
| 	}
 | |
| 	else /* different buffer is being displayed */
 | |
| 	{
 | |
| 	    /* perform update action */
 | |
| 
 | |
| 	    switch (ppMBWindow[i]->updateAction)
 | |
| 	    {
 | |
| 	    case MultibufferUpdateActionUndefined:
 | |
| 		break;
 | |
| 
 | |
| 	    case MultibufferUpdateActionBackground:
 | |
| 
 | |
| 		r.x = r.y = 0;
 | |
| 		r.width  = pPrevPixmap->drawable.width;
 | |
| 		r.height = pPrevPixmap->drawable.height;
 | |
| 		MultibufferPaintBackgroundRectangles(pWin,
 | |
| 						     (DrawablePtr)pPrevPixmap,
 | |
| 						     1, &r);
 | |
| 		break;
 | |
| 
 | |
| 	    case MultibufferUpdateActionUntouched:
 | |
| 		
 | |
| 		/* copy the window to the pixmap that represents the
 | |
| 		 * currently displayed buffer
 | |
| 		 */
 | |
| 
 | |
| 		if (pPrevMBBuffer->eventMask & ExposureMask)
 | |
| 		{
 | |
| 		    bool = TRUE;
 | |
| 		    DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
 | |
| 		}
 | |
| 		ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
 | |
| 		pExposed = (*pGC->ops->CopyArea)((DrawablePtr) pWin,
 | |
| 						 (DrawablePtr) pPrevPixmap,
 | |
| 						 pGC,
 | |
| 						 0, 0,
 | |
| 						 pWin->drawable.width,
 | |
| 						 pWin->drawable.height,
 | |
| 						 0, 0);
 | |
| 
 | |
| 		/* if we couldn't copy the whole window to the buffer,
 | |
| 		 * send expose events (if any client wants them)
 | |
| 		 */
 | |
| 
 | |
| 		if (pPrevMBBuffer->eventMask & ExposureMask)
 | |
| 		{ /* some client wants expose events */
 | |
| 		    if (pExposed)
 | |
| 		    {
 | |
| 			RegionPtr	 pWinSize;
 | |
| 			extern RegionPtr CreateUnclippedWinSize();
 | |
| 			ScreenPtr pScreen = pWin->drawable.pScreen;
 | |
| 			pWinSize = CreateUnclippedWinSize (pWin);
 | |
| 			/*
 | |
| 			 * pExposed is window-relative, but at this point
 | |
| 			 * pWinSize is screen-relative.  Make pWinSize be
 | |
| 			 * window-relative so that region ops involving
 | |
| 			 * pExposed and pWinSize behave sensibly.
 | |
| 			 */
 | |
| 			REGION_TRANSLATE(pScreen, pWinSize,
 | |
| 						     -pWin->drawable.x,
 | |
| 						     -pWin->drawable.y);
 | |
| 			REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize);
 | |
| 			REGION_DESTROY(pScreen, pWinSize);
 | |
| 			MultibufferExpose (pPrevMBBuffer, pExposed);
 | |
| 			REGION_DESTROY(pScreen, pExposed);
 | |
| 		    }
 | |
| 		    bool = FALSE;
 | |
| 		    DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
 | |
| 		} /* end some client wants expose events */
 | |
| 
 | |
| 		break; /* end case MultibufferUpdateActionUntouched */
 | |
| 
 | |
| 	    case MultibufferUpdateActionCopied:
 | |
| 
 | |
| 		ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
 | |
| 		(*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap,
 | |
| 				       (DrawablePtr)pPrevPixmap, pGC,
 | |
| 				       0, 0, pWin->drawable.width,
 | |
| 				       pWin->drawable.height, 0, 0);
 | |
| 		break;
 | |
| 
 | |
| 	    } /* end switch on update action */
 | |
| 
 | |
| 	    /* display the new buffer */
 | |
| 
 | |
| 	    ValidateGC ((DrawablePtr)pWin, pGC);
 | |
| 	    (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin,
 | |
| 				   pGC, 0, 0,
 | |
| 				   pWin->drawable.width, pWin->drawable.height,
 | |
| 				   0, 0);
 | |
| 	}
 | |
| 
 | |
| 	ppMBWindow[i]->lastUpdate = currentTime;
 | |
|     }
 | |
| 
 | |
|     if (pGC) FreeScratchGC (pGC);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * resize the buffers when the window is resized
 | |
|  */ 
 | |
| 
 | |
| static Bool
 | |
| pixPositionWindow (pWin, x, y)
 | |
|     WindowPtr	pWin;
 | |
|     int		x, y;
 | |
| {
 | |
|     ScreenPtr	    pScreen;
 | |
|     mbufPixmapPrivPtr pMBPriv;
 | |
|     mbufWindowPtr   pMBWindow;
 | |
|     mbufBufferPtr   pMBBuffer;
 | |
|     int		    width, height;
 | |
|     int		    i;
 | |
|     int		    dx, dy, dw, dh;
 | |
|     int		    sourcex, sourcey;
 | |
|     int		    destx, desty;
 | |
|     PixmapPtr	    pPixmap;
 | |
|     GCPtr	    pGC;
 | |
|     int		    savewidth, saveheight;
 | |
|     Bool	    clear;
 | |
|     RegionRec       exposedRegion;
 | |
|     Bool	    ret;
 | |
| 
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
|     pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
 | |
| 
 | |
|     UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow);
 | |
|     ret = (* pScreen->PositionWindow) (pWin, x, y);
 | |
|     REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow);
 | |
| 
 | |
|     if (!(pMBWindow = MB_WINDOW_PRIV(pWin)))
 | |
| 	return ret;
 | |
| 
 | |
|     /* if new size is same as old, we're done */
 | |
| 
 | |
|     if (pMBWindow->width == pWin->drawable.width &&
 | |
|         pMBWindow->height == pWin->drawable.height)
 | |
| 	return ret;
 | |
| 
 | |
|     width = pWin->drawable.width;
 | |
|     height = pWin->drawable.height;
 | |
|     dx = pWin->drawable.x - pMBWindow->x;
 | |
|     dy = pWin->drawable.x - pMBWindow->y;
 | |
|     dw = width - pMBWindow->width;
 | |
|     dh = height - pMBWindow->height;
 | |
|     GravityTranslate (0, 0, -dx, -dy, dw, dh,
 | |
| 		      pWin->bitGravity, &destx, &desty);
 | |
| 
 | |
|     /* if the window grew, remember to paint the window background,
 | |
|      * and maybe send expose events, for the new areas of the buffers
 | |
|      */
 | |
| 
 | |
|     clear = pMBWindow->width < width || pMBWindow->height < height ||
 | |
| 	    pWin->bitGravity == ForgetGravity;
 | |
| 
 | |
|     sourcex = 0;
 | |
|     sourcey = 0;
 | |
|     savewidth = pMBWindow->width;
 | |
|     saveheight = pMBWindow->height;
 | |
|     /* clip rectangle to source and destination */
 | |
|     if (destx < 0)
 | |
|     {
 | |
| 	savewidth += destx;
 | |
| 	sourcex -= destx;
 | |
| 	destx = 0;
 | |
|     }
 | |
|     if (destx + savewidth > width)
 | |
| 	savewidth = width - destx;
 | |
|     if (desty < 0)
 | |
|     {
 | |
| 	saveheight += desty;
 | |
| 	sourcey -= desty;
 | |
| 	desty = 0;
 | |
|     }
 | |
|     if (desty + saveheight > height)
 | |
| 	saveheight = height - desty;
 | |
| 
 | |
|     pMBWindow->width = width;
 | |
|     pMBWindow->height = height;
 | |
|     pMBWindow->x = pWin->drawable.x;
 | |
|     pMBWindow->y = pWin->drawable.y;
 | |
| 
 | |
|     if (clear)
 | |
|     {
 | |
| 	BoxRec box;
 | |
| 
 | |
| 	box.x1 = box.y1 = 0;
 | |
| 	box.x2 = width;
 | |
| 	box.y2 = height;
 | |
| 	REGION_INIT(pScreen, &exposedRegion, &box, 1);
 | |
| 	if (pWin->bitGravity != ForgetGravity)
 | |
| 	{
 | |
| 	    RegionRec preservedRegion;
 | |
| 	    box.x1 = destx;
 | |
| 	    box.y1 = desty;
 | |
| 	    box.x2 = destx + savewidth;
 | |
| 	    box.y2 = desty + saveheight;
 | |
| 	    REGION_INIT(pScreen, &preservedRegion, &box, 1);
 | |
| 	    REGION_SUBTRACT(pScreen, &exposedRegion, &exposedRegion, &preservedRegion);
 | |
| 	    REGION_UNINIT(pScreen, &preservedRegion);
 | |
| 	}
 | |
| 
 | |
|     } /* end if (clear) */
 | |
| 
 | |
|     pGC = GetScratchGC (pWin->drawable.depth, pScreen);
 | |
| 
 | |
|     /* create buffers with new window size */
 | |
| 
 | |
|     for (i = 0; i < pMBWindow->numMultibuffer; i++)
 | |
|     {
 | |
| 	pMBBuffer = &pMBWindow->buffers[i];
 | |
| 	pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, pWin->drawable.depth);
 | |
| 	if (!pPixmap)
 | |
| 	{
 | |
| 	    (* MB_SCREEN_PRIV(pScreen)->DestroyImageBuffers)(pWin);
 | |
| 	    break;
 | |
| 	}
 | |
| 	if (clear)
 | |
| 	{
 | |
| 	    MultibufferPaintBackgroundRegion(pWin, (DrawablePtr)pPixmap, &exposedRegion);
 | |
| 	    MultibufferExpose(pMBBuffer, &exposedRegion);
 | |
| 	}
 | |
| 	if (pWin->bitGravity != ForgetGravity)
 | |
| 	{
 | |
| 	    ValidateGC ((DrawablePtr)pPixmap, pGC);
 | |
| 	    (*pGC->ops->CopyArea) (pMBBuffer->pDrawable, (DrawablePtr)pPixmap,
 | |
| 				   pGC,
 | |
| 				   sourcex, sourcey, savewidth, saveheight,
 | |
| 				   destx, desty);
 | |
| 	}
 | |
| 	pPixmap->drawable.id = pMBBuffer->pDrawable->id;
 | |
| 	(*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable);
 | |
| 	pMBBuffer->pDrawable = (DrawablePtr) pPixmap;
 | |
| 	if (i != pMBWindow->displayedMultibuffer)
 | |
| 	{
 | |
| 	    ChangeResourceValue (pPixmap->drawable.id,
 | |
| 				 MultibufferDrawableResType,
 | |
| 				 (pointer) pPixmap);
 | |
| 	}
 | |
|     }
 | |
|     FreeScratchGC (pGC);
 | |
|     if (clear)
 | |
| 	REGION_UNINIT(pScreen, &exposedRegion);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| pixWrapScreenFuncs(pScreen)
 | |
|     ScreenPtr pScreen;
 | |
| {
 | |
|     mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
 | |
|     WRAP_SCREEN_FUNC(pScreen, pMBPriv, PositionWindow, pixPositionWindow);
 | |
| }
 | |
| 
 | |
| static void
 | |
| pixResetProc(pScreen)
 | |
|     ScreenPtr pScreen;
 | |
| {
 | |
|     mbufScreenPtr pMBScreen = MB_SCREEN_PRIV(pScreen);
 | |
|     mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
 | |
| 
 | |
|     xfree(pMBScreen->pInfo);
 | |
|     xfree(pMBPriv);
 | |
| }
 | |
| 
 | |
| static void
 | |
| pixClearImageBufferArea(pMBBuffer, x,y, width,height, exposures)
 | |
|     mbufBufferPtr	pMBBuffer;
 | |
|     short		x, y;
 | |
|     unsigned short	width, height;
 | |
|     Bool		exposures;
 | |
| {
 | |
|     WindowPtr pWin;
 | |
|     ScreenPtr pScreen;
 | |
|     BoxRec box;
 | |
|     RegionRec region;
 | |
|     int w_width, w_height;
 | |
|     DrawablePtr pDrawable;
 | |
| 
 | |
|     pWin = pMBBuffer->pMBWindow->pWindow;
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
| 
 | |
|     w_width  = pWin->drawable.width;
 | |
|     w_height = pWin->drawable.height;
 | |
| 
 | |
|     box.x1 = x;
 | |
|     box.y1 = y;
 | |
|     box.x2 = width  ? (box.x1 + width)  : w_width;
 | |
|     box.y2 = height ? (box.y1 + height) : w_height;
 | |
| 
 | |
|     if (box.x1 < 0)        box.x1 = 0;
 | |
|     if (box.y1 < 0)        box.y1 = 0;
 | |
|     if (box.x2 > w_width)  box.x2 = w_width;
 | |
|     if (box.y2 > w_height) box.y2 = w_height;
 | |
| 
 | |
|     REGION_INIT(pScreen, ®ion, &box, 1);
 | |
| 
 | |
|     if (pMBBuffer->number == pMBBuffer->pMBWindow->displayedMultibuffer)
 | |
|       pDrawable = (DrawablePtr) pWin;
 | |
|     else
 | |
|       pDrawable = pMBBuffer->pDrawable;
 | |
| 
 | |
|     MultibufferPaintBackgroundRegion(pWin, pDrawable, ®ion);
 | |
| 
 | |
|     if (exposures)
 | |
| 	MultibufferExpose(pMBBuffer, ®ion);
 | |
| 
 | |
|     REGION_UNINIT(pScreen, ®ion);
 | |
| }
 | |
| 
 | |
| static void
 | |
| pixDeleteBufferDrawable(pDrawable)
 | |
|     DrawablePtr	pDrawable;
 | |
| {
 | |
|     (* pDrawable->pScreen->DestroyPixmap)((PixmapPtr) pDrawable);
 | |
| }
 |