1772 lines
44 KiB
C
1772 lines
44 KiB
C
/* $Xorg: cmap.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
|
|
/* $XdotOrg: $ */
|
|
|
|
/*
|
|
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.
|
|
*/
|
|
|
|
/*
|
|
* Copyright 1994 Network Computing Devices, Inc.
|
|
*
|
|
* 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, and that the name Network Computing Devices, Inc. not be
|
|
* used in advertising or publicity pertaining to distribution of this
|
|
* software without specific, written prior permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
|
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
|
|
* LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
* PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
|
|
* COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
|
|
* SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
|
|
* OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
|
|
* WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
*/
|
|
/* $XFree86: xc/programs/lbxproxy/di/cmap.c,v 1.6 2001/12/14 20:00:50 dawes Exp $ */
|
|
|
|
#include <stdio.h>
|
|
#include "assert.h"
|
|
#include "misc.h"
|
|
#include "lbx.h"
|
|
#include "atomcache.h"
|
|
#include "util.h"
|
|
#include "tags.h"
|
|
#include "colormap.h"
|
|
#include "resource.h"
|
|
#include "wire.h"
|
|
#include "swap.h"
|
|
#include "reqtype.h"
|
|
#include "lbxext.h"
|
|
|
|
static void LocalAllocColor ();
|
|
static void FoundPixel ();
|
|
static Bool grab_cmap_reply();
|
|
static Bool alloc_named_color_reply();
|
|
static Bool alloc_color_cells_reply();
|
|
static Bool alloc_color_planes_reply();
|
|
static Bool lookup_color_reply();
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* ResolveColor scales down an rgb to the specified number of bits.
|
|
*/
|
|
|
|
void
|
|
ResolveColor (pVisual, red, green, blue)
|
|
LbxVisualPtr pVisual;
|
|
CARD16 *red, *green, *blue;
|
|
{
|
|
int shift = 16 - pVisual->bitsPerRGB;
|
|
unsigned lim = (1 << pVisual->bitsPerRGB) - 1;
|
|
unsigned limr, limg, limb;
|
|
|
|
switch (pVisual->class) {
|
|
case PseudoColor:
|
|
case DirectColor:
|
|
case StaticColor:
|
|
/* rescale to rgb bits */
|
|
*red = ((*red >> shift) * 65535) / lim;
|
|
*green = ((*green >> shift) * 65535) / lim;
|
|
*blue = ((*blue >> shift) * 65535) / lim;
|
|
break;
|
|
case GrayScale:
|
|
/* rescale to gray then rgb bits */
|
|
*red = (30L * *red + 59L * *green + 11L * *blue) / 100;
|
|
*blue = *green = *red = ((*red >> shift) * 65535) / lim;
|
|
break;
|
|
case StaticGray:
|
|
limg = pVisual->colormapEntries - 1;
|
|
/* rescale to gray then [0..limg] then [0..65535] then rgb bits */
|
|
*red = (30L * *red + 59L * *green + 11L * *blue) / 100;
|
|
*red = ((((*red * (limg + 1))) >> 16) * 65535) / limg;
|
|
*blue = *green = *red = ((*red >> shift) * 65535) / lim;
|
|
break;
|
|
case TrueColor:
|
|
limr = NUMRED(pVisual) - 1;
|
|
limg = NUMGREEN(pVisual) - 1;
|
|
limb = NUMBLUE(pVisual) - 1;
|
|
/* rescale to [0..limN] then [0..65535] then rgb bits */
|
|
*red = ((((((*red * (limr + 1)) >> 16) *
|
|
65535) / limr) >> shift) * 65535) / lim;
|
|
*green = ((((((*green * (limg + 1)) >> 16) *
|
|
65535) / limg) >> shift) * 65535) / lim;
|
|
*blue = ((((((*blue * (limb + 1)) >> 16) *
|
|
65535) / limb) >> shift) * 65535) / lim;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void (* LbxResolveColor)(
|
|
LbxVisualPtr /* pVisual */,
|
|
CARD16* /* red */,
|
|
CARD16* /* green */,
|
|
CARD16* /* blue */
|
|
) = ResolveColor;
|
|
|
|
static Pixel
|
|
find_cell(pent, num, rgb, channel)
|
|
Entry *pent;
|
|
int num;
|
|
CARD32 rgb;
|
|
int channel;
|
|
{
|
|
Pixel pixel, freep;
|
|
|
|
freep = ~((Pixel)0);
|
|
for (pixel = 0; pixel < num; pixel++, pent++) {
|
|
if (pent->status == PIXEL_SHARED) {
|
|
switch (channel) {
|
|
case DoRed:
|
|
if (pent->red == rgb)
|
|
return pixel;
|
|
break;
|
|
case DoGreen:
|
|
if (pent->green == rgb)
|
|
return pixel;
|
|
break;
|
|
case DoBlue:
|
|
if (pent->blue == rgb)
|
|
return pixel;
|
|
break;
|
|
}
|
|
}
|
|
if (pent->status == PIXEL_FREE && freep == ~((Pixel)0))
|
|
freep = pixel;
|
|
}
|
|
return freep;
|
|
}
|
|
|
|
/*
|
|
* Find a free pixel in the colormap.
|
|
*/
|
|
|
|
Pixel
|
|
FindFreePixel (pmap, red, green, blue)
|
|
ColormapPtr pmap;
|
|
CARD32 red, green, blue;
|
|
{
|
|
Entry *pent;
|
|
Pixel pixel, p;
|
|
|
|
if (pmap->pVisual->class != DirectColor) {
|
|
for (pixel = 0, pent = pmap->red;
|
|
pixel < pmap->pVisual->colormapEntries;
|
|
pixel++, pent++)
|
|
{
|
|
if (pent->status == PIXEL_FREE)
|
|
return pixel;
|
|
}
|
|
return ~((Pixel)0);
|
|
}
|
|
p = find_cell(pmap->red, NUMRED(pmap->pVisual), red, DoRed);
|
|
if (p == ~((Pixel)0))
|
|
return p;
|
|
pixel = p << pmap->pVisual->offsetRed;
|
|
p = find_cell(pmap->green, NUMGREEN(pmap->pVisual), green, DoGreen);
|
|
if (p == ~((Pixel)0))
|
|
return p;
|
|
pixel |= p << pmap->pVisual->offsetGreen;
|
|
p = find_cell(pmap->blue, NUMBLUE(pmap->pVisual), blue, DoBlue);
|
|
if (p == ~((Pixel)0))
|
|
return p;
|
|
pixel |= p << pmap->pVisual->offsetBlue;
|
|
return pixel;
|
|
}
|
|
|
|
Pixel (* LbxFindFreePixel)(
|
|
ColormapPtr /* pmap */,
|
|
CARD32 /* red */,
|
|
CARD32 /* green */,
|
|
CARD32 /* blue */
|
|
) = FindFreePixel;
|
|
|
|
typedef unsigned short BigNumUpper;
|
|
typedef unsigned long BigNumLower;
|
|
|
|
#define BIGNUMLOWERBITS 24
|
|
#define BIGNUMUPPERBITS 16
|
|
#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
|
|
#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
|
|
#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
|
|
#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
|
|
|
|
typedef struct _bignum {
|
|
BigNumUpper upper;
|
|
BigNumLower lower;
|
|
} BigNumRec, *BigNumPtr;
|
|
|
|
#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
|
|
(((x)->upper == (y)->upper) &&\
|
|
((x)->lower > (y)->lower)))
|
|
|
|
#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
|
|
((r)->lower = LOWERPART(u)))
|
|
|
|
#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
|
|
((r)->lower = BIGNUMLOWER-1))
|
|
|
|
static void
|
|
BigNumAdd (x, y, r)
|
|
BigNumPtr x, y, r;
|
|
{
|
|
BigNumLower lower, carry = 0;
|
|
|
|
lower = x->lower + y->lower;
|
|
if (lower >= BIGNUMLOWER) {
|
|
lower -= BIGNUMLOWER;
|
|
carry = 1;
|
|
}
|
|
r->lower = lower;
|
|
r->upper = x->upper + y->upper + carry;
|
|
}
|
|
|
|
Entry *
|
|
FindBestPixel(pmap, red, green, blue, channels)
|
|
ColormapPtr pmap;
|
|
CARD32 red,
|
|
green,
|
|
blue;
|
|
int channels;
|
|
{
|
|
Entry *pent;
|
|
int num;
|
|
Entry *final;
|
|
Pixel pixel;
|
|
long dr, dg, db;
|
|
unsigned long sq;
|
|
BigNumRec minval, sum, temp;
|
|
|
|
switch(channels)
|
|
{
|
|
case DoRed:
|
|
pent = pmap->red;
|
|
num = NUMRED(pmap->pVisual);
|
|
break;
|
|
case DoGreen:
|
|
pent = pmap->green;
|
|
num = NUMGREEN(pmap->pVisual);
|
|
break;
|
|
case DoBlue:
|
|
pent = pmap->blue;
|
|
num = NUMBLUE(pmap->pVisual);
|
|
break;
|
|
default:
|
|
pent = pmap->red;
|
|
num = pmap->pVisual->colormapEntries;
|
|
break;
|
|
}
|
|
final = pent;
|
|
MaxBigNum(&minval);
|
|
/* look for the minimal difference */
|
|
for (pixel = 0; pixel < num; pent++, pixel++)
|
|
{
|
|
dr = dg = db = 0;
|
|
switch(channels) {
|
|
case DoRed:
|
|
dr = pent->red - red;
|
|
break;
|
|
case DoGreen:
|
|
dg = pent->green - green;
|
|
break;
|
|
case DoBlue:
|
|
db = pent->blue - blue;
|
|
break;
|
|
default:
|
|
dr = pent->red - red;
|
|
dg = pent->green - green;
|
|
db = pent->blue - blue;
|
|
break;
|
|
}
|
|
sq = dr * dr;
|
|
UnsignedToBigNum (sq, &sum);
|
|
sq = dg * dg;
|
|
UnsignedToBigNum (sq, &temp);
|
|
BigNumAdd (&sum, &temp, &sum);
|
|
sq = db * db;
|
|
UnsignedToBigNum (sq, &temp);
|
|
BigNumAdd (&sum, &temp, &sum);
|
|
if (BigNumGreater (&minval, &sum))
|
|
{
|
|
final = pent;
|
|
minval = sum;
|
|
}
|
|
}
|
|
return final;
|
|
}
|
|
|
|
Entry * (* LbxFindBestPixel)(
|
|
ColormapPtr /* pmap */,
|
|
CARD32 /* red */,
|
|
CARD32 /* green */,
|
|
CARD32 /* blue */,
|
|
int /* channels */
|
|
) = FindBestPixel;
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#define PIX_IN(ptr,is2,dst) \
|
|
if (is2) { \
|
|
dst = *ptr++ << 8; dst |= *ptr++; \
|
|
} else \
|
|
dst = *ptr++
|
|
|
|
#define RGB_IN(ptr,is2,lim,dst) \
|
|
if (is2) { \
|
|
dst = *ptr++ << 8; dst |= *ptr++; \
|
|
} else \
|
|
dst = (*ptr++ * 65535) / lim
|
|
|
|
static CARD8 *
|
|
DecodeChannel(pmap, pent, flags, channels, data)
|
|
ColormapPtr pmap;
|
|
Entry *pent;
|
|
CARD8 flags;
|
|
CARD8 channels;
|
|
CARD8 *data;
|
|
{
|
|
Bool px2;
|
|
Bool rgb2;
|
|
CARD16 pixel1, pixel2;
|
|
int i;
|
|
int lim;
|
|
CARD8 code;
|
|
|
|
px2 = (flags & LBX_2BYTE_PIXELS) != 0;
|
|
rgb2 = (flags & LBX_RGB_BITS_MASK) > 7;
|
|
lim = (1 << ((flags & LBX_RGB_BITS_MASK) + 1)) - 1;
|
|
/*
|
|
* All pixels other than the ones specified in the GrabCmap reply
|
|
* are implied to be free. Mark all the cells free now, and then
|
|
* mark the cells specified in the GrabCmap reply either:
|
|
*
|
|
* PIXEL_PRIVATE - a read/write cell - proxy can't do local alloc
|
|
* in this cell. We don't care about the contents.
|
|
* PIXEL_SHARED - a read only cell that can be shared.
|
|
*/
|
|
|
|
for (i = 0; i < pmap->pVisual->colormapEntries; i++)
|
|
{
|
|
if ((pent[i].status == PIXEL_SHARED && pent[i].refcnt == 0) ||
|
|
(pent[i].status == PIXEL_PRIVATE && pent[i].server_ref))
|
|
pent[i].status = PIXEL_FREE;
|
|
}
|
|
|
|
while ((code = *data++))
|
|
{
|
|
if (code == LBX_PIXEL_PRIVATE)
|
|
{
|
|
PIX_IN(data, px2, pixel1);
|
|
|
|
pent[pixel1].pixel = pixel1;
|
|
if (pent[pixel1].status != PIXEL_PRIVATE)
|
|
pent[pixel1].server_ref = 1;
|
|
pent[pixel1].status = PIXEL_PRIVATE;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "Got PIXEL_PRIVATE, pixel = %d\n", pixel1);
|
|
#endif
|
|
}
|
|
else if (code == LBX_PIXEL_RANGE_PRIVATE)
|
|
{
|
|
PIX_IN(data, px2, pixel1);
|
|
PIX_IN(data, px2, pixel2);
|
|
|
|
for (i = pixel1; i <= pixel2; i++)
|
|
{
|
|
pent[i].pixel = i;
|
|
if (pent[i].status != PIXEL_PRIVATE)
|
|
pent[i].server_ref = 1;
|
|
pent[i].status = PIXEL_PRIVATE;
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "Got PIXEL_RANGE_PRIVATE, pixels = %d...%d\n",
|
|
pixel1, pixel2);
|
|
#endif
|
|
}
|
|
else if (code == LBX_PIXEL_SHARED)
|
|
{
|
|
PIX_IN(data, px2, pixel1);
|
|
|
|
pent[pixel1].pixel = pixel1;
|
|
if (pent[pixel1].status != PIXEL_SHARED)
|
|
pent[pixel1].refcnt = 0;
|
|
pent[pixel1].status = PIXEL_SHARED;
|
|
pent[pixel1].server_ref = 1;
|
|
if (channels & DoRed) {
|
|
RGB_IN(data, rgb2, lim, pent[pixel1].red);
|
|
}
|
|
if (channels & DoGreen) {
|
|
RGB_IN(data, rgb2, lim, pent[pixel1].green);
|
|
}
|
|
if (channels & DoBlue) {
|
|
RGB_IN(data, rgb2, lim, pent[pixel1].blue);
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr,
|
|
"Got PIXEL_SHARED, pixel = %d, rgb = (%d,%d,%d)\n",
|
|
pixel1, pent[pixel1].red, pent[pixel1].green,
|
|
pent[pixel1].blue);
|
|
#endif
|
|
}
|
|
else if (code == LBX_PIXEL_RANGE_SHARED)
|
|
{
|
|
PIX_IN(data, px2, pixel1);
|
|
PIX_IN(data, px2, pixel2);
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "Got PIXEL_RANGE_SHARED, pixels = %d...%d\n",
|
|
pixel1, pixel2);
|
|
#endif
|
|
|
|
for (i = pixel1; i <= pixel2; i++)
|
|
{
|
|
pent[i].pixel = i;
|
|
if (pent[i].status != PIXEL_SHARED)
|
|
pent[i].refcnt = 0;
|
|
pent[i].status = PIXEL_SHARED;
|
|
pent[i].server_ref = 1;
|
|
if (channels & DoRed) {
|
|
RGB_IN(data, rgb2, lim, pent[i].red);
|
|
}
|
|
if (channels & DoGreen) {
|
|
RGB_IN(data, rgb2, lim, pent[i].green);
|
|
}
|
|
if (channels & DoBlue) {
|
|
RGB_IN(data, rgb2, lim, pent[i].blue);
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, " pixel = %d, rgb = (%d,%d,%d)\n",
|
|
i, pent[i].red, pent[i].green, pent[i].blue);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
GotColormapGrab (pmap, flags, data)
|
|
ColormapPtr pmap;
|
|
CARD8 flags;
|
|
CARD8 *data;
|
|
{
|
|
|
|
pmap->grab_status = CMAP_GRABBED;
|
|
|
|
if (flags & LBX_SMART_GRAB)
|
|
{
|
|
/*
|
|
* We have a SMART GRAB : 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.
|
|
*/
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pmap->pVisual->class | DynamicClass) != DirectColor)
|
|
DecodeChannel(pmap, pmap->red, flags, DoRed|DoGreen|DoBlue, data);
|
|
else {
|
|
data = DecodeChannel(pmap, pmap->red, flags, DoRed, data);
|
|
data = DecodeChannel(pmap, pmap->green, flags, DoGreen, data);
|
|
DecodeChannel(pmap, pmap->blue, flags, DoBlue, data);
|
|
}
|
|
}
|
|
|
|
static void
|
|
GrabCmap (client, pmap, red, green, blue, alloc_named, xred, xgreen, xblue)
|
|
ClientPtr client;
|
|
ColormapPtr pmap;
|
|
CARD16 red, green, blue;
|
|
Bool alloc_named;
|
|
CARD16 xred, xgreen, xblue;
|
|
{
|
|
xLbxGrabCmapReq req;
|
|
ReplyStuffPtr nr;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "LbxGrabCmapReq: cmap = 0x%x, seq = 0x%x\n",
|
|
pmap->id, LBXSequenceNumber(client));
|
|
fprintf (stderr, "suspending %s (%d, %d, %d)\n",
|
|
alloc_named ? "AllocNamedColor" : "AllocColor",
|
|
red, green, blue);
|
|
#endif
|
|
|
|
nr = NewReply(client, client->server->lbxReq, X_LbxGrabCmap,
|
|
grab_cmap_reply);
|
|
if (nr)
|
|
{
|
|
--nr->sequenceNumber;
|
|
nr->request_info.lbxgrabcmap.pmap = pmap;
|
|
nr->request_info.lbxgrabcmap.alloc_named = alloc_named;
|
|
nr->request_info.lbxgrabcmap.vred = red;
|
|
nr->request_info.lbxgrabcmap.vgreen = green;
|
|
nr->request_info.lbxgrabcmap.vblue = blue;
|
|
nr->request_info.lbxgrabcmap.xred = xred;
|
|
nr->request_info.lbxgrabcmap.xgreen = xgreen;
|
|
nr->request_info.lbxgrabcmap.xblue = xblue;
|
|
}
|
|
|
|
req.reqType = client->server->lbxReq;
|
|
req.lbxReqType = X_LbxGrabCmap;
|
|
req.length = sz_xLbxGrabCmapReq >> 2;
|
|
req.cmap = pmap->id;
|
|
|
|
if (client->swapped)
|
|
SwapGrabCmap (&req);
|
|
|
|
WriteReqToServer (client, sz_xLbxGrabCmapReq, (char *) &req, TRUE);
|
|
|
|
pmap->grab_status = CMAP_GRAB_REQUESTED;
|
|
}
|
|
|
|
static Bool
|
|
grab_cmap_reply(client, nr, data)
|
|
ClientPtr client;
|
|
ReplyStuffPtr nr;
|
|
char *data;
|
|
{
|
|
xLbxGrabCmapReply *reply;
|
|
Entry *pent;
|
|
|
|
reply = (xLbxGrabCmapReply *) data;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "LbxGrabCmapReply: cmap = 0x%x, seq = 0x%x, ",
|
|
nr->request_info.lbxgrabcmap.pmap->id, reply->sequenceNumber);
|
|
fprintf (stderr, "flags = %x\n", reply->flags);
|
|
fprintf (stderr, "resuming %s (%d, %d, %d)\n",
|
|
nr->request_info.lbxgrabcmap.alloc_named ?
|
|
"AllocNamedColor" : "AllocColor",
|
|
nr->request_info.lbxgrabcmap.vred,
|
|
nr->request_info.lbxgrabcmap.vgreen,
|
|
nr->request_info.lbxgrabcmap.vblue);
|
|
#endif
|
|
|
|
GotColormapGrab (nr->request_info.lbxgrabcmap.pmap, reply->flags,
|
|
(CARD8 *) reply + sz_xLbxGrabCmapReplyHdr);
|
|
|
|
/*
|
|
* We suspended an AllocColor request so we could grab the colormap.
|
|
* Now that the colormap is grabbed we resume handling the AllocColor.
|
|
* We first check to see if the color is already allocated.
|
|
*/
|
|
|
|
FindPixel (client,
|
|
nr->request_info.lbxgrabcmap.pmap,
|
|
nr->request_info.lbxgrabcmap.vred,
|
|
nr->request_info.lbxgrabcmap.vgreen,
|
|
nr->request_info.lbxgrabcmap.vblue,
|
|
&pent);
|
|
|
|
if (pent)
|
|
{
|
|
/*
|
|
* We found the pixel in the proxy's colormap. We can
|
|
* immediately short circuit this AllocColor.
|
|
*/
|
|
|
|
FoundPixel (client, TRUE, nr->request_info.lbxgrabcmap.pmap, pent,
|
|
nr->request_info.lbxgrabcmap.alloc_named,
|
|
nr->request_info.lbxgrabcmap.xred,
|
|
nr->request_info.lbxgrabcmap.xgreen,
|
|
nr->request_info.lbxgrabcmap.xblue);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We didn't find the pixel, but we just grabbed the color map,
|
|
* so we can handle the color allocation locally now, then do
|
|
* the short circuit.
|
|
*/
|
|
|
|
LocalAllocColor (client, TRUE,
|
|
nr->request_info.lbxgrabcmap.pmap,
|
|
nr->request_info.lbxgrabcmap.vred,
|
|
nr->request_info.lbxgrabcmap.vgreen,
|
|
nr->request_info.lbxgrabcmap.vblue,
|
|
nr->request_info.lbxgrabcmap.alloc_named,
|
|
nr->request_info.lbxgrabcmap.xred,
|
|
nr->request_info.lbxgrabcmap.xgreen,
|
|
nr->request_info.lbxgrabcmap.xblue);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Release the colormap currently grabbed by the proxy.
|
|
*/
|
|
|
|
void
|
|
ReleaseCmap (client, pmap)
|
|
ClientPtr client;
|
|
ColormapPtr pmap;
|
|
{
|
|
xLbxReleaseCmapReq req;
|
|
|
|
pmap->grab_status = CMAP_NOT_GRABBED;
|
|
|
|
req.reqType = client->server->lbxReq;
|
|
req.lbxReqType = X_LbxReleaseCmap;
|
|
req.length = sz_xLbxReleaseCmapReq >> 2;
|
|
req.cmap = pmap->id;
|
|
|
|
/* write the request on the proxy control connection */
|
|
|
|
WriteReqToServer (client->server->serverClient,
|
|
sz_xLbxReleaseCmapReq,
|
|
(char *) &req,
|
|
FALSE);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
DoAllocColorReply (client, in_reply, red, green, blue, pixel)
|
|
ClientPtr client;
|
|
Bool in_reply;
|
|
CARD16 red, green, blue;
|
|
Pixel pixel;
|
|
{
|
|
/*
|
|
* Prepare the AllocColor reply for the client.
|
|
*/
|
|
|
|
xAllocColorReply reply;
|
|
|
|
reply.type = X_Reply;
|
|
reply.length = 0;
|
|
reply.sequenceNumber = LBXSequenceNumber(client);
|
|
|
|
reply.red = red;
|
|
reply.green = green;
|
|
reply.blue = blue;
|
|
reply.pixel = pixel;
|
|
|
|
if (client->swapped)
|
|
SwapAllocColorReply (&reply);
|
|
|
|
if (LBXCacheSafe (client))
|
|
{
|
|
/*
|
|
* We can write the AllocColor reply now.
|
|
*/
|
|
|
|
if (!in_reply)
|
|
FinishLBXRequest(client, REQ_REPLACE);
|
|
|
|
WriteToClient (client, sizeof (xAllocColorReply), &reply);
|
|
|
|
#ifdef LBX_STATS
|
|
ac_good++;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We can't write the AllocColor reply now, we must first sync.
|
|
*/
|
|
|
|
if (!LBXCanDelayReply(client))
|
|
SendLbxSync (client);
|
|
if (!in_reply)
|
|
FinishLBXRequest(client, REQ_REPLACELATE);
|
|
|
|
/*
|
|
* Save the AllocColor reply. We will write it when the
|
|
* LbxSync reply comes back.
|
|
*/
|
|
|
|
SaveReplyData (client, (xReply *) & reply, 0, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
DoAllocNamedColorReply (client, in_reply, red, green, blue, pixel,
|
|
xred, xgreen, xblue)
|
|
ClientPtr client;
|
|
Bool in_reply;
|
|
CARD16 red, green, blue;
|
|
Pixel pixel;
|
|
CARD16 xred, xgreen, xblue;
|
|
{
|
|
/*
|
|
* Prepare the AllocNamedColor reply for the client.
|
|
*/
|
|
|
|
xAllocNamedColorReply reply;
|
|
|
|
reply.type = X_Reply;
|
|
reply.length = 0;
|
|
reply.sequenceNumber = LBXSequenceNumber(client);
|
|
|
|
reply.exactRed = xred;
|
|
reply.exactGreen = xgreen;
|
|
reply.exactBlue = xblue;
|
|
reply.screenRed = red;
|
|
reply.screenGreen = green;
|
|
reply.screenBlue = blue;
|
|
reply.pixel = pixel;
|
|
|
|
if (client->swapped)
|
|
SwapAllocNamedColorReply (&reply);
|
|
|
|
if (LBXCacheSafe (client))
|
|
{
|
|
/*
|
|
* We can write the AllocColor reply now.
|
|
*/
|
|
|
|
if (!in_reply)
|
|
FinishLBXRequest(client, REQ_REPLACE);
|
|
|
|
WriteToClient (client, sizeof (xAllocNamedColorReply), &reply);
|
|
|
|
#ifdef LBX_STATS
|
|
anc_good++;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We can't write the AllocColor reply now, we must first sync.
|
|
*/
|
|
|
|
if (!LBXCanDelayReply(client))
|
|
SendLbxSync (client);
|
|
if (!in_reply)
|
|
FinishLBXRequest(client, REQ_REPLACELATE);
|
|
|
|
/*
|
|
* We can't write the AllocNamedColor reply now, we must first
|
|
* sync. You might ask why we didn't just send the AllocNamedColor
|
|
* request to the server? The answer is that if the colormap is
|
|
* grabbed, we don't want to send the AllocNamedColor to the server
|
|
* because that would force the proxy to give up control over the
|
|
* colormap. So the proxy generates the reply on its own, but must
|
|
* force a round trip sync before the reply is written.
|
|
*/
|
|
|
|
SaveReplyData (client, (xReply *) & reply, 0, NULL);
|
|
|
|
#ifdef LBX_STATS
|
|
anc_miss++;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
* LocalAllocColor is called when the specified color is not already
|
|
* allocated in the colormap, and the proxy has the colormap grabbed.
|
|
* The proxy handles the AllocColor locally, and tells the server
|
|
* what allocation it made.
|
|
*
|
|
* (red, green, blue) are actual rgb values, not requested ones -
|
|
* they have already been put through ResolveColor.
|
|
*/
|
|
|
|
static void
|
|
LocalAllocColor (client, in_reply, pmap, red, green, blue, alloc_named,
|
|
xred, xgreen, xblue)
|
|
ClientPtr client;
|
|
Bool in_reply;
|
|
ColormapPtr pmap;
|
|
CARD16 red, green, blue;
|
|
Bool alloc_named;
|
|
CARD16 xred, xgreen, xblue;
|
|
{
|
|
Pixel pixel;
|
|
|
|
/*
|
|
* First find a free cell.
|
|
*/
|
|
|
|
pixel = (*LbxFindFreePixel) (pmap, red, green, blue);
|
|
|
|
if (pixel == ~((Pixel)0))
|
|
{
|
|
#ifdef COLOR_DEBUG
|
|
fprintf(stderr, "alloc failed: (%d, %d, %d)\n", red, green, blue);
|
|
#endif
|
|
if (in_reply)
|
|
WriteError(client,
|
|
alloc_named ? X_AllocNamedColor : X_AllocColor,
|
|
0, pmap->id, BadAlloc);
|
|
else
|
|
SendErrorToClient(client,
|
|
alloc_named ? X_AllocNamedColor : X_AllocColor,
|
|
0, pmap->id, BadAlloc);
|
|
return;
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
if (LBXCacheSafe (client))
|
|
fprintf (stderr,
|
|
"X %s: short circuiting (allocating color locally):\n",
|
|
alloc_named ? "AllocNamedColor" : "AllocColor");
|
|
else
|
|
fprintf (stderr,
|
|
"X %s: allocating color locally, but need Sync:\n",
|
|
alloc_named ? "AllocNamedColor" : "AllocColor");
|
|
|
|
fprintf (stderr,
|
|
" seq = 0x%x, cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
|
|
LBXSequenceNumber(client), pmap->id, pixel, red, green, blue);
|
|
#endif
|
|
|
|
/*
|
|
* Now handle the X AllocColor reply to the client.
|
|
*/
|
|
|
|
if (alloc_named)
|
|
DoAllocNamedColorReply (client, in_reply, red, green, blue, pixel,
|
|
xred, xgreen, xblue);
|
|
else
|
|
DoAllocColorReply (client, in_reply, red, green, blue, pixel);
|
|
|
|
/*
|
|
* Store the rgb in the cell.
|
|
*/
|
|
|
|
StorePixel (client, pmap, red, green, blue, pixel, FALSE);
|
|
}
|
|
|
|
|
|
static void
|
|
FoundPixel (client, in_reply, pmap, pent, alloc_named, xred, xgreen, xblue)
|
|
ClientPtr client;
|
|
Bool in_reply;
|
|
ColormapPtr pmap;
|
|
Entry *pent;
|
|
Bool alloc_named;
|
|
CARD16 xred, xgreen, xblue;
|
|
{
|
|
#ifdef COLOR_DEBUG
|
|
if (LBXCacheSafe (client))
|
|
fprintf (stderr,
|
|
"X %s: short circuiting (color already exists):\n",
|
|
alloc_named ? "AllocNamedColor" : "AllocColor");
|
|
else
|
|
{
|
|
fprintf (stderr,
|
|
"X %s: color already exists locally, but need Sync:\n",
|
|
alloc_named ? "AllocNamedColor" : "AllocColor");
|
|
}
|
|
|
|
fprintf (stderr,
|
|
" seq = 0x%x, cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
|
|
LBXSequenceNumber(client), pmap->id, pent->pixel,
|
|
pent->red, pent->green, pent->blue);
|
|
#endif
|
|
|
|
/*
|
|
* Now handle the X AllocColor reply to the client.
|
|
*/
|
|
|
|
if (alloc_named)
|
|
DoAllocNamedColorReply (client, in_reply,
|
|
pent->red, pent->green, pent->blue,
|
|
pent->pixel, xred, xgreen, xblue);
|
|
else
|
|
DoAllocColorReply (client, in_reply,
|
|
pent->red, pent->green, pent->blue, pent->pixel);
|
|
|
|
/*
|
|
* We found a match. Increment our ref count and tell the
|
|
* server to bump up its own ref count.
|
|
*/
|
|
|
|
IncrementPixel (client, pmap, pent, FALSE);
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXCreateColormap(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xCreateColormapReq);
|
|
Colormap cmap;
|
|
VisualID vis;
|
|
char n;
|
|
|
|
/* AllocAll are read/write, so ignore */
|
|
if (stuff->alloc) {
|
|
cmap = stuff->mid;
|
|
vis = stuff->visual;
|
|
if (client->swapped) {
|
|
swapl(&cmap, n);
|
|
swapl(&vis, n);
|
|
}
|
|
CreateColormap(client, cmap, vis);
|
|
}
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
static ColormapPtr
|
|
create_colormap(cmap, visual)
|
|
Colormap cmap;
|
|
VisualID visual;
|
|
{
|
|
ColormapPtr pmap;
|
|
LbxVisualPtr pvis;
|
|
int tsize, csize;
|
|
Pixel **pptr;
|
|
|
|
pvis = GetVisual(visual);
|
|
if (!pvis)
|
|
return ((ColormapPtr) NULL);
|
|
csize = pvis->colormapEntries;
|
|
tsize = (csize * sizeof(Entry)) + (MAXCLIENTS * sizeof(Pixel *)) +
|
|
(MAXCLIENTS * sizeof(int));
|
|
if ((pvis->class | DynamicClass) == DirectColor)
|
|
tsize *= 3;
|
|
tsize += sizeof(ColormapRec);
|
|
pmap = (ColormapPtr) xalloc(tsize);
|
|
if (!pmap)
|
|
return pmap;
|
|
bzero((char *) pmap, tsize);
|
|
pmap->id = cmap;
|
|
pmap->pVisual = pvis;
|
|
pmap->grab_status = CMAP_NOT_GRABBED;
|
|
pmap->red = (Entry *) ((char *) pmap + sizeof(ColormapRec));
|
|
pmap->clientPixelsRed = (Pixel **)
|
|
((char *) pmap->red + (csize * sizeof(Entry)));
|
|
pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
|
|
(MAXCLIENTS * sizeof(Pixel *)));
|
|
bzero((char *) pmap->red, (csize * sizeof(Entry)));
|
|
bzero((char *) pmap->numPixelsRed, (MAXCLIENTS * sizeof(int)));
|
|
for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
|
|
--pptr >= pmap->clientPixelsRed; )
|
|
*pptr = (Pixel *) NULL;
|
|
if ((pvis->class | DynamicClass) != DirectColor) {
|
|
pmap->green = NULL;
|
|
pmap->numPixelsGreen = NULL;
|
|
pmap->clientPixelsGreen = NULL;
|
|
pmap->blue = NULL;
|
|
pmap->numPixelsBlue = NULL;
|
|
pmap->clientPixelsBlue = NULL;
|
|
return pmap;
|
|
}
|
|
pmap->green = (Entry *) ((char *) pmap->numPixelsRed +
|
|
(MAXCLIENTS * sizeof(int)));
|
|
pmap->clientPixelsGreen = (Pixel **)
|
|
((char *) pmap->green + (csize * sizeof(Entry)));
|
|
pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
|
|
(MAXCLIENTS * sizeof(Pixel *)));
|
|
bzero((char *) pmap->green, (csize * sizeof(Entry)));
|
|
bzero((char *) pmap->numPixelsGreen, (MAXCLIENTS * sizeof(int)));
|
|
for (pptr = &pmap->clientPixelsGreen[MAXCLIENTS];
|
|
--pptr >= pmap->clientPixelsGreen; )
|
|
*pptr = (Pixel *) NULL;
|
|
pmap->blue = (Entry *) ((char *) pmap->numPixelsGreen +
|
|
(MAXCLIENTS * sizeof(int)));
|
|
pmap->clientPixelsBlue = (Pixel **)
|
|
((char *) pmap->blue + (csize * sizeof(Entry)));
|
|
pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
|
|
(MAXCLIENTS * sizeof(Pixel *)));
|
|
bzero((char *) pmap->blue, (csize * sizeof(Entry)));
|
|
bzero((char *) pmap->numPixelsBlue, (MAXCLIENTS * sizeof(int)));
|
|
for (pptr = &pmap->clientPixelsBlue[MAXCLIENTS];
|
|
--pptr >= pmap->clientPixelsBlue; )
|
|
*pptr = (Pixel *) NULL;
|
|
return pmap;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
Bool
|
|
CreateColormap(client, cmap, visual)
|
|
ClientPtr client;
|
|
Colormap cmap;
|
|
VisualID visual;
|
|
{
|
|
ColormapPtr pmap;
|
|
|
|
pmap = create_colormap(cmap, visual);
|
|
if (!pmap)
|
|
return FALSE;
|
|
return AddResource(client, cmap, RT_COLORMAP, (pointer) pmap);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
|
|
int
|
|
ProcLBXFreeColormap(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xResourceReq);
|
|
Colormap cmap;
|
|
char n;
|
|
|
|
cmap = stuff->id;
|
|
if (client->swapped) {
|
|
swapl(&cmap, n);
|
|
}
|
|
FreeColormap(client, cmap);
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
Bool
|
|
FreeColormap(client, cmap)
|
|
ClientPtr client;
|
|
Colormap cmap;
|
|
{
|
|
ColormapPtr pmap;
|
|
|
|
pmap = (ColormapPtr) LookupIDByType(client, cmap, RT_COLORMAP);
|
|
if (!pmap)
|
|
return FALSE;
|
|
FreeResource(client, cmap, RT_NONE);
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* cop out: don't try to track the new colormap
|
|
*/
|
|
int
|
|
ProcLBXCopyColormapAndFree(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xCopyColormapAndFreeReq);
|
|
Colormap srcmap;
|
|
ColormapPtr pmap;
|
|
char n;
|
|
|
|
srcmap = stuff->srcCmap;
|
|
if (client->swapped) {
|
|
swapl(&srcmap, n);
|
|
}
|
|
pmap = (ColormapPtr) LookupIDByType(client, srcmap, RT_COLORMAP);
|
|
if (pmap)
|
|
FreeAllClientPixels(pmap, client->index);
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXFreeColors(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xFreeColorsReq);
|
|
int num;
|
|
Pixel *pixels;
|
|
CARD32 mask;
|
|
Colormap cmap;
|
|
Bool freepix = FALSE;
|
|
int n;
|
|
CARD16 len;
|
|
ColormapPtr pmap;
|
|
|
|
mask = stuff->planeMask;
|
|
cmap = stuff->cmap;
|
|
len = stuff->length;
|
|
|
|
if (client->swapped) {
|
|
swapl(&cmap, n);
|
|
swapl(&mask, n);
|
|
swaps(&len, n);
|
|
}
|
|
pmap = (ColormapPtr) LookupIDByType(client, cmap, RT_COLORMAP);
|
|
if (!pmap)
|
|
return ProcStandardRequest(client);
|
|
|
|
num = ((len << 2) - sizeof(xFreeColorsReq)) >> 2;
|
|
|
|
if (client->swapped) {
|
|
pixels = (Pixel *) ALLOCATE_LOCAL(num * sizeof(Pixel));
|
|
if (pixels) {
|
|
memcpy((char *) pixels, (char *) &stuff[1], (num * sizeof(Pixel)));
|
|
SwapLongs((CARD32 *) pixels, num);
|
|
}
|
|
freepix = TRUE;
|
|
} else
|
|
pixels = (Pixel *) &stuff[1];
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf(stderr, "freeing on cmap 0x%x mask: %d pixels:", cmap, mask);
|
|
for (n = 0; n < num; n++)
|
|
fprintf(stderr, " %d", pixels[n]);
|
|
fprintf(stderr, "\n");
|
|
#endif
|
|
FreePixels(client, pmap, num, pixels, mask);
|
|
|
|
if (freepix)
|
|
DEALLOCATE_LOCAL(pixels);
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXAllocColor(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xAllocColorReq);
|
|
Entry *pent;
|
|
Colormap cmap;
|
|
ColormapPtr pmap;
|
|
CARD16 red, green, blue;
|
|
char n;
|
|
|
|
cmap = stuff->cmap;
|
|
|
|
if (client->swapped)
|
|
swapl(&cmap, n);
|
|
|
|
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
|
|
|
|
if (!pmap)
|
|
return ProcStandardRequest(client);
|
|
|
|
red = stuff->red;
|
|
green = stuff->green;
|
|
blue = stuff->blue;
|
|
|
|
if (client->swapped)
|
|
{
|
|
swaps(&red, n);
|
|
swaps(&green, n);
|
|
swaps(&blue, n);
|
|
}
|
|
|
|
|
|
/*
|
|
* Resolve the color (requested rgb -> actual rgb)
|
|
*/
|
|
|
|
(*LbxResolveColor)(pmap->pVisual, &red, &green, &blue);
|
|
|
|
|
|
/*
|
|
* Search for the pixel in the proxy's colormap.
|
|
*/
|
|
|
|
FindPixel (client, pmap, red, green, blue, &pent);
|
|
|
|
if (pent && (pent->refcnt || pmap->grab_status == CMAP_GRABBED))
|
|
{
|
|
/*
|
|
* We found the pixel in the proxy's colormap. We can
|
|
* short circuit this AllocColor.
|
|
*/
|
|
|
|
FoundPixel (client, FALSE, pmap, pent, FALSE, 0, 0, 0);
|
|
}
|
|
else if (pmap->grab_status == CMAP_GRABBED)
|
|
{
|
|
/*
|
|
* The color map is already grabbed by the proxy, so we
|
|
* can handle the AllocColor locally now.
|
|
*/
|
|
|
|
LocalAllocColor(client, FALSE, pmap, red, green, blue, FALSE, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The proxy must first grab the color map. Then it can
|
|
* handle the AllocColor.
|
|
*/
|
|
|
|
FinishLBXRequest(client, REQ_REPLACELATE);
|
|
|
|
GrabCmap(client, pmap, red, green, blue, FALSE, 0, 0, 0);
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXAllocNamedColor(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xAllocNamedColorReq);
|
|
Entry *pent;
|
|
RGBEntryPtr rgbe;
|
|
ReplyStuffPtr nr;
|
|
CARD16 nbytes;
|
|
Colormap cmap;
|
|
ColormapPtr pmap;
|
|
char n;
|
|
|
|
cmap = stuff->cmap;
|
|
nbytes = stuff->nbytes;
|
|
|
|
if (client->swapped) {
|
|
swapl(&cmap, n);
|
|
swaps(&nbytes, n);
|
|
}
|
|
|
|
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
|
|
|
|
if (nbytes > MAX_COLORNAME_LENGTH || !pmap)
|
|
return ProcStandardRequest(client);
|
|
|
|
pent = NULL;
|
|
rgbe = FindColorName(client->server, (char *) &stuff[1], nbytes,
|
|
pmap->pVisual);
|
|
if (rgbe) {
|
|
#ifdef COLOR_DEBUG
|
|
fprintf(stderr, "looking for %.*s = (%d,%d,%d)\n", nbytes,
|
|
(char *)&stuff[1], rgbe->vred, rgbe->vgreen, rgbe->vblue);
|
|
#endif
|
|
FindPixel (client, pmap, rgbe->vred, rgbe->vgreen, rgbe->vblue, &pent);
|
|
}
|
|
if (pent && (pent->refcnt || pmap->grab_status == CMAP_GRABBED)) {
|
|
FoundPixel (client, FALSE, pmap, pent, TRUE,
|
|
rgbe->xred, rgbe->xgreen, rgbe->xblue);
|
|
} else if (rgbe) {
|
|
if (pmap->grab_status == CMAP_GRABBED) {
|
|
/*
|
|
* The color map is already grabbed by the proxy, so we
|
|
* can handle the AllocNamedColor locally now.
|
|
*/
|
|
|
|
LocalAllocColor (client, FALSE, pmap,
|
|
rgbe->vred, rgbe->vgreen, rgbe->vblue,
|
|
TRUE,
|
|
rgbe->xred, rgbe->xgreen, rgbe->xblue);
|
|
} else {
|
|
FinishLBXRequest(client, REQ_REPLACELATE);
|
|
GrabCmap(client, pmap,
|
|
rgbe->vred, rgbe->vgreen, rgbe->vblue,
|
|
TRUE, rgbe->xred, rgbe->xgreen, rgbe->xblue);
|
|
}
|
|
} else {
|
|
|
|
/*
|
|
* We can't short circuit the AllocNamedColor request.
|
|
* The proxy will need control over the colormap to handle
|
|
* this request, so rather than wait for the server to ask
|
|
* the proxy to release the colormap, we release it now.
|
|
*/
|
|
|
|
if (pmap->grab_status == CMAP_GRABBED &&
|
|
(pmap->pVisual->class & DynamicClass))
|
|
ReleaseCmap (client, pmap);
|
|
|
|
|
|
/*
|
|
* We need to catch the AllocNamedColor reply so we can cache
|
|
* the results for future short circuiting.
|
|
*/
|
|
|
|
nr = NewReply(client, X_AllocNamedColor, 0, alloc_named_color_reply);
|
|
if (!nr)
|
|
return ProcStandardRequest(client);
|
|
nr->request_info.xallocnamedcolor.pmap = pmap;
|
|
strncpy(nr->request_info.xallocnamedcolor.name, (char *) &stuff[1],
|
|
nbytes);
|
|
nr->request_info.xallocnamedcolor.namelen = nbytes;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "X AllocNamedColor: could not short circuit\n");
|
|
fprintf (stderr, " seq = 0x%x, cmap = 0x%x\n",
|
|
LBXSequenceNumber(client), cmap);
|
|
#endif
|
|
|
|
#ifdef LBX_STATS
|
|
anc_miss++;
|
|
#endif
|
|
return ProcStandardRequest(client);
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
static Bool
|
|
alloc_named_color_reply(client, nr, data)
|
|
ClientPtr client;
|
|
ReplyStuffPtr nr;
|
|
char *data;
|
|
{
|
|
xAllocNamedColorReply *reply;
|
|
Pixel pixel;
|
|
char n;
|
|
RGBEntryRec rgbe;
|
|
|
|
reply = (xAllocNamedColorReply *) data;
|
|
|
|
rgbe.xred = reply->exactRed;
|
|
rgbe.xgreen = reply->exactGreen;
|
|
rgbe.xblue = reply->exactBlue;
|
|
rgbe.vred = reply->screenRed;
|
|
rgbe.vgreen = reply->screenGreen;
|
|
rgbe.vblue = reply->screenBlue;
|
|
pixel = reply->pixel;
|
|
|
|
if (client->swapped) {
|
|
swapl(&pixel, n);
|
|
swaps(&rgbe.xred, n);
|
|
swaps(&rgbe.xgreen, n);
|
|
swaps(&rgbe.xblue, n);
|
|
swaps(&rgbe.vred, n);
|
|
swaps(&rgbe.vgreen, n);
|
|
swaps(&rgbe.vblue, n);
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr,
|
|
"X AllocNamedColorReply: caching results\n");
|
|
fprintf (stderr, "pixel = %d, rgb = (%d,%d,%d)\n",
|
|
pixel, rgbe.vred, rgbe.vgreen, rgbe.vblue);
|
|
#endif
|
|
|
|
AddColorName(client->server,
|
|
nr->request_info.xallocnamedcolor.name,
|
|
nr->request_info.xallocnamedcolor.namelen,
|
|
&rgbe);
|
|
|
|
return StorePixel(client, nr->request_info.xallocnamedcolor.pmap,
|
|
rgbe.vred, rgbe.vgreen, rgbe.vblue, pixel, TRUE);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXAllocColorCells(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xAllocColorCellsReq);
|
|
ReplyStuffPtr nr;
|
|
Colormap cmap;
|
|
ColormapPtr pmap;
|
|
char n;
|
|
|
|
cmap = stuff->cmap;
|
|
if (client->swapped)
|
|
swapl(&cmap, n);
|
|
|
|
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
|
|
|
|
if (!pmap)
|
|
return ProcStandardRequest(client);
|
|
if (!(pmap->pVisual->class & DynamicClass))
|
|
return BadAlloc;
|
|
|
|
/*
|
|
* We don't short circuit AllocColorCells requests.
|
|
* The server will need control over the colormap to handle
|
|
* this request, so rather than wait for the server to ask
|
|
* the proxy to release the colormap, we release it now.
|
|
*/
|
|
|
|
if (pmap->grab_status == CMAP_GRABBED)
|
|
ReleaseCmap (client, pmap);
|
|
|
|
|
|
/*
|
|
* The proxy needs to keep track of all read/write cells allocated
|
|
* for its own clients. By doing this, we can optimize the special
|
|
* case of GrabCmapReply with smartGrab = TRUE. This means
|
|
* that the proxy asked back for a grab that it temporarily gave up
|
|
* to the server, and no other client or proxy did a color allocation
|
|
* in the colormap.
|
|
*/
|
|
|
|
nr = NewReply(client, X_AllocColorCells, 0, alloc_color_cells_reply);
|
|
|
|
if (nr)
|
|
nr->request_info.xalloccolorcells.pmap = pmap;
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
static Bool
|
|
alloc_color_cells_reply(client, nr, data)
|
|
ClientPtr client;
|
|
ReplyStuffPtr nr;
|
|
char *data;
|
|
{
|
|
xAllocColorCellsReply *reply;
|
|
CARD16 nPixels, nMasks;
|
|
CARD32 *pixels, *masks;
|
|
ColormapPtr pmap;
|
|
int i, j, k;
|
|
char n;
|
|
|
|
reply = (xAllocColorCellsReply *) data;
|
|
|
|
pmap = nr->request_info.xalloccolorcells.pmap;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "AllocColorCells on cmap 0x%x:",
|
|
nr->request_info.xalloccolorcells.pmap->id);
|
|
#endif
|
|
|
|
nPixels = reply->nPixels;
|
|
nMasks = reply->nMasks;
|
|
|
|
if (client->swapped)
|
|
{
|
|
swaps(&nPixels, n);
|
|
swaps(&nMasks, n);
|
|
|
|
pixels = (CARD32 *) xalloc (nPixels * sizeof (CARD32));
|
|
masks = (CARD32 *) xalloc (nMasks * sizeof (CARD32));
|
|
|
|
memcpy (pixels, (char *) (reply + 1), nPixels * sizeof (CARD32));
|
|
memcpy (masks, ((char *) (reply + 1)) + nPixels * sizeof (CARD32),
|
|
nMasks * sizeof (CARD32));
|
|
|
|
for (i = 0; i < nPixels; i++)
|
|
swapl (&pixels[i], n);
|
|
for (i = 0; i < nMasks; i++)
|
|
swapl (&masks[i], n);
|
|
}
|
|
else
|
|
{
|
|
pixels = (CARD32 *) (reply + 1);
|
|
masks = pixels + nPixels;
|
|
}
|
|
|
|
for (i = 0; i < nPixels; i++)
|
|
for (j = 0; j < (1 << nMasks); j++)
|
|
{
|
|
CARD32 pixel, plane_mask = 0;
|
|
int bits = j;
|
|
|
|
for (k = 0; k < nMasks; k++)
|
|
{
|
|
if (bits & 1)
|
|
plane_mask |= masks[k];
|
|
bits >>= 1;
|
|
}
|
|
|
|
pixel = pixels[i] | plane_mask;
|
|
|
|
AllocCell(client, pmap, pixel);
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, " %d", pixel);
|
|
#endif
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "\n");
|
|
#endif
|
|
if (client->swapped)
|
|
{
|
|
xfree (pixels);
|
|
xfree (masks);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXAllocColorPlanes(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xAllocColorPlanesReq);
|
|
ReplyStuffPtr nr;
|
|
Colormap cmap;
|
|
ColormapPtr pmap;
|
|
char n;
|
|
|
|
cmap = stuff->cmap;
|
|
if (client->swapped)
|
|
swapl(&cmap, n);
|
|
|
|
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
|
|
|
|
if (!pmap)
|
|
return ProcStandardRequest(client);
|
|
if (!(pmap->pVisual->class & DynamicClass))
|
|
return BadAlloc;
|
|
|
|
/*
|
|
* We don't short circuit AllocColorPlanes requests.
|
|
* The server will need control over the colormap to handle
|
|
* this request, so rather than wait for the server to ask
|
|
* the proxy to release the colormap, we release it now.
|
|
*/
|
|
|
|
if (pmap->grab_status == CMAP_GRABBED)
|
|
ReleaseCmap (client, pmap);
|
|
|
|
|
|
/*
|
|
* The proxy needs to keep track of all read/write cells allocated
|
|
* for its own clients. By doing this, we can optimize the special
|
|
* case of GrabCmapReply with smartGrab = TRUE. This means
|
|
* that the proxy asked back for a grab that it temporarily gave up
|
|
* to the server, and no other client or proxy did a color allocation
|
|
* in the colormap.
|
|
*/
|
|
|
|
nr = NewReply(client, X_AllocColorPlanes, 0, alloc_color_planes_reply);
|
|
|
|
if (nr)
|
|
nr->request_info.xalloccolorplanes.pmap = pmap;
|
|
|
|
return ProcStandardRequest(client);
|
|
}
|
|
|
|
static Bool
|
|
alloc_color_planes_reply(client, nr, data)
|
|
ClientPtr client;
|
|
ReplyStuffPtr nr;
|
|
char *data;
|
|
{
|
|
xAllocColorPlanesReply *reply;
|
|
CARD32 redMask, greenMask, blueMask, mask;
|
|
CARD16 nPixels;
|
|
CARD32 *pixels;
|
|
ColormapPtr pmap;
|
|
int i;
|
|
char n;
|
|
|
|
reply = (xAllocColorPlanesReply *) data;
|
|
|
|
pmap = nr->request_info.xalloccolorplanes.pmap;
|
|
|
|
nPixels = reply->nPixels;
|
|
redMask = reply->redMask;
|
|
greenMask = reply->greenMask;
|
|
blueMask = reply->blueMask;
|
|
|
|
if (client->swapped)
|
|
{
|
|
swaps(&nPixels, n);
|
|
swapl(&redMask, n);
|
|
swapl(&greenMask, n);
|
|
swapl(&blueMask, n);
|
|
|
|
pixels = (CARD32 *) xalloc (nPixels * sizeof (CARD32));
|
|
|
|
memcpy (pixels, (char *) (reply + 1), nPixels * sizeof (CARD32));
|
|
|
|
for (i = 0; i < nPixels; i++)
|
|
swapl (&pixels[i], n);
|
|
|
|
}
|
|
else
|
|
{
|
|
pixels = (CARD32 *) (reply + 1);
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf (stderr, "AllocColorPlanes on cmap 0x%x:",
|
|
nr->request_info.xalloccolorplanes.pmap->id);
|
|
#endif
|
|
|
|
mask = redMask | greenMask | blueMask;
|
|
|
|
for (i = 0; i < nPixels; i++)
|
|
{
|
|
Pixel pixel, x = 0;
|
|
|
|
do
|
|
{
|
|
x = (x + ~mask + 1) & mask;
|
|
|
|
pixel = x | pixels[i];
|
|
|
|
AllocCell(client, pmap, pixel);
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf(stderr, " %d", pixel);
|
|
#endif
|
|
} while (x);
|
|
}
|
|
|
|
#ifdef COLOR_DEBUG
|
|
fprintf(stderr, "\n");
|
|
#endif
|
|
if (client->swapped)
|
|
{
|
|
xfree (pixels);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
int
|
|
ProcLBXLookupColor(client)
|
|
ClientPtr client;
|
|
{
|
|
REQUEST(xLookupColorReq);
|
|
xLookupColorReply reply;
|
|
ReplyStuffPtr nr;
|
|
RGBEntryPtr rgbe;
|
|
int len;
|
|
char n;
|
|
Colormap cmap;
|
|
ColormapPtr pmap;
|
|
|
|
len = stuff->nbytes;
|
|
cmap = stuff->cmap;
|
|
|
|
if (client->swapped) {
|
|
swapl(&cmap, n);
|
|
swaps(&len, n);
|
|
}
|
|
|
|
pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
|
|
|
|
if (len > MAX_COLORNAME_LENGTH || !pmap)
|
|
return ProcStandardRequest(client);
|
|
|
|
rgbe = FindColorName(client->server, (char *) &stuff[1], len,
|
|
pmap->pVisual);
|
|
|
|
if (rgbe) { /* found the value */
|
|
reply.type = X_Reply;
|
|
reply.length = 0;
|
|
reply.sequenceNumber = LBXSequenceNumber(client);
|
|
|
|
reply.exactRed = rgbe->xred;
|
|
reply.exactBlue = rgbe->xblue;
|
|
reply.exactGreen = rgbe->xgreen;
|
|
|
|
reply.screenRed = rgbe->vred;
|
|
reply.screenBlue = rgbe->vblue;
|
|
reply.screenGreen = rgbe->vgreen;
|
|
|
|
#ifdef COLOR_DEBUG
|
|
if (LBXCacheSafe (client))
|
|
fprintf(stderr, "X LookupColor: short circuiting:\n");
|
|
else
|
|
fprintf(stderr,
|
|
"X LookupColor: short circuiting, but need Sync:\n");
|
|
fprintf (stderr, " seq = 0x%x, name = %.*s\n",
|
|
LBXSequenceNumber(client), len, (char *)&stuff[1]);
|
|
#endif
|
|
|
|
if (client->swapped)
|
|
SwapLookupColorReply(&reply);
|
|
if (LBXCacheSafe(client)) {
|
|
FinishLBXRequest(client, REQ_YANK);
|
|
WriteToClient(client, sizeof(xLookupColorReply), &reply);
|
|
} else {
|
|
if (!LBXCanDelayReply(client))
|
|
SendLbxSync(client);
|
|
FinishLBXRequest(client, REQ_YANKLATE);
|
|
SaveReplyData(client, (xReply *) & reply, 0, NULL);
|
|
}
|
|
|
|
#ifdef LBX_STATS
|
|
luc_good++;
|
|
#endif
|
|
|
|
return Success;
|
|
} else {
|
|
nr = NewReply(client, X_LookupColor, 0, lookup_color_reply);
|
|
if (!nr)
|
|
return ProcStandardRequest(client);
|
|
strncpy(nr->request_info.xlookupcolor.name,
|
|
(char *) &stuff[1], len);
|
|
nr->request_info.xlookupcolor.namelen = len;
|
|
nr->request_info.xlookupcolor.visual = pmap->pVisual->id;
|
|
|
|
#ifdef LBX_STATS
|
|
luc_miss++;
|
|
#endif
|
|
return ProcStandardRequest(client);
|
|
}
|
|
}
|
|
|
|
|
|
static Bool
|
|
lookup_color_reply(client, nr, data)
|
|
ClientPtr client;
|
|
ReplyStuffPtr nr;
|
|
char *data;
|
|
{
|
|
xLookupColorReply *reply;
|
|
RGBEntryRec rgbe;
|
|
char n;
|
|
|
|
reply = (xLookupColorReply *) data;
|
|
|
|
rgbe.xred = reply->exactRed;
|
|
rgbe.xblue = reply->exactBlue;
|
|
rgbe.xgreen = reply->exactGreen;
|
|
rgbe.vred = reply->screenRed;
|
|
rgbe.vgreen = reply->screenGreen;
|
|
rgbe.vblue = reply->screenBlue;
|
|
|
|
rgbe.visual = nr->request_info.xlookupcolor.visual;
|
|
if (client->swapped) {
|
|
swaps(&rgbe.xred, n);
|
|
swaps(&rgbe.xgreen, n);
|
|
swaps(&rgbe.xblue, n);
|
|
swaps(&rgbe.vred, n);
|
|
swaps(&rgbe.vgreen, n);
|
|
swaps(&rgbe.vblue, n);
|
|
}
|
|
AddColorName(client->server,
|
|
nr->request_info.xlookupcolor.name,
|
|
nr->request_info.xlookupcolor.namelen,
|
|
&rgbe);
|
|
return TRUE;
|
|
}
|