1012 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1012 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
#define NEED_REPLIES
 | 
						|
#define NEED_EVENTS
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/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 "validate.h"
 | 
						|
#include <sys/time.h>
 | 
						|
 | 
						|
#define _MULTIBUF_SERVER_	/* don't want Xlib structures */
 | 
						|
#define _MULTIBUF_BUFFER_
 | 
						|
#include <X11/extensions/multibufst.h>
 | 
						|
 | 
						|
/* 
 | 
						|
Support for doublebuffer hardare
 | 
						|
 | 
						|
This code is designed to support doublebuffer hardware where the
 | 
						|
displayed buffer is selected on a per-pixel basis by an additional bit
 | 
						|
plane, called the select plane. It could probably be easily modified
 | 
						|
to work with systems that use window-id planes.
 | 
						|
 | 
						|
This is done by creating a new drawable type, DRAWABLE_BUFFER. The
 | 
						|
type has the same exact layout as a window drawable. Your code should
 | 
						|
treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW
 | 
						|
when handling the gc drawing functions. In addition, PaintWindowBackground,
 | 
						|
CopyWindow, and all of the gc drawing functions to be able to draw into both
 | 
						|
framebuffers. Which framebuffer to draw into is selected by the contents of
 | 
						|
	pWin->devPrivates[frameWindowPrivateIndex].
 | 
						|
The content of the devPrivate is either from frameBuffer[0] or
 | 
						|
frameBuffer[1], depending on which buffer is being drawn into. When
 | 
						|
	pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0],
 | 
						|
the functions should draw into the front framebuffer. When
 | 
						|
	pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1],
 | 
						|
the functions should draw into the back framebuffer.
 | 
						|
 | 
						|
In addition, you need to provide a function that allows you to copy
 | 
						|
bits between the buffers (optional since CopyArea can be used) and a
 | 
						|
function that draws into the select plane. Then, you need to register
 | 
						|
your functions and other information, by calling:
 | 
						|
 | 
						|
void
 | 
						|
RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
 | 
						|
			     CopyBufferBitsFunc, DrawSelectPlaneFunc)
 | 
						|
    int			nInfo;
 | 
						|
    xMbufBufferInfo	*pInfo;
 | 
						|
    DevUnion		*frameBuffer;
 | 
						|
    DevUnion		selectPlane;
 | 
						|
 | 
						|
"pInfo" is an array indicating which visuals and depths that double
 | 
						|
buffering is supported on. "nInfo" is the length of the array.
 | 
						|
 | 
						|
"frameBuffer" is array of length 2. The contents of the array element
 | 
						|
is ddx-specific. The content of frameBuffer[0] should, when placed in
 | 
						|
the window private, indicate that framebuffer 0 should be drawn into.
 | 
						|
The contents of frameBuffer[1], when placed into the window private,
 | 
						|
should indicate that framebuffer 1 should be drawn into.
 | 
						|
 | 
						|
"selectPlane" is ddx-specific. It should contain information
 | 
						|
neccessary for your displayProc to access the select plane.
 | 
						|
It is passed to DrawSelectPlaneFunc.
 | 
						|
 | 
						|
"CopyBufferBitsFunc" is a ddx-specific function that copies from one
 | 
						|
buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc
 | 
						|
is NULL, a default function will be used that calls pScreen->CopyArea.
 | 
						|
 | 
						|
    void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum)
 | 
						|
        mbufWindowPtr pMBWindow;
 | 
						|
        int srcBufferNum, dstBufferNum;
 | 
						|
 | 
						|
"DrawSelectPlaneFunc" is a ddx-specific function that fills the
 | 
						|
regions "prgn" of select plane with the value "bufferNum". If 
 | 
						|
selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass
 | 
						|
NULL for DrawSelectPlaneFunc, a default function will be used that
 | 
						|
calls FillRectangle on the selectPlane.
 | 
						|
 | 
						|
    void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum)
 | 
						|
        ScreenPtr	pScreen;
 | 
						|
        DevUnion	selectPlane;
 | 
						|
        RegionPtr	prgn;
 | 
						|
        long		bufferNum;
 | 
						|
 | 
						|
...
 | 
						|
...
 | 
						|
...
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#define MAX_BUFFERS  2	/* Only supports 2 buffers */
 | 
						|
#define FRONT_BUFFER 0
 | 
						|
#define BACK_BUFFER  1
 | 
						|
 | 
						|
 | 
						|
/* Buffer drawables have the same structure as window drawables */
 | 
						|
typedef WindowRec BufferRec;
 | 
						|
typedef WindowPtr BufferPtr;
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware. 
 | 
						|
 */
 | 
						|
 | 
						|
static int		bufNumInfo[MAXSCREENS];
 | 
						|
static xMbufBufferInfo	*bufInfo[MAXSCREENS];
 | 
						|
static DevUnion		*bufFrameBuffer[MAXSCREENS];
 | 
						|
static DevUnion		bufselectPlane[MAXSCREENS];
 | 
						|
static void		(* bufCopyBufferBitsFunc[MAXSCREENS])();
 | 
						|
static void		(* bufDrawSelectPlaneFunc[MAXSCREENS])();
 | 
						|
 | 
						|
