1153 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1153 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
/* $Xorg: lbxcmap.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */
 | 
						|
 | 
						|
/*
 | 
						|
Copyright 1996, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included
 | 
						|
in all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | 
						|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | 
						|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | 
						|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | 
						|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
						|
OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall
 | 
						|
not be used in advertising or otherwise to promote the sale, use or
 | 
						|
other dealings in this Software without prior written authorization
 | 
						|
from The Open Group.
 | 
						|
*/
 | 
						|
/* $XFree86: xc/programs/Xserver/lbx/lbxcmap.c,v 1.9 2001/08/23 14:46:57 alanh Exp $ */
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#define NEED_REPLIES
 | 
						|
#define NEED_EVENTS
 | 
						|
#include "X.h"
 | 
						|
#include "Xproto.h"
 | 
						|
#include "Xos.h"
 | 
						|
#include "misc.h"
 | 
						|
#include "os.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
#include "resource.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "colormapst.h"
 | 
						|
#include "propertyst.h"
 | 
						|
#define _XLBX_SERVER_
 | 
						|
#include "lbxstr.h"
 | 
						|
#include "lbxserve.h"
 | 
						|
#include "Xfuncproto.h"
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
static int lbxScreenPrivIndex;		/* lbx screen private index */
 | 
						|
static int lbxColormapPrivIndex;	/* lbx colormap private index */
 | 
						|
 | 
						|
typedef struct {			/* lbx screen private */
 | 
						|
    CreateColormapProcPtr CreateColormap;
 | 
						|
    DestroyColormapProcPtr DestroyColormap;
 | 
						|
  CloseScreenProcPtr CloseScreen;
 | 
						|
} LbxScreenPriv;
 | 
						|
 | 
						|
typedef struct _LbxStalled {
 | 
						|
    XID id;
 | 
						|
    struct _LbxStalled *next;
 | 
						|
} LbxStalled;
 | 
						|
 | 
						|
typedef struct _LbxColormapPriv {	/* lbx colormap private */
 | 
						|
    char	grab_status;
 | 
						|
    char	smart_grab;
 | 
						|
    LbxProxyPtr	grabber;
 | 
						|
    int		last_grabber;	/* uid, not pid */
 | 
						|
    LbxStalled	*stalled_clients;
 | 
						|
    ColormapPtr	next;		/* proxy chain */
 | 
						|
} LbxColormapPriv;
 | 
						|
 | 
						|
#define CMAP_NOT_GRABBED	0
 | 
						|
#define CMAP_GRABBED		1
 | 
						|
#define CMAP_WAITING_FOR_UNGRAB	2
 | 
						|
 | 
						|
static int LbxUnstallClient(pointer data, XID id);
 | 
						|
 | 
						|
static RESTYPE StalledResType;
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize the fields in the colormap private allocated for LBX.
 | 
						|
 */
 | 
						|
 | 
						|
static LbxColormapPriv *
 | 
						|
