5f1431f613
Reported to iDefense by regenrecht. Patch from Dave Airlie.
1930 lines
54 KiB
C
1930 lines
54 KiB
C
/******************************************************************************
|
||
*
|
||
* Copyright (c) 1994, 1995 Hewlett-Packard Company
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining
|
||
* a copy of this software and associated documentation files (the
|
||
* "Software"), to deal in the Software without restriction, including
|
||
* without limitation the rights to use, copy, modify, merge, publish,
|
||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||
* permit persons to whom the Software is furnished to do so, subject to
|
||
* the following conditions:
|
||
*
|
||
* 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 HEWLETT-PACKARD COMPANY 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 Hewlett-Packard
|
||
* Company 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 Hewlett-Packard Company.
|
||
*
|
||
* DIX DBE code
|
||
*
|
||
*****************************************************************************/
|
||
|
||
|
||
/* INCLUDES */
|
||
|
||
#define NEED_EVENTS
|
||
#ifdef HAVE_DIX_CONFIG_H
|
||
#include <dix-config.h>
|
||
#endif
|
||
|
||
#include <string.h>
|
||
#if HAVE_STDINT_H
|
||
#include <stdint.h>
|
||
#elif !defined(UINT32_MAX)
|
||
#define UINT32_MAX 0xffffffffU
|
||
#endif
|
||
|
||
#include <X11/X.h>
|
||
#include <X11/Xproto.h>
|
||
#include "scrnintstr.h"
|
||
#include "extnsionst.h"
|
||
#include "gcstruct.h"
|
||
#include "dixstruct.h"
|
||
#define NEED_DBE_PROTOCOL
|
||
#include "dbestruct.h"
|
||
#include "midbe.h"
|
||
|
||
/* GLOBALS */
|
||
|
||
/* Per-screen initialization functions [init'ed by DbeRegisterFunction()] */
|
||
static Bool (* DbeInitFunct[MAXSCREENS])(); /* pScreen, pDbeScreenPriv */
|
||
|
||
/* These are static globals copied to DBE's screen private for use by DDX */
|
||
static int dbeScreenPrivIndex;
|
||
static int dbeWindowPrivIndex;
|
||
|
||
/* These are static globals copied to DBE's screen private for use by DDX */
|
||
static RESTYPE dbeDrawableResType;
|
||
static RESTYPE dbeWindowPrivResType;
|
||
|
||
/* This global is used by DbeAllocWinPrivPrivIndex() */
|
||
static int winPrivPrivCount = 0;
|
||
|
||
/* Used to generate DBE's BadBuffer error. */
|
||
static int dbeErrorBase;
|
||
|
||
/* Used by DbeRegisterFunction() to initialize the initialization function
|
||
* table only once per server lifetime.
|
||
*/
|
||
static Bool firstRegistrationPass = TRUE;
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeRegisterFunction
|
||
*
|
||
* Description:
|
||
*
|
||
* This function registers the DBE init function for the specified screen.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
void
|
||
DbeRegisterFunction(ScreenPtr pScreen, Bool (*funct) (/* ??? */))
|
||
{
|
||
int i;
|
||
|
||
/* Initialize the initialization function table if it has not been
|
||
* initialized already.
|
||
*/
|
||
if (firstRegistrationPass)
|
||
{
|
||
for (i = 0; i < MAXSCREENS; i++)
|
||
{
|
||
DbeInitFunct[i] = NULL;
|
||
}
|
||
|
||
firstRegistrationPass = FALSE;
|
||
}
|
||
|
||
DbeInitFunct[pScreen->myNum] = funct;
|
||
|
||
} /* DbeRegisterFunction() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeAllocWinPriv
|
||
*
|
||
* Description:
|
||
*
|
||
* This function was cloned from AllocateWindow() in window.c.
|
||
* This function allocates a window priv structure to be associated
|
||
* with a double-buffered window.
|
||
*
|
||
*****************************************************************************/
|
||
static DbeWindowPrivPtr
|
||
DbeAllocWinPriv(ScreenPtr pScreen)
|
||
{
|
||
DbeWindowPrivPtr pDbeWindowPriv;
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
register char *ptr;
|
||
register DevUnion *ppriv;
|
||
register unsigned int *sizes;
|
||
register unsigned int size;
|
||
register int i;
|
||
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
pDbeWindowPriv = (DbeWindowPrivPtr)xalloc(pDbeScreenPriv->totalWinPrivSize);
|
||
|
||
if (pDbeWindowPriv)
|
||
{
|
||
ppriv = (DevUnion *)(pDbeWindowPriv + 1);
|
||
pDbeWindowPriv->devPrivates = ppriv;
|
||
sizes = pDbeScreenPriv->winPrivPrivSizes;
|
||
ptr = (char *)(ppriv + pDbeScreenPriv->winPrivPrivLen);
|
||
for (i = pDbeScreenPriv->winPrivPrivLen; --i >= 0; ppriv++, sizes++)
|
||
{
|
||
if ((size = *sizes))
|
||
{
|
||
ppriv->ptr = (pointer)ptr;
|
||
ptr += size;
|
||
}
|
||
else
|
||
ppriv->ptr = (pointer)NULL;
|
||
}
|
||
}
|
||
|
||
return(pDbeWindowPriv);
|
||
|
||
} /* DbeAllocWinPriv() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeFallbackAllocWinPriv
|
||
*
|
||
* Description:
|
||
*
|
||
* This is a fallback function for AllocWinPriv().
|
||
*
|
||
*****************************************************************************/
|
||
|
||
#if 0 /* NOT USED */
|
||
static DbeWindowPrivPtr
|
||
DbeFallbackAllocWinPriv(pScreen)
|
||
ScreenPtr pScreen;
|
||
{
|
||
return (NULL);
|
||
} /* DbeFallbackAllocWinPriv() */
|
||
#endif
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeAllocWinPrivPrivIndex
|
||
*
|
||
* Description:
|
||
*
|
||
* This function was cloned from AllocateWindowPrivateIndex() in window.c.
|
||
* This function allocates a new window priv priv index by simply returning
|
||
* an incremented private counter.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
DbeAllocWinPrivPrivIndex(void)
|
||
{
|
||
return winPrivPrivCount++;
|
||
|
||
} /* DbeAllocWinPrivPrivIndex() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeAllocWinPrivPriv
|
||
*
|
||
* Description:
|
||
*
|
||
* This function was cloned from AllocateWindowPrivate() in privates.c.
|
||
* This function allocates a private structure to be hung off
|
||
* a window private.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static Bool
|
||
DbeAllocWinPrivPriv(register ScreenPtr pScreen, int index, unsigned int amount)
|
||
{
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
unsigned int oldamount;
|
||
|
||
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
|
||
if (index >= pDbeScreenPriv->winPrivPrivLen)
|
||
{
|
||
unsigned *nsizes;
|
||
nsizes = (unsigned *)xrealloc(pDbeScreenPriv->winPrivPrivSizes,
|
||
(index + 1) * sizeof(unsigned));
|
||
if (!nsizes)
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
while (pDbeScreenPriv->winPrivPrivLen <= index)
|
||
{
|
||
nsizes[pDbeScreenPriv->winPrivPrivLen++] = 0;
|
||
pDbeScreenPriv->totalWinPrivSize += sizeof(DevUnion);
|
||
}
|
||
|
||
pDbeScreenPriv->winPrivPrivSizes = nsizes;
|
||
}
|
||
|
||
oldamount = pDbeScreenPriv->winPrivPrivSizes[index];
|
||
|
||
if (amount > oldamount)
|
||
{
|
||
pDbeScreenPriv->winPrivPrivSizes[index] = amount;
|
||
pDbeScreenPriv->totalWinPrivSize += (amount - oldamount);
|
||
}
|
||
return(TRUE);
|
||
|
||
} /* DbeAllocWinPrivPriv() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeStubScreen
|
||
*
|
||
* Description:
|
||
*
|
||
* This is function stubs the function pointers in the given DBE screen
|
||
* private and increments the number of stubbed screens.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static void
|
||
DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens)
|
||
{
|
||
/* Stub DIX. */
|
||
pDbeScreenPriv->SetupBackgroundPainter = NULL;
|
||
pDbeScreenPriv->AllocWinPriv = NULL;
|
||
pDbeScreenPriv->AllocWinPrivPrivIndex = NULL;
|
||
pDbeScreenPriv->AllocWinPrivPriv = NULL;
|
||
|
||
/* Do not unwrap PositionWindow nor DestroyWindow. If the DDX
|
||
* initialization function failed, we assume that it did not wrap
|
||
* PositionWindow. Also, DestroyWindow is only wrapped if the DDX
|
||
* initialization function succeeded.
|
||
*/
|
||
|
||
/* Stub DDX. */
|
||
pDbeScreenPriv->GetVisualInfo = NULL;
|
||
pDbeScreenPriv->AllocBackBufferName = NULL;
|
||
pDbeScreenPriv->SwapBuffers = NULL;
|
||
pDbeScreenPriv->BeginIdiom = NULL;
|
||
pDbeScreenPriv->EndIdiom = NULL;
|
||
pDbeScreenPriv->WinPrivDelete = NULL;
|
||
pDbeScreenPriv->ResetProc = NULL;
|
||
|
||
(*nStubbedScreens)++;
|
||
|
||
} /* DbeStubScreen() */
|
||
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeGetVersion
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeGetVersion request.
|
||
* This request returns the major and minor version numbers of this
|
||
* extension.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeGetVersion(ClientPtr client)
|
||
{
|
||
/* REQUEST(xDbeGetVersionReq); */
|
||
xDbeGetVersionReply rep;
|
||
register int n;
|
||
|
||
|
||
REQUEST_SIZE_MATCH(xDbeGetVersionReq);
|
||
|
||
rep.type = X_Reply;
|
||
rep.length = 0;
|
||
rep.sequenceNumber = client->sequence;
|
||
rep.majorVersion = DBE_MAJOR_VERSION;
|
||
rep.minorVersion = DBE_MINOR_VERSION;
|
||
|
||
if (client->swapped)
|
||
{
|
||
swaps(&rep.sequenceNumber, n);
|
||
}
|
||
|
||
WriteToClient(client, sizeof(xDbeGetVersionReply), (char *)&rep);
|
||
|
||
return(client->noClientException);
|
||
|
||
} /* ProcDbeGetVersion() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeAllocateBackBufferName
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeAllocateBackBufferName request.
|
||
* This request allocates a drawable ID used to refer to the back buffer
|
||
* of a window.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadAlloc - server can not allocate resources
|
||
* BadIDChoice - id is out of range for client; id is already in use
|
||
* BadMatch - window is not an InputOutput window;
|
||
* visual of window is not on list returned by
|
||
* DBEGetVisualInfo;
|
||
* BadValue - invalid swap action is specified
|
||
* BadWindow - window is not a valid window
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeAllocateBackBufferName(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeAllocateBackBufferNameReq);
|
||
WindowPtr pWin;
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
DbeWindowPrivPtr pDbeWindowPriv;
|
||
XdbeScreenVisualInfo scrVisInfo;
|
||
register int i;
|
||
Bool visualMatched = FALSE;
|
||
xDbeSwapAction swapAction;
|
||
VisualID visual;
|
||
int status;
|
||
int add_index;
|
||
|
||
REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
|
||
|
||
/* The window must be valid. */
|
||
status = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
|
||
if (status != Success)
|
||
return status;
|
||
|
||
/* The window must be InputOutput. */
|
||
if (pWin->drawable.class != InputOutput)
|
||
{
|
||
return(BadMatch);
|
||
}
|
||
|
||
/* The swap action must be valid. */
|
||
swapAction = stuff->swapAction; /* use local var for performance. */
|
||
if ((swapAction != XdbeUndefined ) &&
|
||
(swapAction != XdbeBackground) &&
|
||
(swapAction != XdbeUntouched ) &&
|
||
(swapAction != XdbeCopied ))
|
||
{
|
||
return(BadValue);
|
||
}
|
||
|
||
/* The id must be in range and not already in use. */
|
||
LEGAL_NEW_RESOURCE(stuff->buffer, client);
|
||
|
||
/* The visual of the window must be in the list returned by
|
||
* GetVisualInfo.
|
||
*/
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
|
||
if (!pDbeScreenPriv->GetVisualInfo)
|
||
return(BadMatch); /* screen doesn't support double buffering */
|
||
|
||
if (!(*pDbeScreenPriv->GetVisualInfo)(pWin->drawable.pScreen, &scrVisInfo))
|
||
{
|
||
/* GetVisualInfo() failed to allocate visual info data. */
|
||
return(BadAlloc);
|
||
}
|
||
|
||
/* See if the window's visual is on the list. */
|
||
visual = wVisual(pWin);
|
||
for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++)
|
||
{
|
||
if (scrVisInfo.visinfo[i].visual == visual)
|
||
{
|
||
visualMatched = TRUE;
|
||
}
|
||
}
|
||
|
||
/* Free what was allocated by the GetVisualInfo() call above. */
|
||
xfree(scrVisInfo.visinfo);
|
||
|
||
if (!visualMatched)
|
||
{
|
||
return(BadMatch);
|
||
}
|
||
|
||
if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL)
|
||
{
|
||
/* There is no buffer associated with the window.
|
||
* Allocate a window priv.
|
||
*/
|
||
|
||
if (!(pDbeWindowPriv =
|
||
(*pDbeScreenPriv->AllocWinPriv)(pWin->drawable.pScreen)))
|
||
{
|
||
return(BadAlloc);
|
||
}
|
||
|
||
/* Fill out window priv information. */
|
||
pDbeWindowPriv->pWindow = pWin;
|
||
pDbeWindowPriv->width = pWin->drawable.width;
|
||
pDbeWindowPriv->height = pWin->drawable.height;
|
||
pDbeWindowPriv->x = pWin->drawable.x;
|
||
pDbeWindowPriv->y = pWin->drawable.y;
|
||
pDbeWindowPriv->nBufferIDs = 0;
|
||
|
||
/* Set the buffer ID array pointer to the initial (static) array). */
|
||
pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs;
|
||
|
||
/* Initialize the buffer ID list. */
|
||
pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS;
|
||
|
||
add_index = 0;
|
||
for (i = 1; i < DBE_INIT_MAX_IDS; i++)
|
||
{
|
||
pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT;
|
||
}
|
||
|
||
/* Actually connect the window priv to the window. */
|
||
pWin->devPrivates[dbeWindowPrivIndex].ptr = (pointer)pDbeWindowPriv;
|
||
|
||
} /* if -- There is no buffer associated with the window. */
|
||
|
||
else
|
||
{
|
||
/* A buffer is already associated with the window.
|
||
* Add the new buffer ID to the array, reallocating the array memory
|
||
* if necessary.
|
||
*/
|
||
|
||
/* Determine if there is a free element in the ID array. */
|
||
for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++)
|
||
{
|
||
if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT)
|
||
{
|
||
/* There is still room in the ID array. */
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == pDbeWindowPriv->maxAvailableIDs)
|
||
{
|
||
/* No more room in the ID array -- reallocate another array. */
|
||
XID *pIDs;
|
||
|
||
|
||
/* Setup an array pointer for the realloc operation below. */
|
||
if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS)
|
||
{
|
||
/* We will malloc a new array. */
|
||
pIDs = NULL;
|
||
}
|
||
else
|
||
{
|
||
/* We will realloc a new array. */
|
||
pIDs = pDbeWindowPriv->IDs;
|
||
}
|
||
|
||
/* malloc/realloc a new array and initialize all elements to 0. */
|
||
pDbeWindowPriv->IDs = (XID *)xrealloc(pIDs,
|
||
(pDbeWindowPriv->maxAvailableIDs+DBE_INCR_MAX_IDS)*sizeof(XID));
|
||
if (!pDbeWindowPriv->IDs)
|
||
{
|
||
return(BadAlloc);
|
||
}
|
||
memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0,
|
||
(pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS -
|
||
pDbeWindowPriv->nBufferIDs) * sizeof(XID));
|
||
|
||
if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS)
|
||
{
|
||
/* We just went from using the initial (static) array to a
|
||
* newly allocated array. Copy the IDs from the initial array
|
||
* to the new array.
|
||
*/
|
||
memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs,
|
||
DBE_INIT_MAX_IDS * sizeof(XID));
|
||
}
|
||
|
||
pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS;
|
||
}
|
||
|
||
add_index = i;
|
||
|
||
} /* else -- A buffer is already associated with the window. */
|
||
|
||
|
||
/* Call the DDX routine to allocate the back buffer. */
|
||
status = (*pDbeScreenPriv->AllocBackBufferName)(pWin, stuff->buffer,
|
||
stuff->swapAction);
|
||
|
||
if (status == Success)
|
||
{
|
||
pDbeWindowPriv->IDs[add_index] = stuff->buffer;
|
||
if (!AddResource(stuff->buffer, dbeWindowPrivResType,
|
||
(pointer)pDbeWindowPriv))
|
||
{
|
||
pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT;
|
||
|
||
if (pDbeWindowPriv->nBufferIDs == 0) {
|
||
status = BadAlloc;
|
||
goto out_free;
|
||
}
|
||
}
|
||
} else {
|
||
/* The DDX buffer allocation routine failed for the first buffer of
|
||
* this window.
|
||
*/
|
||
|
||
if (pDbeWindowPriv->nBufferIDs == 0) {
|
||
goto out_free;
|
||
}
|
||
}
|
||
|
||
/* Increment the number of buffers (XIDs) associated with this window. */
|
||
pDbeWindowPriv->nBufferIDs++;
|
||
|
||
/* Set swap action on all calls. */
|
||
pDbeWindowPriv->swapAction = stuff->swapAction;
|
||
|
||
|
||
return(status);
|
||
|
||
out_free:
|
||
pWin->devPrivates[dbeWindowPrivIndex].ptr = NULL;
|
||
xfree(pDbeWindowPriv);
|
||
return(status);
|
||
|
||
} /* ProcDbeAllocateBackBufferName() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeDeallocateBackBufferName
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeDeallocateBackBufferName request.
|
||
* This request frees a drawable ID that was obtained by a
|
||
* DbeAllocateBackBufferName request.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadBuffer - buffer to deallocate is not associated with a window
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeDeallocateBackBufferName(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeDeallocateBackBufferNameReq);
|
||
DbeWindowPrivPtr pDbeWindowPriv;
|
||
int i;
|
||
|
||
|
||
REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
|
||
|
||
/* Buffer name must be valid */
|
||
if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client,
|
||
stuff->buffer, dbeWindowPrivResType, DixDestroyAccess)) ||
|
||
!(SecurityLookupIDByType(client, stuff->buffer, dbeDrawableResType,
|
||
DixDestroyAccess)))
|
||
{
|
||
client->errorValue = stuff->buffer;
|
||
return(dbeErrorBase + DbeBadBuffer);
|
||
}
|
||
|
||
/* Make sure that the id is valid for the window.
|
||
* This is paranoid code since we already looked up the ID by type
|
||
* above.
|
||
*/
|
||
|
||
for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++)
|
||
{
|
||
/* Loop through the ID list to find the ID. */
|
||
if (pDbeWindowPriv->IDs[i] == stuff->buffer)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == pDbeWindowPriv->nBufferIDs)
|
||
{
|
||
/* We did not find the ID in the ID list. */
|
||
client->errorValue = stuff->buffer;
|
||
return(dbeErrorBase + DbeBadBuffer);
|
||
}
|
||
|
||
FreeResource(stuff->buffer, RT_NONE);
|
||
|
||
return(Success);
|
||
|
||
} /* ProcDbeDeallocateBackBufferName() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeSwapBuffers
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeSwapBuffers request.
|
||
* This request swaps the buffers for all windows listed, applying the
|
||
* appropriate swap action for each window.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadAlloc - local allocation failed; this return value is not defined
|
||
* by the protocol
|
||
* BadMatch - a window in request is not double-buffered; a window in
|
||
* request is listed more than once
|
||
* BadValue - invalid swap action is specified; no swap action is
|
||
* specified
|
||
* BadWindow - a window in request is not valid
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeSwapBuffers(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeSwapBuffersReq);
|
||
WindowPtr pWin;
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
DbeSwapInfoPtr swapInfo;
|
||
xDbeSwapInfo *dbeSwapInfo;
|
||
int error;
|
||
register int i, j;
|
||
int nStuff;
|
||
|
||
|
||
REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
|
||
nStuff = stuff->n; /* use local variable for performance. */
|
||
|
||
if (nStuff == 0)
|
||
{
|
||
return(Success);
|
||
}
|
||
|
||
if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec))
|
||
return BadAlloc;
|
||
|
||
/* Get to the swap info appended to the end of the request. */
|
||
dbeSwapInfo = (xDbeSwapInfo *)&stuff[1];
|
||
|
||
/* Allocate array to record swap information. */
|
||
swapInfo = (DbeSwapInfoPtr)Xalloc(nStuff * sizeof(DbeSwapInfoRec));
|
||
if (swapInfo == NULL)
|
||
{
|
||
return(BadAlloc);
|
||
}
|
||
|
||
|
||
for (i = 0; i < nStuff; i++)
|
||
{
|
||
/* Check all windows to swap. */
|
||
|
||
/* Each window must be a valid window - BadWindow. */
|
||
error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client,
|
||
DixWriteAccess);
|
||
if (error != Success) {
|
||
Xfree(swapInfo);
|
||
return error;
|
||
}
|
||
|
||
/* Each window must be double-buffered - BadMatch. */
|
||
if (DBE_WINDOW_PRIV(pWin) == NULL)
|
||
{
|
||
Xfree(swapInfo);
|
||
return(BadMatch);
|
||
}
|
||
|
||
/* Each window must only be specified once - BadMatch. */
|
||
for (j = i + 1; j < nStuff; j++)
|
||
{
|
||
if (dbeSwapInfo[i].window == dbeSwapInfo[j].window)
|
||
{
|
||
Xfree(swapInfo);
|
||
return(BadMatch);
|
||
}
|
||
}
|
||
|
||
/* Each swap action must be valid - BadValue. */
|
||
if ((dbeSwapInfo[i].swapAction != XdbeUndefined ) &&
|
||
(dbeSwapInfo[i].swapAction != XdbeBackground) &&
|
||
(dbeSwapInfo[i].swapAction != XdbeUntouched ) &&
|
||
(dbeSwapInfo[i].swapAction != XdbeCopied ))
|
||
{
|
||
Xfree(swapInfo);
|
||
return(BadValue);
|
||
}
|
||
|
||
/* Everything checks out OK. Fill in the swap info array. */
|
||
swapInfo[i].pWindow = pWin;
|
||
swapInfo[i].swapAction = dbeSwapInfo[i].swapAction;
|
||
|
||
} /* for (i = 0; i < nStuff; i++) */
|
||
|
||
|
||
/* Call the DDX routine to perform the swap(s). The DDX routine should
|
||
* scan the swap list (swap info), swap any buffers that it knows how to
|
||
* handle, delete them from the list, and update nStuff to indicate how
|
||
* many windows it did not handle.
|
||
*
|
||
* This scheme allows a range of sophistication in the DDX SwapBuffers()
|
||
* implementation. Naive implementations could just swap the first buffer
|
||
* in the list, move the last buffer to the front, decrement nStuff, and
|
||
* return. The next level of sophistication could be to scan the whole
|
||
* list for windows on the same screen. Up another level, the DDX routine
|
||
* could deal with cross-screen synchronization.
|
||
*/
|
||
|
||
while (nStuff > 0)
|
||
{
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow);
|
||
error = (*pDbeScreenPriv->SwapBuffers)(client, &nStuff, swapInfo);
|
||
if (error != Success)
|
||
{
|
||
Xfree(swapInfo);
|
||
return(error);
|
||
}
|
||
}
|
||
|
||
Xfree(swapInfo);
|
||
return(Success);
|
||
|
||
} /* ProcDbeSwapBuffers() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeBeginIdiom
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeBeginIdiom request.
|
||
* This request informs the server that a complex swap will immediately
|
||
* follow this request.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeBeginIdiom(ClientPtr client)
|
||
{
|
||
/* REQUEST(xDbeBeginIdiomReq); */
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
register int i;
|
||
|
||
|
||
REQUEST_SIZE_MATCH(xDbeBeginIdiomReq);
|
||
|
||
for (i = 0; i < screenInfo.numScreens; i++)
|
||
{
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]);
|
||
|
||
/* Call the DDX begin idiom procedure if there is one. */
|
||
if (pDbeScreenPriv->BeginIdiom)
|
||
{
|
||
(*pDbeScreenPriv->BeginIdiom)(client);
|
||
}
|
||
}
|
||
|
||
return(Success);
|
||
|
||
} /* ProcDbeBeginIdiom() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeGetVisualInfo
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a ProcDbeGetVisualInfo request.
|
||
* This request returns information about which visuals support
|
||
* double buffering.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadDrawable - value in screen specifiers is not a valid drawable
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeGetVisualInfo(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeGetVisualInfoReq);
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
xDbeGetVisualInfoReply rep;
|
||
Drawable *drawables;
|
||
DrawablePtr *pDrawables = NULL;
|
||
register int i, j, n, rc;
|
||
register int count; /* number of visual infos in reply */
|
||
register int length; /* length of reply */
|
||
ScreenPtr pScreen;
|
||
XdbeScreenVisualInfo *pScrVisInfo;
|
||
|
||
|
||
REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
|
||
|
||
if (stuff->n > UINT32_MAX / sizeof(DrawablePtr))
|
||
return BadAlloc;
|
||
/* Make sure any specified drawables are valid. */
|
||
if (stuff->n != 0)
|
||
{
|
||
if (!(pDrawables = (DrawablePtr *)Xalloc(stuff->n *
|
||
sizeof(DrawablePtr))))
|
||
{
|
||
return(BadAlloc);
|
||
}
|
||
|
||
drawables = (Drawable *)&stuff[1];
|
||
|
||
for (i = 0; i < stuff->n; i++)
|
||
{
|
||
rc = dixLookupDrawable(pDrawables+i, drawables[i], client, 0,
|
||
DixReadAccess);
|
||
if (rc != Success) {
|
||
Xfree(pDrawables);
|
||
return rc;
|
||
}
|
||
}
|
||
}
|
||
|
||
count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n;
|
||
if (!(pScrVisInfo = (XdbeScreenVisualInfo *)xalloc(count *
|
||
sizeof(XdbeScreenVisualInfo))))
|
||
{
|
||
if (pDrawables)
|
||
{
|
||
Xfree(pDrawables);
|
||
}
|
||
|
||
return(BadAlloc);
|
||
}
|
||
|
||
length = 0;
|
||
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
pScreen = (stuff->n == 0) ? screenInfo.screens[i] :
|
||
pDrawables[i]->pScreen;
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
|
||
if (!(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i]))
|
||
{
|
||
/* We failed to alloc pScrVisInfo[i].visinfo. */
|
||
|
||
/* Free visinfos that we allocated for previous screen infos.*/
|
||
for (j = 0; j < i; j++)
|
||
{
|
||
xfree(pScrVisInfo[j].visinfo);
|
||
}
|
||
|
||
/* Free pDrawables if we needed to allocate it above. */
|
||
if (pDrawables)
|
||
{
|
||
Xfree(pDrawables);
|
||
}
|
||
|
||
return(BadAlloc);
|
||
}
|
||
|
||
/* Account for n, number of xDbeVisInfo items in list. */
|
||
length += sizeof(CARD32);
|
||
|
||
/* Account for n xDbeVisInfo items */
|
||
length += pScrVisInfo[i].count * sizeof(xDbeVisInfo);
|
||
}
|
||
|
||
rep.type = X_Reply;
|
||
rep.sequenceNumber = client->sequence;
|
||
rep.length = length >> 2;
|
||
rep.m = count;
|
||
|
||
if (client->swapped)
|
||
{
|
||
swaps(&rep.sequenceNumber, n);
|
||
swapl(&rep.length, n);
|
||
swapl(&rep.m, n);
|
||
}
|
||
|
||
/* Send off reply. */
|
||
WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep);
|
||
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
CARD32 data32;
|
||
|
||
/* For each screen in the reply, send off the visual info */
|
||
|
||
/* Send off number of visuals. */
|
||
data32 = (CARD32)pScrVisInfo[i].count;
|
||
|
||
if (client->swapped)
|
||
{
|
||
swapl(&data32, n);
|
||
}
|
||
|
||
WriteToClient(client, sizeof(CARD32), (char *)&data32);
|
||
|
||
/* Now send off visual info items. */
|
||
for (j = 0; j < pScrVisInfo[i].count; j++)
|
||
{
|
||
xDbeVisInfo visInfo;
|
||
|
||
/* Copy the data in the client data structure to a protocol
|
||
* data structure. We will send data to the client from the
|
||
* protocol data structure.
|
||
*/
|
||
|
||
visInfo.visualID = (CARD32)pScrVisInfo[i].visinfo[j].visual;
|
||
visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth;
|
||
visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel;
|
||
|
||
if (client->swapped)
|
||
{
|
||
swapl(&visInfo.visualID, n);
|
||
|
||
/* We do not need to swap depth and perfLevel since they are
|
||
* already 1 byte quantities.
|
||
*/
|
||
}
|
||
|
||
/* Write visualID(32), depth(8), perfLevel(8), and pad(16). */
|
||
WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID);
|
||
}
|
||
}
|
||
|
||
/* Clean up memory. */
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
xfree(pScrVisInfo[i].visinfo);
|
||
}
|
||
xfree(pScrVisInfo);
|
||
|
||
if (pDrawables)
|
||
{
|
||
Xfree(pDrawables);
|
||
}
|
||
|
||
return(client->noClientException);
|
||
|
||
} /* ProcDbeGetVisualInfo() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeGetbackBufferAttributes
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a ProcDbeGetbackBufferAttributes
|
||
* request. This request returns information about a back buffer.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeGetBackBufferAttributes(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeGetBackBufferAttributesReq);
|
||
xDbeGetBackBufferAttributesReply rep;
|
||
DbeWindowPrivPtr pDbeWindowPriv;
|
||
int n;
|
||
|
||
|
||
REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
|
||
|
||
if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client,
|
||
stuff->buffer, dbeWindowPrivResType, DixReadAccess)))
|
||
{
|
||
rep.attributes = None;
|
||
}
|
||
else
|
||
{
|
||
rep.attributes = pDbeWindowPriv->pWindow->drawable.id;
|
||
}
|
||
|
||
rep.type = X_Reply;
|
||
rep.sequenceNumber = client->sequence;
|
||
rep.length = 0;
|
||
|
||
if (client->swapped)
|
||
{
|
||
swaps(&rep.sequenceNumber, n);
|
||
swapl(&rep.length, n);
|
||
swapl(&rep.attributes, n);
|
||
}
|
||
|
||
WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply),
|
||
(char *)&rep);
|
||
return(client->noClientException);
|
||
|
||
} /* ProcDbeGetbackBufferAttributes() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: ProcDbeDispatch
|
||
*
|
||
* Description:
|
||
*
|
||
* This function dispatches DBE requests.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
ProcDbeDispatch(ClientPtr client)
|
||
{
|
||
REQUEST(xReq);
|
||
|
||
|
||
switch (stuff->data)
|
||
{
|
||
case X_DbeGetVersion:
|
||
return(ProcDbeGetVersion(client));
|
||
|
||
case X_DbeAllocateBackBufferName:
|
||
return(ProcDbeAllocateBackBufferName(client));
|
||
|
||
case X_DbeDeallocateBackBufferName:
|
||
return(ProcDbeDeallocateBackBufferName(client));
|
||
|
||
case X_DbeSwapBuffers:
|
||
return(ProcDbeSwapBuffers(client));
|
||
|
||
case X_DbeBeginIdiom:
|
||
return(ProcDbeBeginIdiom(client));
|
||
|
||
case X_DbeEndIdiom:
|
||
return(Success);
|
||
|
||
case X_DbeGetVisualInfo:
|
||
return(ProcDbeGetVisualInfo(client));
|
||
|
||
case X_DbeGetBackBufferAttributes:
|
||
return(ProcDbeGetBackBufferAttributes(client));
|
||
|
||
default:
|
||
return(BadRequest);
|
||
}
|
||
|
||
} /* ProcDbeDispatch() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeGetVersion
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeGetVersion request on a swapped
|
||
* server. This request returns the major and minor version numbers of
|
||
* this extension.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeGetVersion(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeGetVersionReq);
|
||
register int n;
|
||
|
||
|
||
swaps(&stuff->length, n);
|
||
return(ProcDbeGetVersion(client));
|
||
|
||
} /* SProcDbeGetVersion() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeAllocateBackBufferName
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeAllocateBackBufferName request on
|
||
* a swapped server. This request allocates a drawable ID used to refer
|
||
* to the back buffer of a window.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadAlloc - server can not allocate resources
|
||
* BadIDChoice - id is out of range for client; id is already in use
|
||
* BadMatch - window is not an InputOutput window;
|
||
* visual of window is not on list returned by
|
||
* DBEGetVisualInfo;
|
||
* BadValue - invalid swap action is specified
|
||
* BadWindow - window is not a valid window
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeAllocateBackBufferName(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeAllocateBackBufferNameReq);
|
||
register int n;
|
||
|
||
swaps(&stuff->length, n);
|
||
REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
|
||
|
||
swapl(&stuff->window, n);
|
||
swapl(&stuff->buffer, n);
|
||
/* stuff->swapAction is a byte. We do not need to swap this field. */
|
||
|
||
return(ProcDbeAllocateBackBufferName(client));
|
||
|
||
} /* SProcDbeAllocateBackBufferName() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeDeallocateBackBufferName
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeDeallocateBackBufferName request
|
||
* on a swapped server. This request frees a drawable ID that was
|
||
* obtained by a DbeAllocateBackBufferName request.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadBuffer - buffer to deallocate is not associated with a window
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeDeallocateBackBufferName(ClientPtr client)
|
||
{
|
||
REQUEST (xDbeDeallocateBackBufferNameReq);
|
||
register int n;
|
||
|
||
|
||
swaps(&stuff->length, n);
|
||
REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
|
||
|
||
swapl(&stuff->buffer, n);
|
||
|
||
return(ProcDbeDeallocateBackBufferName(client));
|
||
|
||
} /* SProcDbeDeallocateBackBufferName() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeSwapBuffers
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeSwapBuffers request on a swapped
|
||
* server. This request swaps the buffers for all windows listed,
|
||
* applying the appropriate swap action for each window.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadMatch - a window in request is not double-buffered; a window in
|
||
* request is listed more than once; all windows in request do
|
||
* not have the same root
|
||
* BadValue - invalid swap action is specified
|
||
* BadWindow - a window in request is not valid
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeSwapBuffers(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeSwapBuffersReq);
|
||
register int i, n;
|
||
xDbeSwapInfo *pSwapInfo;
|
||
|
||
|
||
swaps(&stuff->length, n);
|
||
REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
|
||
|
||
swapl(&stuff->n, n);
|
||
|
||
if (stuff->n != 0)
|
||
{
|
||
pSwapInfo = (xDbeSwapInfo *)stuff+1;
|
||
|
||
/* The swap info following the fix part of this request is a window(32)
|
||
* followed by a 1 byte swap action and then 3 pad bytes. We only need
|
||
* to swap the window information.
|
||
*/
|
||
for (i = 0; i < stuff->n; i++)
|
||
{
|
||
swapl(&pSwapInfo->window, n);
|
||
}
|
||
}
|
||
|
||
return(ProcDbeSwapBuffers(client));
|
||
|
||
} /* SProcDbeSwapBuffers() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeBeginIdiom
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a DbeBeginIdiom request on a swapped
|
||
* server. This request informs the server that a complex swap will
|
||
* immediately follow this request.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeBeginIdiom(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeBeginIdiomReq);
|
||
register int n;
|
||
|
||
swaps(&stuff->length, n);
|
||
return(ProcDbeBeginIdiom(client));
|
||
|
||
} /* SProcDbeBeginIdiom() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeGetVisualInfo
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a ProcDbeGetVisualInfo request on a
|
||
* swapped server. This request returns information about which visuals
|
||
* support double buffering.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* BadDrawable - value in screen specifiers is not a valid drawable
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeGetVisualInfo(ClientPtr client)
|
||
{
|
||
REQUEST(xDbeGetVisualInfoReq);
|
||
register int n;
|
||
|
||
|
||
swaps(&stuff->length, n);
|
||
REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
|
||
|
||
swapl(&stuff->n, n);
|
||
SwapRestL(stuff);
|
||
|
||
return(ProcDbeGetVisualInfo(client));
|
||
|
||
} /* SProcDbeGetVisualInfo() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeGetbackBufferAttributes
|
||
*
|
||
* Description:
|
||
*
|
||
* This function is for processing a ProcDbeGetbackBufferAttributes
|
||
* request on a swapped server. This request returns information about a
|
||
* back buffer.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* Success
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeGetBackBufferAttributes(ClientPtr client)
|
||
{
|
||
REQUEST (xDbeGetBackBufferAttributesReq);
|
||
register int n;
|
||
|
||
swaps(&stuff->length, n);
|
||
REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
|
||
|
||
swapl(&stuff->buffer, n);
|
||
|
||
return(ProcDbeGetBackBufferAttributes(client));
|
||
|
||
} /* SProcDbeGetBackBufferAttributes() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: SProcDbeDispatch
|
||
*
|
||
* Description:
|
||
*
|
||
* This function dispatches DBE requests on a swapped server.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static int
|
||
SProcDbeDispatch(ClientPtr client)
|
||
{
|
||
REQUEST(xReq);
|
||
|
||
|
||
switch (stuff->data)
|
||
{
|
||
case X_DbeGetVersion:
|
||
return(SProcDbeGetVersion(client));
|
||
|
||
case X_DbeAllocateBackBufferName:
|
||
return(SProcDbeAllocateBackBufferName(client));
|
||
|
||
case X_DbeDeallocateBackBufferName:
|
||
return(SProcDbeDeallocateBackBufferName(client));
|
||
|
||
case X_DbeSwapBuffers:
|
||
return(SProcDbeSwapBuffers(client));
|
||
|
||
case X_DbeBeginIdiom:
|
||
return(SProcDbeBeginIdiom(client));
|
||
|
||
case X_DbeEndIdiom:
|
||
return(Success);
|
||
|
||
case X_DbeGetVisualInfo:
|
||
return(SProcDbeGetVisualInfo(client));
|
||
|
||
case X_DbeGetBackBufferAttributes:
|
||
return(SProcDbeGetBackBufferAttributes(client));
|
||
|
||
default:
|
||
return (BadRequest);
|
||
}
|
||
|
||
} /* SProcDbeDispatch() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeSetupBackgroundPainter
|
||
*
|
||
* Description:
|
||
*
|
||
* This function sets up pGC to clear pixmaps.
|
||
*
|
||
* Return Values:
|
||
*
|
||
* TRUE - setup was successful
|
||
* FALSE - the window's background state is NONE
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static Bool
|
||
DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC)
|
||
{
|
||
pointer 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] = (pointer)background.pixel;
|
||
gcvalues[1] = (pointer)FillSolid;
|
||
gcmask = GCForeground|GCFillStyle;
|
||
break;
|
||
|
||
case BackgroundPixmap:
|
||
gcvalues[0] = (pointer)FillTiled;
|
||
gcvalues[1] = (pointer)background.pixmap;
|
||
gcvalues[2] = (pointer)(long)ts_x_origin;
|
||
gcvalues[3] = (pointer)(long)ts_y_origin;
|
||
gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
|
||
break;
|
||
|
||
default:
|
||
/* pWin->backgroundState == None */
|
||
return(FALSE);
|
||
}
|
||
|
||
if (DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE) != 0)
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
return(TRUE);
|
||
|
||
} /* DbeSetupBackgroundPainter() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeDrawableDelete
|
||
*
|
||
* Description:
|
||
*
|
||
* This is the resource delete function for dbeDrawableResType.
|
||
* It is registered when the drawable resource type is created in
|
||
* DbeExtensionInit().
|
||
*
|
||
* To make resource deletion simple, we do not do anything in this function
|
||
* and leave all resource deleteion to DbeWindowPrivDelete(), which will
|
||
* eventually be called or already has been called. Deletion functions are
|
||
* not guaranteed to be called in any particular order.
|
||
*
|
||
*****************************************************************************/
|
||
static int
|
||
DbeDrawableDelete(pointer pDrawable, XID id)
|
||
{
|
||
return(Success);
|
||
|
||
} /* DbeDrawableDelete() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeWindowPrivDelete
|
||
*
|
||
* Description:
|
||
*
|
||
* This is the resource delete function for dbeWindowPrivResType.
|
||
* It is registered when the drawable resource type is created in
|
||
* DbeExtensionInit().
|
||
*
|
||
*****************************************************************************/
|
||
static int
|
||
DbeWindowPrivDelete(pointer pDbeWinPriv, XID id)
|
||
{
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv;
|
||
int i;
|
||
|
||
|
||
/*
|
||
**************************************************************************
|
||
** Remove the buffer ID from the ID array.
|
||
**************************************************************************
|
||
*/
|
||
|
||
/* Find the ID in the ID array. */
|
||
i = 0;
|
||
while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id))
|
||
{
|
||
i++;
|
||
}
|
||
|
||
if (i == pDbeWindowPriv->nBufferIDs)
|
||
{
|
||
/* We did not find the ID in the array. We should never get here. */
|
||
return(BadValue);
|
||
}
|
||
|
||
/* Remove the ID from the array. */
|
||
|
||
if (i < (pDbeWindowPriv->nBufferIDs - 1))
|
||
{
|
||
/* Compress the buffer ID array, overwriting the ID in the process. */
|
||
memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1],
|
||
(pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID));
|
||
}
|
||
else
|
||
{
|
||
/* We are removing the last ID in the array, in which case, the
|
||
* assignement below is all that we need to do.
|
||
*/
|
||
}
|
||
pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT;
|
||
|
||
pDbeWindowPriv->nBufferIDs--;
|
||
|
||
/* If an extended array was allocated, then check to see if the remaining
|
||
* buffer IDs will fit in the static array.
|
||
*/
|
||
|
||
if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) &&
|
||
(pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS))
|
||
{
|
||
/* Copy the IDs back into the static array. */
|
||
memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs,
|
||
DBE_INIT_MAX_IDS * sizeof(XID));
|
||
|
||
/* Free the extended array; use the static array. */
|
||
xfree(pDbeWindowPriv->IDs);
|
||
pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs;
|
||
pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS;
|
||
}
|
||
|
||
|
||
/*
|
||
**************************************************************************
|
||
** Perform DDX level tasks.
|
||
**************************************************************************
|
||
*/
|
||
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV(
|
||
(DbeWindowPrivPtr)pDbeWindowPriv);
|
||
(*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id);
|
||
|
||
|
||
/*
|
||
**************************************************************************
|
||
** Perform miscellaneous tasks if this is the last buffer associated
|
||
** with the window.
|
||
**************************************************************************
|
||
*/
|
||
|
||
if (pDbeWindowPriv->nBufferIDs == 0)
|
||
{
|
||
/* Reset the DBE window priv pointer. */
|
||
pDbeWindowPriv->pWindow->devPrivates[dbeWindowPrivIndex].ptr =
|
||
(pointer)NULL;
|
||
|
||
/* We are done with the window priv. */
|
||
xfree(pDbeWindowPriv);
|
||
}
|
||
|
||
return(Success);
|
||
|
||
} /* DbeWindowPrivDelete() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeResetProc
|
||
*
|
||
* Description:
|
||
*
|
||
* This routine is called at the end of every server generation.
|
||
* It deallocates any memory reserved for the extension and performs any
|
||
* other tasks related to shutting down the extension.
|
||
*
|
||
*****************************************************************************/
|
||
static void
|
||
DbeResetProc(ExtensionEntry *extEntry)
|
||
{
|
||
int i;
|
||
ScreenPtr pScreen;
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
|
||
|
||
if (dbeScreenPrivIndex < 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < screenInfo.numScreens; i++)
|
||
{
|
||
pScreen = screenInfo.screens[i];
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
|
||
if (pDbeScreenPriv)
|
||
{
|
||
/* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/
|
||
pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
|
||
|
||
if (pDbeScreenPriv->ResetProc)
|
||
(*pDbeScreenPriv->ResetProc)(pScreen);
|
||
|
||
if (pDbeScreenPriv->winPrivPrivSizes)
|
||
{
|
||
xfree(pDbeScreenPriv->winPrivPrivSizes);
|
||
}
|
||
|
||
xfree(pDbeScreenPriv);
|
||
}
|
||
}
|
||
|
||
/* We want to init the initialization function table after every server
|
||
* reset in DbeRegisterFunction().
|
||
*/
|
||
firstRegistrationPass = TRUE;
|
||
|
||
} /* DbeResetProc() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeDestroyWindow
|
||
*
|
||
* Description:
|
||
*
|
||
* This is the wrapper for pScreen->DestroyWindow.
|
||
* This function frees buffer resources for a window before it is
|
||
* destroyed.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
static Bool
|
||
DbeDestroyWindow(WindowPtr pWin)
|
||
{
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
DbeWindowPrivPtr pDbeWindowPriv;
|
||
ScreenPtr pScreen;
|
||
Bool ret;
|
||
|
||
|
||
/*
|
||
**************************************************************************
|
||
** 1. Unwrap the member routine.
|
||
**************************************************************************
|
||
*/
|
||
|
||
pScreen = pWin->drawable.pScreen;
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
|
||
|
||
/*
|
||
**************************************************************************
|
||
** 2. Do any work necessary before the member routine is called.
|
||
**
|
||
** Call the window priv delete function for all buffer IDs associated
|
||
** with this window.
|
||
**************************************************************************
|
||
*/
|
||
|
||
if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
|
||
{
|
||
while (pDbeWindowPriv)
|
||
{
|
||
/* *DbeWinPrivDelete() will free the window private and set it to
|
||
* NULL if there are no more buffer IDs associated with this
|
||
* window.
|
||
*/
|
||
FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
|
||
pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
|
||
}
|
||
}
|
||
|
||
/*
|
||
**************************************************************************
|
||
** 3. Call the member routine, saving its result if necessary.
|
||
**************************************************************************
|
||
*/
|
||
|
||
ret = (*pScreen->DestroyWindow)(pWin);
|
||
|
||
/*
|
||
**************************************************************************
|
||
** 4. Rewrap the member routine, restoring the wrapper value first in case
|
||
** the wrapper (or something that it wrapped) change this value.
|
||
**************************************************************************
|
||
*/
|
||
|
||
pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
|
||
pScreen->DestroyWindow = DbeDestroyWindow;
|
||
|
||
/*
|
||
**************************************************************************
|
||
** 5. Do any work necessary after the member routine has been called.
|
||
**
|
||
** In this case we do not need to do anything.
|
||
**************************************************************************
|
||
*/
|
||
|
||
return(ret);
|
||
|
||
} /* DbeDestroyWindow() */
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* DBE DIX Procedure: DbeExtensionInit
|
||
*
|
||
* Description:
|
||
*
|
||
* Called from InitExtensions in main()
|
||
*
|
||
*****************************************************************************/
|
||
|
||
void
|
||
DbeExtensionInit(void)
|
||
{
|
||
ExtensionEntry *extEntry;
|
||
register int i, j;
|
||
ScreenPtr pScreen = NULL;
|
||
DbeScreenPrivPtr pDbeScreenPriv;
|
||
int nStubbedScreens = 0;
|
||
Bool ddxInitSuccess;
|
||
|
||
#ifdef PANORAMIX
|
||
if(!noPanoramiXExtension) return;
|
||
#endif
|
||
|
||
/* Allocate private pointers in windows and screens. */
|
||
|
||
if ((dbeScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if ((dbeWindowPrivIndex = AllocateWindowPrivateIndex()) < 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
/* Initialize the priv priv counts between server generations. */
|
||
winPrivPrivCount = 0;
|
||
|
||
/* Create the resource types. */
|
||
dbeDrawableResType =
|
||
CreateNewResourceType(DbeDrawableDelete) | RC_CACHED | RC_DRAWABLE;
|
||
dbeWindowPrivResType =
|
||
CreateNewResourceType(DbeWindowPrivDelete);
|
||
|
||
for (i = 0; i < screenInfo.numScreens; i++)
|
||
{
|
||
/* For each screen, set up DBE screen privates and init DIX and DDX
|
||
* interface.
|
||
*/
|
||
|
||
pScreen = screenInfo.screens[i];
|
||
|
||
if (!AllocateWindowPrivate(pScreen, dbeWindowPrivIndex, 0) ||
|
||
!(pDbeScreenPriv =
|
||
(DbeScreenPrivPtr)Xcalloc(sizeof(DbeScreenPrivRec))))
|
||
{
|
||
/* If we can not alloc a window or screen private,
|
||
* then free any privates that we already alloc'ed and return
|
||
*/
|
||
|
||
for (j = 0; j < i; j++)
|
||
{
|
||
xfree(screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr);
|
||
screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr = NULL;
|
||
}
|
||
return;
|
||
}
|
||
|
||
pScreen->devPrivates[dbeScreenPrivIndex].ptr = (pointer)pDbeScreenPriv;
|
||
|
||
/* Store the DBE priv priv size info for later use when allocating
|
||
* priv privs at the driver level.
|
||
*/
|
||
pDbeScreenPriv->winPrivPrivLen = 0;
|
||
pDbeScreenPriv->winPrivPrivSizes = (unsigned *)NULL;
|
||
pDbeScreenPriv->totalWinPrivSize = sizeof(DbeWindowPrivRec);
|
||
|
||
/* Copy the resource types */
|
||
pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType;
|
||
pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType;
|
||
|
||
/* Copy the private indices */
|
||
pDbeScreenPriv->dbeScreenPrivIndex = dbeScreenPrivIndex;
|
||
pDbeScreenPriv->dbeWindowPrivIndex = dbeWindowPrivIndex;
|
||
|
||
if(DbeInitFunct[i])
|
||
{
|
||
/* This screen supports DBE. */
|
||
|
||
/* Setup DIX. */
|
||
pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter;
|
||
pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv;
|
||
pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex;
|
||
pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv;
|
||
|
||
/* Setup DDX. */
|
||
ddxInitSuccess = (*DbeInitFunct[i])(pScreen, pDbeScreenPriv);
|
||
|
||
/* DDX DBE initialization may have the side affect of
|
||
* reallocating pDbeScreenPriv, so we need to update it.
|
||
*/
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
|
||
if (ddxInitSuccess)
|
||
{
|
||
/* Wrap DestroyWindow. The DDX initialization function
|
||
* already wrapped PositionWindow for us.
|
||
*/
|
||
|
||
pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
|
||
pScreen->DestroyWindow = DbeDestroyWindow;
|
||
}
|
||
else
|
||
{
|
||
/* DDX initialization failed. Stub the screen. */
|
||
DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* This screen does not support DBE. */
|
||
|
||
#ifndef DISABLE_MI_DBE_BY_DEFAULT
|
||
/* Setup DIX. */
|
||
pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter;
|
||
pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv;
|
||
pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex;
|
||
pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv;
|
||
|
||
/* Setup DDX. */
|
||
ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv);
|
||
|
||
/* DDX DBE initialization may have the side affect of
|
||
* reallocating pDbeScreenPriv, so we need to update it.
|
||
*/
|
||
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
|
||
|
||
if (ddxInitSuccess)
|
||
{
|
||
/* Wrap DestroyWindow. The DDX initialization function
|
||
* already wrapped PositionWindow for us.
|
||
*/
|
||
|
||
pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
|
||
pScreen->DestroyWindow = DbeDestroyWindow;
|
||
}
|
||
else
|
||
{
|
||
/* DDX initialization failed. Stub the screen. */
|
||
DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
|
||
}
|
||
#else
|
||
DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
|
||
#endif
|
||
|
||
} /* else -- this screen does not support DBE. */
|
||
|
||
} /* for (i = 0; i < screenInfo.numScreens; i++) */
|
||
|
||
|
||
if (nStubbedScreens == screenInfo.numScreens)
|
||
{
|
||
/* All screens stubbed. Clean up and return. */
|
||
|
||
for (i = 0; i < screenInfo.numScreens; i++)
|
||
{
|
||
xfree(screenInfo.screens[i]->devPrivates[dbeScreenPrivIndex].ptr);
|
||
pScreen->devPrivates[dbeScreenPrivIndex].ptr = NULL;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
/* Now add the extension. */
|
||
extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents,
|
||
DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch,
|
||
DbeResetProc, StandardMinorOpcode);
|
||
|
||
dbeErrorBase = extEntry->errorBase;
|
||
|
||
} /* DbeExtensionInit() */
|
||
|