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