static Bool bufMultibufferInit();
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
 | 
						|
			     CopyBufferBitsFunc, DrawSelectPlaneFunc)
 | 
						|
    ScreenPtr		pScreen;
 | 
						|
    int			nInfo;
 | 
						|
    xMbufBufferInfo	*pInfo;
 | 
						|
    DevUnion		*frameBuffer;
 | 
						|
    DevUnion		selectPlane;
 | 
						|
    void		(* CopyBufferBitsFunc)();
 | 
						|
    void		(* DrawSelectPlaneFunc)();
 | 
						|
{
 | 
						|
    bufNumInfo[pScreen->myNum]     = nInfo;
 | 
						|
    bufInfo[pScreen->myNum]        = pInfo;
 | 
						|
    bufFrameBuffer[pScreen->myNum] = frameBuffer;
 | 
						|
    bufselectPlane[pScreen->myNum] = selectPlane;
 | 
						|
 | 
						|
    bufCopyBufferBitsFunc[pScreen->myNum]  = CopyBufferBitsFunc;
 | 
						|
    bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc;
 | 
						|
 | 
						|
    /* Register ourselves with device-independent multibuffers code */
 | 
						|
    RegisterMultibufferInit(pScreen, bufMultibufferInit);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Called by Multibuffer extension initialization.
 | 
						|
 * Initializes mbufScreenRec and its devPrivate.
 | 
						|
 */
 | 
						|
    
 | 
						|
static Bool NoopDDA_True() { return TRUE; }
 | 
						|
static Bool bufPositionWindow();
 | 
						|
static int  bufCreateImageBuffers();
 | 
						|
static void bufDestroyImageBuffers();
 | 
						|
static void bufDisplayImageBuffers();
 | 
						|
static void bufClearImageBufferArea();
 | 
						|
static void bufDestroyBuffer();
 | 
						|
static void bufCopyBufferBits();
 | 
						|
static void bufDrawSelectPlane();
 | 
						|
static void bufWrapScreenFuncs();
 | 
						|
static void bufResetProc();
 | 
						|
 | 
						|
static void bufPostValidateTree();
 | 
						|
static void bufClipNotify();
 | 
						|
static void bufWindowExposures();
 | 
						|
static Bool bufChangeWindowAttributes();
 | 
						|
static void bufClearToBackground();
 | 
						|
static void bufCopyWindow();
 | 
						|
 | 
						|
extern WindowPtr *WindowTable;
 | 
						|
 | 
						|
static Bool
 | 
						|
bufMultibufferInit(pScreen, pMBScreen)
 | 
						|
    ScreenPtr pScreen;
 | 
						|
    mbufScreenPtr pMBScreen;
 | 
						|
{
 | 
						|
    mbufBufferPrivPtr	pMBPriv;
 | 
						|
    BoxRec		box;
 | 
						|
 | 
						|
    /* Multibuffer info */
 | 
						|
    pMBScreen->nInfo = bufNumInfo[pScreen->myNum];
 | 
						|
    pMBScreen->pInfo = bufInfo[pScreen->myNum];
 | 
						|
 | 
						|
    /* Hooks */
 | 
						|
    pMBScreen->CreateImageBuffers = bufCreateImageBuffers;
 | 
						|
    pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers;
 | 
						|
    pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers;
 | 
						|
    pMBScreen->ClearImageBufferArea = bufClearImageBufferArea;
 | 
						|
    pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
 | 
						|
    pMBScreen->ChangeBufferAttributes = NoopDDA_True;
 | 
						|
    pMBScreen->DeleteBufferDrawable = bufDestroyBuffer;
 | 
						|
    pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs;
 | 
						|
    pMBScreen->ResetProc = bufResetProc;
 | 
						|
    /* Create devPrivate part */
 | 
						|
    pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv);
 | 
						|
    if (!pMBPriv)
 | 
						|
	return (FALSE);
 | 
						|
 | 
						|
    pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
 | 
						|
    pMBPriv->frameBuffer  = bufFrameBuffer[pScreen->myNum];
 | 
						|
    pMBPriv->selectPlane = bufselectPlane[pScreen->myNum];
 | 
						|
 | 
						|
    /*
 | 
						|
     * Initializing the subtractRgn to the screen area will ensure that
 | 
						|
     * the selectPlane will get cleared on the first PostValidateTree.
 | 
						|
     */
 | 
						|
 | 
						|
    box.x1 = 0;
 | 
						|
    box.y1 = 0;
 | 
						|
    box.x2 = pScreen->width;
 | 
						|
    box.y2 = pScreen->height;
 | 
						|
 | 
						|
    pMBPriv->rgnChanged = TRUE;
 | 
						|
    REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1);
 | 
						|
    REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1);
 | 
						|
    REGION_NULL(pScreen, &pMBPriv->unionRgn);
 | 
						|
 | 
						|
    /* Misc functions */
 | 
						|
    pMBPriv->CopyBufferBits  = bufCopyBufferBitsFunc[pScreen->myNum];
 | 
						|
    pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum];
 | 
						|
 | 
						|
    if (!pMBPriv->CopyBufferBits)
 | 
						|
	pMBPriv->CopyBufferBits = bufCopyBufferBits;
 | 
						|
 | 
						|
    if (!pMBPriv->DrawSelectPlane)
 | 
						|
	pMBPriv->DrawSelectPlane = bufDrawSelectPlane;
 | 
						|
 | 
						|
    /* screen functions */
 | 
						|
    pMBPriv->funcsWrapped = 0;
 | 
						|
    pMBPriv->inClearToBackground = FALSE;
 | 
						|
    pMBPriv->WindowExposures = NULL;
 | 
						|
    pMBPriv->CopyWindow = NULL;
 | 
						|
    pMBPriv->ClearToBackground = NULL;
 | 
						|
    pMBPriv->ClipNotify = NULL;
 | 
						|
    pMBPriv->ChangeWindowAttributes = NULL;
 | 
						|
 | 
						|
    /* Start out wrapped to clear select plane */
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
UpdateBufferFromWindow(pBuffer, pWin)
 | 
						|
    BufferPtr	pBuffer;
 | 
						|
    WindowPtr	pWin;
 | 
						|
{
 | 
						|
    pBuffer->drawable.x      = pWin->drawable.x;
 | 
						|
    pBuffer->drawable.y      = pWin->drawable.y;
 | 
						|
    pBuffer->drawable.width  = pWin->drawable.width;
 | 
						|
    pBuffer->drawable.height = pWin->drawable.height;
 | 
						|
 | 
						|
    pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 | 
						|
 | 
						|
    /* Update for PaintWindowBackground */
 | 
						|
    pBuffer->parent = pWin->parent;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Make the borderClip the same as the clipList so
 | 
						|
     * NotClippedByChildren comes out with just clipList.
 | 
						|
     */
 | 
						|
 | 
						|
    pBuffer->clipList   = pWin->clipList;
 | 
						|
    pBuffer->borderClip = pWin->clipList;
 | 
						|
    pBuffer->winSize    = pWin->winSize;
 | 
						|
    pBuffer->borderSize = pWin->borderSize;
 | 
						|
 | 
						|
    pBuffer->origin = pWin->origin;
 | 
						|
}
 | 
						|
 | 
						|
