Merge branch 'mesa_7_7_branch'
[mesa.git] / src / glx / x11 / single2.c
1 /*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31 #include <stdio.h>
32 #include <assert.h>
33 #include "glxclient.h"
34 #include "packsingle.h"
35 #include "glxextensions.h"
36 #include "indirect.h"
37 #include "indirect_vertex_array.h"
38 #include "glapitable.h"
39 #include "glapidispatch.h"
40 #include "glapi.h"
41 #ifdef USE_XCB
42 #include <xcb/xcb.h>
43 #include <xcb/glx.h>
44 #include <X11/Xlib-xcb.h>
45 #endif /* USE_XCB */
46
47
48 /* Used for GL_ARB_transpose_matrix */
49 static void
50 TransposeMatrixf(GLfloat m[16])
51 {
52 int i, j;
53 for (i = 0; i < 4; i++) {
54 for (j = 0; j < i; j++) {
55 GLfloat tmp = m[i * 4 + j];
56 m[i * 4 + j] = m[j * 4 + i];
57 m[j * 4 + i] = tmp;
58 }
59 }
60 }
61
62 /* Used for GL_ARB_transpose_matrix */
63 static void
64 TransposeMatrixb(GLboolean m[16])
65 {
66 int i, j;
67 for (i = 0; i < 4; i++) {
68 for (j = 0; j < i; j++) {
69 GLboolean tmp = m[i * 4 + j];
70 m[i * 4 + j] = m[j * 4 + i];
71 m[j * 4 + i] = tmp;
72 }
73 }
74 }
75
76 /* Used for GL_ARB_transpose_matrix */
77 static void
78 TransposeMatrixd(GLdouble m[16])
79 {
80 int i, j;
81 for (i = 0; i < 4; i++) {
82 for (j = 0; j < i; j++) {
83 GLdouble tmp = m[i * 4 + j];
84 m[i * 4 + j] = m[j * 4 + i];
85 m[j * 4 + i] = tmp;
86 }
87 }
88 }
89
90 /* Used for GL_ARB_transpose_matrix */
91 static void
92 TransposeMatrixi(GLint m[16])
93 {
94 int i, j;
95 for (i = 0; i < 4; i++) {
96 for (j = 0; j < i; j++) {
97 GLint tmp = m[i * 4 + j];
98 m[i * 4 + j] = m[j * 4 + i];
99 m[j * 4 + i] = tmp;
100 }
101 }
102 }
103
104
105 /**
106 * Remap a transpose-matrix enum to a non-transpose-matrix enum. Enums
107 * that are not transpose-matrix enums are unaffected.
108 */
109 static GLenum
110 RemapTransposeEnum(GLenum e)
111 {
112 switch (e) {
113 case GL_TRANSPOSE_MODELVIEW_MATRIX:
114 case GL_TRANSPOSE_PROJECTION_MATRIX:
115 case GL_TRANSPOSE_TEXTURE_MATRIX:
116 return e - (GL_TRANSPOSE_MODELVIEW_MATRIX - GL_MODELVIEW_MATRIX);
117 case GL_TRANSPOSE_COLOR_MATRIX:
118 return GL_COLOR_MATRIX;
119 default:
120 return e;
121 };
122 }
123
124
125 GLenum
126 __indirect_glGetError(void)
127 {
128 __GLX_SINGLE_DECLARE_VARIABLES();
129 GLuint retval = GL_NO_ERROR;
130 xGLXGetErrorReply reply;
131
132 if (gc->error) {
133 /* Use internal error first */
134 retval = gc->error;
135 gc->error = GL_NO_ERROR;
136 return retval;
137 }
138
139 __GLX_SINGLE_LOAD_VARIABLES();
140 __GLX_SINGLE_BEGIN(X_GLsop_GetError, 0);
141 __GLX_SINGLE_READ_XREPLY();
142 retval = reply.error;
143 __GLX_SINGLE_END();
144
145 return retval;
146 }
147
148
149 /**
150 * Get the selected attribute from the client state.
151 *
152 * \returns
153 * On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
154 */
155 static GLboolean
156 get_client_data(__GLXcontext * gc, GLenum cap, GLintptr * data)
157 {
158 GLboolean retval = GL_TRUE;
159 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
160 const GLint tex_unit = __glXGetActiveTextureUnit(state);
161
162
163 switch (cap) {
164 case GL_VERTEX_ARRAY:
165 case GL_NORMAL_ARRAY:
166 case GL_COLOR_ARRAY:
167 case GL_INDEX_ARRAY:
168 case GL_EDGE_FLAG_ARRAY:
169 case GL_SECONDARY_COLOR_ARRAY:
170 case GL_FOG_COORD_ARRAY:
171 retval = __glXGetArrayEnable(state, cap, 0, data);
172 break;
173
174 case GL_VERTEX_ARRAY_SIZE:
175 retval = __glXGetArraySize(state, GL_VERTEX_ARRAY, 0, data);
176 break;
177 case GL_COLOR_ARRAY_SIZE:
178 retval = __glXGetArraySize(state, GL_COLOR_ARRAY, 0, data);
179 break;
180 case GL_SECONDARY_COLOR_ARRAY_SIZE:
181 retval = __glXGetArraySize(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
182 break;
183
184 case GL_VERTEX_ARRAY_TYPE:
185 retval = __glXGetArrayType(state, GL_VERTEX_ARRAY, 0, data);
186 break;
187 case GL_NORMAL_ARRAY_TYPE:
188 retval = __glXGetArrayType(state, GL_NORMAL_ARRAY, 0, data);
189 break;
190 case GL_INDEX_ARRAY_TYPE:
191 retval = __glXGetArrayType(state, GL_INDEX_ARRAY, 0, data);
192 break;
193 case GL_COLOR_ARRAY_TYPE:
194 retval = __glXGetArrayType(state, GL_COLOR_ARRAY, 0, data);
195 break;
196 case GL_SECONDARY_COLOR_ARRAY_TYPE:
197 retval = __glXGetArrayType(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
198 break;
199 case GL_FOG_COORD_ARRAY_TYPE:
200 retval = __glXGetArrayType(state, GL_FOG_COORD_ARRAY, 0, data);
201 break;
202
203 case GL_VERTEX_ARRAY_STRIDE:
204 retval = __glXGetArrayStride(state, GL_VERTEX_ARRAY, 0, data);
205 break;
206 case GL_NORMAL_ARRAY_STRIDE:
207 retval = __glXGetArrayStride(state, GL_NORMAL_ARRAY, 0, data);
208 break;
209 case GL_INDEX_ARRAY_STRIDE:
210 retval = __glXGetArrayStride(state, GL_INDEX_ARRAY, 0, data);
211 break;
212 case GL_EDGE_FLAG_ARRAY_STRIDE:
213 retval = __glXGetArrayStride(state, GL_EDGE_FLAG_ARRAY, 0, data);
214 break;
215 case GL_COLOR_ARRAY_STRIDE:
216 retval = __glXGetArrayStride(state, GL_COLOR_ARRAY, 0, data);
217 break;
218 case GL_SECONDARY_COLOR_ARRAY_STRIDE:
219 retval = __glXGetArrayStride(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
220 break;
221 case GL_FOG_COORD_ARRAY_STRIDE:
222 retval = __glXGetArrayStride(state, GL_FOG_COORD_ARRAY, 0, data);
223 break;
224
225 case GL_TEXTURE_COORD_ARRAY:
226 retval =
227 __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
228 break;
229 case GL_TEXTURE_COORD_ARRAY_SIZE:
230 retval =
231 __glXGetArraySize(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
232 break;
233 case GL_TEXTURE_COORD_ARRAY_TYPE:
234 retval =
235 __glXGetArrayType(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
236 break;
237 case GL_TEXTURE_COORD_ARRAY_STRIDE:
238 retval =
239 __glXGetArrayStride(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
240 break;
241
242 case GL_MAX_ELEMENTS_VERTICES:
243 case GL_MAX_ELEMENTS_INDICES:
244 retval = GL_TRUE;
245 *data = ~0UL;
246 break;
247
248
249 case GL_PACK_ROW_LENGTH:
250 *data = (GLintptr) state->storePack.rowLength;
251 break;
252 case GL_PACK_IMAGE_HEIGHT:
253 *data = (GLintptr) state->storePack.imageHeight;
254 break;
255 case GL_PACK_SKIP_ROWS:
256 *data = (GLintptr) state->storePack.skipRows;
257 break;
258 case GL_PACK_SKIP_PIXELS:
259 *data = (GLintptr) state->storePack.skipPixels;
260 break;
261 case GL_PACK_SKIP_IMAGES:
262 *data = (GLintptr) state->storePack.skipImages;
263 break;
264 case GL_PACK_ALIGNMENT:
265 *data = (GLintptr) state->storePack.alignment;
266 break;
267 case GL_PACK_SWAP_BYTES:
268 *data = (GLintptr) state->storePack.swapEndian;
269 break;
270 case GL_PACK_LSB_FIRST:
271 *data = (GLintptr) state->storePack.lsbFirst;
272 break;
273 case GL_UNPACK_ROW_LENGTH:
274 *data = (GLintptr) state->storeUnpack.rowLength;
275 break;
276 case GL_UNPACK_IMAGE_HEIGHT:
277 *data = (GLintptr) state->storeUnpack.imageHeight;
278 break;
279 case GL_UNPACK_SKIP_ROWS:
280 *data = (GLintptr) state->storeUnpack.skipRows;
281 break;
282 case GL_UNPACK_SKIP_PIXELS:
283 *data = (GLintptr) state->storeUnpack.skipPixels;
284 break;
285 case GL_UNPACK_SKIP_IMAGES:
286 *data = (GLintptr) state->storeUnpack.skipImages;
287 break;
288 case GL_UNPACK_ALIGNMENT:
289 *data = (GLintptr) state->storeUnpack.alignment;
290 break;
291 case GL_UNPACK_SWAP_BYTES:
292 *data = (GLintptr) state->storeUnpack.swapEndian;
293 break;
294 case GL_UNPACK_LSB_FIRST:
295 *data = (GLintptr) state->storeUnpack.lsbFirst;
296 break;
297 case GL_CLIENT_ATTRIB_STACK_DEPTH:
298 *data = (GLintptr) (gc->attributes.stackPointer - gc->attributes.stack);
299 break;
300 case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
301 *data = (GLintptr) __GL_CLIENT_ATTRIB_STACK_DEPTH;
302 break;
303 case GL_CLIENT_ACTIVE_TEXTURE:
304 *data = (GLintptr) (tex_unit + GL_TEXTURE0);
305 break;
306
307 default:
308 retval = GL_FALSE;
309 break;
310 }
311
312
313 return retval;
314 }
315
316
317 void
318 __indirect_glGetBooleanv(GLenum val, GLboolean * b)
319 {
320 const GLenum origVal = val;
321 __GLX_SINGLE_DECLARE_VARIABLES();
322 xGLXSingleReply reply;
323
324 val = RemapTransposeEnum(val);
325
326 __GLX_SINGLE_LOAD_VARIABLES();
327 __GLX_SINGLE_BEGIN(X_GLsop_GetBooleanv, 4);
328 __GLX_SINGLE_PUT_LONG(0, val);
329 __GLX_SINGLE_READ_XREPLY();
330 __GLX_SINGLE_GET_SIZE(compsize);
331
332 if (compsize == 0) {
333 /*
334 ** Error occured; don't modify user's buffer.
335 */
336 }
337 else {
338 GLintptr data;
339
340 /*
341 ** We still needed to send the request to the server in order to
342 ** find out whether it was legal to make a query (it's illegal,
343 ** for example, to call a query between glBegin() and glEnd()).
344 */
345
346 if (get_client_data(gc, val, &data)) {
347 *b = (GLboolean) data;
348 }
349 else {
350 /*
351 ** Not a local value, so use what we got from the server.
352 */
353 if (compsize == 1) {
354 __GLX_SINGLE_GET_CHAR(b);
355 }
356 else {
357 __GLX_SINGLE_GET_CHAR_ARRAY(b, compsize);
358 if (val != origVal) {
359 /* matrix transpose */
360 TransposeMatrixb(b);
361 }
362 }
363 }
364 }
365 __GLX_SINGLE_END();
366 }
367
368 void
369 __indirect_glGetDoublev(GLenum val, GLdouble * d)
370 {
371 const GLenum origVal = val;
372 __GLX_SINGLE_DECLARE_VARIABLES();
373 xGLXSingleReply reply;
374
375 val = RemapTransposeEnum(val);
376
377 __GLX_SINGLE_LOAD_VARIABLES();
378 __GLX_SINGLE_BEGIN(X_GLsop_GetDoublev, 4);
379 __GLX_SINGLE_PUT_LONG(0, val);
380 __GLX_SINGLE_READ_XREPLY();
381 __GLX_SINGLE_GET_SIZE(compsize);
382
383 if (compsize == 0) {
384 /*
385 ** Error occured; don't modify user's buffer.
386 */
387 }
388 else {
389 GLintptr data;
390
391 /*
392 ** We still needed to send the request to the server in order to
393 ** find out whether it was legal to make a query (it's illegal,
394 ** for example, to call a query between glBegin() and glEnd()).
395 */
396
397 if (get_client_data(gc, val, &data)) {
398 *d = (GLdouble) data;
399 }
400 else {
401 /*
402 ** Not a local value, so use what we got from the server.
403 */
404 if (compsize == 1) {
405 __GLX_SINGLE_GET_DOUBLE(d);
406 }
407 else {
408 __GLX_SINGLE_GET_DOUBLE_ARRAY(d, compsize);
409 if (val != origVal) {
410 /* matrix transpose */
411 TransposeMatrixd(d);
412 }
413 }
414 }
415 }
416 __GLX_SINGLE_END();
417 }
418
419 void
420 __indirect_glGetFloatv(GLenum val, GLfloat * f)
421 {
422 const GLenum origVal = val;
423 __GLX_SINGLE_DECLARE_VARIABLES();
424 xGLXSingleReply reply;
425
426 val = RemapTransposeEnum(val);
427
428 __GLX_SINGLE_LOAD_VARIABLES();
429 __GLX_SINGLE_BEGIN(X_GLsop_GetFloatv, 4);
430 __GLX_SINGLE_PUT_LONG(0, val);
431 __GLX_SINGLE_READ_XREPLY();
432 __GLX_SINGLE_GET_SIZE(compsize);
433
434 if (compsize == 0) {
435 /*
436 ** Error occured; don't modify user's buffer.
437 */
438 }
439 else {
440 GLintptr data;
441
442 /*
443 ** We still needed to send the request to the server in order to
444 ** find out whether it was legal to make a query (it's illegal,
445 ** for example, to call a query between glBegin() and glEnd()).
446 */
447
448 if (get_client_data(gc, val, &data)) {
449 *f = (GLfloat) data;
450 }
451 else {
452 /*
453 ** Not a local value, so use what we got from the server.
454 */
455 if (compsize == 1) {
456 __GLX_SINGLE_GET_FLOAT(f);
457 }
458 else {
459 __GLX_SINGLE_GET_FLOAT_ARRAY(f, compsize);
460 if (val != origVal) {
461 /* matrix transpose */
462 TransposeMatrixf(f);
463 }
464 }
465 }
466 }
467 __GLX_SINGLE_END();
468 }
469
470 void
471 __indirect_glGetIntegerv(GLenum val, GLint * i)
472 {
473 const GLenum origVal = val;
474 __GLX_SINGLE_DECLARE_VARIABLES();
475 xGLXSingleReply reply;
476
477 val = RemapTransposeEnum(val);
478
479 __GLX_SINGLE_LOAD_VARIABLES();
480 __GLX_SINGLE_BEGIN(X_GLsop_GetIntegerv, 4);
481 __GLX_SINGLE_PUT_LONG(0, val);
482 __GLX_SINGLE_READ_XREPLY();
483 __GLX_SINGLE_GET_SIZE(compsize);
484
485 if (compsize == 0) {
486 /*
487 ** Error occured; don't modify user's buffer.
488 */
489 }
490 else {
491 GLintptr data;
492
493 /*
494 ** We still needed to send the request to the server in order to
495 ** find out whether it was legal to make a query (it's illegal,
496 ** for example, to call a query between glBegin() and glEnd()).
497 */
498
499 if (get_client_data(gc, val, &data)) {
500 *i = (GLint) data;
501 }
502 else {
503 /*
504 ** Not a local value, so use what we got from the server.
505 */
506 if (compsize == 1) {
507 __GLX_SINGLE_GET_LONG(i);
508 }
509 else {
510 __GLX_SINGLE_GET_LONG_ARRAY(i, compsize);
511 if (val != origVal) {
512 /* matrix transpose */
513 TransposeMatrixi(i);
514 }
515 }
516 }
517 }
518 __GLX_SINGLE_END();
519 }
520
521 /*
522 ** Send all pending commands to server.
523 */
524 void
525 __indirect_glFlush(void)
526 {
527 __GLX_SINGLE_DECLARE_VARIABLES();
528
529 if (!dpy)
530 return;
531
532 __GLX_SINGLE_LOAD_VARIABLES();
533 __GLX_SINGLE_BEGIN(X_GLsop_Flush, 0);
534 __GLX_SINGLE_END();
535
536 /* And finally flush the X protocol data */
537 XFlush(dpy);
538 }
539
540 void
541 __indirect_glFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer)
542 {
543 __GLX_SINGLE_DECLARE_VARIABLES();
544
545 if (!dpy)
546 return;
547
548 __GLX_SINGLE_LOAD_VARIABLES();
549 __GLX_SINGLE_BEGIN(X_GLsop_FeedbackBuffer, 8);
550 __GLX_SINGLE_PUT_LONG(0, size);
551 __GLX_SINGLE_PUT_LONG(4, type);
552 __GLX_SINGLE_END();
553
554 gc->feedbackBuf = buffer;
555 }
556
557 void
558 __indirect_glSelectBuffer(GLsizei numnames, GLuint * buffer)
559 {
560 __GLX_SINGLE_DECLARE_VARIABLES();
561
562 if (!dpy)
563 return;
564
565 __GLX_SINGLE_LOAD_VARIABLES();
566 __GLX_SINGLE_BEGIN(X_GLsop_SelectBuffer, 4);
567 __GLX_SINGLE_PUT_LONG(0, numnames);
568 __GLX_SINGLE_END();
569
570 gc->selectBuf = buffer;
571 }
572
573 GLint
574 __indirect_glRenderMode(GLenum mode)
575 {
576 __GLX_SINGLE_DECLARE_VARIABLES();
577 GLint retval = 0;
578 xGLXRenderModeReply reply;
579
580 if (!dpy)
581 return -1;
582
583 __GLX_SINGLE_LOAD_VARIABLES();
584 __GLX_SINGLE_BEGIN(X_GLsop_RenderMode, 4);
585 __GLX_SINGLE_PUT_LONG(0, mode);
586 __GLX_SINGLE_READ_XREPLY();
587 __GLX_SINGLE_GET_RETVAL(retval, GLint);
588
589 if (reply.newMode != mode) {
590 /*
591 ** Switch to new mode did not take effect, therefore an error
592 ** occured. When an error happens the server won't send us any
593 ** other data.
594 */
595 }
596 else {
597 /* Read the feedback or selection data */
598 if (gc->renderMode == GL_FEEDBACK) {
599 __GLX_SINGLE_GET_SIZE(compsize);
600 __GLX_SINGLE_GET_FLOAT_ARRAY(gc->feedbackBuf, compsize);
601 }
602 else if (gc->renderMode == GL_SELECT) {
603 __GLX_SINGLE_GET_SIZE(compsize);
604 __GLX_SINGLE_GET_LONG_ARRAY(gc->selectBuf, compsize);
605 }
606 gc->renderMode = mode;
607 }
608 __GLX_SINGLE_END();
609
610 return retval;
611 }
612
613 void
614 __indirect_glFinish(void)
615 {
616 __GLX_SINGLE_DECLARE_VARIABLES();
617 xGLXSingleReply reply;
618
619 __GLX_SINGLE_LOAD_VARIABLES();
620 __GLX_SINGLE_BEGIN(X_GLsop_Finish, 0);
621 __GLX_SINGLE_READ_XREPLY();
622 __GLX_SINGLE_END();
623 }
624
625
626 /**
627 * Extract the major and minor version numbers from a version string.
628 */
629 static void
630 version_from_string(const char *ver, int *major_version, int *minor_version)
631 {
632 const char *end;
633 long major;
634 long minor;
635
636 major = strtol(ver, (char **) &end, 10);
637 minor = strtol(end + 1, NULL, 10);
638 *major_version = major;
639 *minor_version = minor;
640 }
641
642
643 const GLubyte *
644 __indirect_glGetString(GLenum name)
645 {
646 __GLXcontext *gc = __glXGetCurrentContext();
647 Display *dpy = gc->currentDpy;
648 GLubyte *s = NULL;
649
650 if (!dpy)
651 return 0;
652
653 /*
654 ** Return the cached copy if the string has already been fetched
655 */
656 switch (name) {
657 case GL_VENDOR:
658 if (gc->vendor)
659 return gc->vendor;
660 break;
661 case GL_RENDERER:
662 if (gc->renderer)
663 return gc->renderer;
664 break;
665 case GL_VERSION:
666 if (gc->version)
667 return gc->version;
668 break;
669 case GL_EXTENSIONS:
670 if (gc->extensions)
671 return gc->extensions;
672 break;
673 default:
674 __glXSetError(gc, GL_INVALID_ENUM);
675 return 0;
676 }
677
678 /*
679 ** Get requested string from server
680 */
681
682 (void) __glXFlushRenderBuffer(gc, gc->pc);
683 s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag,
684 name);
685 if (!s) {
686 /* Throw data on the floor */
687 __glXSetError(gc, GL_OUT_OF_MEMORY);
688 }
689 else {
690 /*
691 ** Update local cache
692 */
693 switch (name) {
694 case GL_VENDOR:
695 gc->vendor = s;
696 break;
697
698 case GL_RENDERER:
699 gc->renderer = s;
700 break;
701
702 case GL_VERSION:{
703 int client_major;
704 int client_minor;
705
706 version_from_string((char *) s,
707 &gc->server_major, &gc->server_minor);
708 __glXGetGLVersion(&client_major, &client_minor);
709
710 if ((gc->server_major < client_major)
711 || ((gc->server_major == client_major)
712 && (gc->server_minor <= client_minor))) {
713 gc->version = s;
714 }
715 else {
716 /* Allow 7 bytes for the client-side GL version. This allows
717 * for upto version 999.999. I'm not holding my breath for
718 * that one! The extra 4 is for the ' ()\0' that will be
719 * added.
720 */
721 const size_t size = 7 + strlen((char *) s) + 4;
722
723 gc->version = Xmalloc(size);
724 if (gc->version == NULL) {
725 /* If we couldn't allocate memory for the new string,
726 * make a best-effort and just copy the client-side version
727 * to the string and use that. It probably doesn't
728 * matter what is done here. If there not memory available
729 * for a short string, the system is probably going to die
730 * soon anyway.
731 */
732 snprintf((char *) s, strlen((char *) s) + 1, "%u.%u",
733 client_major, client_minor);
734 gc->version = s;
735 }
736 else {
737 snprintf((char *) gc->version, size, "%u.%u (%s)",
738 client_major, client_minor, s);
739 Xfree(s);
740 s = gc->version;
741 }
742 }
743 break;
744 }
745
746 case GL_EXTENSIONS:{
747 int major = 1;
748 int minor = 0;
749
750 /* This code is currently disabled. I was reminded that some
751 * vendors intentionally exclude some extensions from their
752 * extension string that are part of the core version they
753 * advertise. In particular, on Nvidia drivers this means that
754 * the functionality is supported by the driver, but is not
755 * hardware accelerated. For example, a TNT will show core
756 * version 1.5, but most of the post-1.2 functionality is a
757 * software fallback.
758 *
759 * I don't want to break applications that rely on this odd
760 * behavior. At the same time, the code is written and tested,
761 * so I didn't want to throw it away. Therefore, the code is here
762 * but disabled. In the future, we may wish to and an environment
763 * variable to enable it.
764 */
765
766 #if 0
767 /* Call glGetString just to make sure that gc->server_major and
768 * gc->server_minor are set. This version may be higher than we
769 * can completely support, but it may imply support for some
770 * extensions that we can support.
771 *
772 * For example, at the time of this writing, the client-side
773 * library only supports upto core GL version 1.2. However, cubic
774 * textures, multitexture, multisampling, and some other 1.3
775 * features are supported. If the server reports back version
776 * 1.3, but does not report all of those extensions, we will
777 * enable them.
778 */
779 (void *) glGetString(GL_VERSION);
780 major = gc->server_major, minor = gc->server_minor;
781 #endif
782
783 __glXCalculateUsableGLExtensions(gc, (char *) s, major, minor);
784 XFree(s);
785 s = gc->extensions;
786 break;
787 }
788 }
789 }
790 return s;
791 }
792
793 GLboolean
794 __indirect_glIsEnabled(GLenum cap)
795 {
796 __GLX_SINGLE_DECLARE_VARIABLES();
797 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
798 xGLXSingleReply reply;
799 GLboolean retval = 0;
800 GLintptr enable;
801
802 if (!dpy)
803 return 0;
804
805 switch (cap) {
806 case GL_VERTEX_ARRAY:
807 case GL_NORMAL_ARRAY:
808 case GL_COLOR_ARRAY:
809 case GL_INDEX_ARRAY:
810 case GL_EDGE_FLAG_ARRAY:
811 case GL_SECONDARY_COLOR_ARRAY:
812 case GL_FOG_COORD_ARRAY:
813 retval = __glXGetArrayEnable(state, cap, 0, &enable);
814 assert(retval);
815 return (GLboolean) enable;
816 break;
817 case GL_TEXTURE_COORD_ARRAY:
818 retval = __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY,
819 __glXGetActiveTextureUnit(state), &enable);
820 assert(retval);
821 return (GLboolean) enable;
822 break;
823 }
824
825 __GLX_SINGLE_LOAD_VARIABLES();
826 __GLX_SINGLE_BEGIN(X_GLsop_IsEnabled, 4);
827 __GLX_SINGLE_PUT_LONG(0, cap);
828 __GLX_SINGLE_READ_XREPLY();
829 __GLX_SINGLE_GET_RETVAL(retval, GLboolean);
830 __GLX_SINGLE_END();
831 return retval;
832 }
833
834 void
835 __indirect_glGetPointerv(GLenum pname, void **params)
836 {
837 __GLXcontext *gc = __glXGetCurrentContext();
838 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
839 Display *dpy = gc->currentDpy;
840
841 if (!dpy)
842 return;
843
844 switch (pname) {
845 case GL_VERTEX_ARRAY_POINTER:
846 case GL_NORMAL_ARRAY_POINTER:
847 case GL_COLOR_ARRAY_POINTER:
848 case GL_INDEX_ARRAY_POINTER:
849 case GL_EDGE_FLAG_ARRAY_POINTER:
850 __glXGetArrayPointer(state, pname - GL_VERTEX_ARRAY_POINTER
851 + GL_VERTEX_ARRAY, 0, params);
852 return;
853 case GL_TEXTURE_COORD_ARRAY_POINTER:
854 __glXGetArrayPointer(state, GL_TEXTURE_COORD_ARRAY,
855 __glXGetActiveTextureUnit(state), params);
856 return;
857 case GL_SECONDARY_COLOR_ARRAY_POINTER:
858 case GL_FOG_COORD_ARRAY_POINTER:
859 __glXGetArrayPointer(state, pname - GL_FOG_COORD_ARRAY_POINTER
860 + GL_FOG_COORD_ARRAY, 0, params);
861 return;
862 case GL_FEEDBACK_BUFFER_POINTER:
863 *params = (void *) gc->feedbackBuf;
864 return;
865 case GL_SELECTION_BUFFER_POINTER:
866 *params = (void *) gc->selectBuf;
867 return;
868 default:
869 __glXSetError(gc, GL_INVALID_ENUM);
870 return;
871 }
872 }
873
874
875
876 /**
877 * This was previously auto-generated, but we need to special-case
878 * how we handle writing into the 'residences' buffer when n%4!=0.
879 */
880 #define X_GLsop_AreTexturesResident 143
881 GLboolean
882 __indirect_glAreTexturesResident(GLsizei n, const GLuint * textures,
883 GLboolean * residences)
884 {
885 __GLXcontext *const gc = __glXGetCurrentContext();
886 Display *const dpy = gc->currentDpy;
887 GLboolean retval = (GLboolean) 0;
888 const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
889 if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
890 #ifdef USE_XCB
891 xcb_connection_t *c = XGetXCBConnection(dpy);
892 (void) __glXFlushRenderBuffer(gc, gc->pc);
893 xcb_glx_are_textures_resident_reply_t *reply =
894 xcb_glx_are_textures_resident_reply(c,
895 xcb_glx_are_textures_resident
896 (c, gc->currentContextTag, n,
897 textures), NULL);
898 (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply),
899 xcb_glx_are_textures_resident_data_length(reply) *
900 sizeof(GLboolean));
901 retval = reply->ret_val;
902 free(reply);
903 #else
904 GLubyte const *pc =
905 __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen);
906 (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
907 (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
908 if (n & 3) {
909 /* n is not a multiple of four.
910 * When reply_is_always_array is TRUE, __glXReadReply() will
911 * put a multiple of four bytes into the dest buffer. If the
912 * caller's buffer is not a multiple of four in size, we'll write
913 * out of bounds. So use a temporary buffer that's a few bytes
914 * larger.
915 */
916 GLboolean *res4 = malloc((n + 3) & ~3);
917 retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
918 memcpy(residences, res4, n);
919 free(res4);
920 }
921 else {
922 retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
923 }
924 UnlockDisplay(dpy);
925 SyncHandle();
926 #endif /* USE_XCB */
927 }
928 return retval;
929 }
930
931
932 /**
933 * This was previously auto-generated, but we need to special-case
934 * how we handle writing into the 'residences' buffer when n%4!=0.
935 */
936 #define X_GLvop_AreTexturesResidentEXT 11
937 GLboolean
938 glAreTexturesResidentEXT(GLsizei n, const GLuint * textures,
939 GLboolean * residences)
940 {
941 __GLXcontext *const gc = __glXGetCurrentContext();
942
943 if (gc->isDirect) {
944 return CALL_AreTexturesResident(GET_DISPATCH(),
945 (n, textures, residences));
946 }
947 else {
948 __GLXcontext *const gc = __glXGetCurrentContext();
949 Display *const dpy = gc->currentDpy;
950 GLboolean retval = (GLboolean) 0;
951 const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
952 if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
953 GLubyte const *pc =
954 __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply,
955 X_GLvop_AreTexturesResidentEXT,
956 cmdlen);
957 (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
958 (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
959 if (n & 3) {
960 /* see comments in __indirect_glAreTexturesResident() */
961 GLboolean *res4 = malloc((n + 3) & ~3);
962 retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
963 memcpy(residences, res4, n);
964 free(res4);
965 }
966 else {
967 retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
968 }
969 UnlockDisplay(dpy);
970 SyncHandle();
971 }
972 return retval;
973 }
974 }