#include <stdio.h>
#include "assert.h"
#include "misc.h"
#include "lbx.h"
#include "util.h"
#include "resource.h"
#include "wire.h"
#include "lbximage.h"
#include "proxyopts.h"
#include "swap.h"
static Bool GetLbxImageReply();
static int pad[4] = {0, 3, 2, 1};
#define REENCODE_PSHORT(val, out) \
if ((val) >= 0 && (val) < 0xf0) \
*(out)++ = (val); \
else if ((val) >= 0xef0 || (val) < (short)0xfe00) \
return 0; \
else if ((val) < 0) { \
*(out)++ = 0xf0 | (((val) + 0x1000) >> 8); \
*(out)++ = (val) + 0x1000; \
} else { \
*(out)++ = 0xf0 | (((val) - 0xf0) >> 8); \
*(out)++ = (val) - 0xf0; \
}
#define REENCODE_SHORT(val, out) \
if ((val) >= (short)0xff90 && (val) < 0x80) \
*(out)++ = (val); \
else if ((val) >= (short)0x0880 || (val) < (short)0xf790) \
return 0; \
else if ((val) < 0) { \
*(out)++ = 0x80 | ((((val) + 0x70) >> 8) & 0x0f); \
*(out)++ = (val) + 0x70; \
} else { \
*(out)++ = 0x80 | ((((val) - 0x80) >> 8) & 0x0f); \
*(out)++ = (val) - 0x80; \
}
#define REENCODE_USHORT(val, out) \
if ((val) < 0xf0) \
*(out)++ = (val); \
else if ((unsigned short)(val) >= 0x10f0) \
return 0; \
else { \
*(out)++ = 0xf0 | (((val) - 0xf0) >> 8); \
*(out)++ = (val) - 0xf0; \
}
#define REENCODE_ANGLE(val, out) \
if ((val) > (360 << 6) || (val) < -(360 << 6)) \
return 0; \
else if ((val) >= 0 && (val) <= (95 << 6) && !((val) % (5 << 6))) \
*(out)++ = 0x5a + ((val) / (5 << 6)); \
else if ((val) >= (105 << 6) && !((val) % (15 << 6))) \
*(out)++ = 0x67 + ((val) / (15 << 6)); \
else if ((val) >= -(100 << 6) && (val) <= -(5 << 6) && \
!((val) % (5 << 6))) \
*(out)++ = 0xa6 + ((val) / (5 << 6)); \
else if ((val) <= -(105 << 6) && !((val) % (15 << 6))) \
*(out)++ = 0x98 + ((val) / (15 << 6)); \
else { \
*(out)++ = (val) >> 8; \
*(out)++ = (val); \
}
#define COPY_AND_SWAPS(oval, ival) \
{ \
register int n; \
(oval) = (ival); \
if (client->swapped) \
swaps(&(oval), n); \
}
#define SWAP_REENCODE_PSHORT(ival, out) { \
register int _n; \
short _val; \
_val = (ival); \
if (client->swapped) swaps (&_val, _n); \
REENCODE_PSHORT(_val, out); \
}
#define SWAP_REENCODE_SHORT(ival, out) { \
register int _n; \
short _val; \
_val = (ival); \
if (client->swapped) swaps (&_val, _n); \
REENCODE_SHORT(_val, out); \
}
#define SWAP_REENCODE_USHORT(ival, out) { \
register int _n; \
unsigned short _val; \
_val = (ival); \
if (client->swapped) swaps (&_val, _n); \
REENCODE_USHORT(_val, out); \
}
int gfx_gc_hit;
int gfx_gc_miss;
int gfx_draw_hit;
int gfx_draw_miss;
int gfx_total;
static void
push(cache, xid)
XID cache[GFX_CACHE_SIZE];
XID xid;
{
memmove(cache + 1, cache, (GFX_CACHE_SIZE - 1) * sizeof(cache[0]));
cache[0] = xid;
}
static void
use(cache, i)
XID cache[GFX_CACHE_SIZE];
int i;
{
XID tmp;
if (i == 0)
return;
tmp = cache[i];
memmove(cache + 1, cache, i * sizeof(cache[0]));
cache[0] = tmp;
}
static int
match(cache, xid)
XID cache[GFX_CACHE_SIZE];
XID xid;
{
int j;
for (j = 0; j < GFX_CACHE_SIZE; j++)
if (cache[j] == xid)
return j;
return GFXCacheNone;
}
#define GFX_REQ_PAD 8
#define GFX_SRC_DST_REQ_PAD 12
#define GFX_CACHE_DECLARE int _dcache, _gcache; \
Drawable _drawable; \
GContext _gcontext
#define GFX_SRC_DST_CACHE_DECLARE int _srcDcache, _dstDcache, _gcache; \
Drawable _srcDrawable, _dstDrawable; \
GContext _gcontext
#define GFX_SETUP_DRAWABLE_AND_GC(after) {\
_drawable = stuff->drawable; \
_gcontext = stuff->gc; \
if (client->swapped) { \
register int _n; \
swapl(&_drawable, _n); \
swapl(&_gcontext, _n); \
} \
_dcache = match (LBXDrawableCache(client), _drawable); \
if (_dcache == GFXCacheNone) \
{ \
memcpy (after, &stuff->drawable, 4); \
after += 4; \
} \
_gcache = match (LBXGContextCache(client), _gcontext); \
if (_gcache == GFXCacheNone) \
{ \
memcpy (after, &stuff->gc, 4); \
after += 4; \
} \
}
#define GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after) {\
Drawable tmpDrawableCache[GFX_CACHE_SIZE]; \
memcpy (tmpDrawableCache, LBXDrawableCache(client), sizeof (LBXDrawableCache(client))); \
_srcDrawable = stuff->srcDrawable; \
_dstDrawable = stuff->dstDrawable; \
_gcontext = stuff->gc; \
if (client->swapped) { \
register int _n; \
swapl (&_srcDrawable, _n); \
swapl (&_dstDrawable, _n); \
swapl (&_gcontext, _n); \
} \
_srcDcache = match (LBXDrawableCache(client), _srcDrawable); \
if (_srcDcache == GFXCacheNone) \
{ \
memcpy (after, &stuff->srcDrawable, 4); \
after += 4; \
push (tmpDrawableCache, _srcDrawable); \
} else \
use (tmpDrawableCache, _srcDcache); \
_dstDcache = match (tmpDrawableCache, _dstDrawable); \
if (_dstDcache == GFXCacheNone) \
{ \
memcpy (after, &stuff->dstDrawable, 4); \
after += 4; \
} \
_gcache = match (LBXGContextCache(client), _gcontext); \
if (_gcache == GFXCacheNone) \
{ \
memcpy (after, &stuff->gc, 4); \
after += 4; \
} \
}
#define GFX_SET_DRAWABLE_AND_GC {\
if (_dcache == GFXCacheNone) { \
gfx_draw_miss++; \
push (LBXDrawableCache(client), _drawable); \
} else { \
gfx_draw_hit++; \
use (LBXDrawableCache(client), _dcache); \
} \
if (_gcache == GFXCacheNone) { \
gfx_gc_miss++; \
push (LBXGContextCache(client), _gcontext);\
} else { \
gfx_gc_hit++; \
use (LBXGContextCache(client), _gcache); \
} \
newreq->cacheEnts = GFXCacheEnts (_dcache, _gcache); \
gfx_total++; \
}
#define GFX_SET_SRC_DST_DRAWABLE_AND_GC {\
if (_srcDcache == GFXCacheNone) { \
gfx_draw_miss++; \
push (LBXDrawableCache(client), _srcDrawable); \
} else { \
gfx_draw_hit++; \
use (LBXDrawableCache(client), _srcDcache); \
} \
newreq->srcCache = GFXCacheEnts (_srcDcache, 0); \
if (_dstDcache == GFXCacheNone) { \
gfx_draw_miss++; \
push (LBXDrawableCache(client), _dstDrawable); \
} else { \
gfx_draw_hit++; \
use (LBXDrawableCache(client), _dstDcache); \
} \
if (_gcache == GFXCacheNone) { \
gfx_gc_miss++; \
push (LBXGContextCache(client), _gcontext);\
} else { \
gfx_gc_hit++; \
use (LBXGContextCache(client), _gcache); \
} \
newreq->cacheEnts = GFXCacheEnts (_dstDcache, _gcache); \
gfx_total++; \
}
static int
reencode_poly(client, lbxreq, reencode_rtn)
ClientPtr client;
CARD8 lbxreq;
int (*reencode_rtn) ();
{
REQUEST(xPolyPointReq);
XServerPtr server = client->server;
int len = client->req_len << 2;
int space;
xLbxPolyPointReq *newreq = NULL;
char *after;
int bytes;
GFX_CACHE_DECLARE;
space = len - sz_xPolyPointReq + sz_xLbxPolyPointReq + GFX_REQ_PAD + 3;
newreq = (xLbxPolyPointReq *) xalloc(space);
if (newreq == NULL)
goto bail;
after = ((char *) newreq) + sz_xLbxPolyPointReq;
GFX_SETUP_DRAWABLE_AND_GC(after);
bytes = (*reencode_rtn) (client, (short *) &stuff[1],
(char *) after,
(len - sz_xPolyPointReq) >> 2);
if (bytes == 0)
goto bail;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->lbxReqType = lbxreq;
GFX_SET_DRAWABLE_AND_GC;
len = after - ((char *) newreq) + bytes;
newreq->padBytes = pad[len & 3];
bzero(((char *) newreq) + len, newreq->padBytes);
len += newreq->padBytes;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
xfree(newreq);
return Success;
bail:
if (newreq)
xfree(newreq);
return ProcStandardRequest(client);
}
static int
reencode_points_origin(client, in, out, count)
ClientPtr client;
register short *in;
register char *out;
int count;
{
register short diff;
int i;
short inval;
short last_x = 0;
short last_y = 0;
char *start_out = out;
for (i = 0; i < count; i++, in += 2) {
COPY_AND_SWAPS(inval, in[0]);
diff = inval - last_x;
last_x = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[1]);
diff = inval - last_y;
last_y = inval;
REENCODE_SHORT(diff, out);
}
return out - start_out;
}
static int
reencode_points_previous(client, in, out, count)
ClientPtr client;
register short *in;
register char *out;
int count;
{
int i;
short inval;
char *start_out = out;
for (i = 0; i < count; i++, in += 2) {
COPY_AND_SWAPS(inval, in[0]);
REENCODE_SHORT(inval, out);
COPY_AND_SWAPS(inval, in[1]);
REENCODE_SHORT(inval, out);
}
return out - start_out;
}
static int
reencode_segment(client, in, out, count)
ClientPtr client;
register short *in;
register char *out;
int count;
{
register short diff;
int i;
short inval;
short last_x = 0;
short last_y = 0;
char *start_out = out;
count >>= 1;
for (i = 0; i < count; i++, in += 4) {
COPY_AND_SWAPS(inval, in[0]);
diff = inval - last_x;
last_x = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[1]);
diff = inval - last_y;
last_y = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[2]);
diff = inval - last_x;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[3]);
diff = inval - last_y;
REENCODE_SHORT(diff, out);
}
return out - start_out;
}
static int
reencode_rectangle(client, in, out, count)
ClientPtr client;
register short *in;
register char *out;
int count;
{
register short diff;
int i;
short inval;
short last_x = 0;
short last_y = 0;
char *start_out = out;
count >>= 1;
for (i = 0; i < count; i++, in += 4) {
COPY_AND_SWAPS(inval, in[0]);
diff = inval - last_x;
last_x = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[1]);
diff = inval - last_y;
last_y = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[2]);
REENCODE_USHORT(inval, out);
COPY_AND_SWAPS(inval, in[3]);
REENCODE_USHORT(inval, out);
}
return out - start_out;
}
static int
reencode_arc(client, in, out, count)
ClientPtr client;
register short *in;
register char *out;
int count;
{
register short diff;
int i;
short inval;
short last_x = 0;
short last_y = 0;
char *start_out = out;
count = count / 3;
for (i = 0; i < count; i++, in += 6) {
COPY_AND_SWAPS(inval, in[0]);
diff = inval - last_x;
last_x = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[1]);
diff = inval - last_y;
last_y = inval;
REENCODE_SHORT(diff, out);
COPY_AND_SWAPS(inval, in[2]);
REENCODE_USHORT(inval, out);
COPY_AND_SWAPS(inval, in[3]);
REENCODE_USHORT(inval, out);
COPY_AND_SWAPS(inval, in[4]);
REENCODE_ANGLE(inval, out);
COPY_AND_SWAPS(inval, in[5]);
REENCODE_ANGLE(inval, out);
}
return out - start_out;
}
int
ProcLBXPolyPoint(client)
ClientPtr client;
{
REQUEST(xPolyPointReq);
int (*reencode_rtn) ();
reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
reencode_points_origin;
return reencode_poly(client, X_LbxPolyPoint, reencode_rtn);
}
int
ProcLBXPolyLine(client)
ClientPtr client;
{
REQUEST(xPolyLineReq);
int (*reencode_rtn) ();
reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
reencode_points_origin;
return reencode_poly(client, X_LbxPolyLine, reencode_rtn);
}
int
ProcLBXPolySegment(client)
ClientPtr client;
{
return reencode_poly(client, X_LbxPolySegment, reencode_segment);
}
int
ProcLBXPolyRectangle(client)
ClientPtr client;
{
return reencode_poly(client, X_LbxPolyRectangle, reencode_rectangle);
}
int
ProcLBXPolyArc(client)
ClientPtr client;
{
return reencode_poly(client, X_LbxPolyArc, reencode_arc);
}
int
ProcLBXFillPoly(client)
ClientPtr client;
{
REQUEST(xFillPolyReq);
XServerPtr server = client->server;
int len = client->req_len << 2;
xLbxFillPolyReq *newreq = NULL;
char *after;
int bytes;
int space;
int (*reencode_rtn) ();
GFX_CACHE_DECLARE;
reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
reencode_points_origin;
space = len - sz_xFillPolyReq + sz_xLbxPolyPointReq + GFX_REQ_PAD + 3;
newreq = (xLbxFillPolyReq *) xalloc(space);
if (newreq == NULL)
goto bail;
after = ((char *) newreq) + sz_xLbxFillPolyReq;
GFX_SETUP_DRAWABLE_AND_GC(after);
bytes = (*reencode_rtn) (client, (short *) &stuff[1], after,
(len - sz_xFillPolyReq) >> 2);
if (bytes == 0)
goto bail;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->lbxReqType = X_LbxFillPoly;
newreq->shape = stuff->shape;
GFX_SET_DRAWABLE_AND_GC;
len = after - ((char *) newreq) + bytes;
newreq->padBytes = pad[len & 3];
bzero(((char *) newreq) + len, newreq->padBytes);
len += newreq->padBytes;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
xfree(newreq);
return Success;
bail:
if (newreq)
xfree(newreq);
return ProcStandardRequest(client);
}
int
ProcLBXPolyFillRectangle(client)
ClientPtr client;
{
return reencode_poly(client, X_LbxPolyFillRectangle, reencode_rectangle);
}
int
ProcLBXPolyFillArc(client)
ClientPtr client;
{
return reencode_poly(client, X_LbxPolyFillArc, reencode_arc);
}
static int
reencode_copy(client, in, out)
ClientPtr client;
register xCopyAreaReq *in;
register char *out;
{
char *start_out = out;
SWAP_REENCODE_PSHORT(in->srcX, out);
SWAP_REENCODE_PSHORT(in->srcY, out);
SWAP_REENCODE_PSHORT(in->dstX, out);
SWAP_REENCODE_PSHORT(in->dstY, out);
SWAP_REENCODE_USHORT(in->width, out);
SWAP_REENCODE_USHORT(in->height, out);
return out - start_out;
}
int
ProcLBXCopyArea(client)
ClientPtr client;
{
REQUEST(xCopyAreaReq);
XServerPtr server = client->server;
int len;
xLbxCopyAreaReq *newreq = NULL;
unsigned long space[(SIZEOF(xLbxCopyAreaReq) + GFX_SRC_DST_REQ_PAD + 7 * sizeof(unsigned long) - 1) / sizeof(unsigned long)];
char *after;
int extra;
int bytes;
GFX_SRC_DST_CACHE_DECLARE;
newreq = (xLbxCopyAreaReq *) space;
after = ((char *) newreq) + sz_xLbxCopyAreaReq;
GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after);
bytes = reencode_copy(client, stuff, after);
if (bytes == 0)
goto bail;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->lbxReqType = X_LbxCopyArea;
GFX_SET_SRC_DST_DRAWABLE_AND_GC;
len = ((after + bytes) - ((char *) newreq));
extra = pad[len & 3];
bzero(((char *) newreq) + len, extra);
len += extra;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
return Success;
bail:
return ProcStandardRequest(client);
}
int
ProcLBXCopyPlane(client)
ClientPtr client;
{
REQUEST(xCopyPlaneReq);
XServerPtr server = client->server;
int len;
xLbxCopyPlaneReq *newreq = NULL;
unsigned long space[(SIZEOF(xLbxCopyPlaneReq) + GFX_SRC_DST_REQ_PAD + 7 * sizeof(unsigned long) - 1) / sizeof(unsigned long)];
char *after;
int bytes;
int extra;
GFX_SRC_DST_CACHE_DECLARE;
newreq = (xLbxCopyPlaneReq *) space;
after = ((char *) newreq) + sz_xLbxCopyPlaneReq;
GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after);
bytes = reencode_copy(client, (xCopyAreaReq *)stuff, after);
if (bytes == 0)
goto bail;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->bitPlane = stuff->bitPlane;
newreq->lbxReqType = X_LbxCopyPlane;
GFX_SET_SRC_DST_DRAWABLE_AND_GC;
len = ((after + bytes) - ((char *) newreq));
extra = pad[len & 3];
bzero(((char *) newreq) + len, extra);
len += extra;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
return Success;
bail:
return ProcStandardRequest(client);
}
static int
reencode_text_pos(client, in, out)
ClientPtr client;
xPolyTextReq *in;
char *out;
{
char *start_out;
start_out = out;
SWAP_REENCODE_PSHORT(in->x, out);
SWAP_REENCODE_PSHORT(in->y, out);
return out - start_out;
}
int
ProcLBXPolyText(client)
ClientPtr client;
{
REQUEST(xPolyTextReq);
XServerPtr server = client->server;
int len = client->req_len << 2;
xLbxPolyTextReq *newreq = NULL;
int space;
char *after;
int bytes;
int extra;
GFX_CACHE_DECLARE;
space = len - sz_xPolyTextReq + sz_xLbxPolyTextReq + GFX_REQ_PAD + 4 + 3;
newreq = (xLbxPolyTextReq *) xalloc(space);
if (newreq == NULL)
goto bail;
after = ((char *) newreq) + sz_xLbxPolyTextReq;
GFX_SETUP_DRAWABLE_AND_GC(after);
bytes = reencode_text_pos(client, stuff, after);
if (bytes == 0)
goto bail;
memcpy(after + bytes, (char *) &stuff[1], len - sz_xPolyTextReq);
bytes += len - sz_xPolyTextReq;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->lbxReqType = stuff->reqType == X_PolyText8 ? X_LbxPolyText8 : X_LbxPolyText16;
GFX_SET_DRAWABLE_AND_GC;
len = ((after + bytes) - ((char *) newreq));
extra = pad[len & 3];
bzero(((char *) newreq) + len, extra);
len += extra;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
xfree(newreq);
return Success;
bail:
if (newreq)
xfree(newreq);
return ProcStandardRequest(client);
}
int
ProcLBXImageText(client)
ClientPtr client;
{
REQUEST(xImageTextReq);
XServerPtr server = client->server;
int len = client->req_len << 2;
xLbxImageTextReq *newreq = NULL;
int space;
char *after;
int bytes;
int extra;
GFX_CACHE_DECLARE;
space = len - sz_xImageTextReq + sz_xLbxImageTextReq + GFX_REQ_PAD + 4 + 3;
newreq = (xLbxImageTextReq *) xalloc(space);
if (newreq == NULL)
goto bail;
after = ((char *) newreq) + sz_xLbxImageTextReq;
GFX_SETUP_DRAWABLE_AND_GC(after);
bytes = reencode_text_pos(client, (xPolyTextReq *) stuff, after);
if (bytes == 0)
goto bail;
memcpy(after + bytes, (char *) &stuff[1], len - sz_xImageTextReq);
bytes += len - sz_xImageTextReq;
FinishLBXRequest(client, REQ_PASSTHROUGH);
newreq->reqType = server->lbxReq;
newreq->lbxReqType = stuff->reqType == X_ImageText8 ? X_LbxImageText8 : X_LbxImageText16;
newreq->nChars = stuff->nChars;
GFX_SET_DRAWABLE_AND_GC;
len = ((after + bytes) - ((char *) newreq));
extra = pad[len & 3];
bzero(((char *) newreq) + len, extra);
len += extra;
newreq->length = len >> 2;
WriteReqToServer(client, len, (char *) newreq, TRUE);
xfree(newreq);
return Success;
bail:
if (newreq)
xfree(newreq);
return ProcStandardRequest(client);
}
static void
SwapXPutImage(req)
xPutImageReq *req;
{
char n;
swaps(&req->width, n);
swaps(&req->height, n);
swaps(&req->dstX, n);
swaps(&req->dstY, n);
}
static char *
reencode_putimage(stuff, newreq)
xPutImageReq *stuff;
xLbxPutImageReq *newreq;
{
char *out;
if (stuff->format > ZPixmap || stuff->leftPad > 31 ||
!stuff->depth || stuff->depth > 32 ||
(stuff->format == ZPixmap && stuff->leftPad != 0))
return 0;
out = (char *)newreq + sz_xLbxPutImageReq;
if (!stuff->leftPad && stuff->depth <= 8)
newreq->bitPacked = 0x80 | (stuff->format << 5) |
((stuff->depth - 1) << 2);
else {
newreq->bitPacked = ((stuff->depth - 1) << 2);
*out++ = (stuff->format << 5) | stuff->leftPad;
}
REENCODE_USHORT(stuff->width, out);
REENCODE_USHORT(stuff->height, out);
REENCODE_PSHORT(stuff->dstX, out);
REENCODE_PSHORT(stuff->dstY, out);
return out;
}
#define MaxPutImageSz sz_xLbxPutImageReq + 1 + 2 + 2 + 2 + 2 + GFX_REQ_PAD
int
ProcLBXPutImage(client)
ClientPtr client;
{
REQUEST(xPutImageReq);
XServerPtr server = client->server;
unsigned long space[(MaxPutImageSz + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
xLbxPutImageReq *newreq;
char *data = NULL;
char *out;
int len,
reqlen,
method = 0,
compBytes,
status;
#ifdef LBX_STATS
float percentCompression;
char *methodName;
#endif
LbxBitmapCompMethod *bcompMethod = NULL;
LbxPixmapCompMethod *pcompMethod = NULL;
GFX_CACHE_DECLARE;
status = LBX_IMAGE_COMPRESS_SUCCESS;
if (stuff->format != ZPixmap ||
(stuff->depth == 1 && LBXZBitsPerPixel1(client) == 1))
{
bcompMethod = LbxFindPreferredBitmapCompMethod (client->server);
if (!bcompMethod)
status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
} else {
pcompMethod = LbxFindPreferredPixmapCompMethod (client->server,
(int) stuff->format, (int) stuff->depth);
if (!pcompMethod)
status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
}
if (status == LBX_IMAGE_COMPRESS_NO_SUPPORT &&
client->req_len >= 64 + (sz_xPutImageReq >> 2))
return ProcStandardRequest(client);
if (client->swapped)
SwapXPutImage(stuff);
newreq = (xLbxPutImageReq *)space;
newreq->reqType = server->lbxReq;
newreq->lbxReqType = X_LbxPutImage;
out = reencode_putimage(stuff, newreq);
if (!out) {
SwapXPutImage(stuff);
return ProcStandardRequest(client);
}
GFX_SETUP_DRAWABLE_AND_GC(out);
reqlen = out - (char *)space;
len = client->req_len << 2;
data = (char *) xalloc(len);
if (!data || status == LBX_IMAGE_COMPRESS_NO_SUPPORT)
{
if (!data)
status = LBX_IMAGE_COMPRESS_BAD_MALLOC;
}
else if (stuff->format != ZPixmap ||
(stuff->depth == 1 && LBXZBitsPerPixel1(client) == 1))
{
int ppl, bpl, nbytes;
if (!bcompMethod->inited)
{
if (bcompMethod->compInit)
(*bcompMethod->compInit)();
bcompMethod->inited = 1;
}
ppl = stuff->width + stuff->leftPad;
if (LBXBitmapBitOrder(client) != LBXImageByteOrder(client))
ppl = ((ppl + LBXBitmapScanlineUnit(client) - 1) &
~LBXBitmapScanlineUnit(client));
bpl = (((ppl + LBXBitmapScanlinePad(client) - 1) /
LBXBitmapScanlinePad(client)) *
(LBXBitmapScanlinePad(client) >> 3));
nbytes = bpl * stuff->height;
if (stuff->format == XYPixmap)
nbytes *= stuff->depth;
status = (*bcompMethod->compFunc) (
(unsigned char *) &stuff[1],
(unsigned char *) data + reqlen,
len - reqlen,
nbytes,
ppl,
bpl,
LBXBitmapBitOrder(client) == LSBFirst,
&compBytes);
method = bcompMethod->methodOpCode;
#ifdef LBX_STATS
methodName = bcompMethod->methodName;
#endif
}
else
{
if (!pcompMethod->inited)
{
if (pcompMethod->compInit)
(*pcompMethod->compInit)();
pcompMethod->inited = 1;
}
status = (*pcompMethod->compFunc) (
(char *) &stuff[1],
(char *) data + reqlen,
len - reqlen,
(int) stuff->format,
(int) stuff->depth,
(int) stuff->height,
(int) (len - sz_xPutImageReq) / stuff->height,
&compBytes);
method = pcompMethod->methodOpCode;
#ifdef LBX_STATS
methodName = pcompMethod->methodName;
#endif
}
#ifdef LBX_STATS
fprintf(stderr, "PutImage (xid=%x, w=%d, h=%d, x=%d, y=%d): ",
stuff->drawable, stuff->width, stuff->height,
stuff->dstX, stuff->dstY);
#endif
if (status != LBX_IMAGE_COMPRESS_SUCCESS)
{
#ifdef LBX_STATS
fprintf(stderr, "image not compressed - ");
if (status == LBX_IMAGE_COMPRESS_NO_SUPPORT)
fprintf(stderr, "no support for compressing this image\n");
else if (status == LBX_IMAGE_COMPRESS_NOT_WORTH_IT)
fprintf(stderr, "not worth it\n");
else if (status == LBX_IMAGE_COMPRESS_BAD_MALLOC)
fprintf(stderr, "bad malloc\n");
#endif
if (!data || len >= 256 || reqlen > sz_xPutImageReq) {
if (data)
xfree(data);
if (client->swapped)
SwapXPutImage(stuff);
return ProcStandardRequest(client);
}
method = 0;
compBytes = len - sz_xPutImageReq;
memcpy(data + reqlen, (char *) &stuff[1], compBytes);
}
GFX_SET_DRAWABLE_AND_GC;
newreq->compressionMethod = method;
len = reqlen + compBytes;
newreq->bitPacked |= pad[len & 3];
len += pad[len & 3];
newreq->length = len >> 2;
memcpy(data, (char *)newreq, reqlen);
FinishLBXRequest(client, REQ_PASSTHROUGH);
#ifdef LBX_STATS
percentCompression = 100.0 * (1.0 -
((float) (compBytes + pad[compBytes & 3]) /
(float) ((client->req_len << 2) - sz_xPutImageReq)));
fprintf(stderr, "%f percent compression (%s)\n",
percentCompression, methodName);
#endif
if (newreq->length > (client->req_len >> 2) ||
DELTA_CACHEABLE(&server->outdeltas, len))
WriteReqToServer(client, len, data, TRUE);
else
WriteToServerUncompressed(client, len, data, TRUE);
xfree(data);
return Success;
}
int
ProcLBXGetImage(client)
ClientPtr client;
{
REQUEST(xGetImageReq);
ReplyStuffPtr nr;
nr = NewReply(client, client->server->lbxReq, X_LbxGetImage,
GetLbxImageReply);
if (!nr)
return ProcStandardRequest(client);
if (client->swapped) {
char n;
swapl(&stuff->drawable, n);
swaps(&stuff->x, n);
swaps(&stuff->y, n);
swaps(&stuff->width, n);
swaps(&stuff->height, n);
swapl(&stuff->planeMask, n);
}
nr->request_info.lbxgetimage.width = stuff->width;
nr->request_info.lbxgetimage.height = stuff->height;
nr->request_info.lbxgetimage.format = stuff->format;
#ifdef LBX_STATS
nr->request_info.lbxgetimage.drawable = stuff->drawable;
nr->request_info.lbxgetimage.x = stuff->x;
nr->request_info.lbxgetimage.y = stuff->y;
#endif
FinishLBXRequest(client, REQ_PASSTHROUGH);
SendGetImage(client, stuff->drawable, stuff->x, stuff->y,
stuff->width, stuff->height, stuff->planeMask,
stuff->format);
return Success;
}
static Bool
GetLbxImageReply(client, nr, data)
ClientPtr client;
ReplyStuffPtr nr;
char *data;
{
xLbxGetImageReply *rep;
xGetImageReply reply;
pointer imageData;
int freeIt = 1;
#ifdef LBX_STATS
char *methodName;
#endif
rep = (xLbxGetImageReply *) data;
if (client->swapped) {
char n;
swapl(&rep->xLength, n);
swapl(&rep->visual, n);
}
if ((imageData = (pointer) xalloc((rep->xLength << 2) + 1)) == NULL)
return FALSE;
if (rep->compressionMethod == LbxImageCompressNone)
{
xfree((char *) imageData);
imageData = (pointer) &rep[1];
freeIt = 0;
}
else if (nr->request_info.lbxgetimage.format != ZPixmap ||
(rep->depth == 1 && LBXZBitsPerPixel1(client) == 1))
{
LbxBitmapCompMethod *compMethod;
compMethod = LbxLookupBitmapCompMethod (client->server,
rep->compressionMethod);
if (!compMethod)
{
xfree((char *) imageData);
return FALSE;
}
else
{
int ppl, bpl, nbytes;
if (!compMethod->inited)
{
if (compMethod->compInit)
(*compMethod->compInit)();
compMethod->inited = 1;
}
ppl = nr->request_info.lbxgetimage.width;
if (LBXBitmapBitOrder(client) != LBXImageByteOrder(client))
ppl = ((ppl + LBXBitmapScanlineUnit(client) - 1) &
~LBXBitmapScanlineUnit(client));
bpl = (((ppl + LBXBitmapScanlinePad(client) - 1) /
LBXBitmapScanlinePad(client)) *
(LBXBitmapScanlinePad(client) >> 3));
nbytes = bpl * nr->request_info.lbxgetimage.height;
if (nr->request_info.lbxgetimage.format == XYPixmap)
nbytes *= rep->depth;
(*compMethod->decompFunc) (
(unsigned char *) &rep[1],
(unsigned char *) imageData,
nbytes,
ppl,
bpl,
LBXBitmapBitOrder(client) == LSBFirst);
#ifdef LBX_STATS
methodName = compMethod->methodName;
#endif
}
}
else
{
LbxPixmapCompMethod *compMethod;
compMethod = LbxLookupPixmapCompMethod (client->server,
rep->compressionMethod);
if (!compMethod)
{
xfree((char *) imageData);
return FALSE;
}
else
{
if (!compMethod->inited)
{
if (compMethod->compInit)
(*compMethod->compInit)();
compMethod->inited = 1;
}
(*compMethod->decompFunc) (
(char *) &rep[1],
(char *) imageData,
(int) nr->request_info.lbxgetimage.height,
(rep->xLength << 2) / nr->request_info.lbxgetimage.height);
#ifdef LBX_STATS
methodName = compMethod->methodName;
#endif
}
}
reply.type = X_Reply;
reply.depth = rep->depth;
reply.sequenceNumber = rep->sequenceNumber;
reply.length = rep->xLength;
reply.visual = rep->visual;
if (client->swapped)
SwapGetImageReply(&reply);
#ifdef LBX_STATS
fprintf (stderr, "GetImage (xid=%x, w=%d, h=%d, x=%d, y=%d): ",
nr->request_info.lbxgetimage.drawable,
nr->request_info.lbxgetimage.width,
nr->request_info.lbxgetimage.height,
nr->request_info.lbxgetimage.x,
nr->request_info.lbxgetimage.y);
if (rep->compressionMethod == LbxImageCompressNone) {
fprintf(stderr, "image not compressed\n");
} else {
float percentCompression = 100.0 * (1.0 -
((float) rep->lbxLength / (float) rep->xLength));
fprintf(stderr, "%f percent compression (%s)\n",
percentCompression, methodName);
}
#endif
WriteToClient(client, sizeof(xGetImageReply), &reply);
WriteToClient(client, rep->xLength << 2, imageData);
if (freeIt)
xfree((char *) imageData);
return TRUE;
}