LbxColormapPrivInit (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv;
 | 
						|
 | 
						|
    cmapPriv = (LbxColormapPriv *) xalloc (sizeof (LbxColormapPriv));
 | 
						|
    if (!cmapPriv)
 | 
						|
	return cmapPriv;
 | 
						|
 | 
						|
    pmap->devPrivates[lbxColormapPrivIndex].ptr = (pointer) cmapPriv;
 | 
						|
 | 
						|
    cmapPriv->grab_status = CMAP_NOT_GRABBED;
 | 
						|
    cmapPriv->grabber = NULL;
 | 
						|
    cmapPriv->last_grabber = 0;
 | 
						|
    cmapPriv->smart_grab = FALSE;
 | 
						|
    cmapPriv->stalled_clients = NULL;
 | 
						|
    cmapPriv->next = NULL;
 | 
						|
 | 
						|
    return cmapPriv;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
LbxDefCmapPrivInit (ColormapPtr pmap, int index)
 | 
						|
{
 | 
						|
#if 0
 | 
						|
    /* BUG: You can't do that. lbxColormapPrivIndex hasn't 
 | 
						|
	been initialized yet.  */
 | 
						|
    pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | 
						|
#endif
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
LbxCreateColormap (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pmap->pScreen;
 | 
						|
    Bool ret;
 | 
						|
 | 
						|
    pScreen->CreateColormap = ((LbxScreenPriv *) (pScreen->devPrivates[
 | 
						|
	lbxScreenPrivIndex].ptr))->CreateColormap;
 | 
						|
 | 
						|
    pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | 
						|
    ret = (*pScreen->CreateColormap) (pmap);
 | 
						|
 
 | 
						|
    pScreen->CreateColormap = LbxCreateColormap;
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
LbxDestroyColormap (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pmap->pScreen;
 | 
						|
 | 
						|
    LbxReleaseCmap(pmap, FALSE);
 | 
						|
    pScreen->DestroyColormap = ((LbxScreenPriv *) (pScreen->devPrivates[
 | 
						|
	lbxScreenPrivIndex].ptr))->DestroyColormap;
 | 
						|
    (*pScreen->DestroyColormap) (pmap);
 | 
						|
    if (pmap->devPrivates && pmap->devPrivates[lbxColormapPrivIndex].ptr)
 | 
						|
	xfree(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
    pScreen->DestroyColormap = LbxDestroyColormap;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
LbxCloseScreen(int i, ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    LbxScreenPriv* pLbxScrPriv = ((LbxScreenPriv *) 
 | 
						|
			     (pScreen->devPrivates[lbxScreenPrivIndex].ptr));
 | 
						|
    
 | 
						|
    pScreen->CloseScreen = pLbxScrPriv->CloseScreen;
 | 
						|
 | 
						|
    xfree(pScreen->devPrivates[lbxScreenPrivIndex].ptr);
 | 
						|
    pScreen->devPrivates[lbxScreenPrivIndex].ptr = NULL;
 | 
						|
 | 
						|
    return pScreen->CloseScreen(i, pScreen);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize LBX colormap private.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
LbxCmapInit (void)
 | 
						|
 | 
						|
{
 | 
						|
    LbxScreenPriv *pScreenPriv;
 | 
						|
    ColormapPtr defMap;
 | 
						|
    ScreenPtr pScreen;
 | 
						|
    int i;
 | 
						|
 | 
						|
    StalledResType = CreateNewResourceType(LbxUnstallClient);
 | 
						|
 | 
						|
    lbxScreenPrivIndex = AllocateScreenPrivateIndex ();
 | 
						|
    if (lbxScreenPrivIndex < 0)
 | 
						|
	return 0;
 | 
						|
 | 
						|
    lbxColormapPrivIndex = AllocateColormapPrivateIndex (LbxDefCmapPrivInit);
 | 
						|
    if (lbxColormapPrivIndex < 0)
 | 
						|
	return 0;
 | 
						|
 | 
						|
    for (i = 0; i < screenInfo.numScreens; i++)
 | 
						|
    {
 | 
						|
	pScreen = screenInfo.screens[i];
 | 
						|
 | 
						|
        defMap = (ColormapPtr) LookupIDByType(
 | 
						|
			pScreen->defColormap, RT_COLORMAP);
 | 
						|
 | 
						|
	/* now lbxColormapPrivIndex exists */
 | 
						|
        defMap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | 
						|
 | 
						|
	pScreenPriv = (LbxScreenPriv *) xalloc (sizeof (LbxScreenPriv));
 | 
						|
	if (!pScreenPriv)
 | 
						|
	    return 0;
 | 
						|
 | 
						|
	pScreenPriv->CreateColormap = pScreen->CreateColormap;
 | 
						|
	pScreen->CreateColormap = LbxCreateColormap;
 | 
						|
	pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
 | 
						|
	pScreen->DestroyColormap = LbxDestroyColormap;
 | 
						|
	pScreenPriv->CloseScreen = pScreen->CloseScreen;
 | 
						|
	pScreen->CloseScreen = LbxCloseScreen;
 | 
						|
	pScreen->devPrivates[lbxScreenPrivIndex].ptr = (pointer) pScreenPriv;
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Return the number of allocated cells in the PSEUDO colormap.
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
NumAllocatedCells (EntryPtr pent,
 | 
						|
		   int size)
 | 
						|
{
 | 
						|
    Pixel pixel;
 | 
						|
    int count = 0;
 | 
						|
 | 
						|
    for (pixel = 0; pixel < size; pixel++)
 | 
						|
    {
 | 
						|
	if (pent[pixel].refcnt != 0 && pent[pixel].refcnt != AllocTemporary)
 | 
						|
	    count++;
 | 
						|
    }
 | 
						|
 | 
						|
    return count;
 | 
						|
}
 | 
						|
 | 
						|
#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
 | 
						|
#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
 | 
						|
#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
 | 
						|
 | 
						|
#define PIX_OUT(ptr,is2,val) \
 | 
						|
    if (is2) *ptr++ = (val) >> 8; \
 | 
						|
    *ptr++ = (val)
 | 
						|
#define RGB_OUT(ptr,is2,shift,val) \
 | 
						|
    *ptr++ = (val) >> shift; \
 | 
						|
    if (is2) *ptr++ = (val)
 | 
						|
 | 
						|
/*
 | 
						|
 * Return the list of allocated cells in the channel in
 | 
						|
 * the format required by LbxGrabCmapReply.
 | 
						|
 */
 | 
						|
 | 
						|
static CARD8 *
 | 
						|
OutputChannel(ColormapPtr pmap,
 | 
						|
	      EntryPtr chan,
 | 
						|
	      int size,
 | 
						|
	      CARD8 *ptr,
 | 
						|
	      CARD8 flags,
 | 
						|
	      CARD8 channels)
 | 
						|
{
 | 
						|
    Bool	px2;
 | 
						|
    Bool	rgb2;
 | 
						|
    int		shift;
 | 
						|
    int		rgb_sz;
 | 
						|
    Pixel	pixel;
 | 
						|
    EntryPtr	pent;
 | 
						|
    CARD8 *pixel_private_range_ptr = NULL;
 | 
						|
    CARD8 *pixel_shared_range_ptr = NULL;
 | 
						|
    int		allocpriv;
 | 
						|
 | 
						|
    px2 = (flags & LBX_2BYTE_PIXELS) != 0;
 | 
						|
    rgb2 = (flags & LBX_RGB_BITS_MASK) > 7;
 | 
						|
    if (rgb2)
 | 
						|
	shift = 8;
 | 
						|
    else
 | 
						|
	shift = 15 - (flags & LBX_RGB_BITS_MASK);
 | 
						|
    rgb_sz = rgb2 + 1;
 | 
						|
    if (channels == (DoRed|DoGreen|DoBlue))
 | 
						|
	rgb_sz *= 3;
 | 
						|
    /* kinda gross, but ddxen use AllocAll on static maps */
 | 
						|
    allocpriv = (pmap->pVisual->class & DynamicClass) ? AllocPrivate : 0;
 | 
						|
    for (pixel = 0; pixel < size; pixel++)
 | 
						|
    {
 | 
						|
	pent = (EntryPtr) &chan[pixel];
 | 
						|
 | 
						|
	if (pent->refcnt == 0 || pent->refcnt == AllocTemporary)
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * A free pixel.  This disrupts all ranges.
 | 
						|
	     */
 | 
						|
 | 
						|
	    pixel_private_range_ptr = pixel_shared_range_ptr = NULL;
 | 
						|
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	else if (pent->refcnt == allocpriv)
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * A private pixel.  This disrupts any PIXEL_SHARED_RANGE.
 | 
						|
	     */
 | 
						|
 | 
						|
	    pixel_shared_range_ptr = NULL;
 | 
						|
 | 
						|
	    if (!pixel_private_range_ptr)
 | 
						|
	    {
 | 
						|
		pixel_private_range_ptr = ptr;
 | 
						|
 | 
						|
		*ptr++ = LBX_PIXEL_PRIVATE;
 | 
						|
		PIX_OUT(ptr, px2, pixel);
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		CARD8 *pos = pixel_private_range_ptr + 2 + px2;
 | 
						|
		if (*pixel_private_range_ptr == LBX_PIXEL_PRIVATE) {
 | 
						|
		    *pixel_private_range_ptr = LBX_PIXEL_RANGE_PRIVATE;
 | 
						|
		    ptr += 1 + px2;
 | 
						|
		}
 | 
						|
		PIX_OUT(pos, px2, pixel);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * A shared pixel.  This disrupts any PIXEL_PRIVATE_RANGE.
 | 
						|
	     */
 | 
						|
 | 
						|
	    pixel_private_range_ptr = NULL;
 | 
						|
 | 
						|
	    if (!pixel_shared_range_ptr)
 | 
						|
	    {
 | 
						|
		pixel_shared_range_ptr = ptr;
 | 
						|
 | 
						|
		*ptr++ = LBX_PIXEL_SHARED;
 | 
						|
		PIX_OUT(ptr, px2, pixel);
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		CARD8 *pos = pixel_shared_range_ptr + 2 + px2;
 | 
						|
		if (*pixel_shared_range_ptr == LBX_PIXEL_SHARED)
 | 
						|
		{
 | 
						|
		    *pixel_shared_range_ptr = LBX_PIXEL_RANGE_SHARED;
 | 
						|
		    memmove (pos + 1 + px2, pos, rgb_sz);
 | 
						|
		    ptr += 1 + px2;
 | 
						|
		}
 | 
						|
		PIX_OUT(pos, px2, pixel);
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (channels & DoRed) {
 | 
						|
		RGB_OUT(ptr, rgb2, shift, pent->co.local.red);
 | 
						|
	    }
 | 
						|
	    if (channels & DoGreen) {
 | 
						|
		RGB_OUT(ptr, rgb2, shift, pent->co.local.green);
 | 
						|
	    }
 | 
						|
	    if (channels & DoBlue) {
 | 
						|
		RGB_OUT(ptr, rgb2, shift, pent->co.local.blue);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return ptr;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
GetAllocatedCells (ColormapPtr pmap,
 | 
						|
		   CARD8 *flags,
 | 
						|
		   CARD8 *buf,
 | 
						|
		   int *bytes)
 | 
						|
{
 | 
						|
    CARD8	*ptr;
 | 
						|
 | 
						|
    *flags = pmap->pVisual->bitsPerRGBValue - 1;
 | 
						|
    if (pmap->pVisual->ColormapEntries > 256)
 | 
						|
	*flags |= LBX_2BYTE_PIXELS;
 | 
						|
    if (!(pmap->pVisual->class & DynamicClass))
 | 
						|
	*flags |= LBX_AUTO_RELEASE;
 | 
						|
    if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
 | 
						|
	*flags |= LBX_3CHANNELS;
 | 
						|
	ptr = OutputChannel(pmap, pmap->red, NUMRED(pmap->pVisual),
 | 
						|
			    buf, *flags, DoRed);
 | 
						|
	*ptr++ = LBX_NEXT_CHANNEL;
 | 
						|
	ptr = OutputChannel(pmap, pmap->green, NUMGREEN(pmap->pVisual),
 | 
						|
			    ptr, *flags, DoGreen);
 | 
						|
	*ptr++ = LBX_NEXT_CHANNEL;
 | 
						|
	ptr = OutputChannel(pmap, pmap->blue, NUMBLUE(pmap->pVisual),
 | 
						|
			    ptr, *flags, DoBlue);
 | 
						|
    } else
 | 
						|
	ptr = OutputChannel(pmap, pmap->red, pmap->pVisual->ColormapEntries,
 | 
						|
			    buf, *flags, DoRed|DoGreen|DoBlue);
 | 
						|
    *ptr++ = LBX_LIST_END;
 | 
						|
    *bytes = ptr - buf;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Send an LbxReleaseCmapEvent to a proxy.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SendReleaseCmapEvent (LbxProxyPtr proxy,
 | 
						|
		      Colormap cmap)
 | 
						|
{
 | 
						|
    xLbxReleaseCmapEvent ev;
 | 
						|
    ClientPtr client;
 | 
						|
    LbxClientPtr lbxcp;
 | 
						|
    int n;
 | 
						|
 | 
						|
    lbxcp = proxy->lbxClients[0];
 | 
						|
 | 
						|
    if (lbxcp && (client = lbxcp->client))
 | 
						|
    {
 | 
						|
	ev.type = LbxEventCode;
 | 
						|
	ev.lbxType = LbxReleaseCmapEvent;
 | 
						|
	ev.sequenceNumber = client->sequence;
 | 
						|
	ev.colormap = cmap;
 | 
						|
	ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = ev.pad6 = 0;
 | 
						|
 | 
						|
	if (client->swapped)
 | 
						|
	{
 | 
						|
	    swaps(&ev.sequenceNumber, n);
 | 
						|
	    swapl(&ev.colormap, n);
 | 
						|
	}
 | 
						|
 | 
						|
	WriteToClient(client, sz_xLbxReleaseCmapEvent, (char *) &ev);
 | 
						|
	LbxForceOutput(proxy);
 | 
						|
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
	fprintf (stderr,
 | 
						|
	    "Sent LbxReleaseCmapEvent to proxy %d, seq = 0x%x, cmap = 0x%x\n",
 | 
						|
	    proxy->pid, client->sequence, cmap);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * WaitForServerCmapControl checks if the colormap is grabbed by a proxy,
 | 
						|
 * and if so, sends an LbxReleaseCmapEvent to the proxy.  It then suspends
 | 
						|
 * the current request until the server gets the ReleaseCmap message from
 | 
						|
 * the proxy.
 | 
						|
 */
 | 
						|
 | 
						|
static Bool
 | 
						|
WaitForServerCmapControl (ClientPtr client,
 | 
						|
			  ColormapPtr pmap)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
    LbxStalled *stalled;
 | 
						|
 | 
						|
    if (cmapPriv->grab_status == CMAP_GRABBED)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * Send an LbxReleaseCmapEvent to the proxy that has the grab.
 | 
						|
	 */
 | 
						|
 | 
						|
	SendReleaseCmapEvent (cmapPriv->grabber, pmap->mid);
 | 
						|
	cmapPriv->grab_status = CMAP_WAITING_FOR_UNGRAB;
 | 
						|
    }
 | 
						|
 | 
						|
    stalled = (LbxStalled *)xalloc(sizeof(LbxStalled));
 | 
						|
    if (!stalled)
 | 
						|
	return FALSE;
 | 
						|
    stalled->id = FakeClientID(client->index);
 | 
						|
    stalled->next = cmapPriv->stalled_clients;
 | 
						|
    cmapPriv->stalled_clients = stalled;
 | 
						|
    return AddResource(stalled->id, StalledResType, (pointer)cmapPriv);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * When the X server gets any of the requests that allocate color cells,
 | 
						|
 * it calls LbxCheckColorRequest on the request.  This function will check
 | 
						|
 * if the colormap is grabbed by a proxy, and if so, will suspend the
 | 
						|
 * current request and wait for the proxy to release the colormap.
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
LbxCheckColorRequest (ClientPtr client,
 | 
						|
		      ColormapPtr pmap,
 | 
						|
		      xReq *req)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
 | 
						|
    if (!cmapPriv)
 | 
						|
	return FALSE;
 | 
						|
 | 
						|
    if (cmapPriv->grab_status != CMAP_NOT_GRABBED)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * The colormap is grabbed by a proxy.  Reset this request, and
 | 
						|
	 * process it after the server gets back control of the colormap.
 | 
						|
	 * Before we reset the request, we must put it back in the
 | 
						|
	 * client's byte order.
 | 
						|
	 */
 | 
						|
 | 
						|
	if (!WaitForServerCmapControl (client, pmap))
 | 
						|
	    return FALSE;
 | 
						|
 | 
						|
	if (client->swapped)
 | 
						|
	{
 | 
						|
	    register int n;
 | 
						|
 | 
						|
	    switch (req->reqType)
 | 
						|
	    {
 | 
						|
	    case X_AllocColor:
 | 
						|
	    {
 | 
						|
		xAllocColorReq *stuff = (xAllocColorReq *) req;
 | 
						|
		swaps(&stuff->length, n);
 | 
						|
		swapl(&stuff->cmap, n);
 | 
						|
		swaps(&stuff->red, n);
 | 
						|
		swaps(&stuff->green, n);
 | 
						|
		swaps(&stuff->blue, n);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    case X_AllocNamedColor:
 | 
						|
	    {
 | 
						|
		xAllocNamedColorReq *stuff = (xAllocNamedColorReq *) req;
 | 
						|
		swaps(&stuff->length, n);
 | 
						|
		swapl(&stuff->cmap, n);
 | 
						|
		swaps(&stuff->nbytes, n);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    case X_AllocColorCells:
 | 
						|
	    {
 | 
						|
		xAllocColorCellsReq *stuff = (xAllocColorCellsReq *) req;
 | 
						|
		swaps(&stuff->length, n);
 | 
						|
		swapl(&stuff->cmap, n);
 | 
						|
		swaps(&stuff->colors, n);
 | 
						|
		swaps(&stuff->planes, n);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    case X_AllocColorPlanes:
 | 
						|
	    {
 | 
						|
		xAllocColorPlanesReq *stuff = (xAllocColorPlanesReq *) req;
 | 
						|
		swaps(&stuff->length, n);
 | 
						|
		swapl(&stuff->cmap, n);
 | 
						|
		swaps(&stuff->colors, n);
 | 
						|
		swaps(&stuff->red, n);
 | 
						|
		swaps(&stuff->green, n);
 | 
						|
		swaps(&stuff->blue, n);
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    default:
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	ResetCurrentRequest(client);
 | 
						|
	client->sequence--;
 | 
						|
	IgnoreClient(client);
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!LbxClient(client) ||
 | 
						|
	LbxProxy(client)->uid != cmapPriv->last_grabber)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * Next time the proxy for this client does a colormap grab, it
 | 
						|
	 * will have to get the colormap state (a non-smart grab).
 | 
						|
	 */
 | 
						|
 | 
						|
	cmapPriv->smart_grab = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
LbxGrabbedByClient (ClientPtr client,
 | 
						|
		    ColormapPtr pmap)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
    return (cmapPriv &&
 | 
						|
	    (cmapPriv->grab_status != CMAP_NOT_GRABBED) &&
 | 
						|
	    (cmapPriv->grabber == LbxProxy(client)));
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Check if a colormap is grabbed by a proxy.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
LbxCheckCmapGrabbed (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
 | 
						|
    return (cmapPriv && (cmapPriv->grab_status == CMAP_GRABBED));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Disable a smart grab on the specified colormap.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
LbxDisableSmartGrab (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
 | 
						|
    if (cmapPriv)
 | 
						|
	cmapPriv->smart_grab = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Send an LbxFreeCellsEvent to the specified proxy.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
SendFreeCellsEvent (LbxProxyPtr proxy,
 | 
						|
		    Colormap cmap,
 | 
						|
		    Pixel pixel_start,
 | 
						|
		    Pixel pixel_end)
 | 
						|
{
 | 
						|
    xLbxFreeCellsEvent ev;
 | 
						|
    ClientPtr client;
 | 
						|
    LbxClientPtr lbxcp;
 | 
						|
    int n;
 | 
						|
 | 
						|
    lbxcp = proxy->lbxClients[0];
 | 
						|
 | 
						|
    if (lbxcp && (client = lbxcp->client))
 | 
						|
    {
 | 
						|
	ev.type = LbxEventCode;
 | 
						|
	ev.lbxType =  LbxFreeCellsEvent;
 | 
						|
	ev.sequenceNumber = client->sequence;
 | 
						|
	ev.colormap = cmap;
 | 
						|
	ev.pixelStart = pixel_start;
 | 
						|
	ev.pixelEnd = pixel_end;
 | 
						|
	ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = 0;
 | 
						|
 | 
						|
	if (client->swapped)
 | 
						|
	{
 | 
						|
	    swaps(&ev.sequenceNumber, n);
 | 
						|
	    swapl(&ev.colormap, n);
 | 
						|
	    swapl(&ev.pixelStart, n);
 | 
						|
	    swapl(&ev.pixelEnd, n);
 | 
						|
	}
 | 
						|
 | 
						|
	WriteToClient(client, sz_xLbxFreeCellsEvent, (char *) &ev);
 | 
						|
	LbxForceOutput(proxy);
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
	fprintf (stderr, "Sent LbxFreeCellsEvent to proxy %d, seq = 0x%x\n",
 | 
						|
	    proxy->pid, client->sequence);
 | 
						|
	fprintf (stderr, "   cmap = 0x%x, pixelStart = %d, pixelEnd = %d\n",
 | 
						|
	    cmap, pixel_start, pixel_end);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* XXX use of globals like this is gross */
 | 
						|
static long pixel_start;
 | 
						|
static long pixel_end;
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * LbxFreeCellsEvent generation functions.
 | 
						|
 */
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
void
 | 
						|
LbxBeginFreeCellsEvent (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    pixel_start = -1;
 | 
						|
    pixel_end = -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
LbxAddFreeCellToEvent (ColormapPtr pmap,
 | 
						|
		       Pixel pixel)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * We must notify the proxy that has this colormap
 | 
						|
     * grabbed which cells are being freed (their refcount
 | 
						|
     * has reached zero).
 | 
						|
     */
 | 
						|
 | 
						|
    if (pixel_start == -1)
 | 
						|
	pixel_start = pixel;
 | 
						|
    else
 | 
						|
    {
 | 
						|
	if (pixel_end == -1)
 | 
						|
	    pixel_end = pixel;
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (pixel_end + 1 == pixel)
 | 
						|
		pixel_end = pixel;
 | 
						|
	    else if (pixel > pixel_end + 1)
 | 
						|
	    {
 | 
						|
		LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
		    (pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
 | 
						|
		SendFreeCellsEvent (cmapPriv->grabber,
 | 
						|
				    pmap->mid, pixel_start, pixel_end);
 | 
						|
 | 
						|
		pixel_start = pixel;
 | 
						|
		pixel_end = -1;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
LbxEndFreeCellsEvent (ColormapPtr pmap)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Check if there is an LbxFreeCellEvent we need to write.
 | 
						|
     */
 | 
						|
 | 
						|
    if (pixel_start != -1)
 | 
						|
    {
 | 
						|
	LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | 
						|
	    (pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
 | 
						|
	SendFreeCellsEvent (cmapPriv->grabber,
 | 
						|
			    pmap->mid, pixel_start,
 | 
						|
			    pixel_end == -1 ? pixel_start : pixel_end);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Sort the specified pixel list.  This optimizes generation
 | 
						|
 * of LbxFreeCellsEvent.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
LbxSortPixelList (Pixel *pixels,
 | 
						|
		  int count)
 | 
						|
{
 | 
						|
     int i, j;
 | 
						|
 | 
						|
     for (i = 0; i <= count - 2; i++)
 | 
						|
	 for (j = count - 1; j > i; j--)
 | 
						|
	    if (pixels[j - 1] > pixels[j])
 | 
						|
	    {
 | 
						|
		Pixel temp = pixels[j - 1];
 | 
						|
		pixels[j - 1] = pixels[j];
 | 
						|
		pixels[j] = temp;
 | 
						|
	    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Handle a colormap grab request from a proxy.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
ProcLbxGrabCmap(ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xLbxGrabCmapReq);
 | 
						|
    xLbxGrabCmapReply *reply;
 | 
						|
    Bool smartGrab;
 | 
						|
    LbxColormapPriv *cmapPriv;
 | 
						|
    ColormapPtr pmap;
 | 
						|
    int bytes, n;
 | 
						|
    LbxProxyPtr proxy = LbxProxy(client);
 | 
						|
 | 
						|
    client->sequence--;		/* not a counted request */
 | 
						|
 | 
						|
    pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | 
						|
						 RT_COLORMAP,
 | 
						|
						 SecurityWriteAccess);
 | 
						|
 | 
						|
    if (!pmap)
 | 
						|
    {
 | 
						|
        client->errorValue = stuff->cmap;
 | 
						|
	return BadColor;
 | 
						|
    }
 | 
						|
 | 
						|
    cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
    if (!cmapPriv)
 | 
						|
    {
 | 
						|
	cmapPriv = LbxColormapPrivInit (pmap);
 | 
						|
	if (!cmapPriv)
 | 
						|
	    return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /*
 | 
						|
     * We have a SMART GRAB if since this proxy last ungrabbed the
 | 
						|
     * colormap, no color cell was alloc'd by an entity other than
 | 
						|
     * this proxy (this includes other proxies as well as clients
 | 
						|
     * directly connected to the X server without a proxy).
 | 
						|
     *
 | 
						|
     * We want to optimize this special case because a proxy may give
 | 
						|
     * up a grab because it got a request that it could not handle
 | 
						|
     * (e.g. AllocNamedColor or LookupColor).  When it asks back for
 | 
						|
     * the grab, there is no need for the server to send the colormap
 | 
						|
     * state, because the proxy is already up to date on the state of
 | 
						|
     * the colormap.
 | 
						|
     *
 | 
						|
     * In order for this to work, the following assumptions are made
 | 
						|
     * about the proxy:
 | 
						|
     *
 | 
						|
     * - the proxy is kept up to date on all cell allocations made on its
 | 
						|
     *   behalf resulting from the following requests: AllocNamedColor, 
 | 
						|
     *   AllocColorCells, AllocColorPlanes
 | 
						|
     * - the proxy is kept up to date on all cells freed by any client
 | 
						|
     *   via the LbxFreeCell event.
 | 
						|
     */
 | 
						|
 | 
						|
    /* if proxy is this confused, give it full info */
 | 
						|
    if (cmapPriv->grab_status == CMAP_GRABBED && cmapPriv->grabber == proxy)
 | 
						|
	LbxReleaseCmap(pmap, FALSE);
 | 
						|
 | 
						|
    if (proxy->uid != cmapPriv->last_grabber)
 | 
						|
	cmapPriv->smart_grab = FALSE;
 | 
						|
    smartGrab = cmapPriv->smart_grab;
 | 
						|
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
    fprintf (stderr, "\nGot colormap grab request, ");
 | 
						|
    fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n",
 | 
						|
	client->sequence, proxy->pid, client->index, stuff->cmap);
 | 
						|
 | 
						|
    if (cmapPriv->grab_status == CMAP_NOT_GRABBED)
 | 
						|
    {
 | 
						|
	fprintf (stderr, "cmap 0x%x is not grabbed by any proxy\n",
 | 
						|
	    stuff->cmap);
 | 
						|
	if (smartGrab)
 | 
						|
	    fprintf (stderr, "This is a smart grab\n");
 | 
						|
    }
 | 
						|
    else if (cmapPriv->grab_status == CMAP_GRABBED)
 | 
						|
    {
 | 
						|
	if (cmapPriv->grabber == proxy)
 | 
						|
	{
 | 
						|
	    fprintf (stderr, "cmap 0x%x is already grabbed by proxy %d\n",
 | 
						|
	        stuff->cmap, proxy->pid);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    fprintf (stderr, "cmap 0x%x is currently grabbed by proxy %d\n",
 | 
						|
	        stuff->cmap, cmapPriv->grabber->pid);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else if (cmapPriv->grab_status == CMAP_WAITING_FOR_UNGRAB)
 | 
						|
    {
 | 
						|
	fprintf (stderr,
 | 
						|
	    "Already waiting for cmap 0x%x to be ungrabbed by proxy %d\n",
 | 
						|
	    stuff->cmap, cmapPriv->grabber->pid);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    if (cmapPriv->grab_status != CMAP_NOT_GRABBED &&
 | 
						|
	cmapPriv->grabber != proxy)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * The colormap is grabbed by a proxy other than the one that
 | 
						|
	 * is requesting this grab.  Reset this grab request, and process
 | 
						|
         * it after the server gets back control of the colormap.  Before
 | 
						|
	 * we reset the request, we must put it back in the client's byte
 | 
						|
	 * order.
 | 
						|
	 */
 | 
						|
 | 
						|
	if (!WaitForServerCmapControl (client, pmap))
 | 
						|
	    return BadAlloc;
 | 
						|
 | 
						|
	if (client->swapped)
 | 
						|
	{
 | 
						|
	    swaps(&stuff->length, n);
 | 
						|
	    swapl(&stuff->cmap, n);
 | 
						|
	}
 | 
						|
 | 
						|
	ResetCurrentRequest(client);
 | 
						|
	IgnoreClient(client);
 | 
						|
 | 
						|
	return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pmap->pVisual->class & DynamicClass) {
 | 
						|
	cmapPriv->grabber = proxy;
 | 
						|
	cmapPriv->grab_status = CMAP_GRABBED;
 | 
						|
	cmapPriv->next = proxy->grabbedCmaps;
 | 
						|
	proxy->grabbedCmaps = pmap;
 | 
						|
    } else
 | 
						|
	smartGrab = FALSE;
 | 
						|
 | 
						|
    /*
 | 
						|
     * For an smart grab (see comments above), there is no information
 | 
						|
     * sent about the colormap cells because the proxy is all up to date.
 | 
						|
     * Otherwise, the server sends the proxy the state of all allocated
 | 
						|
     * cells in the colormap.  All cells not specified are assumed free.
 | 
						|
     */
 | 
						|
 | 
						|
    bytes = 0;
 | 
						|
    if (!smartGrab) {
 | 
						|
	if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
 | 
						|
	    bytes = NumAllocatedCells(pmap->red,
 | 
						|
				      NUMRED(pmap->pVisual)) * 9;
 | 
						|
	    bytes += NumAllocatedCells(pmap->green,
 | 
						|
				       NUMGREEN(pmap->pVisual)) * 9;
 | 
						|
	    bytes += NumAllocatedCells(pmap->blue,
 | 
						|
				       NUMBLUE(pmap->pVisual)) * 9;
 | 
						|
	    bytes += 2;
 | 
						|
	} else
 | 
						|
	    bytes = NumAllocatedCells(pmap->red,
 | 
						|
				      pmap->pVisual->ColormapEntries) * 9;
 | 
						|
    }
 | 
						|
    bytes += sz_xLbxGrabCmapReply + 1;
 | 
						|
    reply = (xLbxGrabCmapReply *) xalloc (bytes);
 | 
						|
    bzero (reply, sz_xLbxGrabCmapReply);
 | 
						|
 | 
						|
    if (smartGrab)
 | 
						|
    {
 | 
						|
	reply->flags = LBX_SMART_GRAB;
 | 
						|
	reply->length = 0;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	GetAllocatedCells (pmap, &reply->flags,
 | 
						|
			   (CARD8 *) reply + sz_xLbxGrabCmapReplyHdr, &bytes);
 | 
						|
	if (bytes <= (sz_xLbxGrabCmapReply - sz_xLbxGrabCmapReplyHdr))
 | 
						|
	    reply->length = 0;
 | 
						|
	else
 | 
						|
	    reply->length = (sz_xLbxGrabCmapReplyHdr +
 | 
						|
		bytes - sz_xLbxGrabCmapReply + 3) >> 2;
 | 
						|
    }
 | 
						|
 | 
						|
    reply->type = X_Reply;
 | 
						|
    reply->sequenceNumber = client->sequence;
 | 
						|
 | 
						|
    bytes = sz_xLbxGrabCmapReply + (reply->length << 2);
 | 
						|
 | 
						|
    if (client->swapped)
 | 
						|
    {
 | 
						|
	register char n;
 | 
						|
 | 
						|
	swaps (&reply->sequenceNumber, n);
 | 
						|
	swapl (&reply->length, n);
 | 
						|
    }
 | 
						|
 | 
						|
    WriteToClient (client, bytes, (char *)reply);
 | 
						|
    
 | 
						|
    xfree (reply);
 | 
						|
 | 
						|
    return (client->noClientException);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
LbxUnstallClient(pointer     data,
 | 
						|
		 XID         id)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv = (LbxColormapPriv *)data;
 | 
						|
    LbxStalled **prev;
 | 
						|
    ClientPtr client;
 | 
						|
 | 
						|
    for (prev = &cmapPriv->stalled_clients; *prev && (*prev)->id != id; )
 | 
						|
	prev = &(*prev)->next;
 | 
						|
    *prev = (*prev)->next;
 | 
						|
    client = clients[CLIENT_ID(id)];
 | 
						|
    if (!client->clientGone)
 | 
						|
	AttendClient(client);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
LbxReleaseCmap(ColormapPtr pmap,
 | 
						|
	       Bool smart)
 | 
						|
{
 | 
						|
    LbxColormapPriv *cmapPriv;
 | 
						|
    ColormapPtr *prev;
 | 
						|
 | 
						|
    if (!pmap->devPrivates)
 | 
						|
	return;
 | 
						|
    cmapPriv = (LbxColormapPriv *)
 | 
						|
	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | 
						|
    if (!cmapPriv || (cmapPriv->grab_status == CMAP_NOT_GRABBED))
 | 
						|
	return;
 | 
						|
 | 
						|
    for (prev = &cmapPriv->grabber->grabbedCmaps; *prev && *prev != pmap; )
 | 
						|
	prev = &((LbxColormapPriv *)
 | 
						|
		 (*prev)->devPrivates[lbxColormapPrivIndex].ptr)->next;
 | 
						|
    if (*prev == pmap)
 | 
						|
	*prev = cmapPriv->next;
 | 
						|
 | 
						|
    while (cmapPriv->stalled_clients)
 | 
						|
	FreeResource(cmapPriv->stalled_clients->id, 0);
 | 
						|
 | 
						|
    cmapPriv->grab_status = CMAP_NOT_GRABBED;
 | 
						|
    cmapPriv->last_grabber = smart ? cmapPriv->grabber->uid : 0;
 | 
						|
    cmapPriv->grabber = NULL;
 | 
						|
    cmapPriv->smart_grab = smart;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Handle a colormap release request from a proxy.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
ProcLbxReleaseCmap(ClientPtr	client)
 | 
						|
{
 | 
						|
    REQUEST(xLbxReleaseCmapReq);
 | 
						|
    ColormapPtr pmap;
 | 
						|
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
    fprintf (stderr, "Got colormap release request, ");
 | 
						|
    fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n",
 | 
						|
	client->sequence, LbxProxyID(client), client->index, stuff->cmap);
 | 
						|
#endif
 | 
						|
 | 
						|
    pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | 
						|
						 RT_COLORMAP,
 | 
						|
						 SecurityWriteAccess);
 | 
						|
 | 
						|
    if (!pmap)
 | 
						|
    {
 | 
						|
        client->errorValue = stuff->cmap;
 | 
						|
	return BadColor;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LbxGrabbedByClient(client, pmap))
 | 
						|
	LbxReleaseCmap(pmap, TRUE);
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Handle an LbxAllocColor request.  The proxy did the alloc and
 | 
						|
 * is telling the server what rgb and pixel value to use.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
ProcLbxAllocColor(ClientPtr	client)
 | 
						|
{
 | 
						|
    REQUEST(xLbxAllocColorReq);
 | 
						|
    ColormapPtr pmap;
 | 
						|
    CARD32 pixel = stuff->pixel;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH (xLbxAllocColorReq);
 | 
						|
    pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | 
						|
						 RT_COLORMAP,
 | 
						|
						 SecurityWriteAccess);
 | 
						|
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
    fprintf (stderr,
 | 
						|
	"Got LBX alloc color: seq = 0x%x, proxy = %d, client = %d\n",
 | 
						|
	client->sequence, LbxProxyID(client), client->index);
 | 
						|
    fprintf (stderr, "  cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
 | 
						|
        stuff->cmap, stuff->pixel, stuff->red, stuff->green, stuff->blue);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (pmap)
 | 
						|
    {
 | 
						|
	int status;
 | 
						|
	if (!LbxGrabbedByClient(client, pmap))
 | 
						|
	    return BadAccess;
 | 
						|
 | 
						|
	status = AllocColor (pmap,
 | 
						|
	    &stuff->red, &stuff->green, &stuff->blue,
 | 
						|
	    &pixel, client->index);
 | 
						|
 | 
						|
	if (status == Success && pixel != stuff->pixel)
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * Internal error - Proxy allocated different pixel from server
 | 
						|
	     */
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
	    fprintf(stderr, "got pixel %d (%d, %d, %d), expected %d\n",
 | 
						|
		    pixel, stuff->red, stuff->green, stuff->blue, stuff->pixel);
 | 
						|
#endif
 | 
						|
	    FreeColors (pmap, client->index, 1, &pixel, 0L);
 | 
						|
	    return BadAlloc;
 | 
						|
	}
 | 
						|
 | 
						|
	return status;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        client->errorValue = stuff->cmap;
 | 
						|
        return (BadColor);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * The proxy sends an LbxIncrementPixel request when it short circuits
 | 
						|
 * an AllocColor.  The server must bump up the reference count the
 | 
						|
 * specified amount.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
ProcLbxIncrementPixel(ClientPtr	client)
 | 
						|
{
 | 
						|
    REQUEST(xLbxIncrementPixelReq);
 | 
						|
    ColormapPtr pmap;
 | 
						|
    EntryPtr    pent;
 | 
						|
    Pixel	pixel;
 | 
						|
    unsigned	short red, green, blue;
 | 
						|
    VisualPtr	pVisual;
 | 
						|
    int		status;
 | 
						|
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
    fprintf (stderr,
 | 
						|
	"Got LBX increment pixel: seq = 0x%x, proxy = %d, client = %d\n",
 | 
						|
	client->sequence, LbxProxyID(client), client->index);
 | 
						|
    fprintf (stderr, "  cmap = 0x%x, pixel = %d\n",
 | 
						|
        stuff->cmap, stuff->pixel);
 | 
						|
#endif
 | 
						|
 | 
						|
    /*
 | 
						|
     * Looks up the color associated with the pixel, and then call
 | 
						|
     * AllocColor() - a bit round-about, but it should work.
 | 
						|
     */
 | 
						|
 | 
						|
    pmap = (ColormapPtr) SecurityLookupIDByType(client, stuff->cmap,
 | 
						|
						RT_COLORMAP,
 | 
						|
						SecurityWriteAccess);
 | 
						|
    if (!pmap) {
 | 
						|
        client->errorValue = stuff->cmap;
 | 
						|
	return BadColor;
 | 
						|
    }
 | 
						|
 | 
						|
    pixel = stuff->pixel;
 | 
						|
 | 
						|
    switch (pmap->class) {
 | 
						|
    case StaticColor:
 | 
						|
    case StaticGray:
 | 
						|
	red = pmap->red[pixel].co.local.red;
 | 
						|
	green = pmap->red[pixel].co.local.green;
 | 
						|
	blue = pmap->red[pixel].co.local.blue;
 | 
						|
	break;
 | 
						|
    case GrayScale:
 | 
						|
    case PseudoColor:
 | 
						|
	pent = pmap->red + pixel;
 | 
						|
	red = pent->co.local.red;
 | 
						|
	green = pent->co.local.green;
 | 
						|
	blue = pent->co.local.blue;
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	pVisual = pmap->pVisual;
 | 
						|
	red = pmap->red[(pixel & pVisual->redMask) >> pVisual->offsetRed].co.local.red;
 | 
						|
	green = pmap->green[(pixel & pVisual->greenMask) >> pVisual->offsetGreen].co.local.green;
 | 
						|
	blue = pmap->blue[(pixel & pVisual->blueMask) >> pVisual->offsetBlue].co.local.blue;
 | 
						|
	break;
 | 
						|
    }
 | 
						|
 | 
						|
    status = AllocColor(pmap, &red, &green, &blue, &pixel, client->index);
 | 
						|
 | 
						|
    if (status == Success && pixel != stuff->pixel)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * Internal error - Proxy allocated different pixel from server
 | 
						|
	 */
 | 
						|
#ifdef COLOR_DEBUG
 | 
						|
	fprintf(stderr, "got pixel %d, expected %d\n", pixel, stuff->pixel);
 | 
						|
#endif
 | 
						|
	FreeColors (pmap, client->index, 1, &pixel, 0L);
 | 
						|
	return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    return status;
 | 
						|
}
 |