• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
50 static void
TransposeMatrixf(GLfloat m[16])51 TransposeMatrixf(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 */
64 static void
TransposeMatrixb(GLboolean m[16])65 TransposeMatrixb(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 */
78 static void
TransposeMatrixd(GLdouble m[16])79 TransposeMatrixd(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 */
92 static void
TransposeMatrixi(GLint m[16])93 TransposeMatrixi(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  */
110 static GLenum
RemapTransposeEnum(GLenum e)111 RemapTransposeEnum(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 
126 GLenum
__indirect_glGetError(void)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  */
156 static GLboolean
get_client_data(struct glx_context * gc,GLenum cap,GLintptr * data)157 get_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 
318 void
__indirect_glGetBooleanv(GLenum val,GLboolean * b)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 
369 void
__indirect_glGetDoublev(GLenum val,GLdouble * d)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 
420 void
__indirect_glGetFloatv(GLenum val,GLfloat * f)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 
471 void
__indirect_glGetIntegerv(GLenum val,GLint * i)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 */
525 void
__indirect_glFlush(void)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 
541 void
__indirect_glFeedbackBuffer(GLsizei size,GLenum type,GLfloat * buffer)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 
558 void
__indirect_glSelectBuffer(GLsizei numnames,GLuint * buffer)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 
574 GLint
__indirect_glRenderMode(GLenum mode)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 
614 void
__indirect_glFinish(void)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  */
630 static void
version_from_string(const char * ver,int * major_version,int * minor_version)631 version_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 
644 const GLubyte *
__indirect_glGetString(GLenum name)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 
794 GLboolean
__indirect_glIsEnabled(GLenum cap)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 
835 void
__indirect_glGetPointerv(GLenum pname,void ** params)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
882 GLboolean
__indirect_glAreTexturesResident(GLsizei n,const GLuint * textures,GLboolean * residences)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
938 GLboolean
glAreTexturesResidentEXT(GLsizei n,const GLuint * textures,GLboolean * residences)939 glAreTexturesResidentEXT(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