#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();
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:
*red = ((*red >> shift) * 65535) / lim;
*green = ((*green >> shift) * 65535) / lim;
*blue = ((*blue >> shift) * 65535) / lim;
break;
case GrayScale:
*red = (30L * *red + 59L * *green + 11L * *blue) / 100;
*blue = *green = *red = ((*red >> shift) * 65535) / lim;
break;
case StaticGray:
limg = pVisual->colormapEntries - 1;
*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;
*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 ,
CARD16* ,
CARD16* ,
CARD16*
) = 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;
}
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 ,
CARD32 ,
CARD32 ,
CARD32
) = 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);
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 ,
CARD32 ,
CARD32 ,
CARD32 ,
int
) = 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;
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)
{
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);
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)
{
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
{
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;
}
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;
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;
{
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))
{
if (!in_reply)
FinishLBXRequest(client, REQ_REPLACE);
WriteToClient (client, sizeof (xAllocColorReply), &reply);
#ifdef LBX_STATS
ac_good++;
#endif
}
else
{
if (!LBXCanDelayReply(client))
SendLbxSync (client);
if (!in_reply)
FinishLBXRequest(client, REQ_REPLACELATE);
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;
{
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))
{
if (!in_reply)
FinishLBXRequest(client, REQ_REPLACE);
WriteToClient (client, sizeof (xAllocNamedColorReply), &reply);
#ifdef LBX_STATS
anc_good++;
#endif
}
else
{
if (!LBXCanDelayReply(client))
SendLbxSync (client);
if (!in_reply)
FinishLBXRequest(client, REQ_REPLACELATE);
SaveReplyData (client, (xReply *) & reply, 0, NULL);
#ifdef LBX_STATS
anc_miss++;
#endif
}
}
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;
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
if (alloc_named)
DoAllocNamedColorReply (client, in_reply, red, green, blue, pixel,
xred, xgreen, xblue);
else
DoAllocColorReply (client, in_reply, red, green, blue, pixel);
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
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);
IncrementPixel (client, pmap, pent, FALSE);
}
int
ProcLBXCreateColormap(client)
ClientPtr client;
{
REQUEST(xCreateColormapReq);
Colormap cmap;
VisualID vis;
char n;
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);
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;
}
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);
}
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;
}
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);
}
(*LbxResolveColor)(pmap->pVisual, &red, &green, &blue);
FindPixel (client, pmap, red, green, blue, &pent);
if (pent && (pent->refcnt || pmap->grab_status == CMAP_GRABBED))
{
FoundPixel (client, FALSE, pmap, pent, FALSE, 0, 0, 0);
}
else if (pmap->grab_status == CMAP_GRABBED)
{
LocalAllocColor(client, FALSE, pmap, red, green, blue, FALSE, 0, 0, 0);
}
else
{
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) {
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 {
if (pmap->grab_status == CMAP_GRABBED &&
(pmap->pVisual->class & DynamicClass))
ReleaseCmap (client, pmap);
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;
if (pmap->grab_status == CMAP_GRABBED)
ReleaseCmap (client, pmap);
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;
if (pmap->grab_status == CMAP_GRABBED)
ReleaseCmap (client, pmap);
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) {
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;
}