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