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