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