static BufferPtr
 | 
						|
bufCreateBuffer(pScreen, pWin, bufferNum)
 | 
						|
    ScreenPtr	pScreen;
 | 
						|
    WindowPtr	pWin;
 | 
						|
    int		bufferNum;
 | 
						|
{
 | 
						|
    mbufBufferPrivPtr	pMBPriv;
 | 
						|
    DevUnion	*devPrivates;
 | 
						|
    BufferPtr	pBuffer;
 | 
						|
    int		i;
 | 
						|
 | 
						|
    pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    pBuffer = AllocateWindow(pWin->drawable.pScreen);
 | 
						|
    if (!pBuffer)
 | 
						|
	return (NULL);
 | 
						|
 | 
						|
    /* XXX- Until we know what is needed, copy everything. */
 | 
						|
    devPrivates = pBuffer->devPrivates;
 | 
						|
    *pBuffer = *pWin;
 | 
						|
    pBuffer->devPrivates   = devPrivates;
 | 
						|
 | 
						|
    pBuffer->drawable.type = DRAWABLE_BUFFER;
 | 
						|
    pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 | 
						|
 | 
						|
    pBuffer->nextSib    = NULL;
 | 
						|
    pBuffer->prevSib    = NULL;
 | 
						|
    pBuffer->firstChild = NULL;
 | 
						|
    pBuffer->lastChild  = NULL;
 | 
						|
 | 
						|
    /* XXX - Need to call pScreen->CreateWindow for tile/stipples
 | 
						|
     *       or should I just copy the devPrivates?
 | 
						|
     */
 | 
						|
    
 | 
						|
    for (i=0; i < pScreen->WindowPrivateLen; i++)
 | 
						|
	pBuffer->devPrivates[i] = pWin->devPrivates[i];
 | 
						|
 | 
						|
    pBuffer->devPrivates[frameWindowPrivateIndex] =
 | 
						|
	pMBPriv->frameBuffer[bufferNum];
 | 
						|
 | 
						|
    return pBuffer;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
bufDestroyBuffer(pDrawable)
 | 
						|
    DrawablePtr	pDrawable;
 | 
						|
{
 | 
						|
    xfree(pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
static int
 | 
						|
bufCreateImageBuffers (pWin, nbuf, ids, action, hint)
 | 
						|
    WindowPtr	pWin;
 | 
						|
    int		nbuf;
 | 
						|
    XID		*ids;
 | 
						|
    int		action;
 | 
						|
    int		hint;
 | 
						|
{
 | 
						|
    ScreenPtr		pScreen;
 | 
						|
    mbufScreenPtr	pMBScreen;
 | 
						|
    mbufWindowPtr	pMBWindow;
 | 
						|
    mbufBufferPtr	pMBBuffer;
 | 
						|
    int			i;
 | 
						|
 | 
						|
    pScreen   = pWin->drawable.pScreen;
 | 
						|
    pMBScreen = MB_SCREEN_PRIV(pScreen);
 | 
						|
    pMBWindow = MB_WINDOW_PRIV(pWin);
 | 
						|
 | 
						|
    pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0);
 | 
						|
    if (!pMBWindow->devPrivate.ptr)
 | 
						|
	return(0);
 | 
						|
    REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr,
 | 
						|
			    &pWin->clipList);
 | 
						|
 | 
						|
    for (i = 0; i < nbuf; i++)
 | 
						|
    {
 | 
						|
	pMBBuffer = pMBWindow->buffers + i;
 | 
						|
	pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i);
 | 
						|
 | 
						|
	if (!pMBBuffer->pDrawable)
 | 
						|
	    break;
 | 
						|
 | 
						|
	if (!AddResource (ids[i], MultibufferDrawableResType,
 | 
						|
			  (pointer) pMBBuffer->pDrawable))
 | 
						|
	{
 | 
						|
	    bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable);
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	pMBBuffer->pDrawable->id = ids[i];
 | 
						|
 | 
						|
	/*
 | 
						|
	 * If window is already mapped, generate exposures and
 | 
						|
	 * clear the area of the newly buffers.
 | 
						|
	 */
 | 
						|
 | 
						|
	if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer))
 | 
						|
	    (* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE);
 | 
						|
    }
 | 
						|
 | 
						|
    return i;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
