1
/* $Xorg: lbxopts.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */
3
* Copyright 1994 Network Computing Devices, Inc.
5
* Permission to use, copy, modify, distribute, and sell this software and
6
* its documentation for any purpose is hereby granted without fee, provided
7
* that the above copyright notice appear in all copies and that both that
8
* copyright notice and this permission notice appear in supporting
9
* documentation, and that the name Network Computing Devices, Inc. not be
10
* used in advertising or publicity pertaining to distribution of this
11
* software without specific, written prior permission.
13
* THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
14
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
15
* LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16
* PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
17
* COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
18
* SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
19
* OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
20
* WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
21
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
/* $XFree86: xc/programs/Xserver/lbx/lbxopts.c,v 1.5 2001/01/17 22:37:00 dawes Exp $ */
26
#ifdef HAVE_DIX_CONFIG_H
27
#include <dix-config.h>
34
#include <X11/Xproto.h>
36
#include "colormapst.h"
37
#include "propertyst.h"
39
#include <X11/extensions/lbxstr.h>
40
#include <X11/extensions/lbximage.h>
41
#include <X11/extensions/lbxopts.h>
42
#include "lbxsrvopts.h"
44
#include <X11/extensions/lbxzlib.h>
47
static int LbxProxyDeltaOpt ( LbxNegOptsPtr pno, unsigned char *popt,
48
int optlen, unsigned char *preply );
49
static int LbxServerDeltaOpt ( LbxNegOptsPtr pno, unsigned char *popt,
50
int optlen, unsigned char *preply );
51
static int LbxDeltaOpt ( unsigned char *popt, int optlen,
52
unsigned char *preply, short *pn, short *pmaxlen );
53
static int LbxStreamCompOpt ( LbxNegOptsPtr pno, unsigned char *popt,
54
int optlen, unsigned char *preply );
55
static int ZlibParse ( LbxNegOptsPtr pno, unsigned char *popt, int optlen,
56
unsigned char *preply );
57
static int LbxMessageCompOpt ( LbxNegOptsPtr pno, unsigned char *popt,
58
int optlen, unsigned char *preply );
59
static int LbxUseTagsOpt ( LbxNegOptsPtr pno, unsigned char *popt,
60
int optlen, unsigned char *preply );
61
static int LbxBitmapCompOpt ( LbxNegOptsPtr pno, unsigned char *popt,
62
int optlen, unsigned char *preply );
63
static int LbxPixmapCompOpt ( LbxNegOptsPtr pno, unsigned char *popt,
64
int optlen, unsigned char *preply );
65
static int MergeDepths ( int *depths, LbxPixmapCompMethod *method );
66
static int LbxCmapAllOpt ( LbxNegOptsPtr pno, unsigned char *popt,
67
int optlen, unsigned char *preply );
70
* List of LBX options we recognize and are willing to negotiate
72
static struct _LbxOptionParser {
74
int (*parser)(LbxNegOptsPtr, unsigned char *,
75
int, unsigned char *);
77
{ LBX_OPT_DELTA_PROXY, LbxProxyDeltaOpt },
78
{ LBX_OPT_DELTA_SERVER, LbxServerDeltaOpt },
79
{ LBX_OPT_STREAM_COMP, LbxStreamCompOpt },
80
{ LBX_OPT_BITMAP_COMP, LbxBitmapCompOpt },
81
{ LBX_OPT_PIXMAP_COMP, LbxPixmapCompOpt },
82
{ LBX_OPT_MSG_COMP, LbxMessageCompOpt },
83
{ LBX_OPT_USE_TAGS, LbxUseTagsOpt },
84
{ LBX_OPT_CMAP_ALL, LbxCmapAllOpt }
87
#define LBX_N_OPTS (sizeof(LbxOptions) / sizeof(struct _LbxOptionParser))
93
LbxOptionInit(LbxNegOptsPtr pno)
95
bzero(pno, sizeof(LbxNegOptsRec));
96
pno->proxyDeltaN = pno->serverDeltaN = LBX_OPT_DELTA_NCACHE_DFLT;
97
pno->proxyDeltaMaxLen = pno->serverDeltaMaxLen = LBX_OPT_DELTA_MSGLEN_DFLT;
99
pno->numBitmapCompMethods = 0;
100
pno->bitmapCompMethods = NULL;
101
pno->numPixmapCompMethods = 0;
102
pno->pixmapCompMethods = NULL;
103
pno->pixmapCompDepths = NULL;
108
LbxOptionParse(LbxNegOptsPtr pno,
111
unsigned char *preply)
115
unsigned char *pout = preply;
117
for (i = 0; i < nopts; i++) {
123
LBX_OPT_DECODE_LEN(popt + 1, len, hdrlen);
124
if (len < ++hdrlen || len > optlen) {
126
fprintf(stderr, "bad option length, len = %d, hdrlen = %d, optlen = %d\n", len, hdrlen, optlen);
131
for (j = 0; j < LBX_N_OPTS; j++) {
132
if (popt[0] == LbxOptions[j].optcode) {
133
replylen = (*LbxOptions[j].parser)(pno,
136
pout + LBX_OPT_SMALLHDR_LEN);
139
else if (replylen > 0) {
141
* None of the current options require big headers,
142
* so this works for now.
145
*pout++ = LBX_OPT_SMALLHDR_LEN + replylen;
157
return (pout - preply);
161
LbxProxyDeltaOpt(LbxNegOptsPtr pno,
164
unsigned char *preply)
166
return LbxDeltaOpt(popt, optlen, preply,
167
&pno->proxyDeltaN, &pno->proxyDeltaMaxLen);
171
LbxServerDeltaOpt(LbxNegOptsPtr pno,
174
unsigned char *preply)
176
return LbxDeltaOpt(popt, optlen, preply,
177
&pno->serverDeltaN, &pno->serverDeltaMaxLen);
181
LbxDeltaOpt(unsigned char *popt,
183
unsigned char *preply,
191
* If there's more data than we expect, we just ignore it.
193
if (optlen < LBX_OPT_DELTA_REQLEN) {
195
fprintf(stderr, "bad delta option length = %d\n", optlen);
201
* Accept whatever value the proxy prefers, so skip the
202
* min/max offerings. Note that the max message len value is
203
* encoded as the number of 4-byte values.
209
if ((maxlen <<= 2) == 0)
211
else if (maxlen < 32) {
213
fprintf(stderr, "bad delta max msg length %d\n", maxlen);
219
* Put the response in the reply buffer
222
*preply++ = maxlen >> 2;
227
return LBX_OPT_DELTA_REPLYLEN;
231
static struct _LbxStreamCompParser {
234
int (*parser)(LbxNegOptsPtr, unsigned char *,
235
int, unsigned char *);
236
} LbxStreamComp[] = {
238
{ ZLIB_STRCOMP_OPT_LEN, ZLIB_STRCOMP_OPT, ZlibParse },
242
#define LBX_N_STRCOMP \
243
(sizeof(LbxStreamComp) / sizeof(struct _LbxStreamCompParser))
246
LbxStreamCompOpt(LbxNegOptsPtr pno,
249
unsigned char *preply)
255
for (i = 0; i < nopts; i++) {
262
for (j = 0; j < LBX_N_STRCOMP; j++) {
263
if (typelen == LbxStreamComp[j].typelen &&
264
!strncmp((char *) popt + 1, LbxStreamComp[j].type, typelen))
269
optlen -= 1 + typelen;
270
LBX_OPT_DECODE_LEN(popt, len, lensize);
272
if (j < LBX_N_STRCOMP) {
275
replylen = (*LbxStreamComp[j].parser)(pno,
281
else if (replylen >= 0) {
296
ZlibParse(LbxNegOptsPtr pno,
299
unsigned char *preply)
301
int level; /* compression level */
303
if (*popt++ != 1) /* length should be 1 */
307
if (level < 1 || level > 9)
310
pno->streamOpts.streamCompInit =
311
(LbxStreamCompHandle (*)(int, pointer))ZlibInit;
312
pno->streamOpts.streamCompArg = (pointer)(long)level;
313
pno->streamOpts.streamCompStuffInput = ZlibStuffInput;
314
pno->streamOpts.streamCompInputAvail = ZlibInputAvail;
315
pno->streamOpts.streamCompFlush = ZlibFlush;
316
pno->streamOpts.streamCompRead = ZlibRead;
317
pno->streamOpts.streamCompWriteV = ZlibWriteV;
318
pno->streamOpts.streamCompOn = ZlibCompressOn;
319
pno->streamOpts.streamCompOff = ZlibCompressOff;
320
pno->streamOpts.streamCompFreeHandle =
321
(void (*)(LbxStreamCompHandle))ZlibFree;
327
LbxMessageCompOpt(LbxNegOptsPtr pno,
330
unsigned char *preply)
335
fprintf(stderr, "bad message-comp option length specified %d\n", optlen);
340
pno->squish = *preply = *popt;
346
LbxUseTagsOpt(LbxNegOptsPtr pno,
349
unsigned char *preply)
354
fprintf(stderr, "bad use-tags option length specified %d\n", optlen);
359
pno->useTags = *preply = *popt;
365
* Option negotiation for image compression
369
LbxBitmapCompMethods [] = {
371
"XC-FaxG42D", /* compression method name */
373
2, /* method opcode */
374
NULL, /* init function */
375
LbxImageEncodeFaxG42D, /* encode function */
376
LbxImageDecodeFaxG42D /* decode function */
380
#define NUM_BITMAP_METHODS \
381
(sizeof (LbxBitmapCompMethods) / sizeof (LbxBitmapCompMethod))
386
* Currently, we don't support any pixmap compression algorithms
387
* because regular stream compression does much better than PackBits.
388
* If we want to plug in a better pixmap image compression algorithm,
392
#define NUM_PIXMAP_METHODS 0
393
LbxPixmapCompMethod LbxPixmapCompMethods [1]; /* dummy */
398
LbxPixmapCompMethods [] = {
400
"XC-PackBits", /* compression method name */
401
1 << ZPixmap, /* formats supported */
402
1, {8}, /* depths supported */
404
1, /* method opcode */
405
NULL, /* init function */
406
LbxImageEncodePackBits, /* encode function */
407
LbxImageDecodePackBits /* decode function */
411
#define NUM_PIXMAP_METHODS \
412
(sizeof (LbxPixmapCompMethods) / sizeof (LbxPixmapCompMethod))
417
LbxImageCompOpt (Bool pixmap,
421
unsigned char *preply)
424
unsigned char *preplyStart = preply;
425
int numMethods = *popt++;
426
unsigned char *myIndices, *hisIndices;
427
unsigned int *retFormats = NULL;
428
int **retDepths = NULL;
435
pno->numPixmapCompMethods = 0;
437
pno->numBitmapCompMethods = 0;
443
myIndices = (unsigned char *) xalloc (numMethods);
444
hisIndices = (unsigned char *) xalloc (numMethods);
446
if (!myIndices || !hisIndices)
457
retFormats = (unsigned *) xalloc (numMethods);
458
retDepths = (int **) xalloc (numMethods * sizeof (int *));
460
if (!retFormats || !retDepths)
473
* For each method in the list sent by the proxy, see if the server
474
* supports this method. If YES, update the following lists:
476
* myIndices[] is a list of indices into the server's
477
* LbxBit[Pix]mapCompMethods table.
479
* hisIndices[] is a list of indices into the list of
480
* method names sent by the proxy.
482
* retFormats[] indicates for each pixmap compression method,
483
* the pixmap formats supported.
485
* retDepths[] indicates for each pixmap compression method,
486
* the pixmap depths supported.
489
for (i = 0; i < numMethods; i++)
491
unsigned int formatMask = 0, newFormatMask = 0;
492
int depthCount, *depths = NULL, len;
498
methodName = (char *) popt;
503
formatMask = *popt++;
504
depthCount = *popt++;
505
depths = (int *) xalloc ((depthCount + 1) * sizeof (int));
507
depths[0] = depthCount;
508
for (j = 1; j <= depthCount; j++)
513
j < (pixmap ? NUM_PIXMAP_METHODS : NUM_BITMAP_METHODS); j++)
516
status = strncmp (methodName,
517
(pixmap ? LbxPixmapCompMethods[j].methodName :
518
LbxBitmapCompMethods[j].methodName),
521
if (status == 0 && pixmap)
524
formatMask & LbxPixmapCompMethods[j].formatMask;
526
depthCount = MergeDepths (depths, &LbxPixmapCompMethods[j]);
528
if (newFormatMask == 0 || depthCount == 0)
534
myIndices[replyCount] = j;
535
hisIndices[replyCount] = i;
539
retFormats[replyCount] = newFormatMask;
540
retDepths[replyCount] = depths;
553
*preply++ = replyCount;
556
* Sort the lists by LBX server preference (increasing myIndices[] vals)
559
for (i = 0; i <= replyCount - 2; i++)
560
for (j = replyCount - 1; j >= i; j--)
561
if (myIndices[j - 1] > myIndices[j])
563
char temp1 = myIndices[j - 1];
564
char temp2 = hisIndices[j - 1];
566
myIndices[j - 1] = myIndices[j];
567
myIndices[j] = temp1;
569
hisIndices[j - 1] = hisIndices[j];
570
hisIndices[j] = temp2;
574
unsigned temp3 = retFormats[j - 1];
575
int *temp4 = retDepths[j - 1];
577
retFormats[j - 1] = retFormats[j];
578
retFormats[j] = temp3;
580
retDepths[j - 1] = retDepths[j];
581
retDepths[j] = temp4;
586
* For each method supported, return to the proxy an index into
587
* the list sent by the proxy, the opcode to be used for the method,
588
* the pixmap formats supported, and the list of depths supported.
591
for (i = 0; i < replyCount; i++)
593
*preply++ = hisIndices[i];
598
*preply++ = LbxPixmapCompMethods[myIndices[i]].methodOpCode;
599
*preply++ = retFormats[i];
600
*preply++ = left = retDepths[i][0];
604
*preply++ = retDepths[i][j];
610
*preply++ = LbxBitmapCompMethods[myIndices[i]].methodOpCode;
616
pno->numPixmapCompMethods = replyCount;
617
pno->pixmapCompMethods = myIndices;
618
pno->pixmapCompDepths = retDepths;
622
pno->numBitmapCompMethods = replyCount;
623
pno->bitmapCompMethods = myIndices;
635
return (preply - preplyStart);
641
LbxBitmapCompOpt (LbxNegOptsPtr pno,
644
unsigned char *preply)
647
return (LbxImageCompOpt (0 /* bitmap */, pno, popt, optlen, preply));
652
LbxPixmapCompOpt (LbxNegOptsPtr pno,
655
unsigned char *preply)
658
return (LbxImageCompOpt (1 /* Pixmap */, pno, popt, optlen, preply));
662
LbxBitmapCompMethod *
663
LbxSrvrLookupBitmapCompMethod (LbxProxyPtr proxy,
669
for (i = 0; i < proxy->numBitmapCompMethods; i++)
671
LbxBitmapCompMethod *method;
673
method = &LbxBitmapCompMethods[proxy->bitmapCompMethods[i]];
675
if (method->methodOpCode == methodOpCode)
683
LbxPixmapCompMethod *
684
LbxSrvrLookupPixmapCompMethod (LbxProxyPtr proxy,
690
for (i = 0; i < proxy->numPixmapCompMethods; i++)
692
LbxPixmapCompMethod *method;
694
method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]];
696
if (method->methodOpCode == methodOpCode)
704
LbxBitmapCompMethod *
705
LbxSrvrFindPreferredBitmapCompMethod (LbxProxyPtr proxy)
708
if (proxy->numBitmapCompMethods == 0)
711
return (&LbxBitmapCompMethods[proxy->bitmapCompMethods[0]]);
716
LbxPixmapCompMethod *
717
LbxSrvrFindPreferredPixmapCompMethod (LbxProxyPtr proxy,
722
if (proxy->numPixmapCompMethods == 0)
726
LbxPixmapCompMethod *method;
729
for (i = 0; i < proxy->numPixmapCompMethods; i++)
731
method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]];
733
if ((method->formatMask & (1 << format)))
735
int n = proxy->pixmapCompDepths[i][0];
739
if (depth == proxy->pixmapCompDepths[i][j])
753
MergeDepths (int *depths,
754
LbxPixmapCompMethod *method)
758
int temp[LBX_MAX_DEPTHS + 1];
762
for (i = 1; i <= depths[0]; i++)
764
for (j = 0; j < method->depthCount; j++)
765
if (method->depths[j] == depths[i])
768
temp[++count] = depths[i];
773
memcpy (depths, temp, (count + 1) * sizeof (int));
779
#define LbxCmapAllMethod "XC-CMAP"
782
LbxCmapAllOpt (LbxNegOptsPtr pno,
785
unsigned char *preply)
788
int numMethods = *popt++;
791
for (i = 0; i < numMethods; i++)
797
methodName = (char *) popt;
799
if (!strncmp(methodName, LbxCmapAllMethod, len))
803
i = 0; /* assume first one is proxy's favorite */