• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * 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  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 
27 /**
28  * "Fake" GLX API implemented in terms of the XMesa*() functions.
29  */
30 
31 
32 
33 #define GLX_GLXEXT_PROTOTYPES
34 #include "GL/glx.h"
35 
36 #include <stdio.h>
37 #include <string.h>
38 #include <X11/Xmd.h>
39 #include <GL/glxproto.h>
40 
41 #include "xm_api.h"
42 
43 /* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.
44  * This is in case we don't have the updated header.
45  */
46 #if !defined(X_GLXCreateContextAttribsARB) && \
47      defined(X_GLXCreateContextAtrribsARB)
48 #define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB
49 #endif
50 
51 /* This indicates the client-side GLX API and GLX encoder version. */
52 #define CLIENT_MAJOR_VERSION 1
53 #define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
54 
55 /* This indicates the server-side GLX decoder version.
56  * GLX 1.4 indicates OpenGL 1.3 support
57  */
58 #define SERVER_MAJOR_VERSION 1
59 #define SERVER_MINOR_VERSION 4
60 
61 /* Who implemented this GLX? */
62 #define VENDOR "Brian Paul"
63 
64 #define EXTENSIONS \
65    "GLX_MESA_copy_sub_buffer " \
66    "GLX_MESA_pixmap_colormap " \
67    "GLX_MESA_release_buffers " \
68    "GLX_ARB_create_context " \
69    "GLX_ARB_create_context_profile " \
70    "GLX_ARB_get_proc_address " \
71    "GLX_EXT_create_context_es_profile " \
72    "GLX_EXT_create_context_es2_profile " \
73    "GLX_EXT_texture_from_pixmap " \
74    "GLX_EXT_visual_info " \
75    "GLX_EXT_visual_rating " \
76    /*"GLX_SGI_video_sync "*/ \
77    "GLX_SGIX_fbconfig " \
78    "GLX_SGIX_pbuffer "
79 
80 #define DEFAULT_DIRECT GL_TRUE
81 
82 
83 /** XXX this could be based on gallium's max texture size */
84 #define PBUFFER_MAX_SIZE 16384
85 
86 
87 /**
88  * The GLXContext typedef is defined as a pointer to this structure.
89  */
90 struct __GLXcontextRec
91 {
92    Display *currentDpy;
93    GLboolean isDirect;
94    GLXDrawable currentDrawable;
95    GLXDrawable currentReadable;
96    XID xid;
97 
98    XMesaContext xmesaContext;
99 };
100 
101 
102 
103 static pipe_tsd ContextTSD;
104 
105 /** Set current context for calling thread */
106 static void
SetCurrentContext(GLXContext c)107 SetCurrentContext(GLXContext c)
108 {
109    pipe_tsd_set(&ContextTSD, c);
110 }
111 
112 /** Get current context for calling thread */
113 static GLXContext
GetCurrentContext(void)114 GetCurrentContext(void)
115 {
116    return pipe_tsd_get(&ContextTSD);
117 }
118 
119 
120 
121 /**********************************************************************/
122 /***                       GLX Visual Code                          ***/
123 /**********************************************************************/
124 
125 #define DONT_CARE -1
126 
127 
128 static XMesaVisual *VisualTable = NULL;
129 static int NumVisuals = 0;
130 
131 
132 
133 /* Macro to handle c_class vs class field name in XVisualInfo struct */
134 #if defined(__cplusplus) || defined(c_plusplus)
135 #define CLASS c_class
136 #else
137 #define CLASS class
138 #endif
139 
140 
141 
142 /*
143  * Test if the given XVisualInfo is usable for Mesa rendering.
144  */
145 static GLboolean
is_usable_visual(XVisualInfo * vinfo)146 is_usable_visual( XVisualInfo *vinfo )
147 {
148    switch (vinfo->CLASS) {
149       case StaticGray:
150       case GrayScale:
151          /* Any StaticGray/GrayScale visual works in RGB or CI mode */
152          return GL_TRUE;
153       case StaticColor:
154       case PseudoColor:
155 	 /* Any StaticColor/PseudoColor visual of at least 4 bits */
156 	 if (vinfo->depth>=4) {
157 	    return GL_TRUE;
158 	 }
159 	 else {
160 	    return GL_FALSE;
161 	 }
162       case TrueColor:
163       case DirectColor:
164 	 /* Any depth of TrueColor or DirectColor works in RGB mode */
165 	 return GL_TRUE;
166       default:
167 	 /* This should never happen */
168 	 return GL_FALSE;
169    }
170 }
171 
172 
173 /*
174  * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
175  * configuration in our list of GLX visuals.
176  */
177 static XMesaVisual
save_glx_visual(Display * dpy,XVisualInfo * vinfo,GLboolean rgbFlag,GLboolean alphaFlag,GLboolean dbFlag,GLboolean stereoFlag,GLint depth_size,GLint stencil_size,GLint accumRedSize,GLint accumGreenSize,GLint accumBlueSize,GLint accumAlphaSize,GLint level,GLint numAuxBuffers,GLuint num_samples)178 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
179                  GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
180                  GLboolean stereoFlag,
181                  GLint depth_size, GLint stencil_size,
182                  GLint accumRedSize, GLint accumGreenSize,
183                  GLint accumBlueSize, GLint accumAlphaSize,
184                  GLint level, GLint numAuxBuffers, GLuint num_samples )
185 {
186    GLboolean ximageFlag = GL_TRUE;
187    XMesaVisual xmvis;
188    GLint i;
189    GLboolean comparePointers;
190 
191    if (dbFlag) {
192       /* Check if the MESA_BACK_BUFFER env var is set */
193       char *backbuffer = getenv("MESA_BACK_BUFFER");
194       if (backbuffer) {
195          if (backbuffer[0]=='p' || backbuffer[0]=='P') {
196             ximageFlag = GL_FALSE;
197          }
198          else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
199             ximageFlag = GL_TRUE;
200          }
201          else {
202             _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
203          }
204       }
205    }
206 
207    if (stereoFlag) {
208       /* stereo not supported */
209       return NULL;
210    }
211 
212    if (stencil_size > 0 && depth_size > 0)
213       depth_size = 24;
214 
215    /* Comparing IDs uses less memory but sometimes fails. */
216    /* XXX revisit this after 3.0 is finished. */
217    if (getenv("MESA_GLX_VISUAL_HACK"))
218       comparePointers = GL_TRUE;
219    else
220       comparePointers = GL_FALSE;
221 
222    /* Force the visual to have an alpha channel */
223    if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA"))
224       alphaFlag = GL_TRUE;
225 
226    /* First check if a matching visual is already in the list */
227    for (i=0; i<NumVisuals; i++) {
228       XMesaVisual v = VisualTable[i];
229       if (v->display == dpy
230           && v->mesa_visual.level == level
231           && v->mesa_visual.numAuxBuffers == numAuxBuffers
232           && v->mesa_visual.samples == num_samples
233           && v->ximage_flag == ximageFlag
234           && v->mesa_visual.rgbMode == rgbFlag
235           && v->mesa_visual.doubleBufferMode == dbFlag
236           && v->mesa_visual.stereoMode == stereoFlag
237           && (v->mesa_visual.alphaBits > 0) == alphaFlag
238           && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
239           && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
240           && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
241           && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
242           && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
243           && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
244          /* now either compare XVisualInfo pointers or visual IDs */
245          if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
246              || (comparePointers && v->vishandle == vinfo)) {
247             return v;
248          }
249       }
250    }
251 
252    /* Create a new visual and add it to the list. */
253 
254    xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
255                               stereoFlag, ximageFlag,
256                               depth_size, stencil_size,
257                               accumRedSize, accumBlueSize,
258                               accumBlueSize, accumAlphaSize, num_samples, level,
259                               GLX_NONE_EXT );
260    if (xmvis) {
261       /* Save a copy of the pointer now so we can find this visual again
262        * if we need to search for it in find_glx_visual().
263        */
264       xmvis->vishandle = vinfo;
265       /* Allocate more space for additional visual */
266       VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1));
267       /* add xmvis to the list */
268       VisualTable[NumVisuals] = xmvis;
269       NumVisuals++;
270       /* XXX minor hack, because XMesaCreateVisual doesn't support an
271        * aux buffers parameter.
272        */
273       xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
274    }
275    return xmvis;
276 }
277 
278 
279 /**
280  * Return the default number of bits for the Z buffer.
281  * If defined, use the MESA_GLX_DEPTH_BITS env var value.
282  * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
283  * XXX probably do the same thing for stencil, accum, etc.
284  */
285 static GLint
default_depth_bits(void)286 default_depth_bits(void)
287 {
288    int zBits;
289    const char *zEnv = getenv("MESA_GLX_DEPTH_BITS");
290    if (zEnv)
291       zBits = atoi(zEnv);
292    else
293       zBits = 24;
294    return zBits;
295 }
296 
297 static GLint
default_alpha_bits(void)298 default_alpha_bits(void)
299 {
300    int aBits;
301    const char *aEnv = getenv("MESA_GLX_ALPHA_BITS");
302    if (aEnv)
303       aBits = atoi(aEnv);
304    else
305       aBits = 0;
306    return aBits;
307 }
308 
309 static GLint
default_accum_bits(void)310 default_accum_bits(void)
311 {
312    return 16;
313 }
314 
315 
316 
317 /*
318  * Create a GLX visual from a regular XVisualInfo.
319  * This is called when Fake GLX is given an XVisualInfo which wasn't
320  * returned by glXChooseVisual.  Since this is the first time we're
321  * considering this visual we'll take a guess at reasonable values
322  * for depth buffer size, stencil size, accum size, etc.
323  * This is the best we can do with a client-side emulation of GLX.
324  */
325 static XMesaVisual
create_glx_visual(Display * dpy,XVisualInfo * visinfo)326 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
327 {
328    GLint zBits = default_depth_bits();
329    GLint accBits = default_accum_bits();
330    GLboolean alphaFlag = default_alpha_bits() > 0;
331 
332    if (is_usable_visual( visinfo )) {
333       /* Configure this visual as RGB, double-buffered, depth-buffered. */
334       /* This is surely wrong for some people's needs but what else */
335       /* can be done?  They should use glXChooseVisual(). */
336       return save_glx_visual( dpy, visinfo,
337                               GL_TRUE,   /* rgb */
338                               alphaFlag, /* alpha */
339                               GL_TRUE,   /* double */
340                               GL_FALSE,  /* stereo */
341                               zBits,
342                               8,       /* stencil bits */
343                               accBits, /* r */
344                               accBits, /* g */
345                               accBits, /* b */
346                               accBits, /* a */
347                               0,         /* level */
348                               0,         /* numAux */
349                               0          /* numSamples */
350          );
351    }
352    else {
353       _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
354       return NULL;
355    }
356 }
357 
358 
359 
360 /*
361  * Find the GLX visual associated with an XVisualInfo.
362  */
363 static XMesaVisual
find_glx_visual(Display * dpy,XVisualInfo * vinfo)364 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
365 {
366    int i;
367 
368    /* try to match visual id */
369    for (i=0;i<NumVisuals;i++) {
370       if (VisualTable[i]->display==dpy
371           && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
372          return VisualTable[i];
373       }
374    }
375 
376    /* if that fails, try to match pointers */
377    for (i=0;i<NumVisuals;i++) {
378       if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
379          return VisualTable[i];
380       }
381    }
382 
383    return NULL;
384 }
385 
386 
387 /**
388  * Try to get an X visual which matches the given arguments.
389  */
390 static XVisualInfo *
get_visual(Display * dpy,int scr,unsigned int depth,int xclass)391 get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
392 {
393    XVisualInfo temp, *vis;
394    long mask;
395    int n;
396    unsigned int default_depth;
397    int default_class;
398 
399    mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
400    temp.screen = scr;
401    temp.depth = depth;
402    temp.CLASS = xclass;
403 
404    default_depth = DefaultDepth(dpy,scr);
405    default_class = DefaultVisual(dpy,scr)->CLASS;
406 
407    if (depth==default_depth && xclass==default_class) {
408       /* try to get root window's visual */
409       temp.visualid = DefaultVisual(dpy,scr)->visualid;
410       mask |= VisualIDMask;
411    }
412 
413    vis = XGetVisualInfo( dpy, mask, &temp, &n );
414 
415    /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
416     * An SGI Infinite Reality system, for example, can have 30bpp pixels:
417     * 10 bits per color channel.  Mesa's limited to a max of 8 bits/channel.
418     */
419    if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
420       if (_mesa_bitcount((GLuint) vis->red_mask  ) <= 8 &&
421           _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
422           _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
423          return vis;
424       }
425       else {
426          free((void *) vis);
427          return NULL;
428       }
429    }
430 
431    return vis;
432 }
433 
434 
435 /*
436  * Retrieve the value of the given environment variable and find
437  * the X visual which matches it.
438  * Input:  dpy - the display
439  *         screen - the screen number
440  *         varname - the name of the environment variable
441  * Return:  an XVisualInfo pointer to NULL if error.
442  */
443 static XVisualInfo *
get_env_visual(Display * dpy,int scr,const char * varname)444 get_env_visual(Display *dpy, int scr, const char *varname)
445 {
446    char value[100], type[100];
447    int depth, xclass = -1;
448    XVisualInfo *vis;
449 
450    if (!getenv( varname )) {
451       return NULL;
452    }
453 
454    strncpy( value, getenv(varname), 100 );
455    value[99] = 0;
456 
457    sscanf( value, "%s %d", type, &depth );
458 
459    if (strcmp(type,"TrueColor")==0)          xclass = TrueColor;
460    else if (strcmp(type,"DirectColor")==0)   xclass = DirectColor;
461    else if (strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
462    else if (strcmp(type,"StaticColor")==0)   xclass = StaticColor;
463    else if (strcmp(type,"GrayScale")==0)     xclass = GrayScale;
464    else if (strcmp(type,"StaticGray")==0)    xclass = StaticGray;
465 
466    if (xclass>-1 && depth>0) {
467       vis = get_visual( dpy, scr, depth, xclass );
468       if (vis) {
469 	 return vis;
470       }
471    }
472 
473    _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
474                  type, depth);
475 
476    return NULL;
477 }
478 
479 
480 
481 /*
482  * Select an X visual which satisfies the RGBA flag and minimum depth.
483  * Input:  dpy,
484  *         screen - X display and screen number
485  *         min_depth - minimum visual depth
486  *         preferred_class - preferred GLX visual class or DONT_CARE
487  * Return:  pointer to an XVisualInfo or NULL.
488  */
489 static XVisualInfo *
choose_x_visual(Display * dpy,int screen,int min_depth,int preferred_class)490 choose_x_visual( Display *dpy, int screen, int min_depth,
491                  int preferred_class )
492 {
493    XVisualInfo *vis;
494    int xclass, visclass = 0;
495    int depth;
496 
497    /* First see if the MESA_RGB_VISUAL env var is defined */
498    vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
499    if (vis) {
500       return vis;
501    }
502    /* Otherwise, search for a suitable visual */
503    if (preferred_class==DONT_CARE) {
504       for (xclass=0;xclass<6;xclass++) {
505          switch (xclass) {
506          case 0:  visclass = TrueColor;    break;
507          case 1:  visclass = DirectColor;  break;
508          case 2:  visclass = PseudoColor;  break;
509          case 3:  visclass = StaticColor;  break;
510          case 4:  visclass = GrayScale;    break;
511          case 5:  visclass = StaticGray;   break;
512          }
513          if (min_depth==0) {
514             /* start with shallowest */
515             for (depth=0;depth<=32;depth++) {
516                if (visclass==TrueColor && depth==8) {
517                   /* Special case:  try to get 8-bit PseudoColor before */
518                   /* 8-bit TrueColor */
519                   vis = get_visual( dpy, screen, 8, PseudoColor );
520                   if (vis) {
521                      return vis;
522                   }
523                }
524                vis = get_visual( dpy, screen, depth, visclass );
525                if (vis) {
526                   return vis;
527                }
528             }
529          }
530          else {
531             /* start with deepest */
532             for (depth=32;depth>=min_depth;depth--) {
533                if (visclass==TrueColor && depth==8) {
534                   /* Special case:  try to get 8-bit PseudoColor before */
535                   /* 8-bit TrueColor */
536                   vis = get_visual( dpy, screen, 8, PseudoColor );
537                   if (vis) {
538                      return vis;
539                   }
540                }
541                vis = get_visual( dpy, screen, depth, visclass );
542                if (vis) {
543                   return vis;
544                }
545             }
546          }
547       }
548    }
549    else {
550       /* search for a specific visual class */
551       switch (preferred_class) {
552       case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
553       case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
554       case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
555       case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
556       case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
557       case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
558       default:   return NULL;
559       }
560       if (min_depth==0) {
561          /* start with shallowest */
562          for (depth=0;depth<=32;depth++) {
563             vis = get_visual( dpy, screen, depth, visclass );
564             if (vis) {
565                return vis;
566             }
567          }
568       }
569       else {
570          /* start with deepest */
571          for (depth=32;depth>=min_depth;depth--) {
572             vis = get_visual( dpy, screen, depth, visclass );
573             if (vis) {
574                return vis;
575             }
576          }
577       }
578    }
579 
580    /* didn't find a visual */
581    return NULL;
582 }
583 
584 
585 
586 
587 /**********************************************************************/
588 /***             Display-related functions                          ***/
589 /**********************************************************************/
590 
591 
592 /**
593  * Free all XMesaVisuals which are associated with the given display.
594  */
595 static void
destroy_visuals_on_display(Display * dpy)596 destroy_visuals_on_display(Display *dpy)
597 {
598    int i;
599    for (i = 0; i < NumVisuals; i++) {
600       if (VisualTable[i]->display == dpy) {
601          /* remove this visual */
602          int j;
603          free(VisualTable[i]);
604          for (j = i; j < NumVisuals - 1; j++)
605             VisualTable[j] = VisualTable[j + 1];
606          NumVisuals--;
607       }
608    }
609 }
610 
611 
612 /**
613  * Called from XCloseDisplay() to let us free our display-related data.
614  */
615 static int
close_display_callback(Display * dpy,XExtCodes * codes)616 close_display_callback(Display *dpy, XExtCodes *codes)
617 {
618    xmesa_destroy_buffers_on_display(dpy);
619    destroy_visuals_on_display(dpy);
620    xmesa_close_display(dpy);
621    return 0;
622 }
623 
624 
625 /**
626  * Look for the named extension on given display and return a pointer
627  * to the _XExtension data, or NULL if extension not found.
628  */
629 static _XExtension *
lookup_extension(Display * dpy,const char * extName)630 lookup_extension(Display *dpy, const char *extName)
631 {
632    _XExtension *ext;
633    for (ext = dpy->ext_procs; ext; ext = ext->next) {
634       if (ext->name && strcmp(ext->name, extName) == 0) {
635          return ext;
636       }
637    }
638    return NULL;
639 }
640 
641 
642 /**
643  * Whenever we're given a new Display pointer, call this function to
644  * register our close_display_callback function.
645  */
646 static void
register_with_display(Display * dpy)647 register_with_display(Display *dpy)
648 {
649    const char *extName = "MesaGLX";
650    _XExtension *ext;
651 
652    ext = lookup_extension(dpy, extName);
653    if (!ext) {
654       XExtCodes *c = XAddExtension(dpy);
655       ext = dpy->ext_procs;  /* new extension is at head of list */
656       assert(c->extension == ext->codes.extension);
657       (void) c;
658       ext->name = strdup(extName);
659       ext->close_display = close_display_callback;
660    }
661 }
662 
663 
664 /**
665  * Fake an error.
666  */
667 static int
generate_error(Display * dpy,unsigned char error_code,XID resourceid,unsigned char minor_code,Bool core)668 generate_error(Display *dpy,
669                unsigned char error_code,
670                XID resourceid,
671                unsigned char minor_code,
672                Bool core)
673 {
674    XErrorHandler handler;
675    int major_opcode;
676    int first_event;
677    int first_error;
678    XEvent event;
679 
680    handler = XSetErrorHandler(NULL);
681    XSetErrorHandler(handler);
682    if (!handler) {
683       return 0;
684    }
685 
686    if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) {
687       major_opcode = 0;
688       first_event = 0;
689       first_error = 0;
690    }
691 
692    if (!core) {
693       error_code += first_error;
694    }
695 
696    memset(&event, 0, sizeof event);
697 
698    event.xerror.type = X_Error;
699    event.xerror.display = dpy;
700    event.xerror.resourceid = resourceid;
701    event.xerror.serial = NextRequest(dpy) - 1;
702    event.xerror.error_code = error_code;
703    event.xerror.request_code = major_opcode;
704    event.xerror.minor_code = minor_code;
705 
706    return handler(dpy, &event.xerror);
707 }
708 
709 
710 /**********************************************************************/
711 /***                  Begin Fake GLX API Functions                  ***/
712 /**********************************************************************/
713 
714 
715 /**
716  * Helper used by glXChooseVisual and glXChooseFBConfig.
717  * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for
718  * the later.
719  * In either case, the attribute list is terminated with the value 'None'.
720  */
721 static XMesaVisual
choose_visual(Display * dpy,int screen,const int * list,GLboolean fbConfig)722 choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
723 {
724    const GLboolean rgbModeDefault = fbConfig;
725    const int *parselist;
726    XVisualInfo *vis;
727    int min_red=0, min_green=0, min_blue=0;
728    GLboolean rgb_flag = rgbModeDefault;
729    GLboolean alpha_flag = GL_FALSE;
730    GLboolean double_flag = GL_FALSE;
731    GLboolean stereo_flag = GL_FALSE;
732    GLint depth_size = 0;
733    GLint stencil_size = 0;
734    GLint accumRedSize = 0;
735    GLint accumGreenSize = 0;
736    GLint accumBlueSize = 0;
737    GLint accumAlphaSize = 0;
738    int level = 0;
739    int visual_type = DONT_CARE;
740    GLint caveat = DONT_CARE;
741    XMesaVisual xmvis = NULL;
742    int desiredVisualID = -1;
743    int numAux = 0;
744    GLint num_samples = 0;
745 
746    if (xmesa_init( dpy ) != 0) {
747       _mesa_warning(NULL, "Failed to initialize display");
748       return NULL;
749    }
750 
751    parselist = list;
752 
753    while (*parselist) {
754 
755       if (fbConfig &&
756           parselist[1] == GLX_DONT_CARE &&
757           parselist[0] != GLX_LEVEL) {
758          /* For glXChooseFBConfig(), skip attributes whose value is
759           * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be
760           * a negative value).
761           *
762           * From page 17 (23 of the pdf) of the GLX 1.4 spec:
763           * GLX DONT CARE may be specified for all attributes except GLX LEVEL.
764           */
765          parselist += 2;
766          continue;
767       }
768 
769       switch (*parselist) {
770 	 case GLX_USE_GL:
771             if (fbConfig) {
772                /* invalid token */
773                return NULL;
774             }
775             else {
776                /* skip */
777                parselist++;
778             }
779 	    break;
780 	 case GLX_BUFFER_SIZE:
781 	    parselist++;
782 	    parselist++;
783 	    break;
784 	 case GLX_LEVEL:
785 	    parselist++;
786             level = *parselist++;
787 	    break;
788 	 case GLX_RGBA:
789             if (fbConfig) {
790                /* invalid token */
791                return NULL;
792             }
793             else {
794                rgb_flag = GL_TRUE;
795                parselist++;
796             }
797 	    break;
798 	 case GLX_DOUBLEBUFFER:
799             parselist++;
800             if (fbConfig) {
801                double_flag = *parselist++;
802             }
803             else {
804                double_flag = GL_TRUE;
805             }
806 	    break;
807 	 case GLX_STEREO:
808             parselist++;
809             if (fbConfig) {
810                stereo_flag = *parselist++;
811             }
812             else {
813                stereo_flag = GL_TRUE;
814             }
815             break;
816 	 case GLX_AUX_BUFFERS:
817 	    parselist++;
818             numAux = *parselist++;
819             if (numAux > MAX_AUX_BUFFERS)
820                return NULL;
821 	    break;
822 	 case GLX_RED_SIZE:
823 	    parselist++;
824 	    min_red = *parselist++;
825 	    break;
826 	 case GLX_GREEN_SIZE:
827 	    parselist++;
828 	    min_green = *parselist++;
829 	    break;
830 	 case GLX_BLUE_SIZE:
831 	    parselist++;
832 	    min_blue = *parselist++;
833 	    break;
834 	 case GLX_ALPHA_SIZE:
835 	    parselist++;
836             {
837                GLint size = *parselist++;
838                alpha_flag = size ? GL_TRUE : GL_FALSE;
839             }
840 	    break;
841 	 case GLX_DEPTH_SIZE:
842 	    parselist++;
843 	    depth_size = *parselist++;
844 	    break;
845 	 case GLX_STENCIL_SIZE:
846 	    parselist++;
847 	    stencil_size = *parselist++;
848 	    break;
849 	 case GLX_ACCUM_RED_SIZE:
850 	    parselist++;
851             {
852                GLint size = *parselist++;
853                accumRedSize = MAX2( accumRedSize, size );
854             }
855             break;
856 	 case GLX_ACCUM_GREEN_SIZE:
857 	    parselist++;
858             {
859                GLint size = *parselist++;
860                accumGreenSize = MAX2( accumGreenSize, size );
861             }
862             break;
863 	 case GLX_ACCUM_BLUE_SIZE:
864 	    parselist++;
865             {
866                GLint size = *parselist++;
867                accumBlueSize = MAX2( accumBlueSize, size );
868             }
869             break;
870 	 case GLX_ACCUM_ALPHA_SIZE:
871 	    parselist++;
872             {
873                GLint size = *parselist++;
874                accumAlphaSize = MAX2( accumAlphaSize, size );
875             }
876 	    break;
877 
878          /*
879           * GLX_EXT_visual_info extension
880           */
881          case GLX_X_VISUAL_TYPE_EXT:
882             parselist++;
883             visual_type = *parselist++;
884             break;
885          case GLX_TRANSPARENT_TYPE_EXT:
886             parselist++;
887             parselist++;
888             break;
889          case GLX_TRANSPARENT_INDEX_VALUE_EXT:
890             parselist++;
891             parselist++;
892             break;
893          case GLX_TRANSPARENT_RED_VALUE_EXT:
894          case GLX_TRANSPARENT_GREEN_VALUE_EXT:
895          case GLX_TRANSPARENT_BLUE_VALUE_EXT:
896          case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
897 	    /* ignore */
898 	    parselist++;
899 	    parselist++;
900 	    break;
901 
902          /*
903           * GLX_EXT_visual_info extension
904           */
905          case GLX_VISUAL_CAVEAT_EXT:
906             parselist++;
907             caveat = *parselist++; /* ignored for now */
908             break;
909 
910          /*
911           * GLX_ARB_multisample
912           */
913          case GLX_SAMPLE_BUFFERS_ARB:
914             /* ignore */
915             parselist++;
916             parselist++;
917             break;
918          case GLX_SAMPLES_ARB:
919             parselist++;
920             num_samples = *parselist++;
921             break;
922 
923          /*
924           * FBConfig attribs.
925           */
926          case GLX_RENDER_TYPE:
927             if (!fbConfig)
928                return NULL;
929             parselist++;
930             if (*parselist & GLX_RGBA_BIT) {
931                rgb_flag = GL_TRUE;
932             }
933             else if (*parselist & GLX_COLOR_INDEX_BIT) {
934                rgb_flag = GL_FALSE;
935             }
936             else if (*parselist == 0) {
937                rgb_flag = GL_TRUE;
938             }
939             parselist++;
940             break;
941          case GLX_DRAWABLE_TYPE:
942             if (!fbConfig)
943                return NULL;
944             parselist++;
945             if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
946                return NULL; /* bad bit */
947             }
948             parselist++;
949             break;
950          case GLX_FBCONFIG_ID:
951          case GLX_VISUAL_ID:
952             if (!fbConfig)
953                return NULL;
954             parselist++;
955             desiredVisualID = *parselist++;
956             break;
957          case GLX_X_RENDERABLE:
958          case GLX_MAX_PBUFFER_WIDTH:
959          case GLX_MAX_PBUFFER_HEIGHT:
960          case GLX_MAX_PBUFFER_PIXELS:
961             if (!fbConfig)
962                return NULL; /* invalid config option */
963             parselist += 2; /* ignore the parameter */
964             break;
965 
966          case GLX_BIND_TO_TEXTURE_RGB_EXT:
967             parselist++; /*skip*/
968             break;
969          case GLX_BIND_TO_TEXTURE_RGBA_EXT:
970             parselist++; /*skip*/
971             break;
972          case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
973             parselist++; /*skip*/
974             break;
975          case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
976             parselist++;
977             if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
978                                GLX_TEXTURE_2D_BIT_EXT |
979                                GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
980                /* invalid bit */
981                return NULL;
982             }
983             break;
984          case GLX_Y_INVERTED_EXT:
985             parselist++; /*skip*/
986             break;
987 
988 	 case None:
989             /* end of list */
990 	    break;
991 
992 	 default:
993 	    /* undefined attribute */
994             _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
995                           *parselist);
996 	    return NULL;
997       }
998    }
999 
1000    (void) caveat;
1001 
1002    if (num_samples < 0) {
1003       _mesa_warning(NULL, "GLX_SAMPLES_ARB: number of samples must not be negative");
1004       return NULL;
1005    }
1006 
1007    /*
1008     * Since we're only simulating the GLX extension this function will never
1009     * find any real GL visuals.  Instead, all we can do is try to find an RGB
1010     * or CI visual of appropriate depth.  Other requested attributes such as
1011     * double buffering, depth buffer, etc. will be associated with the X
1012     * visual and stored in the VisualTable[].
1013     */
1014    if (desiredVisualID != -1) {
1015       /* try to get a specific visual, by visualID */
1016       XVisualInfo temp;
1017       int n;
1018       temp.visualid = desiredVisualID;
1019       temp.screen = screen;
1020       vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
1021       if (vis) {
1022          /* give the visual some useful GLX attributes */
1023          double_flag = GL_TRUE;
1024          rgb_flag = GL_TRUE;
1025       }
1026    }
1027    else if (level==0) {
1028       /* normal color planes */
1029       /* Get an RGB visual */
1030       int min_rgb = min_red + min_green + min_blue;
1031       if (min_rgb>1 && min_rgb<8) {
1032          /* a special case to be sure we can get a monochrome visual */
1033          min_rgb = 1;
1034       }
1035       vis = choose_x_visual( dpy, screen, min_rgb, visual_type );
1036    }
1037    else {
1038       _mesa_warning(NULL, "overlay not supported");
1039       return NULL;
1040    }
1041 
1042    if (vis) {
1043       /* Note: we're not exactly obeying the glXChooseVisual rules here.
1044        * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
1045        * largest depth buffer size, which is 32bits/value.  Instead, we
1046        * return 16 to maintain performance with earlier versions of Mesa.
1047        */
1048       if (stencil_size > 0)
1049          depth_size = 24;  /* if Z and stencil, always use 24+8 format */
1050       else if (depth_size > 24)
1051          depth_size = 32;
1052       else if (depth_size > 16)
1053          depth_size = 24;
1054       else if (depth_size > 0) {
1055          depth_size = default_depth_bits();
1056       }
1057 
1058       if (!alpha_flag) {
1059          alpha_flag = default_alpha_bits() > 0;
1060       }
1061 
1062       /* we only support one size of stencil and accum buffers. */
1063       if (stencil_size > 0)
1064          stencil_size = 8;
1065 
1066       if (accumRedSize > 0 ||
1067           accumGreenSize > 0 ||
1068           accumBlueSize > 0 ||
1069           accumAlphaSize > 0) {
1070 
1071          accumRedSize =
1072             accumGreenSize =
1073             accumBlueSize = default_accum_bits();
1074 
1075          accumAlphaSize = alpha_flag ? accumRedSize : 0;
1076       }
1077 
1078       xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1079                                stereo_flag, depth_size, stencil_size,
1080                                accumRedSize, accumGreenSize,
1081                                accumBlueSize, accumAlphaSize, level, numAux,
1082                                num_samples );
1083    }
1084 
1085    return xmvis;
1086 }
1087 
1088 
1089 PUBLIC XVisualInfo *
glXChooseVisual(Display * dpy,int screen,int * list)1090 glXChooseVisual( Display *dpy, int screen, int *list )
1091 {
1092    XMesaVisual xmvis;
1093 
1094    /* register ourselves as an extension on this display */
1095    register_with_display(dpy);
1096 
1097    xmvis = choose_visual(dpy, screen, list, GL_FALSE);
1098    if (xmvis) {
1099       /* create a new vishandle - the cached one may be stale */
1100       xmvis->vishandle = malloc(sizeof(XVisualInfo));
1101       if (xmvis->vishandle) {
1102          memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
1103       }
1104       return xmvis->vishandle;
1105    }
1106    else
1107       return NULL;
1108 }
1109 
1110 
1111 /**
1112  * Helper function used by other glXCreateContext functions.
1113  */
1114 static GLXContext
create_context(Display * dpy,XMesaVisual xmvis,XMesaContext shareCtx,Bool direct,unsigned major,unsigned minor,unsigned profileMask,unsigned contextFlags)1115 create_context(Display *dpy, XMesaVisual xmvis,
1116                XMesaContext shareCtx, Bool direct,
1117                unsigned major, unsigned minor,
1118                unsigned profileMask, unsigned contextFlags)
1119 {
1120    GLXContext glxCtx;
1121 
1122    if (!dpy || !xmvis)
1123       return 0;
1124 
1125    glxCtx = CALLOC_STRUCT(__GLXcontextRec);
1126    if (!glxCtx)
1127       return 0;
1128 
1129    /* deallocate unused windows/buffers */
1130 #if 0
1131    XMesaGarbageCollect();
1132 #endif
1133 
1134    glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor,
1135                                              profileMask, contextFlags);
1136    if (!glxCtx->xmesaContext) {
1137       free(glxCtx);
1138       return NULL;
1139    }
1140 
1141    glxCtx->isDirect = DEFAULT_DIRECT;
1142    glxCtx->currentDpy = dpy;
1143    glxCtx->xid = (XID) glxCtx;  /* self pointer */
1144 
1145    return glxCtx;
1146 }
1147 
1148 
1149 PUBLIC GLXContext
glXCreateContext(Display * dpy,XVisualInfo * visinfo,GLXContext shareCtx,Bool direct)1150 glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1151                   GLXContext shareCtx, Bool direct )
1152 {
1153    XMesaVisual xmvis;
1154 
1155    xmvis = find_glx_visual( dpy, visinfo );
1156    if (!xmvis) {
1157       /* This visual wasn't found with glXChooseVisual() */
1158       xmvis = create_glx_visual( dpy, visinfo );
1159       if (!xmvis) {
1160          /* unusable visual */
1161          return NULL;
1162       }
1163    }
1164 
1165    return create_context(dpy, xmvis,
1166                          shareCtx ? shareCtx->xmesaContext : NULL,
1167                          direct,
1168                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
1169 }
1170 
1171 
1172 /* XXX these may have to be removed due to thread-safety issues. */
1173 static GLXContext MakeCurrent_PrevContext = 0;
1174 static GLXDrawable MakeCurrent_PrevDrawable = 0;
1175 static GLXDrawable MakeCurrent_PrevReadable = 0;
1176 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
1177 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
1178 
1179 
1180 /* GLX 1.3 and later */
1181 PUBLIC Bool
glXMakeContextCurrent(Display * dpy,GLXDrawable draw,GLXDrawable read,GLXContext ctx)1182 glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
1183                        GLXDrawable read, GLXContext ctx )
1184 {
1185    GLXContext glxCtx = ctx;
1186    static boolean firsttime = 1, no_rast = 0;
1187 
1188    if (firsttime) {
1189       no_rast = getenv("SP_NO_RAST") != NULL;
1190       firsttime = 0;
1191    }
1192 
1193    if (ctx && draw && read) {
1194       XMesaBuffer drawBuffer, readBuffer;
1195       XMesaContext xmctx = glxCtx->xmesaContext;
1196 
1197       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
1198       if (ctx == MakeCurrent_PrevContext
1199           && draw == MakeCurrent_PrevDrawable) {
1200          drawBuffer = MakeCurrent_PrevDrawBuffer;
1201       }
1202       else {
1203          drawBuffer = XMesaFindBuffer( dpy, draw );
1204       }
1205       if (!drawBuffer) {
1206          /* drawable must be a new window! */
1207          drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
1208          if (!drawBuffer) {
1209             /* Out of memory, or context/drawable depth mismatch */
1210             return False;
1211          }
1212       }
1213 
1214       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
1215       if (ctx == MakeCurrent_PrevContext
1216           && read == MakeCurrent_PrevReadable) {
1217          readBuffer = MakeCurrent_PrevReadBuffer;
1218       }
1219       else {
1220          readBuffer = XMesaFindBuffer( dpy, read );
1221       }
1222       if (!readBuffer) {
1223          /* drawable must be a new window! */
1224          readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
1225          if (!readBuffer) {
1226             /* Out of memory, or context/drawable depth mismatch */
1227             return False;
1228          }
1229       }
1230 
1231       if (no_rast &&
1232           MakeCurrent_PrevContext == ctx &&
1233           MakeCurrent_PrevDrawable == draw &&
1234           MakeCurrent_PrevReadable == read &&
1235           MakeCurrent_PrevDrawBuffer == drawBuffer &&
1236           MakeCurrent_PrevReadBuffer == readBuffer)
1237          return True;
1238 
1239       MakeCurrent_PrevContext = ctx;
1240       MakeCurrent_PrevDrawable = draw;
1241       MakeCurrent_PrevReadable = read;
1242       MakeCurrent_PrevDrawBuffer = drawBuffer;
1243       MakeCurrent_PrevReadBuffer = readBuffer;
1244 
1245       /* Now make current! */
1246       if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
1247          ctx->currentDpy = dpy;
1248          ctx->currentDrawable = draw;
1249          ctx->currentReadable = read;
1250          SetCurrentContext(ctx);
1251          return True;
1252       }
1253       else {
1254          return False;
1255       }
1256    }
1257    else if (!ctx && !draw && !read) {
1258       /* release current context w/out assigning new one. */
1259       XMesaMakeCurrent2( NULL, NULL, NULL );
1260       MakeCurrent_PrevContext = 0;
1261       MakeCurrent_PrevDrawable = 0;
1262       MakeCurrent_PrevReadable = 0;
1263       MakeCurrent_PrevDrawBuffer = 0;
1264       MakeCurrent_PrevReadBuffer = 0;
1265       SetCurrentContext(NULL);
1266       return True;
1267    }
1268    else {
1269       /* The args must either all be non-zero or all zero.
1270        * This is an error.
1271        */
1272       return False;
1273    }
1274 }
1275 
1276 
1277 PUBLIC Bool
glXMakeCurrent(Display * dpy,GLXDrawable drawable,GLXContext ctx)1278 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1279 {
1280    return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1281 }
1282 
1283 
1284 PUBLIC GLXContext
glXGetCurrentContext(void)1285 glXGetCurrentContext(void)
1286 {
1287    return GetCurrentContext();
1288 }
1289 
1290 
1291 PUBLIC Display *
glXGetCurrentDisplay(void)1292 glXGetCurrentDisplay(void)
1293 {
1294    GLXContext glxCtx = glXGetCurrentContext();
1295 
1296    return glxCtx ? glxCtx->currentDpy : NULL;
1297 }
1298 
1299 
1300 PUBLIC Display *
glXGetCurrentDisplayEXT(void)1301 glXGetCurrentDisplayEXT(void)
1302 {
1303    return glXGetCurrentDisplay();
1304 }
1305 
1306 
1307 PUBLIC GLXDrawable
glXGetCurrentDrawable(void)1308 glXGetCurrentDrawable(void)
1309 {
1310    GLXContext gc = glXGetCurrentContext();
1311    return gc ? gc->currentDrawable : 0;
1312 }
1313 
1314 
1315 PUBLIC GLXDrawable
glXGetCurrentReadDrawable(void)1316 glXGetCurrentReadDrawable(void)
1317 {
1318    GLXContext gc = glXGetCurrentContext();
1319    return gc ? gc->currentReadable : 0;
1320 }
1321 
1322 
1323 PUBLIC GLXDrawable
glXGetCurrentReadDrawableSGI(void)1324 glXGetCurrentReadDrawableSGI(void)
1325 {
1326    return glXGetCurrentReadDrawable();
1327 }
1328 
1329 
1330 PUBLIC GLXPixmap
glXCreateGLXPixmap(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap)1331 glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
1332 {
1333    XMesaVisual v;
1334    XMesaBuffer b;
1335 
1336    v = find_glx_visual( dpy, visinfo );
1337    if (!v) {
1338       v = create_glx_visual( dpy, visinfo );
1339       if (!v) {
1340          /* unusable visual */
1341          return 0;
1342       }
1343    }
1344 
1345    b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1346    if (!b) {
1347       return 0;
1348    }
1349    return b->ws.drawable;
1350 }
1351 
1352 
1353 /*** GLX_MESA_pixmap_colormap ***/
1354 
1355 PUBLIC GLXPixmap
glXCreateGLXPixmapMESA(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap,Colormap cmap)1356 glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1357                         Pixmap pixmap, Colormap cmap )
1358 {
1359    XMesaVisual v;
1360    XMesaBuffer b;
1361 
1362    v = find_glx_visual( dpy, visinfo );
1363    if (!v) {
1364       v = create_glx_visual( dpy, visinfo );
1365       if (!v) {
1366          /* unusable visual */
1367          return 0;
1368       }
1369    }
1370 
1371    b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1372    if (!b) {
1373       return 0;
1374    }
1375    return b->ws.drawable;
1376 }
1377 
1378 
1379 PUBLIC void
glXDestroyGLXPixmap(Display * dpy,GLXPixmap pixmap)1380 glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1381 {
1382    XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1383    if (b) {
1384       XMesaDestroyBuffer(b);
1385    }
1386    else if (getenv("MESA_DEBUG")) {
1387       _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1388    }
1389 }
1390 
1391 
1392 PUBLIC void
glXCopyContext(Display * dpy,GLXContext src,GLXContext dst,unsigned long mask)1393 glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1394                 unsigned long mask )
1395 {
1396    XMesaContext xm_src = src->xmesaContext;
1397    XMesaContext xm_dst = dst->xmesaContext;
1398    (void) dpy;
1399    if (MakeCurrent_PrevContext == src) {
1400       glFlush();
1401    }
1402    XMesaCopyContext(xm_src, xm_dst, mask);
1403 }
1404 
1405 
1406 PUBLIC Bool
glXQueryExtension(Display * dpy,int * errorBase,int * eventBase)1407 glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
1408 {
1409    int op, ev, err;
1410    /* Mesa's GLX isn't really an X extension but we try to act like one. */
1411    if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))
1412       ev = err = 0;
1413    if (errorBase)
1414       *errorBase = err;
1415    if (eventBase)
1416       *eventBase = ev;
1417    return True; /* we're faking GLX so always return success */
1418 }
1419 
1420 
1421 PUBLIC void
glXDestroyContext(Display * dpy,GLXContext ctx)1422 glXDestroyContext( Display *dpy, GLXContext ctx )
1423 {
1424    if (ctx) {
1425       GLXContext glxCtx = ctx;
1426       (void) dpy;
1427       MakeCurrent_PrevContext = 0;
1428       MakeCurrent_PrevDrawable = 0;
1429       MakeCurrent_PrevReadable = 0;
1430       MakeCurrent_PrevDrawBuffer = 0;
1431       MakeCurrent_PrevReadBuffer = 0;
1432       XMesaDestroyContext( glxCtx->xmesaContext );
1433       XMesaGarbageCollect();
1434       free(glxCtx);
1435    }
1436 }
1437 
1438 
1439 PUBLIC Bool
glXIsDirect(Display * dpy,GLXContext ctx)1440 glXIsDirect( Display *dpy, GLXContext ctx )
1441 {
1442    return ctx ? ctx->isDirect : False;
1443 }
1444 
1445 
1446 
1447 PUBLIC void
glXSwapBuffers(Display * dpy,GLXDrawable drawable)1448 glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1449 {
1450    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1451    static boolean firsttime = 1, no_rast = 0;
1452 
1453    if (firsttime) {
1454       no_rast = getenv("SP_NO_RAST") != NULL;
1455       firsttime = 0;
1456    }
1457 
1458    if (no_rast)
1459       return;
1460 
1461    if (buffer) {
1462       XMesaSwapBuffers(buffer);
1463    }
1464    else if (getenv("MESA_DEBUG")) {
1465       _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
1466                     (int) drawable);
1467    }
1468 }
1469 
1470 
1471 
1472 /*** GLX_MESA_copy_sub_buffer ***/
1473 
1474 PUBLIC void
glXCopySubBufferMESA(Display * dpy,GLXDrawable drawable,int x,int y,int width,int height)1475 glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
1476                      int x, int y, int width, int height)
1477 {
1478    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1479    if (buffer) {
1480       XMesaCopySubBuffer(buffer, x, y, width, height);
1481    }
1482    else if (getenv("MESA_DEBUG")) {
1483       _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
1484    }
1485 }
1486 
1487 
1488 PUBLIC Bool
glXQueryVersion(Display * dpy,int * maj,int * min)1489 glXQueryVersion( Display *dpy, int *maj, int *min )
1490 {
1491    (void) dpy;
1492    /* Return GLX version, not Mesa version */
1493    assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
1494    *maj = CLIENT_MAJOR_VERSION;
1495    *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
1496    return True;
1497 }
1498 
1499 
1500 /*
1501  * Query the GLX attributes of the given XVisualInfo.
1502  */
1503 static int
get_config(XMesaVisual xmvis,int attrib,int * value,GLboolean fbconfig)1504 get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
1505 {
1506    assert(xmvis);
1507    switch(attrib) {
1508       case GLX_USE_GL:
1509          if (fbconfig)
1510             return GLX_BAD_ATTRIBUTE;
1511          *value = (int) True;
1512 	 return 0;
1513       case GLX_BUFFER_SIZE:
1514 	 *value = xmvis->visinfo->depth;
1515 	 return 0;
1516       case GLX_LEVEL:
1517 	 *value = xmvis->mesa_visual.level;
1518 	 return 0;
1519       case GLX_RGBA:
1520          if (fbconfig)
1521             return GLX_BAD_ATTRIBUTE;
1522 	 if (xmvis->mesa_visual.rgbMode) {
1523 	    *value = True;
1524 	 }
1525 	 else {
1526 	    *value = False;
1527 	 }
1528 	 return 0;
1529       case GLX_DOUBLEBUFFER:
1530 	 *value = (int) xmvis->mesa_visual.doubleBufferMode;
1531 	 return 0;
1532       case GLX_STEREO:
1533 	 *value = (int) xmvis->mesa_visual.stereoMode;
1534 	 return 0;
1535       case GLX_AUX_BUFFERS:
1536 	 *value = xmvis->mesa_visual.numAuxBuffers;
1537 	 return 0;
1538       case GLX_RED_SIZE:
1539          *value = xmvis->mesa_visual.redBits;
1540 	 return 0;
1541       case GLX_GREEN_SIZE:
1542          *value = xmvis->mesa_visual.greenBits;
1543 	 return 0;
1544       case GLX_BLUE_SIZE:
1545          *value = xmvis->mesa_visual.blueBits;
1546 	 return 0;
1547       case GLX_ALPHA_SIZE:
1548          *value = xmvis->mesa_visual.alphaBits;
1549 	 return 0;
1550       case GLX_DEPTH_SIZE:
1551          *value = xmvis->mesa_visual.depthBits;
1552 	 return 0;
1553       case GLX_STENCIL_SIZE:
1554 	 *value = xmvis->mesa_visual.stencilBits;
1555 	 return 0;
1556       case GLX_ACCUM_RED_SIZE:
1557 	 *value = xmvis->mesa_visual.accumRedBits;
1558 	 return 0;
1559       case GLX_ACCUM_GREEN_SIZE:
1560 	 *value = xmvis->mesa_visual.accumGreenBits;
1561 	 return 0;
1562       case GLX_ACCUM_BLUE_SIZE:
1563 	 *value = xmvis->mesa_visual.accumBlueBits;
1564 	 return 0;
1565       case GLX_ACCUM_ALPHA_SIZE:
1566          *value = xmvis->mesa_visual.accumAlphaBits;
1567 	 return 0;
1568 
1569       /*
1570        * GLX_EXT_visual_info extension
1571        */
1572       case GLX_X_VISUAL_TYPE_EXT:
1573          switch (xmvis->visinfo->CLASS) {
1574             case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
1575             case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
1576             case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
1577             case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
1578             case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
1579             case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
1580          }
1581          return 0;
1582       case GLX_TRANSPARENT_TYPE_EXT:
1583          /* normal planes */
1584          *value = GLX_NONE_EXT;
1585          return 0;
1586       case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1587          /* undefined */
1588          return 0;
1589       case GLX_TRANSPARENT_RED_VALUE_EXT:
1590          /* undefined */
1591          return 0;
1592       case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1593          /* undefined */
1594          return 0;
1595       case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1596          /* undefined */
1597          return 0;
1598       case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1599          /* undefined */
1600          return 0;
1601 
1602       /*
1603        * GLX_EXT_visual_info extension
1604        */
1605       case GLX_VISUAL_CAVEAT_EXT:
1606          /* test for zero, just in case */
1607          if (xmvis->mesa_visual.visualRating > 0)
1608             *value = xmvis->mesa_visual.visualRating;
1609          else
1610             *value = GLX_NONE_EXT;
1611          return 0;
1612 
1613       /*
1614        * GLX_ARB_multisample
1615        */
1616       case GLX_SAMPLE_BUFFERS_ARB:
1617          *value = xmvis->mesa_visual.sampleBuffers;
1618          return 0;
1619       case GLX_SAMPLES_ARB:
1620          *value = xmvis->mesa_visual.samples;
1621          return 0;
1622 
1623       /*
1624        * For FBConfigs:
1625        */
1626       case GLX_SCREEN_EXT:
1627          if (!fbconfig)
1628             return GLX_BAD_ATTRIBUTE;
1629          *value = xmvis->visinfo->screen;
1630          break;
1631       case GLX_DRAWABLE_TYPE: /*SGIX too */
1632          if (!fbconfig)
1633             return GLX_BAD_ATTRIBUTE;
1634          *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
1635          break;
1636       case GLX_RENDER_TYPE_SGIX:
1637          if (!fbconfig)
1638             return GLX_BAD_ATTRIBUTE;
1639          if (xmvis->mesa_visual.rgbMode)
1640             *value = GLX_RGBA_BIT;
1641          else
1642             *value = GLX_COLOR_INDEX_BIT;
1643          break;
1644       case GLX_X_RENDERABLE_SGIX:
1645          if (!fbconfig)
1646             return GLX_BAD_ATTRIBUTE;
1647          *value = True; /* XXX really? */
1648          break;
1649       case GLX_FBCONFIG_ID_SGIX:
1650          if (!fbconfig)
1651             return GLX_BAD_ATTRIBUTE;
1652          *value = xmvis->visinfo->visualid;
1653          break;
1654       case GLX_MAX_PBUFFER_WIDTH:
1655          if (!fbconfig)
1656             return GLX_BAD_ATTRIBUTE;
1657          /* XXX should be same as ctx->Const.MaxRenderbufferSize */
1658          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
1659          break;
1660       case GLX_MAX_PBUFFER_HEIGHT:
1661          if (!fbconfig)
1662             return GLX_BAD_ATTRIBUTE;
1663          *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1664          break;
1665       case GLX_MAX_PBUFFER_PIXELS:
1666          if (!fbconfig)
1667             return GLX_BAD_ATTRIBUTE;
1668          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
1669                   DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1670          break;
1671       case GLX_VISUAL_ID:
1672          if (!fbconfig)
1673             return GLX_BAD_ATTRIBUTE;
1674          *value = xmvis->visinfo->visualid;
1675          break;
1676 
1677       case GLX_BIND_TO_TEXTURE_RGB_EXT:
1678          *value = True; /*XXX*/
1679          break;
1680       case GLX_BIND_TO_TEXTURE_RGBA_EXT:
1681          /* XXX review */
1682          *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
1683          break;
1684       case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
1685          *value = True; /*XXX*/
1686          break;
1687       case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
1688          *value = (GLX_TEXTURE_1D_BIT_EXT |
1689                    GLX_TEXTURE_2D_BIT_EXT |
1690                    GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
1691          break;
1692       case GLX_Y_INVERTED_EXT:
1693          *value = True; /*XXX*/
1694          break;
1695 
1696       default:
1697 	 return GLX_BAD_ATTRIBUTE;
1698    }
1699    return Success;
1700 }
1701 
1702 
1703 PUBLIC int
glXGetConfig(Display * dpy,XVisualInfo * visinfo,int attrib,int * value)1704 glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1705                    int attrib, int *value )
1706 {
1707    XMesaVisual xmvis;
1708    int k;
1709    if (!dpy || !visinfo)
1710       return GLX_BAD_ATTRIBUTE;
1711 
1712    xmvis = find_glx_visual( dpy, visinfo );
1713    if (!xmvis) {
1714       /* this visual wasn't obtained with glXChooseVisual */
1715       xmvis = create_glx_visual( dpy, visinfo );
1716       if (!xmvis) {
1717 	 /* this visual can't be used for GL rendering */
1718 	 if (attrib==GLX_USE_GL) {
1719 	    *value = (int) False;
1720 	    return 0;
1721 	 }
1722 	 else {
1723 	    return GLX_BAD_VISUAL;
1724 	 }
1725       }
1726    }
1727 
1728    k = get_config(xmvis, attrib, value, GL_FALSE);
1729    return k;
1730 }
1731 
1732 
1733 PUBLIC void
glXWaitGL(void)1734 glXWaitGL( void )
1735 {
1736    XMesaContext xmesa = XMesaGetCurrentContext();
1737    XMesaFlush( xmesa );
1738 }
1739 
1740 
1741 
1742 PUBLIC void
glXWaitX(void)1743 glXWaitX( void )
1744 {
1745    XMesaContext xmesa = XMesaGetCurrentContext();
1746    XMesaFlush( xmesa );
1747 }
1748 
1749 
1750 static const char *
get_extensions(void)1751 get_extensions( void )
1752 {
1753    return EXTENSIONS;
1754 }
1755 
1756 
1757 
1758 /* GLX 1.1 and later */
1759 PUBLIC const char *
glXQueryExtensionsString(Display * dpy,int screen)1760 glXQueryExtensionsString( Display *dpy, int screen )
1761 {
1762    (void) dpy;
1763    (void) screen;
1764    return get_extensions();
1765 }
1766 
1767 
1768 
1769 /* GLX 1.1 and later */
1770 PUBLIC const char *
glXQueryServerString(Display * dpy,int screen,int name)1771 glXQueryServerString( Display *dpy, int screen, int name )
1772 {
1773    static char version[1000];
1774    sprintf(version, "%d.%d %s",
1775 	   SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name());
1776 
1777    (void) dpy;
1778    (void) screen;
1779 
1780    switch (name) {
1781       case GLX_EXTENSIONS:
1782          return get_extensions();
1783       case GLX_VENDOR:
1784 	 return VENDOR;
1785       case GLX_VERSION:
1786 	 return version;
1787       default:
1788          return NULL;
1789    }
1790 }
1791 
1792 
1793 
1794 /* GLX 1.1 and later */
1795 PUBLIC const char *
glXGetClientString(Display * dpy,int name)1796 glXGetClientString( Display *dpy, int name )
1797 {
1798    static char version[1000];
1799    sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
1800 	   CLIENT_MINOR_VERSION, xmesa_get_name());
1801 
1802    (void) dpy;
1803 
1804    switch (name) {
1805       case GLX_EXTENSIONS:
1806          return get_extensions();
1807       case GLX_VENDOR:
1808 	 return VENDOR;
1809       case GLX_VERSION:
1810 	 return version;
1811       default:
1812          return NULL;
1813    }
1814 }
1815 
1816 
1817 
1818 /*
1819  * GLX 1.3 and later
1820  */
1821 
1822 
1823 PUBLIC int
glXGetFBConfigAttrib(Display * dpy,GLXFBConfig config,int attribute,int * value)1824 glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
1825                      int attribute, int *value)
1826 {
1827    XMesaVisual v = (XMesaVisual) config;
1828    (void) dpy;
1829    (void) config;
1830 
1831    if (!dpy || !config || !value)
1832       return -1;
1833 
1834    return get_config(v, attribute, value, GL_TRUE);
1835 }
1836 
1837 
1838 PUBLIC GLXFBConfig *
glXGetFBConfigs(Display * dpy,int screen,int * nelements)1839 glXGetFBConfigs( Display *dpy, int screen, int *nelements )
1840 {
1841    XVisualInfo *visuals, visTemplate;
1842    const long visMask = VisualScreenMask;
1843    int i;
1844 
1845    /* Get list of all X visuals */
1846    visTemplate.screen = screen;
1847    visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
1848    if (*nelements > 0) {
1849       XMesaVisual *results = malloc(*nelements * sizeof(XMesaVisual));
1850       if (!results) {
1851          *nelements = 0;
1852          return NULL;
1853       }
1854       for (i = 0; i < *nelements; i++) {
1855          results[i] = create_glx_visual(dpy, visuals + i);
1856          if (!results[i]) {
1857             *nelements = i;
1858             break;
1859          }
1860       }
1861       return (GLXFBConfig *) results;
1862    }
1863    return NULL;
1864 }
1865 
1866 
1867 PUBLIC GLXFBConfig *
glXChooseFBConfig(Display * dpy,int screen,const int * attribList,int * nitems)1868 glXChooseFBConfig(Display *dpy, int screen,
1869                   const int *attribList, int *nitems)
1870 {
1871    XMesaVisual xmvis;
1872 
1873    /* register ourselves as an extension on this display */
1874    register_with_display(dpy);
1875 
1876    if (!attribList || !attribList[0]) {
1877       /* return list of all configs (per GLX_SGIX_fbconfig spec) */
1878       return glXGetFBConfigs(dpy, screen, nitems);
1879    }
1880 
1881    xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
1882    if (xmvis) {
1883       GLXFBConfig *config = malloc(sizeof(XMesaVisual));
1884       if (!config) {
1885          *nitems = 0;
1886          return NULL;
1887       }
1888       *nitems = 1;
1889       config[0] = (GLXFBConfig) xmvis;
1890       return (GLXFBConfig *) config;
1891    }
1892    else {
1893       *nitems = 0;
1894       return NULL;
1895    }
1896 }
1897 
1898 
1899 PUBLIC XVisualInfo *
glXGetVisualFromFBConfig(Display * dpy,GLXFBConfig config)1900 glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
1901 {
1902    if (dpy && config) {
1903       XMesaVisual xmvis = (XMesaVisual) config;
1904 #if 0
1905       return xmvis->vishandle;
1906 #else
1907       /* create a new vishandle - the cached one may be stale */
1908       xmvis->vishandle = malloc(sizeof(XVisualInfo));
1909       if (xmvis->vishandle) {
1910          memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
1911       }
1912       return xmvis->vishandle;
1913 #endif
1914    }
1915    else {
1916       return NULL;
1917    }
1918 }
1919 
1920 
1921 PUBLIC GLXWindow
glXCreateWindow(Display * dpy,GLXFBConfig config,Window win,const int * attribList)1922 glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,
1923                 const int *attribList)
1924 {
1925    XMesaVisual xmvis = (XMesaVisual) config;
1926    XMesaBuffer xmbuf;
1927    if (!xmvis)
1928       return 0;
1929 
1930    xmbuf = XMesaCreateWindowBuffer(xmvis, win);
1931    if (!xmbuf)
1932       return 0;
1933 
1934    (void) dpy;
1935    (void) attribList;  /* Ignored in GLX 1.3 */
1936 
1937    return win;  /* A hack for now */
1938 }
1939 
1940 
1941 PUBLIC void
glXDestroyWindow(Display * dpy,GLXWindow window)1942 glXDestroyWindow( Display *dpy, GLXWindow window )
1943 {
1944    XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);
1945    if (b)
1946       XMesaDestroyBuffer(b);
1947    /* don't destroy X window */
1948 }
1949 
1950 
1951 /* XXX untested */
1952 PUBLIC GLXPixmap
glXCreatePixmap(Display * dpy,GLXFBConfig config,Pixmap pixmap,const int * attribList)1953 glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap,
1954                 const int *attribList)
1955 {
1956    XMesaVisual v = (XMesaVisual) config;
1957    XMesaBuffer b;
1958    const int *attr;
1959    int target = 0, format = 0, mipmap = 0;
1960    int value;
1961 
1962    if (!dpy || !config || !pixmap)
1963       return 0;
1964 
1965    for (attr = attribList; attr && *attr; attr++) {
1966       switch (*attr) {
1967       case GLX_TEXTURE_FORMAT_EXT:
1968          attr++;
1969          switch (*attr) {
1970          case GLX_TEXTURE_FORMAT_NONE_EXT:
1971          case GLX_TEXTURE_FORMAT_RGB_EXT:
1972          case GLX_TEXTURE_FORMAT_RGBA_EXT:
1973             format = *attr;
1974             break;
1975          default:
1976             /* error */
1977             return 0;
1978          }
1979          break;
1980       case GLX_TEXTURE_TARGET_EXT:
1981          attr++;
1982          switch (*attr) {
1983          case GLX_TEXTURE_1D_EXT:
1984          case GLX_TEXTURE_2D_EXT:
1985          case GLX_TEXTURE_RECTANGLE_EXT:
1986             target = *attr;
1987             break;
1988          default:
1989             /* error */
1990             return 0;
1991          }
1992          break;
1993       case GLX_MIPMAP_TEXTURE_EXT:
1994          attr++;
1995          if (*attr)
1996             mipmap = 1;
1997          break;
1998       default:
1999          /* error */
2000          return 0;
2001       }
2002    }
2003 
2004    if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
2005       if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
2006                      &value, GL_TRUE) != Success
2007           || !value) {
2008          return 0; /* error! */
2009       }
2010    }
2011    else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
2012       if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
2013                      &value, GL_TRUE) != Success
2014           || !value) {
2015          return 0; /* error! */
2016       }
2017    }
2018    if (mipmap) {
2019       if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
2020                      &value, GL_TRUE) != Success
2021           || !value) {
2022          return 0; /* error! */
2023       }
2024    }
2025    if (target == GLX_TEXTURE_1D_EXT) {
2026       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
2027                      &value, GL_TRUE) != Success
2028           || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
2029          return 0; /* error! */
2030       }
2031    }
2032    else if (target == GLX_TEXTURE_2D_EXT) {
2033       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
2034                      &value, GL_TRUE) != Success
2035           || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
2036          return 0; /* error! */
2037       }
2038    }
2039    if (target == GLX_TEXTURE_RECTANGLE_EXT) {
2040       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
2041                      &value, GL_TRUE) != Success
2042           || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
2043          return 0; /* error! */
2044       }
2045    }
2046 
2047    if (format || target || mipmap) {
2048       /* texture from pixmap */
2049       b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
2050    }
2051    else {
2052       b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
2053    }
2054    if (!b) {
2055       return 0;
2056    }
2057 
2058    return pixmap;
2059 }
2060 
2061 
2062 PUBLIC void
glXDestroyPixmap(Display * dpy,GLXPixmap pixmap)2063 glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
2064 {
2065    XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);
2066    if (b)
2067       XMesaDestroyBuffer(b);
2068    /* don't destroy X pixmap */
2069 }
2070 
2071 
2072 PUBLIC GLXPbuffer
glXCreatePbuffer(Display * dpy,GLXFBConfig config,const int * attribList)2073 glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
2074 {
2075    XMesaVisual xmvis = (XMesaVisual) config;
2076    XMesaBuffer xmbuf;
2077    const int *attrib;
2078    int width = 0, height = 0;
2079    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
2080 
2081    (void) dpy;
2082 
2083    for (attrib = attribList; *attrib; attrib++) {
2084       switch (*attrib) {
2085          case GLX_PBUFFER_WIDTH:
2086             attrib++;
2087             width = *attrib;
2088             break;
2089          case GLX_PBUFFER_HEIGHT:
2090             attrib++;
2091             height = *attrib;
2092             break;
2093          case GLX_PRESERVED_CONTENTS:
2094             attrib++;
2095             preserveContents = *attrib;
2096             break;
2097          case GLX_LARGEST_PBUFFER:
2098             attrib++;
2099             useLargest = *attrib;
2100             break;
2101          default:
2102             return 0;
2103       }
2104    }
2105 
2106    if (width == 0 || height == 0)
2107       return 0;
2108 
2109    if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) {
2110       /* If allocation would have failed and GLX_LARGEST_PBUFFER is set,
2111        * allocate the largest possible buffer.
2112        */
2113       if (useLargest) {
2114          width = PBUFFER_MAX_SIZE;
2115          height = PBUFFER_MAX_SIZE;
2116       }
2117    }
2118 
2119    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
2120    /* A GLXPbuffer handle must be an X Drawable because that's what
2121     * glXMakeCurrent takes.
2122     */
2123    if (xmbuf) {
2124       xmbuf->largestPbuffer = useLargest;
2125       xmbuf->preservedContents = preserveContents;
2126       return (GLXPbuffer) xmbuf->ws.drawable;
2127    }
2128    else {
2129       return 0;
2130    }
2131 }
2132 
2133 
2134 PUBLIC void
glXDestroyPbuffer(Display * dpy,GLXPbuffer pbuf)2135 glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2136 {
2137    XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
2138    if (b) {
2139       XMesaDestroyBuffer(b);
2140    }
2141 }
2142 
2143 
2144 PUBLIC void
glXQueryDrawable(Display * dpy,GLXDrawable draw,int attribute,unsigned int * value)2145 glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute,
2146                  unsigned int *value)
2147 {
2148    GLuint width, height;
2149    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
2150    if (!xmbuf) {
2151       generate_error(dpy, GLXBadDrawable, draw, X_GLXGetDrawableAttributes, False);
2152       return;
2153    }
2154 
2155    /* make sure buffer's dimensions are up to date */
2156    xmesa_get_window_size(dpy, xmbuf, &width, &height);
2157 
2158    switch (attribute) {
2159       case GLX_WIDTH:
2160          *value = width;
2161          break;
2162       case GLX_HEIGHT:
2163          *value = height;
2164          break;
2165       case GLX_PRESERVED_CONTENTS:
2166          *value = xmbuf->preservedContents;
2167          break;
2168       case GLX_LARGEST_PBUFFER:
2169          *value = xmbuf->largestPbuffer;
2170          break;
2171       case GLX_FBCONFIG_ID:
2172          *value = xmbuf->xm_visual->visinfo->visualid;
2173          return;
2174       case GLX_TEXTURE_FORMAT_EXT:
2175          *value = xmbuf->TextureFormat;
2176          break;
2177       case GLX_TEXTURE_TARGET_EXT:
2178          *value = xmbuf->TextureTarget;
2179          break;
2180       case GLX_MIPMAP_TEXTURE_EXT:
2181          *value = xmbuf->TextureMipmap;
2182          break;
2183 
2184       default:
2185          generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, true);
2186          return;
2187    }
2188 }
2189 
2190 
2191 PUBLIC GLXContext
glXCreateNewContext(Display * dpy,GLXFBConfig config,int renderType,GLXContext shareCtx,Bool direct)2192 glXCreateNewContext( Display *dpy, GLXFBConfig config,
2193                      int renderType, GLXContext shareCtx, Bool direct )
2194 {
2195    XMesaVisual xmvis = (XMesaVisual) config;
2196 
2197    if (!dpy || !config ||
2198        (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
2199       return 0;
2200 
2201    return create_context(dpy, xmvis,
2202                          shareCtx ? shareCtx->xmesaContext : NULL,
2203                          direct,
2204                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
2205 }
2206 
2207 
2208 PUBLIC int
glXQueryContext(Display * dpy,GLXContext ctx,int attribute,int * value)2209 glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
2210 {
2211    GLXContext glxCtx = ctx;
2212    XMesaContext xmctx = glxCtx->xmesaContext;
2213 
2214    (void) dpy;
2215    (void) ctx;
2216 
2217    switch (attribute) {
2218    case GLX_FBCONFIG_ID:
2219       *value = xmctx->xm_visual->visinfo->visualid;
2220       break;
2221    case GLX_RENDER_TYPE:
2222       if (xmctx->xm_visual->mesa_visual.rgbMode)
2223          *value = GLX_RGBA_TYPE;
2224       else
2225          *value = GLX_COLOR_INDEX_TYPE;
2226       break;
2227    case GLX_SCREEN:
2228       *value = 0;
2229       return Success;
2230    default:
2231       return GLX_BAD_ATTRIBUTE;
2232    }
2233    return 0;
2234 }
2235 
2236 
2237 PUBLIC void
glXSelectEvent(Display * dpy,GLXDrawable drawable,unsigned long mask)2238 glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
2239 {
2240    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2241    if (xmbuf)
2242       xmbuf->selectedEvents = mask;
2243 }
2244 
2245 
2246 PUBLIC void
glXGetSelectedEvent(Display * dpy,GLXDrawable drawable,unsigned long * mask)2247 glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
2248 {
2249    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2250    if (xmbuf)
2251       *mask = xmbuf->selectedEvents;
2252    else
2253       *mask = 0;
2254 }
2255 
2256 
2257 
2258 /*** GLX_SGI_swap_control ***/
2259 
2260 PUBLIC int
glXSwapIntervalSGI(int interval)2261 glXSwapIntervalSGI(int interval)
2262 {
2263    (void) interval;
2264    return 0;
2265 }
2266 
2267 
2268 
2269 /*** GLX_SGI_video_sync ***/
2270 
2271 static unsigned int FrameCounter = 0;
2272 
2273 PUBLIC int
glXGetVideoSyncSGI(unsigned int * count)2274 glXGetVideoSyncSGI(unsigned int *count)
2275 {
2276    /* this is a bogus implementation */
2277    *count = FrameCounter++;
2278    return 0;
2279 }
2280 
2281 PUBLIC int
glXWaitVideoSyncSGI(int divisor,int remainder,unsigned int * count)2282 glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
2283 {
2284    if (divisor <= 0 || remainder < 0)
2285       return GLX_BAD_VALUE;
2286    /* this is a bogus implementation */
2287    FrameCounter++;
2288    while (FrameCounter % divisor != remainder)
2289       FrameCounter++;
2290    *count = FrameCounter;
2291    return 0;
2292 }
2293 
2294 
2295 
2296 /*** GLX_SGI_make_current_read ***/
2297 
2298 PUBLIC Bool
glXMakeCurrentReadSGI(Display * dpy,GLXDrawable draw,GLXDrawable read,GLXContext ctx)2299 glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,
2300                       GLXContext ctx)
2301 {
2302    return glXMakeContextCurrent( dpy, draw, read, ctx );
2303 }
2304 
2305 /* not used
2306 static GLXDrawable
2307 glXGetCurrentReadDrawableSGI(void)
2308 {
2309    return 0;
2310 }
2311 */
2312 
2313 
2314 /*** GLX_SGIX_video_source ***/
2315 #if defined(_VL_H)
2316 
2317 PUBLIC GLXVideoSourceSGIX
glXCreateGLXVideoSourceSGIX(Display * dpy,int screen,VLServer server,VLPath path,int nodeClass,VLNode drainNode)2318 glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server,
2319                             VLPath path, int nodeClass, VLNode drainNode)
2320 {
2321    (void) dpy;
2322    (void) screen;
2323    (void) server;
2324    (void) path;
2325    (void) nodeClass;
2326    (void) drainNode;
2327    return 0;
2328 }
2329 
2330 PUBLIC void
glXDestroyGLXVideoSourceSGIX(Display * dpy,GLXVideoSourceSGIX src)2331 glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
2332 {
2333    (void) dpy;
2334    (void) src;
2335 }
2336 
2337 #endif
2338 
2339 
2340 /*** GLX_EXT_import_context ***/
2341 
2342 PUBLIC void
glXFreeContextEXT(Display * dpy,GLXContext context)2343 glXFreeContextEXT(Display *dpy, GLXContext context)
2344 {
2345    (void) dpy;
2346    (void) context;
2347 }
2348 
2349 PUBLIC GLXContextID
glXGetContextIDEXT(const GLXContext context)2350 glXGetContextIDEXT(const GLXContext context)
2351 {
2352    (void) context;
2353    return 0;
2354 }
2355 
2356 PUBLIC GLXContext
glXImportContextEXT(Display * dpy,GLXContextID contextID)2357 glXImportContextEXT(Display *dpy, GLXContextID contextID)
2358 {
2359    (void) dpy;
2360    (void) contextID;
2361    return 0;
2362 }
2363 
2364 PUBLIC int
glXQueryContextInfoEXT(Display * dpy,GLXContext context,int attribute,int * value)2365 glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,
2366                        int *value)
2367 {
2368    (void) dpy;
2369    (void) context;
2370    (void) attribute;
2371    (void) value;
2372    return 0;
2373 }
2374 
2375 
2376 
2377 /*** GLX_SGIX_fbconfig ***/
2378 
2379 PUBLIC int
glXGetFBConfigAttribSGIX(Display * dpy,GLXFBConfigSGIX config,int attribute,int * value)2380 glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
2381                          int attribute, int *value)
2382 {
2383    return glXGetFBConfigAttrib(dpy, config, attribute, value);
2384 }
2385 
2386 PUBLIC GLXFBConfigSGIX *
glXChooseFBConfigSGIX(Display * dpy,int screen,int * attrib_list,int * nelements)2387 glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,
2388                       int *nelements)
2389 {
2390    return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,
2391                                             attrib_list, nelements);
2392 }
2393 
2394 
2395 PUBLIC GLXPixmap
glXCreateGLXPixmapWithConfigSGIX(Display * dpy,GLXFBConfigSGIX config,Pixmap pixmap)2396 glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
2397                                  Pixmap pixmap)
2398 {
2399    XMesaVisual xmvis = (XMesaVisual) config;
2400    XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
2401    return xmbuf->ws.drawable; /* need to return an X ID */
2402 }
2403 
2404 
2405 PUBLIC GLXContext
glXCreateContextWithConfigSGIX(Display * dpy,GLXFBConfigSGIX config,int renderType,GLXContext shareCtx,Bool direct)2406 glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
2407                                int renderType, GLXContext shareCtx,
2408                                Bool direct)
2409 {
2410    XMesaVisual xmvis = (XMesaVisual) config;
2411 
2412    if (!dpy || !config ||
2413        (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
2414       return 0;
2415 
2416    return create_context(dpy, xmvis,
2417                          shareCtx ? shareCtx->xmesaContext : NULL,
2418                          direct,
2419                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
2420 }
2421 
2422 
2423 PUBLIC XVisualInfo *
glXGetVisualFromFBConfigSGIX(Display * dpy,GLXFBConfigSGIX config)2424 glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
2425 {
2426    return glXGetVisualFromFBConfig(dpy, config);
2427 }
2428 
2429 
2430 PUBLIC GLXFBConfigSGIX
glXGetFBConfigFromVisualSGIX(Display * dpy,XVisualInfo * vis)2431 glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
2432 {
2433    XMesaVisual xmvis = find_glx_visual(dpy, vis);
2434    if (!xmvis) {
2435       /* This visual wasn't found with glXChooseVisual() */
2436       xmvis = create_glx_visual(dpy, vis);
2437    }
2438 
2439    return (GLXFBConfigSGIX) xmvis;
2440 }
2441 
2442 
2443 
2444 /*** GLX_SGIX_pbuffer ***/
2445 
2446 PUBLIC GLXPbufferSGIX
glXCreateGLXPbufferSGIX(Display * dpy,GLXFBConfigSGIX config,unsigned int width,unsigned int height,int * attribList)2447 glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
2448                         unsigned int width, unsigned int height,
2449                         int *attribList)
2450 {
2451    XMesaVisual xmvis = (XMesaVisual) config;
2452    XMesaBuffer xmbuf;
2453    const int *attrib;
2454    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
2455 
2456    (void) dpy;
2457 
2458    for (attrib = attribList; attrib && *attrib; attrib++) {
2459       switch (*attrib) {
2460          case GLX_PRESERVED_CONTENTS_SGIX:
2461             attrib++;
2462             preserveContents = *attrib; /* ignored */
2463             break;
2464          case GLX_LARGEST_PBUFFER_SGIX:
2465             attrib++;
2466             useLargest = *attrib; /* ignored */
2467             break;
2468          default:
2469             return 0;
2470       }
2471    }
2472 
2473    /* not used at this time */
2474    (void) useLargest;
2475    (void) preserveContents;
2476 
2477    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
2478    /* A GLXPbuffer handle must be an X Drawable because that's what
2479     * glXMakeCurrent takes.
2480     */
2481    return (GLXPbuffer) xmbuf->ws.drawable;
2482 }
2483 
2484 
2485 PUBLIC void
glXDestroyGLXPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuf)2486 glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
2487 {
2488    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2489    if (xmbuf) {
2490       XMesaDestroyBuffer(xmbuf);
2491    }
2492 }
2493 
2494 
2495 PUBLIC int
glXQueryGLXPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuf,int attribute,unsigned int * value)2496 glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute,
2497                        unsigned int *value)
2498 {
2499    const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2500 
2501    if (!xmbuf) {
2502       /* Generate GLXBadPbufferSGIX for bad pbuffer */
2503       return 0;
2504    }
2505 
2506    switch (attribute) {
2507       case GLX_PRESERVED_CONTENTS_SGIX:
2508          *value = True;
2509          break;
2510       case GLX_LARGEST_PBUFFER_SGIX:
2511          *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
2512          break;
2513       case GLX_WIDTH_SGIX:
2514          *value = xmesa_buffer_width(xmbuf);
2515          break;
2516       case GLX_HEIGHT_SGIX:
2517          *value = xmesa_buffer_height(xmbuf);
2518          break;
2519       case GLX_EVENT_MASK_SGIX:
2520          *value = 0;  /* XXX might be wrong */
2521          break;
2522       default:
2523          *value = 0;
2524    }
2525    return 0;
2526 }
2527 
2528 
2529 PUBLIC void
glXSelectEventSGIX(Display * dpy,GLXDrawable drawable,unsigned long mask)2530 glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
2531 {
2532    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2533    if (xmbuf) {
2534       /* Note: we'll never generate clobber events */
2535       xmbuf->selectedEvents = mask;
2536    }
2537 }
2538 
2539 
2540 PUBLIC void
glXGetSelectedEventSGIX(Display * dpy,GLXDrawable drawable,unsigned long * mask)2541 glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable,
2542                         unsigned long *mask)
2543 {
2544    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2545    if (xmbuf) {
2546       *mask = xmbuf->selectedEvents;
2547    }
2548    else {
2549       *mask = 0;
2550    }
2551 }
2552 
2553 
2554 
2555 /*** GLX_SGI_cushion ***/
2556 
2557 PUBLIC void
glXCushionSGI(Display * dpy,Window win,float cushion)2558 glXCushionSGI(Display *dpy, Window win, float cushion)
2559 {
2560    (void) dpy;
2561    (void) win;
2562    (void) cushion;
2563 }
2564 
2565 
2566 
2567 /*** GLX_SGIX_video_resize ***/
2568 
2569 PUBLIC int
glXBindChannelToWindowSGIX(Display * dpy,int screen,int channel,Window window)2570 glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel,
2571                            Window window)
2572 {
2573    (void) dpy;
2574    (void) screen;
2575    (void) channel;
2576    (void) window;
2577    return 0;
2578 }
2579 
2580 PUBLIC int
glXChannelRectSGIX(Display * dpy,int screen,int channel,int x,int y,int w,int h)2581 glXChannelRectSGIX(Display *dpy, int screen, int channel,
2582                    int x, int y, int w, int h)
2583 {
2584    (void) dpy;
2585    (void) screen;
2586    (void) channel;
2587    (void) x;
2588    (void) y;
2589    (void) w;
2590    (void) h;
2591    return 0;
2592 }
2593 
2594 PUBLIC int
glXQueryChannelRectSGIX(Display * dpy,int screen,int channel,int * x,int * y,int * w,int * h)2595 glXQueryChannelRectSGIX(Display *dpy, int screen, int channel,
2596                         int *x, int *y, int *w, int *h)
2597 {
2598    (void) dpy;
2599    (void) screen;
2600    (void) channel;
2601    (void) x;
2602    (void) y;
2603    (void) w;
2604    (void) h;
2605    return 0;
2606 }
2607 
2608 PUBLIC int
glXQueryChannelDeltasSGIX(Display * dpy,int screen,int channel,int * dx,int * dy,int * dw,int * dh)2609 glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel,
2610                           int *dx, int *dy, int *dw, int *dh)
2611 {
2612    (void) dpy;
2613    (void) screen;
2614    (void) channel;
2615    (void) dx;
2616    (void) dy;
2617    (void) dw;
2618    (void) dh;
2619    return 0;
2620 }
2621 
2622 PUBLIC int
glXChannelRectSyncSGIX(Display * dpy,int screen,int channel,GLenum synctype)2623 glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
2624 {
2625    (void) dpy;
2626    (void) screen;
2627    (void) channel;
2628    (void) synctype;
2629    return 0;
2630 }
2631 
2632 
2633 
2634 /*** GLX_SGIX_dmbuffer **/
2635 
2636 #if defined(_DM_BUFFER_H_)
2637 PUBLIC Bool
glXAssociateDMPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuffer,DMparams * params,DMbuffer dmbuffer)2638 glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer,
2639                           DMparams *params, DMbuffer dmbuffer)
2640 {
2641    (void) dpy;
2642    (void) pbuffer;
2643    (void) params;
2644    (void) dmbuffer;
2645    return False;
2646 }
2647 #endif
2648 
2649 
2650 /*** GLX_SGIX_swap_group ***/
2651 
2652 PUBLIC void
glXJoinSwapGroupSGIX(Display * dpy,GLXDrawable drawable,GLXDrawable member)2653 glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
2654 {
2655    (void) dpy;
2656    (void) drawable;
2657    (void) member;
2658 }
2659 
2660 
2661 
2662 /*** GLX_SGIX_swap_barrier ***/
2663 
2664 PUBLIC void
glXBindSwapBarrierSGIX(Display * dpy,GLXDrawable drawable,int barrier)2665 glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
2666 {
2667    (void) dpy;
2668    (void) drawable;
2669    (void) barrier;
2670 }
2671 
2672 PUBLIC Bool
glXQueryMaxSwapBarriersSGIX(Display * dpy,int screen,int * max)2673 glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
2674 {
2675    (void) dpy;
2676    (void) screen;
2677    (void) max;
2678    return False;
2679 }
2680 
2681 
2682 
2683 /*** GLX_SUN_get_transparent_index ***/
2684 
2685 PUBLIC Status
glXGetTransparentIndexSUN(Display * dpy,Window overlay,Window underlay,long * pTransparent)2686 glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay,
2687                           long *pTransparent)
2688 {
2689    (void) dpy;
2690    (void) overlay;
2691    (void) underlay;
2692    (void) pTransparent;
2693    return 0;
2694 }
2695 
2696 
2697 
2698 /*** GLX_MESA_release_buffers ***/
2699 
2700 /*
2701  * Release the depth, stencil, accum buffers attached to a GLXDrawable
2702  * (a window or pixmap) prior to destroying the GLXDrawable.
2703  */
2704 PUBLIC Bool
glXReleaseBuffersMESA(Display * dpy,GLXDrawable d)2705 glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
2706 {
2707    XMesaBuffer b = XMesaFindBuffer(dpy, d);
2708    if (b) {
2709       XMesaDestroyBuffer(b);
2710       return True;
2711    }
2712    return False;
2713 }
2714 
2715 /*** GLX_EXT_texture_from_pixmap ***/
2716 
2717 PUBLIC void
glXBindTexImageEXT(Display * dpy,GLXDrawable drawable,int buffer,const int * attrib_list)2718 glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
2719                         const int *attrib_list)
2720 {
2721    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
2722    if (b)
2723       XMesaBindTexImage(dpy, b, buffer, attrib_list);
2724 }
2725 
2726 PUBLIC void
glXReleaseTexImageEXT(Display * dpy,GLXDrawable drawable,int buffer)2727 glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
2728 {
2729    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
2730    if (b)
2731       XMesaReleaseTexImage(dpy, b, buffer);
2732 }
2733 
2734 
2735 
2736 /*** GLX_ARB_create_context ***/
2737 
2738 
2739 GLXContext
glXCreateContextAttribsARB(Display * dpy,GLXFBConfig config,GLXContext shareCtx,Bool direct,const int * attrib_list)2740 glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
2741                            GLXContext shareCtx, Bool direct,
2742                            const int *attrib_list)
2743 {
2744    XMesaVisual xmvis = (XMesaVisual) config;
2745    int majorVersion = 1, minorVersion = 0;
2746    int contextFlags = 0x0;
2747    int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
2748    int renderType = GLX_RGBA_TYPE;
2749    unsigned i;
2750    Bool done = False;
2751    const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB |
2752                                 GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2753    GLXContext ctx;
2754 
2755    /* parse attrib_list */
2756    for (i = 0; !done && attrib_list && attrib_list[i]; i++) {
2757       switch (attrib_list[i]) {
2758       case GLX_CONTEXT_MAJOR_VERSION_ARB:
2759          majorVersion = attrib_list[++i];
2760          break;
2761       case GLX_CONTEXT_MINOR_VERSION_ARB:
2762          minorVersion = attrib_list[++i];
2763          break;
2764       case GLX_CONTEXT_FLAGS_ARB:
2765          contextFlags = attrib_list[++i];
2766          break;
2767       case GLX_CONTEXT_PROFILE_MASK_ARB:
2768          profileMask = attrib_list[++i];
2769          break;
2770       case GLX_RENDER_TYPE:
2771          renderType = attrib_list[++i];
2772          break;
2773       case 0:
2774          /* end of list */
2775          done = True;
2776          break;
2777       default:
2778          /* bad attribute */
2779          generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
2780          return NULL;
2781       }
2782    }
2783 
2784    /* check contextFlags */
2785    if (contextFlags & ~contextFlagsAll) {
2786       generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
2787       return NULL;
2788    }
2789 
2790    /* check profileMask */
2791    if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB &&
2792        profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&
2793        profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT) {
2794       generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);
2795       return NULL;
2796    }
2797 
2798    /* check renderType */
2799    if (renderType != GLX_RGBA_TYPE &&
2800        renderType != GLX_COLOR_INDEX_TYPE) {
2801       generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
2802       return NULL;
2803    }
2804 
2805    /* check version */
2806    if (majorVersion <= 0 ||
2807        minorVersion < 0 ||
2808        (profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT &&
2809         ((majorVersion == 1 && minorVersion > 5) ||
2810          (majorVersion == 2 && minorVersion > 1) ||
2811          (majorVersion == 3 && minorVersion > 3) ||
2812          (majorVersion == 4 && minorVersion > 5) ||
2813          majorVersion > 4))) {
2814       generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
2815       return NULL;
2816    }
2817    if (profileMask == GLX_CONTEXT_ES_PROFILE_BIT_EXT &&
2818        ((majorVersion == 1 && minorVersion > 1) ||
2819         (majorVersion == 2 && minorVersion > 0) ||
2820         (majorVersion == 3 && minorVersion > 1) ||
2821         majorVersion > 3)) {
2822       /* GLX_EXT_create_context_es2_profile says nothing to justifying a
2823        * different error code for invalid ES versions, but this is what NVIDIA
2824        * does and piglit expects.
2825        */
2826       generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);
2827       return NULL;
2828    }
2829 
2830    if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&
2831        majorVersion < 3) {
2832       generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
2833       return NULL;
2834    }
2835 
2836    if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) {
2837       generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
2838       return NULL;
2839    }
2840 
2841    ctx = create_context(dpy, xmvis,
2842                         shareCtx ? shareCtx->xmesaContext : NULL,
2843                         direct,
2844                         majorVersion, minorVersion,
2845                         profileMask, contextFlags);
2846    if (!ctx) {
2847       generate_error(dpy, GLXBadFBConfig, 0, X_GLXCreateContextAttribsARB, False);
2848    }
2849 
2850    return ctx;
2851 }
2852