bufDestroyImageBuffers(pWin)
 | 
						|
    WindowPtr	pWin;
 | 
						|
{
 | 
						|
    ScreenPtr		pScreen;
 | 
						|
    mbufWindowPtr	pMBWindow;
 | 
						|
 | 
						|
    pScreen   = pWin->drawable.pScreen;
 | 
						|
 | 
						|
    if (pMBWindow = MB_WINDOW_PRIV(pWin))
 | 
						|
    {
 | 
						|
	mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * if the backbuffer is currently being displayed, move the bits
 | 
						|
	 * to the frontbuffer and display it instead.
 | 
						|
	 */
 | 
						|
 | 
						|
	if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER))
 | 
						|
	{
 | 
						|
	    (* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER);
 | 
						|
	    REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer,
 | 
						|
				  &pMBPriv->backBuffer, &pWin->clipList);
 | 
						|
	    (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
 | 
						|
			    &pWin->clipList, FRONT_BUFFER);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Switch window rendering to front buffer */
 | 
						|
	pWin->devPrivates[frameWindowPrivateIndex] =
 | 
						|
	    pMBPriv->frameBuffer[FRONT_BUFFER];
 | 
						|
 | 
						|
	REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr);
 | 
						|
	pMBWindow->devPrivate.ptr = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask
 | 
						|
 * and wOtherEventsMasks(pBuffer) were setup.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures)
 | 
						|
    mbufBufferPtr	pMBBuffer;
 | 
						|
    short		x,y;
 | 
						|
    unsigned short	w,h;
 | 
						|
    Bool		generateExposures;
 | 
						|
{
 | 
						|
    BoxRec box;
 | 
						|
    RegionRec	reg;
 | 
						|
    RegionPtr pBSReg = NullRegion;
 | 
						|
    ScreenPtr	pScreen;
 | 
						|
    BoxPtr  extents;
 | 
						|
    int	    x1, y1, x2, y2;
 | 
						|
    BufferPtr pBuffer;
 | 
						|
 | 
						|
    pBuffer = (BufferPtr) pMBBuffer->pDrawable;
 | 
						|
    /* compute everything using ints to avoid overflow */
 | 
						|
 | 
						|
    x1 = pBuffer->drawable.x + x;
 | 
						|
    y1 = pBuffer->drawable.y + y;
 | 
						|
    if (w)
 | 
						|
        x2 = x1 + (int) w;
 | 
						|
    else
 | 
						|
        x2 = x1 + (int) pBuffer->drawable.width - (int) x;
 | 
						|
    if (h)
 | 
						|
        y2 = y1 + h;	
 | 
						|
    else
 | 
						|
        y2 = y1 + (int) pBuffer->drawable.height - (int) y;
 | 
						|
 | 
						|
    extents = &pBuffer->clipList.extents;
 | 
						|
    
 | 
						|
    /* clip the resulting rectangle to the window clipList extents.  This
 | 
						|
     * makes sure that the result will fit in a box, given that the
 | 
						|
     * screen is < 32768 on a side.
 | 
						|
     */
 | 
						|
 | 
						|
    if (x1 < extents->x1)
 | 
						|
	x1 = extents->x1;
 | 
						|
    if (x2 > extents->x2)
 | 
						|
	x2 = extents->x2;
 | 
						|
    if (y1 < extents->y1)
 | 
						|
	y1 = extents->y1;
 | 
						|
    if (y2 > extents->y2)
 | 
						|
	y2 = extents->y2;
 | 
						|
 | 
						|
    if (x2 <= x1 || y2 <= y1)
 | 
						|
    {
 | 
						|
	x2 = x1 = 0;
 | 
						|
	y2 = y1 = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    box.x1 = x1;
 | 
						|
    box.x2 = x2;
 | 
						|
    box.y1 = y1;
 | 
						|
    box.y2 = y2;
 | 
						|
 | 
						|
    pScreen = pBuffer->drawable.pScreen;
 | 
						|
    REGION_INIT(pScreen, ®, &box, 1);
 | 
						|
 | 
						|
    REGION_INTERSECT(pScreen, ®, ®, &pBuffer->clipList);
 | 
						|
    if (pBuffer->backgroundState != None)
 | 
						|
	miPaintWindow(pBuffer, ®, PW_BACKGROUND);
 | 
						|
    if (generateExposures)
 | 
						|
	MultibufferExpose(pMBBuffer, ®);
 | 
						|
#ifdef _notdef
 | 
						|
    /* XXBS - This is the original miClearToBackground code.
 | 
						|
     * WindowExposures needs to be called (or the functionality emulated)
 | 
						|
     * in order for backingStore to work, but first, pBuffer->eventMask
 | 
						|
     * and wOtherEventsMasks(pBuffer) need to be setup correctly.
 | 
						|
     */
 | 
						|
 | 
						|
    if (generateExposures)
 | 
						|
	(*pScreen->WindowExposures)(pBuffer, ®, pBSReg);
 | 
						|
    else if (pBuffer->backgroundState != None)
 | 
						|
        miPaintWindow(pBuffer, ®, PW_BACKGROUND);
 | 
						|
#endif
 | 
						|
    REGION_UNINIT(pScreen, ®);
 | 
						|
    if (pBSReg)
 | 
						|
	REGION_DESTROY(pScreen, pBSReg);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
bufWrapScreenFuncs(pScreen)
 | 
						|
    ScreenPtr pScreen;
 | 
						|
{
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify);
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures);
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes);
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground);
 | 
						|
    WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
