1/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED */
2/*
3 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
4 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice including the dates of first publication and
14 * either this permission notice or a reference to
15 * http://oss.sgi.com/projects/FreeB/
16 * shall be included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Except as contained in this notice, the name of Silicon Graphics, Inc.
27 * shall not be used in advertising or otherwise to promote the sale, use or
28 * other dealings in this Software without prior written authorization from
29 * Silicon Graphics, Inc.
30 */
31
32#ifdef HAVE_DMX_CONFIG_H
33#include <dmx-config.h>
34#endif
35
36#include "dmx.h"
37#include "dmxwindow.h"
38#include "dmxpixmap.h"
39#include "dmxfont.h"
40#include "dmxcb.h"
41
42#include "glxserver.h"
43#include "glxext.h"
44#include "g_disptab.h"
45/* #include "g_disptab_EXT.h" */
46#include "unpack.h"
47#include "glxutil.h"
48
49#include "GL/glxproto.h"
50
51#ifdef PANORAMIX
52#include "panoramiXsrv.h"
53#endif
54
55/*
56 * GetReqSingle - this is the equivalent of GetReq macro
57 *    from Xlibint.h but it does not set the reqType field (the opcode).
58 *    this is because the GL single opcodes has different naming convension
59 *    the other X opcodes (ie. X_GLsop_GetFloatv).
60 */
61#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
62#define GetReqSingle(name, req) \
63        WORD64ALIGN\
64	if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\
65		_XFlush(dpy);\
66	req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
67	req->length = (SIZEOF(x##name##Req))>>2;\
68	dpy->bufptr += SIZEOF(x##name##Req);\
69	dpy->request++
70
71#else  /* non-ANSI C uses empty comment instead of "##" for token concatenation */
72#define GetReqSingle(name, req) \
73        WORD64ALIGN\
74	if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\
75		_XFlush(dpy);\
76	req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
77	req->length = (SIZEOF(x/**/name/**/Req))>>2;\
78	dpy->bufptr += SIZEOF(x/**/name/**/Req);\
79	dpy->request++
80#endif
81
82#define X_GLXSingle 0   /* needed by GetReqExtra */
83
84extern Display *GetBackEndDisplay( __GLXclientState *cl, int s );
85extern int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s);
86
87static int swap_vec_element_size = 0;
88
89static void SendSwappedReply( ClientPtr client,
90                              xGLXSingleReply *reply,
91			      char *buf,
92			      int   buf_size )
93{
94   __GLX_DECLARE_SWAP_VARIABLES;
95   __GLX_SWAP_SHORT(&reply->sequenceNumber);
96   __GLX_SWAP_INT(&reply->length);
97   __GLX_SWAP_INT(&reply->retval);
98   __GLX_SWAP_INT(&reply->size);
99
100   if ( (buf_size == 0) && (swap_vec_element_size > 0) ) {
101      /*
102       * the reply has single component - need to swap pad3
103       */
104      if (swap_vec_element_size == 2) {
105	 __GLX_SWAP_SHORT(&reply->pad3);
106      }
107      else if (swap_vec_element_size == 4) {
108	 __GLX_SWAP_INT(&reply->pad3);
109	 __GLX_SWAP_INT(&reply->pad4);    /* some requests use also pad4
110                                          * i.e GetConvolutionFilter
111					  */
112      }
113      else if (swap_vec_element_size == 8) {
114	 __GLX_SWAP_DOUBLE(&reply->pad3);
115      }
116   }
117   else if ( (buf_size > 0) && (swap_vec_element_size > 0) ) {
118      /*
119       * the reply has vector of elements which needs to be swapped
120       */
121      int vsize = buf_size / swap_vec_element_size;
122      char *p = buf;
123      int i;
124
125      for (i=0; i<vsize; i++) {
126	 if (swap_vec_element_size == 2) {
127	    __GLX_SWAP_SHORT(p);
128	 }
129	 else if (swap_vec_element_size == 4) {
130	    __GLX_SWAP_INT(p);
131	 }
132	 else if (swap_vec_element_size == 8) {
133	    __GLX_SWAP_DOUBLE(p);
134	 }
135
136	 p += swap_vec_element_size;
137      }
138
139      /*
140       * swap pad words as well - for case that some single reply uses
141       * them as well
142       */
143      __GLX_SWAP_INT(&reply->pad3);
144      __GLX_SWAP_INT(&reply->pad4);
145      __GLX_SWAP_INT(&reply->pad5);
146      __GLX_SWAP_INT(&reply->pad6);
147
148   }
149
150    WriteToClient(client, sizeof(xGLXSingleReply),(char *)reply);
151    if (buf_size > 0)
152       WriteToClient(client, buf_size, (char *)buf);
153
154}
155
156int __glXForwardSingleReq( __GLXclientState *cl, GLbyte *pc )
157{
158   xGLXSingleReq *req = (xGLXSingleReq *)pc;
159   xGLXSingleReq *be_req;
160    __GLXcontext *glxc;
161   int from_screen = 0;
162   int to_screen = 0;
163   int buf_size;
164   int s;
165
166    glxc = __glXLookupContextByTag(cl, req->contextTag);
167    if (!glxc) {
168	return 0;
169    }
170    from_screen = to_screen = glxc->pScreen->myNum;
171
172#ifdef PANORAMIX
173    if (!noPanoramiXExtension) {
174       from_screen = 0;
175       to_screen = screenInfo.numScreens - 1;
176    }
177#endif
178
179    pc += sz_xGLXSingleReq;
180    buf_size = (req->length << 2) - sz_xGLXSingleReq;
181
182    /*
183     * just forward the request to back-end server(s)
184     */
185    for (s=from_screen; s<=to_screen; s++) {
186       DMXScreenInfo *dmxScreen = &dmxScreens[s];
187       Display *dpy = GetBackEndDisplay(cl,s);
188
189       LockDisplay(dpy);
190       GetReqSingle(GLXSingle,be_req);
191       be_req->reqType = dmxScreen->glxMajorOpcode;
192       be_req->glxCode = req->glxCode;
193       be_req->length = req->length;
194       be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s);
195       if (buf_size > 0)
196	  _XSend(dpy, (const char *)pc, buf_size);
197       UnlockDisplay(dpy);
198       SyncHandle();
199
200       if (req->glxCode == X_GLsop_Flush) {
201	  XFlush(dpy);
202       }
203
204    }
205
206    return Success;
207}
208
209int __glXForwardPipe0WithReply( __GLXclientState *cl, GLbyte *pc )
210{
211   ClientPtr client = cl->client;
212   xGLXSingleReq *req = (xGLXSingleReq *)pc;
213   xGLXSingleReq *be_req;
214   xGLXSingleReply reply;
215   xGLXSingleReply be_reply;
216    __GLXcontext *glxc;
217   int buf_size;
218   char *be_buf = NULL;
219   int   be_buf_size;
220   DMXScreenInfo *dmxScreen;
221   Display *dpy;
222
223    glxc = __glXLookupContextByTag(cl, req->contextTag);
224    if (!glxc) {
225	return __glXBadContext;
226    }
227
228    pc += sz_xGLXSingleReq;
229    buf_size = (req->length << 2) - sz_xGLXSingleReq;
230
231    dmxScreen = &dmxScreens[glxc->pScreen->myNum];
232    dpy = GetBackEndDisplay(cl, glxc->pScreen->myNum);
233
234    /*
235     * send the request to the first back-end server
236     */
237    LockDisplay(dpy);
238    GetReqSingle(GLXSingle,be_req);
239    be_req->reqType = dmxScreen->glxMajorOpcode;
240    be_req->glxCode = req->glxCode;
241    be_req->length = req->length;
242    be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,glxc->pScreen->myNum);
243    if (buf_size > 0)
244       _XSend(dpy, (const char *)pc, buf_size);
245
246    /*
247     * get the reply from the back-end server
248     */
249    _XReply(dpy, (xReply*) &be_reply, 0, False);
250    be_buf_size = be_reply.length << 2;
251    if (be_buf_size > 0) {
252       be_buf = (char *)malloc( be_buf_size );
253       if (be_buf) {
254	  _XRead(dpy, be_buf, be_buf_size);
255       }
256       else {
257	  /* Throw data on the floor */
258	  _XEatData(dpy, be_buf_size);
259	  return BadAlloc;
260       }
261    }
262
263    UnlockDisplay(dpy);
264    SyncHandle();
265
266    /*
267     * send the reply to the client
268     */
269    reply.type = X_Reply;
270    reply.sequenceNumber = client->sequence;
271    reply.length = be_reply.length;
272    reply.retval = be_reply.retval;
273    reply.size = be_reply.size;
274    reply.pad3 = be_reply.pad3;
275    reply.pad4 = be_reply.pad4;
276
277    if (client->swapped) {
278       SendSwappedReply( client, &reply, be_buf, be_buf_size );
279    }
280    else {
281       WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply);
282       if (be_buf_size > 0)
283	  WriteToClient(client, be_buf_size, (char *)be_buf);
284    }
285
286    if (be_buf_size > 0) free(be_buf);
287
288    return Success;
289}
290
291int __glXForwardAllWithReply( __GLXclientState *cl, GLbyte *pc )
292{
293   ClientPtr client = cl->client;
294   xGLXSingleReq *req = (xGLXSingleReq *)pc;
295   xGLXSingleReq *be_req;
296   xGLXSingleReply reply;
297   xGLXSingleReply be_reply;
298    __GLXcontext *glxc;
299   int buf_size;
300   char *be_buf = NULL;
301   int   be_buf_size = 0;
302   int from_screen = 0;
303   int to_screen = 0;
304   int s;
305
306   DMXScreenInfo *dmxScreen;
307   Display *dpy;
308
309    glxc = __glXLookupContextByTag(cl, req->contextTag);
310    if (!glxc) {
311	return 0;
312    }
313    from_screen = to_screen = glxc->pScreen->myNum;
314
315#ifdef PANORAMIX
316    if (!noPanoramiXExtension) {
317       from_screen = 0;
318       to_screen = screenInfo.numScreens - 1;
319    }
320#endif
321
322    pc += sz_xGLXSingleReq;
323    buf_size = (req->length << 2) - sz_xGLXSingleReq;
324
325    /*
326     * send the request to the first back-end server(s)
327     */
328    for (s=to_screen; s>=from_screen; s--) {
329       dmxScreen = &dmxScreens[s];
330       dpy = GetBackEndDisplay(cl,s);
331
332       LockDisplay(dpy);
333       GetReqSingle(GLXSingle,be_req);
334       be_req->reqType = dmxScreen->glxMajorOpcode;
335       be_req->glxCode = req->glxCode;
336       be_req->length = req->length;
337       be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s);
338       if (buf_size > 0)
339	  _XSend(dpy, (const char *)pc, buf_size);
340
341       /*
342	* get the reply from the back-end server
343	*/
344       _XReply(dpy, (xReply*) &be_reply, 0, False);
345       be_buf_size = be_reply.length << 2;
346       if (be_buf_size > 0) {
347	  be_buf = (char *)malloc( be_buf_size );
348	  if (be_buf) {
349	     _XRead(dpy, be_buf, be_buf_size);
350	  }
351	  else {
352	     /* Throw data on the floor */
353	     _XEatData(dpy, be_buf_size);
354	     return BadAlloc;
355	  }
356       }
357
358       UnlockDisplay(dpy);
359       SyncHandle();
360
361       if (s > from_screen && be_buf_size > 0) {
362	  free(be_buf);
363       }
364    }
365
366    /*
367     * send the reply to the client
368     */
369    reply.type = X_Reply;
370    reply.sequenceNumber = client->sequence;
371    reply.length = be_reply.length;
372    reply.retval = be_reply.retval;
373    reply.size = be_reply.size;
374    reply.pad3 = be_reply.pad3;
375    reply.pad4 = be_reply.pad4;
376
377    if (client->swapped) {
378       SendSwappedReply( client, &reply, be_buf, be_buf_size );
379    }
380    else {
381       WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply);
382       if (be_buf_size > 0)
383	  WriteToClient(client, be_buf_size, (char *)be_buf);
384    }
385
386    if (be_buf_size > 0) free(be_buf);
387
388    return Success;
389}
390
391int __glXForwardSingleReqSwap( __GLXclientState *cl, GLbyte *pc )
392{
393   xGLXSingleReq *req = (xGLXSingleReq *)pc;
394   __GLX_DECLARE_SWAP_VARIABLES;
395   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
396
397   __GLX_SWAP_SHORT(&req->length);
398   __GLX_SWAP_INT(&req->contextTag);
399
400   swap_vec_element_size = 0;
401
402   /*
403    * swap extra data in request - assuming all data
404    * (if available) are arrays of 4 bytes components !
405    */
406   if (req->length > sz_xGLXSingleReq/4) {
407      int *data = (int *)(req+1);
408      int count = req->length - sz_xGLXSingleReq/4;
409      __GLX_SWAP_INT_ARRAY(data, count );
410   }
411
412   return( __glXForwardSingleReq( cl, pc ) );
413}
414
415int __glXForwardPipe0WithReplySwap( __GLXclientState *cl, GLbyte *pc )
416{
417   xGLXSingleReq *req = (xGLXSingleReq *)pc;
418   __GLX_DECLARE_SWAP_VARIABLES;
419   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
420
421   __GLX_SWAP_SHORT(&req->length);
422   __GLX_SWAP_INT(&req->contextTag);
423
424   swap_vec_element_size = 0;
425
426   /*
427    * swap extra data in request - assuming all data
428    * (if available) are arrays of 4 bytes components !
429    */
430   if (req->length > sz_xGLXSingleReq/4) {
431      int *data = (int *)(req+1);
432      int count = req->length - sz_xGLXSingleReq/4;
433      __GLX_SWAP_INT_ARRAY(data, count );
434   }
435
436   return( __glXForwardPipe0WithReply( cl, pc ) );
437}
438
439int __glXForwardPipe0WithReplySwapsv( __GLXclientState *cl, GLbyte *pc )
440{
441   xGLXSingleReq *req = (xGLXSingleReq *)pc;
442   __GLX_DECLARE_SWAP_VARIABLES;
443   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
444
445   __GLX_SWAP_SHORT(&req->length);
446   __GLX_SWAP_INT(&req->contextTag);
447
448   swap_vec_element_size = 2;
449
450   /*
451    * swap extra data in request - assuming all data
452    * (if available) are arrays of 4 bytes components !
453    */
454   if (req->length > sz_xGLXSingleReq/4) {
455      int *data = (int *)(req+1);
456      int count = req->length - sz_xGLXSingleReq/4;
457      __GLX_SWAP_INT_ARRAY(data, count );
458   }
459
460
461   return( __glXForwardPipe0WithReply( cl, pc ) );
462}
463
464int __glXForwardPipe0WithReplySwapiv( __GLXclientState *cl, GLbyte *pc )
465{
466   xGLXSingleReq *req = (xGLXSingleReq *)pc;
467   __GLX_DECLARE_SWAP_VARIABLES;
468   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
469
470   __GLX_SWAP_SHORT(&req->length);
471   __GLX_SWAP_INT(&req->contextTag);
472
473   swap_vec_element_size = 4;
474
475   /*
476    * swap extra data in request - assuming all data
477    * (if available) are arrays of 4 bytes components !
478    */
479   if (req->length > sz_xGLXSingleReq/4) {
480      int *data = (int *)(req+1);
481      int count = req->length - sz_xGLXSingleReq/4;
482      __GLX_SWAP_INT_ARRAY(data, count );
483   }
484
485
486   return( __glXForwardPipe0WithReply( cl, pc ) );
487}
488
489int __glXForwardPipe0WithReplySwapdv( __GLXclientState *cl, GLbyte *pc )
490{
491   xGLXSingleReq *req = (xGLXSingleReq *)pc;
492   __GLX_DECLARE_SWAP_VARIABLES;
493   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
494
495   __GLX_SWAP_SHORT(&req->length);
496   __GLX_SWAP_INT(&req->contextTag);
497
498   swap_vec_element_size = 8;
499
500   /*
501    * swap extra data in request - assuming all data
502    * (if available) are arrays of 4 bytes components !
503    */
504   if (req->length > sz_xGLXSingleReq/4) {
505      int *data = (int *)(req+1);
506      int count = req->length - sz_xGLXSingleReq/4;
507      __GLX_SWAP_INT_ARRAY(data, count );
508   }
509
510
511   return( __glXForwardPipe0WithReply( cl, pc ) );
512}
513
514int __glXForwardAllWithReplySwap( __GLXclientState *cl, GLbyte *pc )
515{
516   xGLXSingleReq *req = (xGLXSingleReq *)pc;
517   __GLX_DECLARE_SWAP_VARIABLES;
518   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
519
520   __GLX_SWAP_SHORT(&req->length);
521   __GLX_SWAP_INT(&req->contextTag);
522
523   swap_vec_element_size = 0;
524
525   /*
526    * swap extra data in request - assuming all data
527    * (if available) are arrays of 4 bytes components !
528    */
529   if (req->length > sz_xGLXSingleReq/4) {
530      int *data = (int *)(req+1);
531      int count = req->length - sz_xGLXSingleReq/4;
532      __GLX_SWAP_INT_ARRAY(data, count );
533   }
534
535
536   return( __glXForwardAllWithReply( cl, pc ) );
537}
538
539int __glXForwardAllWithReplySwapsv( __GLXclientState *cl, GLbyte *pc )
540{
541   xGLXSingleReq *req = (xGLXSingleReq *)pc;
542   __GLX_DECLARE_SWAP_VARIABLES;
543   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
544
545   __GLX_SWAP_SHORT(&req->length);
546   __GLX_SWAP_INT(&req->contextTag);
547
548   swap_vec_element_size = 2;
549
550   /*
551    * swap extra data in request - assuming all data
552    * (if available) are arrays of 4 bytes components !
553    */
554   if (req->length > sz_xGLXSingleReq/4) {
555      int *data = (int *)(req+1);
556      int count = req->length - sz_xGLXSingleReq/4;
557      __GLX_SWAP_INT_ARRAY(data, count );
558   }
559
560
561   return( __glXForwardAllWithReply( cl, pc ) );
562}
563
564int __glXForwardAllWithReplySwapiv( __GLXclientState *cl, GLbyte *pc )
565{
566   xGLXSingleReq *req = (xGLXSingleReq *)pc;
567   __GLX_DECLARE_SWAP_VARIABLES;
568   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
569
570   __GLX_SWAP_SHORT(&req->length);
571   __GLX_SWAP_INT(&req->contextTag);
572
573   swap_vec_element_size = 4;
574
575   /*
576    * swap extra data in request - assuming all data
577    * (if available) are arrays of 4 bytes components !
578    */
579   if (req->length > sz_xGLXSingleReq/4) {
580      int *data = (int *)(req+1);
581      int count = req->length - sz_xGLXSingleReq/4;
582      __GLX_SWAP_INT_ARRAY(data, count );
583   }
584
585
586   return( __glXForwardAllWithReply( cl, pc ) );
587}
588
589int __glXForwardAllWithReplySwapdv( __GLXclientState *cl, GLbyte *pc )
590{
591   xGLXSingleReq *req = (xGLXSingleReq *)pc;
592   __GLX_DECLARE_SWAP_VARIABLES;
593   __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
594
595   __GLX_SWAP_SHORT(&req->length);
596   __GLX_SWAP_INT(&req->contextTag);
597
598   swap_vec_element_size = 8;
599
600   /*
601    * swap extra data in request - assuming all data
602    * (if available) are arrays of 4 bytes components !
603    */
604   if (req->length > sz_xGLXSingleReq/4) {
605      int *data = (int *)(req+1);
606      int count = req->length - sz_xGLXSingleReq/4;
607      __GLX_SWAP_INT_ARRAY(data, count );
608   }
609
610
611   return( __glXForwardAllWithReply( cl, pc ) );
612}
613
614static GLint __glReadPixels_size(GLenum format, GLenum type, GLint w, GLint h,
615                          int *elementbits_return, int *rowbytes_return )
616{
617    GLint elements, esize;
618    GLint rowsize, padding;
619
620    if (w < 0 || h < 0) {
621	return -1;
622    }
623    switch (format) {
624      case GL_COLOR_INDEX:
625      case GL_STENCIL_INDEX:
626      case GL_DEPTH_COMPONENT:
627	elements = 1;
628	break;
629      case GL_RED:
630      case GL_GREEN:
631      case GL_BLUE:
632      case GL_ALPHA:
633      case GL_LUMINANCE:
634	elements = 1;
635	break;
636      case GL_LUMINANCE_ALPHA:
637	elements = 2;
638	break;
639      case GL_RGB:
640      case GL_BGR:
641	elements = 3;
642	break;
643      case GL_RGBA:
644      case GL_BGRA:
645      case GL_ABGR_EXT:
646	elements = 4;
647	break;
648      default:
649	return -1;
650    }
651    /*
652    ** According to the GLX protocol, each row must be padded to a multiple of
653    ** 4 bytes.  4 bytes also happens to be the default alignment in the pixel
654    ** store modes of the GL.
655    */
656    switch (type) {
657      case GL_BITMAP:
658	if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) {
659	   rowsize = ((w * elements)+7)/8;
660	   padding = rowsize % 4;
661	   if (padding) {
662	      rowsize += 4 - padding;
663	   }
664	   if (elementbits_return) *elementbits_return = elements;
665	   if (rowbytes_return) *rowbytes_return = rowsize;
666	   return rowsize * h;
667	} else {
668	   return -1;
669	}
670      case GL_BYTE:
671      case GL_UNSIGNED_BYTE:
672	esize = 1;
673	break;
674      case GL_UNSIGNED_BYTE_3_3_2:
675      case GL_UNSIGNED_BYTE_2_3_3_REV:
676	esize = 1;
677	elements = 1;
678	break;
679      case GL_SHORT:
680      case GL_UNSIGNED_SHORT:
681	esize = 2;
682	break;
683      case GL_UNSIGNED_SHORT_5_6_5:
684      case GL_UNSIGNED_SHORT_5_6_5_REV:
685      case GL_UNSIGNED_SHORT_4_4_4_4:
686      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
687      case GL_UNSIGNED_SHORT_5_5_5_1:
688      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
689	esize = 2;
690	elements = 1;
691	break;
692      case GL_INT:
693      case GL_UNSIGNED_INT:
694      case GL_FLOAT:
695	esize = 4;
696	break;
697      case GL_UNSIGNED_INT_8_8_8_8:
698      case GL_UNSIGNED_INT_8_8_8_8_REV:
699      case GL_UNSIGNED_INT_10_10_10_2:
700      case GL_UNSIGNED_INT_2_10_10_10_REV:
701	esize = 4;
702	elements = 1;
703	break;
704      default:
705	return -1;
706    }
707    rowsize = w * elements * esize;
708    padding = rowsize % 4;
709    if (padding) {
710	rowsize += 4 - padding;
711    }
712
713    if (elementbits_return) *elementbits_return = esize*elements*8;
714    if (rowbytes_return) *rowbytes_return = rowsize;
715
716    return rowsize * h;
717}
718
719static int intersectRect( int x1, int x2, int y1, int y2,
720                    int X1, int X2, int Y1, int Y2,
721		    int *ix1, int *ix2, int *iy1, int *iy2 )
722{
723   int right = (x2 < X2 ? x2 : X2);
724   int bottom = (y2 < Y2 ? y2 : Y2);
725   int left = (x1 > X1 ? x1 : X1);
726   int top = (y1 > Y1 ? y1 : Y1);
727   int width = right - left + 1;
728   int height = bottom - top + 1;
729
730   if ( (width <= 0) || (height <= 0) ) {
731      *ix1 = *ix2 = *iy1 = *iy2 = 0;
732      return 0;
733   }
734   else {
735      *ix1 = left;
736      *ix2 = right;
737      *iy1 = top;
738      *iy2 = bottom;
739      return width * height;
740   }
741
742}
743
744int __glXDisp_ReadPixels(__GLXclientState *cl, GLbyte *pc)
745{
746    xGLXSingleReq *req = (xGLXSingleReq *)pc;
747    xGLXSingleReq *be_req;
748    xGLXReadPixelsReply reply;
749    xGLXReadPixelsReply be_reply;
750    GLbyte *be_pc;
751    GLint x,y;
752    GLsizei width, height;
753    GLenum format, type;
754    GLboolean swapBytes, lsbFirst;
755    ClientPtr client = cl->client;
756    DrawablePtr pDraw;
757    __GLXcontext *glxc;
758    int from_screen = 0;
759    int to_screen = 0;
760    char *buf;
761    int buf_size;
762    int s;
763    int win_x1, win_x2;
764    int win_y1, win_y2;
765    int ebits, rowsize;
766    __GLX_DECLARE_SWAP_VARIABLES;
767
768    if (client->swapped) {
769       __GLX_SWAP_INT(&req->contextTag);
770    }
771
772    glxc = __glXLookupContextByTag(cl, req->contextTag);
773    if (!glxc) {
774	return 0;
775    }
776    from_screen = to_screen = glxc->pScreen->myNum;
777
778#ifdef PANORAMIX
779    if (!noPanoramiXExtension) {
780       from_screen = 0;
781       to_screen = screenInfo.numScreens - 1;
782    }
783#endif
784
785    pc += sz_xGLXSingleReq;
786    x = *(GLint *)(pc + 0);
787    y = *(GLint *)(pc + 4);
788    width = *(GLsizei *)(pc + 8);
789    height = *(GLsizei *)(pc + 12);
790    format = *(GLenum *)(pc + 16);
791    type = *(GLenum *)(pc + 20);
792    swapBytes = *(GLboolean *)(pc + 24);
793    lsbFirst = *(GLboolean *)(pc + 25);
794
795    if (client->swapped) {
796       __GLX_SWAP_INT(&x);
797       __GLX_SWAP_INT(&y);
798       __GLX_SWAP_INT(&width);
799       __GLX_SWAP_INT(&height);
800       __GLX_SWAP_INT(&format);
801       __GLX_SWAP_INT(&type);
802       swapBytes = !swapBytes;
803    }
804
805    buf_size = __glReadPixels_size(format,type,width,height, &ebits, &rowsize);
806    if (buf_size > 0) {
807       buf = (char *) malloc( buf_size );
808       if ( !buf ) {
809	  return BadAlloc;
810       }
811    }
812    else {
813       buf_size = 0;
814       buf = NULL;
815    }
816
817    if (buf_size > 0) {
818       /*
819	* Get the current drawable this context is bound to
820	*/
821       pDraw = __glXLookupDrawableByTag( cl, req->contextTag );
822       win_x1 = pDraw->x + x;
823       win_x2 = win_x1 + width - 1;
824       win_y1 = (dmxGlobalHeight - pDraw->y - pDraw->height) + y;
825       win_y2 = win_y1 + height - 1;
826       if (pDraw->type != DRAWABLE_WINDOW) {
827	  from_screen = to_screen = 0;
828       }
829
830       for (s=from_screen; s<=to_screen; s++) {
831	  DMXScreenInfo *dmxScreen = &dmxScreens[s];
832	  Display *dpy = GetBackEndDisplay(cl,s);
833	  int scr_x1 = dmxScreen->rootXOrigin;
834	  int scr_x2 = dmxScreen->rootXOrigin + dmxScreen->scrnWidth - 1;
835	  int scr_y1 = dmxScreen->rootYOrigin;
836	  int scr_y2 = dmxScreen->rootYOrigin + dmxScreen->scrnHeight - 1;
837	  int wx1, wx2, wy1, wy2;
838	  int sx, sy, sw, sh;
839	  int npixels;
840
841	  /*
842	   * find the window portion that is on the current screen
843	   */
844	  if (pDraw->type == DRAWABLE_WINDOW) {
845	     npixels = intersectRect( scr_x1, scr_x2, scr_y1, scr_y2,
846		   win_x1, win_x2, win_y1, win_y2,
847		   &wx1, &wx2, &wy1, &wy2 );
848	  }
849	  else {
850	     wx1 = win_x1;
851	     wx2 = win_x2;
852	     wy1 = win_y1;
853	     wy2 = win_y2;
854	     npixels = (wx2-wx1+1) * (wy2-wy1+1);
855	  }
856
857   	  if (npixels > 0) {
858
859   	     /* send the request to the back-end server */
860   	     LockDisplay(dpy);
861   	     GetReqExtra(GLXSingle,__GLX_PAD(26),be_req);
862   	     be_req->reqType = dmxScreen->glxMajorOpcode;
863   	     be_req->glxCode = X_GLsop_ReadPixels;
864   	     be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s);
865   	     be_pc = ((GLbyte *)(be_req) + sz_xGLXSingleReq);
866
867   	     sx = wx1 - pDraw->x;
868   	     sy = wy1 - (dmxGlobalHeight - pDraw->y - pDraw->height);
869   	     sw = (wx2-wx1+1);
870   	     sh = (wy2-wy1+1);
871
872	     *(GLint *)(be_pc + 0) = sx;    /* x */
873	     *(GLint *)(be_pc + 4) = sy;    /* y */
874	     *(GLsizei *)(be_pc + 8) = sw;    /* width */
875	     *(GLsizei *)(be_pc + 12) = sh;   /* height */
876	     *(GLenum *)(be_pc + 16) = format;
877	     *(GLenum *)(be_pc + 20) = type;
878	     *(GLboolean *)(be_pc + 24) = swapBytes;
879	     *(GLboolean *)(be_pc + 25) = lsbFirst;
880
881	     _XReply(dpy, (xReply*) &be_reply, 0, False);
882
883	     if (be_reply.length > 0) {
884		char *be_buf;
885		int be_buf_size = be_reply.length << 2;
886
887		be_buf = (char *) malloc( be_buf_size );
888		if (be_buf) {
889		   _XRead(dpy, be_buf, be_buf_size);
890
891		   /* copy pixels data to the right location of the */
892		   /* reply buffer */
893		   if ( type != GL_BITMAP ) {
894		      int pbytes = ebits / 8;
895		      char *dst = buf + (sy-y)*rowsize + (sx-x)*pbytes;
896		      char *src = be_buf;
897		      int pad = (pbytes * sw) % 4;
898		      int r;
899
900		      for (r=0; r<sh; r++) {
901			 memcpy( dst, src, pbytes*sw );
902			 dst += rowsize;
903			 src += (pbytes*sw + (pad ? 4-pad : 0) );
904		      }
905		   }
906		   else {
907		      /* this is a GL_BITMAP pixel type, should copy bits */
908		      int r;
909		      int src_rowsize = bits_to_bytes(sw * ebits);
910		      int src_pad = src_rowsize % 4;
911                      if ( src_pad ) {
912			 src_rowsize += (4 - src_pad);
913		      }
914
915		      for (r=0; r<sh; r++) {
916			 unsigned char dst_mask = 0x80 >> (sx % 8);
917			 unsigned char src_mask = 0x80;
918			 char *dst = buf + (sy-y+r)*rowsize + (sx-x)/8;
919			 char *src = be_buf + r*src_rowsize;
920			 int b;
921
922			 for (b=0; b<sw*ebits; b++) {
923			    if ( *src & src_mask ) {
924			       *dst |= dst_mask;
925			    }
926			    else {
927			       *dst &= ~dst_mask;
928			    }
929
930			    if (dst_mask > 1) dst_mask >>= 1;
931			    else {
932			       dst_mask = 0x80;
933			       dst++;
934			    }
935
936			    if (src_mask > 1) src_mask >>= 1;
937			    else {
938			       src_mask = 0x80;
939			       src++;
940			    }
941			 }
942		      }
943
944		   }
945
946		   free( be_buf );
947		}
948		else {
949		   /* Throw data on the floor */
950		   _XEatData(dpy, be_buf_size);
951		   free( buf );
952		   return BadAlloc;
953		}
954	     }
955
956	     UnlockDisplay(dpy);
957	     SyncHandle();
958
959	  } /* of npixels > 0 */
960
961       }  /* of for loop */
962
963    } /* of if buf_size > 0 */
964
965    reply.type = X_Reply;
966    reply.sequenceNumber = client->sequence;
967    reply.length = buf_size >> 2;
968
969    if (client->swapped) {
970       __GLX_SWAP_SHORT(&reply.sequenceNumber);
971       __GLX_SWAP_INT(&reply.length);
972    }
973
974    WriteToClient(client, sizeof(xGLXReadPixelsReply),(char *)&reply);
975    if (buf_size > 0) {
976       WriteToClient(client, buf_size, (char *)buf);
977       free( buf );
978    }
979
980    return Success;
981}
982
983int __glXDispSwap_GetTexImage(__GLXclientState *cl, GLbyte *pc)
984{
985    __GLX_DECLARE_SWAP_VARIABLES;
986    GLbyte *lpc = pc;
987
988    lpc += sz_xGLXSingleReq;
989    __GLX_SWAP_INT(lpc+0);
990    __GLX_SWAP_INT(lpc+4);
991    __GLX_SWAP_INT(lpc+8);
992    __GLX_SWAP_INT(lpc+12);
993
994    /* reverse swapBytes */
995    *(GLboolean *)(lpc + 16) = ! *(GLboolean *)(lpc + 16);
996
997    return( __glXForwardPipe0WithReplySwap( cl, pc ) );
998}
999
1000int __glXDispSwap_GetColorTable(__GLXclientState *cl, GLbyte *pc)
1001{
1002    __GLX_DECLARE_SWAP_VARIABLES;
1003    GLbyte *lpc = pc;
1004
1005    lpc += sz_xGLXSingleReq;
1006    __GLX_SWAP_INT(lpc+0);
1007    __GLX_SWAP_INT(lpc+4);
1008    __GLX_SWAP_INT(lpc+8);
1009
1010    /* reverse swapBytes */
1011    *(GLboolean *)(lpc + 12) = ! *(GLboolean *)(lpc + 12);
1012
1013    return( __glXForwardPipe0WithReplySwap( cl, pc ) );
1014}
1015
1016
1017