xserver-multidpi/dbe/dbe.c
Alan Coopersmith 043c175865 Clean up memory better when GetVisualInfo fails in ProcDbeGetVisualInfo
Use calloc to initialize pScrVisInfo array so we don't have to check
which ones were already initialized when freeing them all.

On failure, set rc if necessary, and jump to code at end that already
frees all the necessary allocations and return rc.

Fixes parfait reported error:
Error: Memory leak (CWE 401)
   Memory leak of pointer 'pScrVisInfo' allocated with malloc((count * 16))
        at line 724 of dbe/dbe.c in function 'ProcDbeGetVisualInfo'.
          'pScrVisInfo' allocated at line 693 with malloc((count * 16)).
          pScrVisInfo leaks when rc != 0 at line 710
              and j >= i at line 716.

[ This bug was found by the Parfait 0.3.7 bug checking tool.
  For more information see http://labs.oracle.com/projects/parfait/ ]

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
2011-05-02 20:38:16 -07:00

1659 lines
47 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
*
* 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 */
#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"
#include "xace.h"
/* GLOBALS */
/* These are globals for use by DDX */
DevPrivateKeyRec dbeScreenPrivKeyRec;
DevPrivateKeyRec dbeWindowPrivKeyRec;
/* These are globals for use by DDX */
RESTYPE dbeDrawableResType;
RESTYPE dbeWindowPrivResType;
/* Used to generate DBE's BadBuffer error. */
static int dbeErrorBase;
/******************************************************************************
*
* 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;
/* 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 Success;
} /* 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, DixManageAccess);
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. */
free(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.
*/
pDbeWindowPriv = dixAllocateObjectWithPrivates(DbeWindowPrivRec, PRIVATE_DBE_WINDOW);
if (!pDbeWindowPriv)
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;
pDbeWindowPriv->IDs[0] = stuff->buffer;
add_index = 0;
for (i = 0; i < DBE_INIT_MAX_IDS; i++)
{
pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT;
}
/* Actually connect the window priv to the window. */
dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, 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 *)realloc(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:
dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, NULL);
free(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 rc, i;
pointer val;
REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
/* Buffer name must be valid */
rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer,
dbeWindowPrivResType, client,
DixDestroyAccess);
if (rc != Success)
return rc;
rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType,
client, DixDestroyAccess);
if (rc != Success)
return rc;
/* 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)malloc(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) {
free(swapInfo);
return error;
}
/* Each window must be double-buffered - BadMatch. */
if (DBE_WINDOW_PRIV(pWin) == NULL)
{
free(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)
{
free(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 ))
{
free(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)
{
free(swapInfo);
return error;
}
}
free(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 *)malloc(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,
DixGetAttrAccess);
if (rc != Success) {
free(pDrawables);
return rc;
}
}
}
count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n;
if (!(pScrVisInfo = calloc(count, sizeof(XdbeScreenVisualInfo))))
{
free(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);
rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
if (rc != Success)
goto freeScrVisInfo;
if (!(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i]))
{
/* We failed to alloc pScrVisInfo[i].visinfo. */
rc = BadAlloc;
/* Free visinfos that we allocated for previous screen infos.*/
goto freeScrVisInfo;
}
/* 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 = bytes_to_int32(length);
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);
}
}
rc = Success;
freeScrVisInfo:
/* Clean up memory. */
for (i = 0; i < count; i++)
{
free(pScrVisInfo[i].visinfo);
}
free(pScrVisInfo);
free(pDrawables);
return rc;
} /* 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 rc, n;
REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer,
dbeWindowPrivResType, client,
DixGetAttrAccess);
if (rc == Success)
{
rep.attributes = pDbeWindowPriv->pWindow->drawable.id;
}
else
{
rep.attributes = None;
}
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 Success;
} /* 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)
{
ChangeGCVal 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].val = background.pixel;
gcvalues[1].val = FillSolid;
gcmask = GCForeground|GCFillStyle;
break;
case BackgroundPixmap:
gcvalues[0].val = FillTiled;
gcvalues[1].ptr = background.pixmap;
gcvalues[2].val = ts_x_origin;
gcvalues[3].val = ts_y_origin;
gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
break;
default:
/* pWin->backgroundState == None */
return FALSE;
}
return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0;
} /* 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. */
free(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. */
dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey,
NULL);
/* We are done with the window priv. */
dixFreeObjectWithPrivates(pDbeWindowPriv, PRIVATE_DBE_WINDOW);
}
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;
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);
free(pDbeScreenPriv);
}
}
} /* 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
/* Create the resource types. */
dbeDrawableResType =
CreateNewResourceType(DbeDrawableDelete, "dbeDrawable");
if (!dbeDrawableResType)
return;
dbeDrawableResType |= RC_DRAWABLE;
dbeWindowPrivResType =
CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow");
if (!dbeWindowPrivResType)
return;
if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec, PRIVATE_SCREEN, 0))
return;
if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec, PRIVATE_WINDOW, 0))
return;
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 (!(pDbeScreenPriv = malloc (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++)
{
free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates,
dbeScreenPrivKey));
dixSetPrivate(&screenInfo.screens[j]->devPrivates,
dbeScreenPrivKey, NULL);
}
return;
}
dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv);
{
/* We don't have DDX support for DBE anymore */
#ifndef DISABLE_MI_DBE_BY_DEFAULT
/* Setup DIX. */
pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter;
/* 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
}
} /* 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++)
{
free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates,
dbeScreenPrivKey));
dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL);
}
return;
}
/* Now add the extension. */
extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents,
DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch,
DbeResetProc, StandardMinorOpcode);
dbeErrorBase = extEntry->errorBase;
SetResourceTypeErrorValue(dbeWindowPrivResType, dbeErrorBase + DbeBadBuffer);
SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer);
} /* DbeExtensionInit() */