bufResetProc(pScreen)
 | 
						|
    ScreenPtr pScreen;
 | 
						|
{
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    /*
 | 
						|
     * frameBuffer, selectPlane, and pInfo should be freed by
 | 
						|
     * whoever called RegisterDoubleBufferHardware
 | 
						|
     */
 | 
						|
 | 
						|
    REGION_UNINIT(pScreen, &pMBPriv->backBuffer);
 | 
						|
    REGION_UNINIT(pScreen, &pMBPriv->subtractRgn);
 | 
						|
    REGION_UNINIT(pScreen, &pMBPriv->unionRgn);
 | 
						|
    xfree(pMBPriv);
 | 
						|
}
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
/* 
 | 
						|
 * Used if CopyBufferBitsFunc is not provided when registering.
 | 
						|
 * This should work for everybody since CopyArea needs to support
 | 
						|
 * copying between buffers anyway.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum)
 | 
						|
    mbufWindowPtr pMBWindow;
 | 
						|
    int srcBufferNum, dstBufferNum;
 | 
						|
{
 | 
						|
    DrawablePtr pSrcBuffer, pDstBuffer;
 | 
						|
    GCPtr pGC;
 | 
						|
 | 
						|
    pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable;
 | 
						|
    pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable;
 | 
						|
 | 
						|
    pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen);
 | 
						|
    if (!pGC)
 | 
						|
	return;
 | 
						|
 | 
						|
    ValidateGC (pDstBuffer, pGC);
 | 
						|
    (* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC,
 | 
						|
		    0,0, pDstBuffer->width, pDstBuffer->height, 0,0);
 | 
						|
    FreeScratchGC (pGC);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Used if DrawSelectPlanFunc is not provided for when registering.
 | 
						|
 * However, it only works if selectPlane.ptr is a drawable. Also
 | 
						|
 * assumes that painting with color 0 selects the front buffer,
 | 
						|
 * while color 1 selects the back buffer.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum)
 | 
						|
    ScreenPtr	pScreen;
 | 
						|
    DevUnion	selectPlane;
 | 
						|
    RegionPtr	prgn;
 | 
						|
    long	bufferNum;
 | 
						|
{
 | 
						|
    DrawablePtr pDrawable;
 | 
						|
    GCPtr pGC;
 | 
						|
    register int i;
 | 
						|
    register BoxPtr pbox;
 | 
						|
    register xRectangle *prect;
 | 
						|
    int numRects;
 | 
						|
    XID	value;
 | 
						|
 | 
						|
    if (REGION_NUM_RECTS(prgn) == 0)
 | 
						|
	return;
 | 
						|
 | 
						|
    pDrawable = (DrawablePtr) selectPlane.ptr;
 | 
						|
    pGC = GetScratchGC (pDrawable->depth, pScreen);
 | 
						|
    if (!pGC)
 | 
						|
	return;
 | 
						|
 | 
						|
    prect = (xRectangle *)xalloc(REGION_NUM_RECTS(prgn) *
 | 
						|
					 sizeof(xRectangle));
 | 
						|
    if (!prect)
 | 
						|
    {
 | 
						|
	FreeScratchGC(pGC);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    value = (XID) bufferNum;
 | 
						|
    DoChangeGC(pGC, GCForeground, &value, 0);
 | 
						|
    ValidateGC(pDrawable, pGC);
 | 
						|
 | 
						|
    numRects = REGION_NUM_RECTS(prgn);
 | 
						|
    pbox = REGION_RECTS(prgn);
 | 
						|
    for (i= numRects; --i >= 0; pbox++, prect++)
 | 
						|
    {
 | 
						|
	prect->x = pbox->x1;
 | 
						|
	prect->y = pbox->y1;
 | 
						|
	prect->width = pbox->x2 - pbox->x1;
 | 
						|
	prect->height = pbox->y2 - pbox->y1;
 | 
						|
    }
 | 
						|
    prect -= numRects;
 | 
						|
    (* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect);
 | 
						|
 | 
						|
    xfree(prect);
 | 
						|
    FreeScratchGC (pGC);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
 | 
						|
    ScreenPtr		pScreen;
 | 
						|
    mbufBufferPtr	*ppMBBuffer;
 | 
						|
    mbufWindowPtr	*ppMBWindow;
 | 
						|
    int			nbuf;
 | 
						|
{
 | 
						|
    WindowPtr       pWin;
 | 
						|
    BufferPtr	    pPrevBuffer, pNewBuffer;
 | 
						|
    int		    i, number;
 | 
						|
    mbufBufferPrivPtr pMBPriv;
 | 
						|
    mbufBufferPtr   pPrevMBBuffer;
 | 
						|
 | 
						|
    pMBPriv   = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    for (i = 0; i < nbuf; i++)
 | 
						|
    {
 | 
						|
	number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */
 | 
						|
	pWin = ppMBWindow[i]->pWindow;
 | 
						|
	pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
 | 
						|
 | 
						|
	pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable;
 | 
						|
	pNewBuffer  = (BufferPtr) ppMBBuffer[i]->pDrawable;
 | 
						|
 | 
						|
	if (pPrevBuffer != pNewBuffer)
 | 
						|
	{
 | 
						|
	    RegionPtr backBuffer = &pMBPriv->backBuffer;
 | 
						|
 | 
						|
	    /*
 | 
						|
	     * Update the select plane and the backBuffer region.
 | 
						|
	     */
 | 
						|
 | 
						|
	    (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
 | 
						|
			    &pWin->clipList, number);
 | 
						|
 | 
						|
	    if (number == BACK_BUFFER)
 | 
						|
		REGION_UNION(pScreen, backBuffer, backBuffer,
 | 
						|
				   &pWin->clipList);
 | 
						|
	    else
 | 
						|
		REGION_SUBTRACT(pScreen, backBuffer, backBuffer,
 | 
						|
				   &pWin->clipList);
 | 
						|
 | 
						|
	    /* Switch which framebuffer the window draws into */
 | 
						|
	    pWin->devPrivates[frameWindowPrivateIndex] =
 | 
						|
		pMBPriv->frameBuffer[number];
 | 
						|
	}
 | 
						|
 | 
						|
	switch (ppMBWindow[i]->updateAction)
 | 
						|
	{
 | 
						|
	case MultibufferUpdateActionUndefined:
 | 
						|
	    break;
 | 
						|
	case MultibufferUpdateActionBackground:
 | 
						|
	    (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
 | 
						|
		(pPrevMBBuffer, 0,0, 0,0, FALSE);
 | 
						|
	    break;
 | 
						|
	case MultibufferUpdateActionUntouched:
 | 
						|
	    break;
 | 
						|
	case MultibufferUpdateActionCopied:
 | 
						|
	    if (pPrevBuffer != pNewBuffer)
 | 
						|
	    {
 | 
						|
		(* pMBPriv->CopyBufferBits) (ppMBWindow[i],
 | 
						|
			ppMBBuffer[i]->number, pPrevMBBuffer->number);
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Updates the backBuffer region and paints the selectPlane. */
 | 
						|
 | 
						|
static void
 | 
						|
bufPostValidateTree(pParent, pChild, kind)
 | 
						|
    WindowPtr	pParent, pChild;
 | 
						|
    VTKind	kind;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen;
 | 
						|
    mbufBufferPrivPtr pMBPriv;
 | 
						|
 | 
						|
    if (pParent)
 | 
						|
	pScreen = pParent->drawable.pScreen;
 | 
						|
    else if (pChild)
 | 
						|
	pScreen = pChild->drawable.pScreen;
 | 
						|
    else
 | 
						|
	return; /* Hopeless */
 | 
						|
 | 
						|
    pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
 | 
						|
    if (pScreen->PostValidateTree)
 | 
						|
	(* pScreen->PostValidateTree)(pParent, pChild, kind);
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
 | 
						|
 | 
						|
    /* Does backBuffer need to change? */
 | 
						|
    if (pMBPriv->rgnChanged)
 | 
						|
    {
 | 
						|
	RegionRec exposed;
 | 
						|
	RegionPtr pSubtractRgn, pUnionRgn;
 | 
						|
	Bool overlap;
 | 
						|
 | 
						|
	pMBPriv->rgnChanged = FALSE;
 | 
						|
 | 
						|
	pSubtractRgn = &pMBPriv->subtractRgn;
 | 
						|
	pUnionRgn    = &pMBPriv->unionRgn;
 | 
						|
	REGION_VALIDATE(pScreen, pSubtractRgn, &overlap);
 | 
						|
#ifdef DEBUG
 | 
						|
	if (overlap)
 | 
						|
	    FatalError("bufPostValidateTree: subtractRgn overlaps");
 | 
						|
#endif
 | 
						|
	REGION_VALIDATE(pScreen, pUnionRgn, &overlap);
 | 
						|
#ifdef DEBUG
 | 
						|
	if (overlap)
 | 
						|
	    FatalError("bufPostValidateTree: unionRgn overlaps");
 | 
						|
#endif
 | 
						|
 | 
						|
	/* Update backBuffer: subtract must come before union */
 | 
						|
	REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
 | 
						|
			      pSubtractRgn);
 | 
						|
	REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
 | 
						|
			      pUnionRgn);
 | 
						|
 | 
						|
	/* Paint gained and lost backbuffer areas in select plane */
 | 
						|
	REGION_NULL(pScreen, &exposed);
 | 
						|
	REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn);
 | 
						|
	(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
 | 
						|
				     &exposed, FRONT_BUFFER);
 | 
						|
 | 
						|
	REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn);
 | 
						|
	(* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
 | 
						|
				    &exposed, BACK_BUFFER);
 | 
						|
	
 | 
						|
	REGION_UNINIT(pScreen, &exposed);
 | 
						|
	REGION_EMPTY(pScreen, pSubtractRgn);
 | 
						|
	REGION_EMPTY(pScreen, pUnionRgn);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * If the window is multibuffered and displaying the backbuffer,
 | 
						|
 * add the old clipList to the subtractRgn and add the new clipList
 | 
						|
 * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn
 | 
						|
 * to update the backBuffer region and the selectPlane.
 | 
						|
 *
 | 
						|
 * Copy changes to the window structure into the buffers.
 | 
						|
 * Send ClobberNotify events.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
bufClipNotify(pWin, dx,dy)
 | 
						|
    WindowPtr pWin;
 | 
						|
    int       dx,dy;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
    mbufWindowPtr	pMBWindow;
 | 
						|
    int i;
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
 | 
						|
    if (pScreen->ClipNotify)
 | 
						|
	(* pScreen->ClipNotify)(pWin, dx,dy);
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
 | 
						|
 | 
						|
    if (pMBWindow = MB_WINDOW_PRIV(pWin))
 | 
						|
    {
 | 
						|
	RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr;
 | 
						|
 | 
						|
	if (! REGION_EQUAL(pScreen, pOldClipList, &pWin->clipList))
 | 
						|
	{
 | 
						|
	    if (pMBWindow->displayedMultibuffer == BACK_BUFFER)
 | 
						|
	    {
 | 
						|
		pMBPriv->rgnChanged = TRUE;
 | 
						|
		REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList);
 | 
						|
		REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList);
 | 
						|
	    }
 | 
						|
 | 
						|
	    REGION_COPY(pScreen, pOldClipList,&pWin->clipList);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Update buffer x,y,w,h, and clipList */
 | 
						|
	for (i=0; i<pMBWindow->numMultibuffer; i++)
 | 
						|
	{
 | 
						|
	    mbufBufferPtr pMBBuffer = pMBWindow->buffers + i;
 | 
						|
	    if (pMBBuffer->clobber != pWin->visibility)
 | 
						|
	    {
 | 
						|
		pMBBuffer->clobber = pWin->visibility;
 | 
						|
		MultibufferClobber(pMBBuffer);
 | 
						|
	    }
 | 
						|
	    UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Updates buffer's background fields when the window's changes.
 | 
						|
 * This is necessary because miPaintWindow is used to paint the buffer.
 | 
						|
 *
 | 
						|
 * XXBS - Backingstore state will have be tracked too if it is supported.
 | 
						|
 */
 | 
						|
 | 
						|
static Bool
 | 
						|
bufChangeWindowAttributes(pWin, mask)
 | 
						|
    WindowPtr pWin;
 | 
						|
    unsigned long mask;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
    mbufWindowPtr pMBWindow;
 | 
						|
    Bool ret;
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
 | 
						|
    ret = (* pScreen->ChangeWindowAttributes)(pWin, mask);
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
 | 
						|
 | 
						|
    if (pMBWindow = MB_WINDOW_PRIV(pWin))
 | 
						|
    {
 | 
						|
	if (mask & (CWBackPixmap | CWBackPixel))
 | 
						|
	{
 | 
						|
	    BufferPtr pBuffer;
 | 
						|
	    int i;
 | 
						|
 | 
						|
	    for (i=0; i<pMBWindow->displayedMultibuffer; i++)
 | 
						|
	    {
 | 
						|
		pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable;
 | 
						|
		pBuffer->backgroundState = pWin->backgroundState;
 | 
						|
		pBuffer->background = pWin->background;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Send exposures and clear the background for a buffer whenever
 | 
						|
 * its corresponding window is exposed, except when called by
 | 
						|
 * ClearToBackground.
 | 
						|
 */
 | 
						|
 | 
						|
static void 
 | 
						|
bufWindowExposures(pWin, prgn, other_exposed)
 | 
						|
    WindowPtr pWin;
 | 
						|
    register RegionPtr prgn, other_exposed;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin);
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
    RegionRec tmp_rgn;
 | 
						|
    int i;
 | 
						|
    Bool handleBuffers;
 | 
						|
 | 
						|
    handleBuffers = (!pMBPriv->inClearToBackground) &&
 | 
						|
	(pWin->drawable.type == DRAWABLE_WINDOW) &&
 | 
						|
	pMBWindow && (prgn && !REGION_NIL(prgn));
 | 
						|
 | 
						|
    /* miWindowExposures munges prgn and other_exposed. */
 | 
						|
    if (handleBuffers)
 | 
						|
    {
 | 
						|
	REGION_NULL(pScreen, &tmp_rgn);
 | 
						|
	REGION_COPY(pScreen, &tmp_rgn, prgn);
 | 
						|
    }
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
 | 
						|
    (* pScreen->WindowExposures) (pWin, prgn, other_exposed);
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
 | 
						|
 | 
						|
    if (!handleBuffers)
 | 
						|
	return;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Send expose events to all clients. Paint the exposed region for all
 | 
						|
     * buffers except the displayed buffer since it is handled when the
 | 
						|
     * window is painted.
 | 
						|
     *
 | 
						|
     * XXBS - Will have to be re-written to handle BackingStore on buffers.
 | 
						|
     */
 | 
						|
 | 
						|
    for (i=0; i<pMBWindow->numMultibuffer; i++)
 | 
						|
    {
 | 
						|
	mbufBufferPtr pMBBuffer;
 | 
						|
	BufferPtr pBuffer;
 | 
						|
 | 
						|
	pMBBuffer = pMBWindow->buffers + i;
 | 
						|
	pBuffer = (BufferPtr) pMBBuffer->pDrawable;
 | 
						|
 | 
						|
	if (i != pMBWindow->displayedMultibuffer)
 | 
						|
	    miPaintWindow(pBuffer, &tmp_rgn, PW_BACKGROUND);
 | 
						|
	if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask)
 | 
						|
	    MultibufferExpose(pMBBuffer, &tmp_rgn);
 | 
						|
    }
 | 
						|
 | 
						|
    REGION_UNINIT(pScreen, &tmp_rgn);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Set ``inClearToBackground'' so that WindowExposures does not attempt
 | 
						|
 * to send expose events or clear the background on the buffers.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
bufClearToBackground(pWin, x,y,w,h, sendExpose)
 | 
						|
    WindowPtr pWin;
 | 
						|
    int x,y, w,h;
 | 
						|
    Bool sendExpose;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
 | 
						|
    pMBPriv->inClearToBackground = TRUE;
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
 | 
						|
    (* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose);
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
 | 
						|
 | 
						|
    pMBPriv->inClearToBackground = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Move bits in both buffers. It does this by calling pScreen->CopyWindow
 | 
						|
 * twice, once with the root window's devPrivate[frameWindowPrivateIndex]
 | 
						|
 * pointing to the frontbuffer pixmap and once with it pointed to the
 | 
						|
 * backbuffer pixmap. It does this if there are *any* existing multibuffered
 | 
						|
 * window... a possible optimization is to copy the backbuffer only if this
 | 
						|
 * window or its inferiors are multibuffered. May be faster, maybe not.
 | 
						|
 *
 | 
						|
 * XXX - Only works if your CopyWindow checks the root window's devPrivate
 | 
						|
 *       to see which buffer to draw into. Works for cfbPaintWindow.
 | 
						|
 */
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
static void 
 | 
						|
bufCopyWindow(pWin, ptOldOrg, prgnSrc)
 | 
						|
    WindowPtr pWin;
 | 
						|
    DDXPointRec ptOldOrg;
 | 
						|
    RegionPtr prgnSrc;
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
 | 
						|
    WindowPtr pwinroot;
 | 
						|
    DevUnion save;
 | 
						|
 | 
						|
    UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
 | 
						|
 | 
						|
    pwinroot = WindowTable[pScreen->myNum];
 | 
						|
    save = pwinroot->devPrivates[frameWindowPrivateIndex];
 | 
						|
 | 
						|
    /*
 | 
						|
     * Copy front buffer
 | 
						|
     */
 | 
						|
 | 
						|
    pwinroot->devPrivates[frameWindowPrivateIndex] =
 | 
						|
	pMBPriv->frameBuffer[FRONT_BUFFER];
 | 
						|
    (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
 | 
						|
 | 
						|
    /*
 | 
						|
     * Copy back buffer
 | 
						|
     */
 | 
						|
 | 
						|
    /* CopyWindow translates prgnSrc... translate it back for 2nd call. */
 | 
						|
    REGION_TRANSLATE(pScreen, prgnSrc,
 | 
						|
				  ptOldOrg.x - pWin->drawable.x,
 | 
						|
				  ptOldOrg.y - pWin->drawable.y);
 | 
						|
    pwinroot->devPrivates[frameWindowPrivateIndex] =
 | 
						|
	pMBPriv->frameBuffer[BACK_BUFFER];
 | 
						|
    (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
 | 
						|
 | 
						|
    pwinroot->devPrivates[frameWindowPrivateIndex] = save;
 | 
						|
    REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
 | 
						|
}
 |