1 #include "sgcf.h"
2 #if defined(HAVE_X11)
3 
4 /* $Id: glx.c,v 1.4 2000/12/31 16:32:58 mholst Exp $ */
5 
6 /*
7  * Mesa 3-D graphics library
8  * Version:  2.2
9  * Copyright (C) 1995-1997  Brian Paul
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the Free
23  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 /*
27  * A pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa.
28  *
29  * Thanks to the contributors:
30  *
31  * Initial version:  Philip Brown (philb@CSUA.Berkeley.EDU)
32  * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
33  * Further visual-handling refinements: Wolfram Gloger
34  *    (wmglo@Dent.MED.Uni-Muenchen.DE).
35  */
36 
37 
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include "GL/gl.h"
45 #include "GL/glx.h"
46 #include "GL/xmesa.h"
47 #include "context.h"
48 #include "config.h"
49 #include "macros.h"
50 #include "types.h"
51 #include "xmesaP.h"
52 
53 
54 
55 #define DONT_CARE -1
56 
57 
58 
59 #define MAX_VISUALS 100
60 static XMesaVisual VisualTable[MAX_VISUALS];
61 static int NumVisuals = 0;
62 
63 
64 #define MAX_BUFFERS 1000
65 static XMesaBuffer BufferList[MAX_BUFFERS];
66 static int NumBuffers = 0;
67 
68 
69 
70 /*
71  * This struct and some code fragments borrowed
72  * from Mark Kilgard's GLUT library.
73  */
74 typedef struct _OverlayInfo {
75   /* Avoid 64-bit portability problems by being careful to use
76      longs due to the way XGetWindowProperty is specified. Note
77      that these parameters are passed as CARD32s over X
78      protocol. */
79   long overlay_visual;
80   long transparent_type;
81   long value;
82   long layer;
83 } OverlayInfo;
84 
85 
86 
87 /* Macro to handle c_class vs class field name in XVisualInfo struct */
88 #if defined(__cplusplus) || defined(c_plusplus)
89 #define CLASS c_class
90 #else
91 #define CLASS class
92 #endif
93 
94 
95 
96 
97 /*
98  * Test if the given XVisualInfo is usable for Mesa rendering.
99  */
is_usable_visual(XVisualInfo * vinfo)100 static GLboolean is_usable_visual( XVisualInfo *vinfo )
101 {
102    switch (vinfo->CLASS) {
103       case StaticGray:
104       case GrayScale:
105          /* Any StaticGray/GrayScale visual works in RGB or CI mode */
106          return GL_TRUE;
107       case StaticColor:
108       case PseudoColor:
109 	 /* Any StaticColor/PseudoColor visual of at least 4 bits */
110 	 if (vinfo->depth>=4) {
111 	    return GL_TRUE;
112 	 }
113 	 else {
114 	    return GL_FALSE;
115 	 }
116       case TrueColor:
117       case DirectColor:
118 	 /* Any depth of TrueColor or DirectColor works in RGB mode */
119 	 return GL_TRUE;
120       default:
121 	 /* This should never happen */
122 	 return GL_FALSE;
123    }
124 }
125 
126 
127 
128 /*
129  * Return the level (overlay, normal, underlay) of a given XVisualInfo.
130  * Input:  dpy - the X display
131  *         vinfo - the XVisualInfo to test
132  * Return:  level of the visual:
133  *             0 = normal planes
134  *            >0 = overlay planes
135  *            <0 = underlay planes
136  */
level_of_visual(Display * dpy,XVisualInfo * vinfo)137 static int level_of_visual( Display *dpy, XVisualInfo *vinfo )
138 {
139    Atom overlayVisualsAtom;
140    OverlayInfo *overlay_info = NULL;
141    int numOverlaysPerScreen;
142    Status status;
143    Atom actualType;
144    int actualFormat;
145    unsigned long sizeData, bytesLeft;
146    int i;
147 
148    /*
149     * The SERVER_OVERLAY_VISUALS property on the root window contains
150     * a list of overlay visuals.  Get that list now.
151     */
152    overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
153    if (overlayVisualsAtom == None) {
154       return 0;
155    }
156 
157    status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
158                                overlayVisualsAtom, 0L, (long) 10000, False,
159                                overlayVisualsAtom, &actualType, &actualFormat,
160                                &sizeData, &bytesLeft,
161                                (unsigned char **) &overlay_info );
162 
163    if (status != Success || actualType != overlayVisualsAtom ||
164        actualFormat != 32 || sizeData < 4) {
165       /* something went wrong */
166       XFree(overlay_info);
167       return 0;
168    }
169 
170    /* search the overlay visual list for the visual ID of interest */
171    numOverlaysPerScreen = sizeData / 4;
172    for (i=0;i<numOverlaysPerScreen;i++) {
173       OverlayInfo *ov;
174       ov = overlay_info + i;
175       if (ov->overlay_visual==vinfo->visualid) {
176          /* found the visual */
177          if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
178             int level = ov->layer;
179             XFree(overlay_info);
180             return level;
181          }
182          else {
183             XFree(overlay_info);
184             return 0;
185          }
186       }
187    }
188 
189    /* The visual ID was not found in the overlay list. */
190    XFree(overlay_info);
191    return 0;
192 }
193 
194 
195 
196 
197 /*
198  * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
199  * configuration in our list of GLX visuals.
200  */
201 static XMesaVisual
save_glx_visual(Display * dpy,XVisualInfo * vinfo,GLboolean rgb,GLboolean alpha,GLboolean dbl,GLint depth_size,GLint stencil_size,GLint accum_size,GLint level)202 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
203                  GLboolean rgb, GLboolean alpha, GLboolean dbl,
204                  GLint depth_size, GLint stencil_size,
205                  GLint accum_size, GLint level )
206 {
207    GLboolean ximage_flag = GL_TRUE;
208    XMesaVisual xmvis;
209 
210    if (NumVisuals>=MAX_VISUALS) {
211       fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
212       return NULL;
213    }
214 
215    if (dbl) {
216       /* Check if the MESA_BACK_BUFFER env var is set */
217       char *backbuffer = getenv("MESA_BACK_BUFFER");
218       if (backbuffer) {
219          if (backbuffer[0]=='p' || backbuffer[0]=='P') {
220             ximage_flag = GL_FALSE;
221          }
222          else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
223             ximage_flag = GL_TRUE;
224          }
225          else {
226             fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
227             fprintf(stderr, "environment variable, using an XImage.\n");
228          }
229       }
230    }
231 
232    xmvis = XMesaCreateVisual( dpy, vinfo, rgb, alpha, dbl, ximage_flag,
233                               depth_size, stencil_size, accum_size, level );
234    if (xmvis) {
235       VisualTable[NumVisuals] = xmvis;
236       NumVisuals++;
237    }
238    return xmvis;
239 }
240 
241 
242 
243 /*
244  * Create a GLX visual from a regular XVisualInfo.
245  */
246 static XMesaVisual
create_glx_visual(Display * dpy,XVisualInfo * visinfo)247 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
248 {
249    int vislevel;
250 
251    vislevel = level_of_visual( dpy, visinfo );
252    if (vislevel) {
253       /* Configure this visual as a CI, single-buffered overlay */
254       return save_glx_visual( dpy, visinfo,
255                               GL_FALSE,  /* rgb */
256                               GL_FALSE,  /* alpha */
257                               GL_FALSE,  /* double */
258                               0,         /* depth bits */
259                               0,         /* stencil bits */
260                               0,         /* accum bits */
261                               vislevel   /* level */
262                             );
263    }
264    else if (is_usable_visual( visinfo )) {
265       /* Configure this visual as RGB, double-buffered, depth-buffered. */
266       /* This is surely wrong for some people's needs but what else */
267       /* can be done?  They should use glXChooseVisual(). */
268       return save_glx_visual( dpy, visinfo,
269                               GL_TRUE,   /* rgb */
270                               GL_FALSE,  /* alpha */
271                               GL_TRUE,   /* double */
272                               8*sizeof(GLdepth),
273                               8*sizeof(GLstencil),
274                               8*sizeof(GLaccum),
275                               0          /* level */
276                             );
277    }
278    else {
279       fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
280       return NULL;
281    }
282 }
283 
284 
285 
286 /*
287  * Find the GLX visual associated with an XVisualInfo.
288  */
289 static XMesaVisual
find_glx_visual(Display * dpy,XVisualInfo * vinfo)290 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
291 {
292    int i;
293 
294    /* First try to match pointers */
295    for (i=0;i<NumVisuals;i++) {
296       if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
297          return VisualTable[i];
298       }
299    }
300    /* try to match visual id */
301    for (i=0;i<NumVisuals;i++) {
302       if (VisualTable[i]->display==dpy
303           && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
304          return VisualTable[i];
305       }
306    }
307    return NULL;
308 }
309 
310 
311 
312 
313 /*
314  * Determine if a given X window ID is valid (window exists).
315  * Do this by calling XGetWindowAttributes() for the window and
316  * checking if we catch an X error.
317  * Input:  dpy - the display
318  *         win - the window to check for existance
319  * Return:  GL_TRUE - window exists
320  *          GL_FALSE - window doesn't exist
321  */
322 static GLboolean WindowExistsFlag;
323 
window_exists_err_handler(Display * dpy,XErrorEvent * xerr)324 static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
325 {
326    if (xerr->error_code == BadWindow) {
327       WindowExistsFlag = GL_FALSE;
328    }
329    return 0;
330 }
331 
window_exists(Display * dpy,Window win)332 static GLboolean window_exists( Display *dpy, Window win )
333 {
334    XWindowAttributes wa;
335    int (*old_handler)( Display*, XErrorEvent* );
336    WindowExistsFlag = GL_TRUE;
337    old_handler = XSetErrorHandler(window_exists_err_handler);
338    XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
339    XSetErrorHandler(old_handler);
340    return WindowExistsFlag;
341 }
342 
343 
344 
345 /*
346  * We occasionally call this function to check if any windows in the
347  * BufferList have been destroyed.  If so, we can then deallocate
348  * the corresponding Mesa ancillary buffers (depth, stencil, accum)
349  * We need to do this because there's no way for Xlib to notify us
350  * when a window gets destroyed.
351  */
free_zombie_buffers(void)352 static void free_zombie_buffers( void )
353 {
354    GLint i, j;
355 
356    for (i=0;i<NumBuffers;i++) {
357       if (!BufferList[i]->pixmap_flag) {
358          Display *dpy = BufferList[i]->xm_visual->display;
359          Window win   = BufferList[i]->frontbuffer;
360          int exists;
361 
362          XSync(dpy,False);
363          exists = window_exists( dpy, win );
364 
365          if (!exists) {
366             /* found a dead window, free the ancillary info */
367             XMesaDestroyBuffer( BufferList[i] );
368             /* move remaining buffer entries up one slot */
369             for (j=i+1;j<NumBuffers;j++) {
370                BufferList[j-1] = BufferList[j];
371             }
372             NumBuffers--;
373             i--;            /* this cancels out the i++ */
374          }
375       }
376    }
377 }
378 
379 
380 
381 /*
382  * Return the XMesaBuffer which corresponds to the given X drawable.
383  * Return NULL if no corresponding XMesaBuffer.
384  */
find_buffer(Display * dpy,Drawable d)385 static XMesaBuffer find_buffer( Display *dpy, Drawable d )
386 {
387    GLint i;
388 
389    for (i=0;i<NumBuffers;i++) {
390       if (BufferList[i]->frontbuffer==d) {
391          return BufferList[i];
392       }
393    }
394    return NULL;
395 }
396 
397 
398 
399 /*
400  * Create a new XMesaBuffer from an X drawable.
401  * Input:  v - the XMesaVisual
402  *         d - the Window or Pixmap
403  *         pixmap_flag - GL_TRUE if d is a pixmap, GL_FALSE if d is a window
404  *         cmap - the colormap if d is a pixmap, ignored otherwise.
405  */
save_buffer(XMesaVisual v,Drawable d,GLboolean pixmap_flag,Colormap cmap)406 static XMesaBuffer save_buffer( XMesaVisual v, Drawable d,
407                                 GLboolean pixmap_flag, Colormap cmap )
408 {
409    XMesaBuffer b;
410 
411    if (NumBuffers>=MAX_BUFFERS) {
412       fprintf( stderr, "GLX Error: maximum number of buffers exceeded\n");
413       return NULL;
414    }
415    if (pixmap_flag) {
416       b = XMesaCreatePixmapBuffer( v, d, cmap );
417    }
418    else {
419       b = XMesaCreateWindowBuffer( v, d );
420    }
421    if (!b) {
422       return NULL;
423    }
424    BufferList[NumBuffers] = b;
425    NumBuffers++;
426    return b;
427 }
428 
429 
430 
431 /*
432  * Return the transparent pixel value for a GLX visual.
433  * Input:  glxvis - the glx_visual
434  * Return:  a pixel value or -1 if no transparent pixel
435  */
transparent_pixel(XMesaVisual glxvis)436 static int transparent_pixel( XMesaVisual glxvis )
437 {
438    Display *dpy = glxvis->display;
439    XVisualInfo *vinfo = glxvis->visinfo;
440    Atom overlayVisualsAtom;
441    OverlayInfo *overlay_info = NULL;
442    int numOverlaysPerScreen;
443    Status status;
444    Atom actualType;
445    int actualFormat;
446    unsigned long sizeData, bytesLeft;
447    int i;
448 
449    /*
450     * The SERVER_OVERLAY_VISUALS property on the root window contains
451     * a list of overlay visuals.  Get that list now.
452     */
453    overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
454    if (overlayVisualsAtom == None) {
455       return -1;
456    }
457 
458    status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
459                                overlayVisualsAtom, 0L, (long) 10000, False,
460                                overlayVisualsAtom, &actualType, &actualFormat,
461                                &sizeData, &bytesLeft,
462                                (unsigned char **) &overlay_info );
463 
464    if (status != Success || actualType != overlayVisualsAtom ||
465        actualFormat != 32 || sizeData < 4) {
466       /* something went wrong */
467       XFree(overlay_info);
468       return -1;
469    }
470 
471    /* search the overlay visual list for the visual ID of interest */
472    numOverlaysPerScreen = sizeData / 4;
473    for (i=0;i<numOverlaysPerScreen;i++) {
474       OverlayInfo *ov;
475       ov = overlay_info + i;
476       if (ov->overlay_visual==vinfo->visualid) {
477          /* found it! */
478          if (ov->transparent_type==0) {
479             /* type 0 indicates no transparency */
480             XFree(overlay_info);
481             return -1;
482          }
483          else {
484             /* ov->value is the transparent pixel */
485             XFree(overlay_info);
486             return ov->value;
487          }
488       }
489    }
490 
491    /* The visual ID was not found in the overlay list. */
492    XFree(overlay_info);
493    return -1;
494 }
495 
496 
497 
498 /*
499  * Try to get an X visual which matches the given arguments.
500  */
get_visual(Display * dpy,int scr,unsigned int depth,int xclass)501 static XVisualInfo *get_visual( Display *dpy, int scr,
502 			        unsigned int depth, int xclass )
503 {
504    XVisualInfo temp;
505    long mask;
506    int n;
507    int default_depth;
508    int default_class;
509 
510    mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
511    temp.screen = scr;
512    temp.depth = depth;
513    temp.CLASS = xclass;
514 
515    default_depth = DefaultDepth(dpy,scr);
516    default_class = DefaultVisual(dpy,scr)->CLASS;
517 
518    if (depth==default_depth && xclass==default_class) {
519       /* try to get root window's visual */
520       temp.visualid = DefaultVisual(dpy,scr)->visualid;
521       mask |= VisualIDMask;
522    }
523 
524    return XGetVisualInfo( dpy, mask, &temp, &n );
525 }
526 
527 
528 
529 /*
530  * Retrieve the value of the given environment variable and find
531  * the X visual which matches it.
532  * Input:  dpy - the display
533  *         screen - the screen number
534  *         varname - the name of the environment variable
535  * Return:  an XVisualInfo pointer to NULL if error.
536  */
get_env_visual(Display * dpy,int scr,char * varname)537 static XVisualInfo *get_env_visual( Display *dpy, int scr, char *varname )
538 {
539    char *value;
540    char type[100];
541    int depth, xclass = -1;
542    XVisualInfo *vis;
543 
544    value = getenv( varname );
545    if (!value) {
546       return NULL;
547    }
548 
549    sscanf( value, "%s %d", type, &depth );
550 
551    if (strcmp(type,"TrueColor")==0)          xclass = TrueColor;
552    else if (strcmp(type,"DirectColor")==0)   xclass = DirectColor;
553    else if (strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
554    else if (strcmp(type,"StaticColor")==0)   xclass = StaticColor;
555    else if (strcmp(type,"GrayScale")==0)     xclass = GrayScale;
556    else if (strcmp(type,"StaticGray")==0)    xclass = StaticGray;
557 
558    if (xclass>-1 && depth>0) {
559       vis = get_visual( dpy, scr, depth, xclass );
560       if (vis) {
561 	 return vis;
562       }
563    }
564 
565    fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
566 	    type, depth );
567    return NULL;
568 }
569 
570 
571 
572 /*
573  * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
574  * Input:  dpy, screen - X display and screen number
575  *         rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
576  *         min_depth - minimum visual depth
577  *         preferred_class - preferred GLX visual class or DONT_CARE
578  * Return:  pointer to an XVisualInfo or NULL.
579  */
choose_x_visual(Display * dpy,int screen,GLboolean rgba,int min_depth,int preferred_class)580 static XVisualInfo *choose_x_visual( Display *dpy, int screen,
581 				     GLboolean rgba, int min_depth,
582                                      int preferred_class )
583 {
584    XVisualInfo *vis;
585    int xclass, visclass;
586    int depth;
587 
588    if (rgba) {
589       Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
590       /* First see if the MESA_RGB_VISUAL env var is defined */
591       vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
592       if (vis) {
593 	 return vis;
594       }
595       /* Otherwise, search for a suitable visual */
596       if (preferred_class==DONT_CARE) {
597          for (xclass=0;xclass<6;xclass++) {
598             switch (xclass) {
599                case 0:  visclass = TrueColor;    break;
600                case 1:  visclass = DirectColor;  break;
601                case 2:  visclass = PseudoColor;  break;
602                case 3:  visclass = StaticColor;  break;
603                case 4:  visclass = GrayScale;    break;
604                case 5:  visclass = StaticGray;   break;
605             }
606             if (min_depth==0) {
607                /* start with shallowest */
608                for (depth=0;depth<=32;depth++) {
609                   if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
610                      /* Special case:  try to get 8-bit PseudoColor before */
611                      /* 8-bit TrueColor */
612                      vis = get_visual( dpy, screen, 8, PseudoColor );
613                      if (vis) {
614                         return vis;
615                      }
616                   }
617                   vis = get_visual( dpy, screen, depth, visclass );
618                   if (vis) {
619                      return vis;
620                   }
621                }
622             }
623             else {
624                /* start with deepest */
625                for (depth=32;depth>=min_depth;depth--) {
626                   if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
627                      /* Special case:  try to get 8-bit PseudoColor before */
628                      /* 8-bit TrueColor */
629                      vis = get_visual( dpy, screen, 8, PseudoColor );
630                      if (vis) {
631                         return vis;
632                      }
633                   }
634                   vis = get_visual( dpy, screen, depth, visclass );
635                   if (vis) {
636                      return vis;
637                   }
638                }
639             }
640          }
641       }
642       else {
643          /* search for a specific visual class */
644          switch (preferred_class) {
645             case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
646             case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
647             case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
648             case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
649             case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
650             case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
651             default:   return NULL;
652          }
653          if (min_depth==0) {
654             /* start with shallowest */
655             for (depth=0;depth<=32;depth++) {
656                vis = get_visual( dpy, screen, depth, visclass );
657                if (vis) {
658                   return vis;
659                }
660             }
661          }
662          else {
663             /* start with deepest */
664             for (depth=32;depth>=min_depth;depth--) {
665                vis = get_visual( dpy, screen, depth, visclass );
666                if (vis) {
667                   return vis;
668                }
669             }
670          }
671       }
672    }
673    else {
674       /* First see if the MESA_CI_VISUAL env var is defined */
675       vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
676       if (vis) {
677 	 return vis;
678       }
679       /* Otherwise, search for a suitable visual, starting with shallowest */
680       if (preferred_class==DONT_CARE) {
681          for (xclass=0;xclass<4;xclass++) {
682             switch (xclass) {
683                case 0:  visclass = PseudoColor;  break;
684                case 1:  visclass = StaticColor;  break;
685                case 2:  visclass = GrayScale;    break;
686                case 3:  visclass = StaticGray;   break;
687             }
688             /* try 8-bit up through 16-bit */
689             for (depth=8;depth<=16;depth++) {
690                vis = get_visual( dpy, screen, depth, visclass );
691                if (vis) {
692                   return vis;
693                }
694             }
695             /* try min_depth up to 8-bit */
696             for (depth=min_depth;depth<8;depth++) {
697                vis = get_visual( dpy, screen, depth, visclass );
698                if (vis) {
699                   return vis;
700                }
701             }
702          }
703       }
704       else {
705          /* search for a specific visual class */
706          switch (preferred_class) {
707             case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
708             case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
709             case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
710             case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
711             case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
712             case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
713             default:   return NULL;
714          }
715          /* try 8-bit up through 16-bit */
716          for (depth=8;depth<=16;depth++) {
717             vis = get_visual( dpy, screen, depth, visclass );
718             if (vis) {
719                return vis;
720             }
721          }
722          /* try min_depth up to 8-bit */
723          for (depth=min_depth;depth<8;depth++) {
724             vis = get_visual( dpy, screen, depth, visclass );
725             if (vis) {
726                return vis;
727             }
728          }
729       }
730    }
731 
732    /* didn't find a visual */
733    return NULL;
734 }
735 
736 
737 
738 /*
739  * Find the deepest X over/underlay visual of at least min_depth.
740  * Input:  dpy, screen - X display and screen number
741  *         level - the over/underlay level
742  *         trans_type - transparent pixel type: GLX_NONE_EXT,
743  *                      GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
744  *                      or DONT_CARE
745  *         trans_value - transparent pixel value or DONT_CARE
746  *         min_depth - minimum visual depth
747  *         preferred_class - preferred GLX visual class or DONT_CARE
748  * Return:  pointer to an XVisualInfo or NULL.
749  */
choose_x_overlay_visual(Display * dpy,int scr,int level,int trans_type,int trans_value,int min_depth,int preferred_class)750 static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr,
751                                              int level, int trans_type,
752                                              int trans_value,
753                                              int min_depth,
754                                              int preferred_class )
755 {
756    Atom overlayVisualsAtom;
757    OverlayInfo *overlay_info;
758    int numOverlaysPerScreen;
759    Status status;
760    Atom actualType;
761    int actualFormat;
762    unsigned long sizeData, bytesLeft;
763    int i;
764    XVisualInfo *deepvis;
765    int deepest;
766 
767    /*TMP*/ int tt, tv;
768 
769    switch (preferred_class) {
770       case GLX_TRUE_COLOR_EXT:    preferred_class = TrueColor;    break;
771       case GLX_DIRECT_COLOR_EXT:  preferred_class = DirectColor;  break;
772       case GLX_PSEUDO_COLOR_EXT:  preferred_class = PseudoColor;  break;
773       case GLX_STATIC_COLOR_EXT:  preferred_class = StaticColor;  break;
774       case GLX_GRAY_SCALE_EXT:    preferred_class = GrayScale;    break;
775       case GLX_STATIC_GRAY_EXT:   preferred_class = StaticGray;   break;
776       default:                    preferred_class = DONT_CARE;
777    }
778 
779    /*
780     * The SERVER_OVERLAY_VISUALS property on the root window contains
781     * a list of overlay visuals.  Get that list now.
782     */
783    overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
784    if (overlayVisualsAtom == None) {
785       return GL_FALSE;
786    }
787 
788    status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
789                                overlayVisualsAtom, 0L, (long) 10000, False,
790                                overlayVisualsAtom, &actualType, &actualFormat,
791                                &sizeData, &bytesLeft,
792                                (unsigned char **) &overlay_info );
793 
794    if (status != Success || actualType != overlayVisualsAtom ||
795        actualFormat != 32 || sizeData < 4) {
796       /* something went wrong */
797       return GL_FALSE;
798    }
799 
800    /* Search for the deepest overlay which satisifies all criteria. */
801    deepest = min_depth;
802    deepvis = NULL;
803 
804    numOverlaysPerScreen = sizeData / 4;
805    for (i=0;i<numOverlaysPerScreen;i++) {
806       XVisualInfo *vislist, vistemplate;
807       int count;
808       OverlayInfo *ov;
809       ov = overlay_info + i;
810 
811       if (ov->layer!=level) {
812          /* failed overlay level criteria */
813          continue;
814       }
815       if (!(trans_type==DONT_CARE
816             || (trans_type==GLX_TRANSPARENT_INDEX_EXT
817                 && ov->transparent_type>0)
818             || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
819          /* failed transparent pixel type criteria */
820          continue;
821       }
822       if (trans_value!=DONT_CARE && trans_value!=ov->value) {
823          /* failed transparent pixel value criteria */
824          continue;
825       }
826 
827       /* get XVisualInfo and check the depth */
828       vistemplate.visualid = ov->overlay_visual;
829       vistemplate.screen = scr;
830       vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
831                                 &vistemplate, &count );
832 
833       if (count!=1) {
834          /* something went wrong */
835          continue;
836       }
837       if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
838          /* wrong visual class */
839          continue;
840       }
841 
842       if (deepvis==NULL || vislist->depth > deepest) {
843          /* YES!  found a satisfactory visual */
844          if (deepvis) {
845             free( deepvis );
846          }
847          deepest = vislist->depth;
848          deepvis = vislist;
849          /* TMP */  tt = ov->transparent_type;
850          /* TMP */  tv = ov->value;
851       }
852    }
853 
854 /*TMP
855    if (deepvis) {
856       printf("chose 0x%x:  layer=%d depth=%d trans_type=%d trans_value=%d\n",
857              deepvis->visualid, level, deepvis->depth, tt, tv );
858    }
859 */
860    return deepvis;
861 }
862 
863 
864 
865 /*
866  * Return the number of bits set in n.
867  */
bitcount(unsigned long n)868 static int bitcount( unsigned long n )
869 {
870    int bits;
871    for (bits=0; n>0; n=n>>1) {
872       if (n&1) {
873          bits++;
874       }
875    }
876    return bits;
877 }
878 
879 
880 
glXChooseVisual(Display * dpy,int screen,int * list)881 XVisualInfo *glXChooseVisual( Display *dpy, int screen, int *list )
882 {
883    int *parselist;
884    XVisualInfo *vis;
885    int min_ci = 0;
886    int min_red=0, min_green=0, min_blue=0;
887    GLboolean rgb_flag = GL_FALSE;
888    GLboolean alpha_flag = GL_FALSE;
889    GLboolean double_flag = GL_FALSE;
890    GLint depth_size = 0;
891    GLint stencil_size = 0;
892    GLint accum_size = 0;
893    int level = 0;
894    int visual_type = DONT_CARE;
895    int trans_type = DONT_CARE;
896    int trans_value = DONT_CARE;
897 
898    parselist = list;
899 
900    while (*parselist) {
901 
902       switch (*parselist) {
903 	 case GLX_USE_GL:
904 	    /* ignore */
905 	    parselist++;
906 	    break;
907 	 case GLX_BUFFER_SIZE:
908 	    parselist++;
909 	    min_ci = *parselist++;
910 	    break;
911 	 case GLX_LEVEL:
912 	    parselist++;
913             level = *parselist++;
914 	    break;
915 	 case GLX_RGBA:
916 	    rgb_flag = GL_TRUE;
917 	    parselist++;
918 	    break;
919 	 case GLX_DOUBLEBUFFER:
920 	    double_flag = GL_TRUE;
921 	    parselist++;
922 	    break;
923 	 case GLX_STEREO:
924 	    /* not supported */
925             return NULL;
926 	 case GLX_AUX_BUFFERS:
927 	    /* ignore */
928 	    parselist++;
929 	    parselist++;
930 	    break;
931 	 case GLX_RED_SIZE:
932 	    parselist++;
933 	    min_red = *parselist++;
934 	    break;
935 	 case GLX_GREEN_SIZE:
936 	    parselist++;
937 	    min_green = *parselist++;
938 	    break;
939 	 case GLX_BLUE_SIZE:
940 	    parselist++;
941 	    min_blue = *parselist++;
942 	    break;
943 	 case GLX_ALPHA_SIZE:
944 	    parselist++;
945             {
946                GLint size = *parselist++;
947                alpha_flag = size>0 ? 1 : 0;
948             }
949 	    break;
950 	 case GLX_DEPTH_SIZE:
951 	    parselist++;
952 	    depth_size = *parselist++;
953 	    break;
954 	 case GLX_STENCIL_SIZE:
955 	    parselist++;
956 	    stencil_size = *parselist++;
957 	    break;
958 	 case GLX_ACCUM_RED_SIZE:
959 	 case GLX_ACCUM_GREEN_SIZE:
960 	 case GLX_ACCUM_BLUE_SIZE:
961 	 case GLX_ACCUM_ALPHA_SIZE:
962 	    parselist++;
963             {
964                GLint size = *parselist++;
965                accum_size = MAX2( accum_size, size );
966             }
967 	    break;
968 
969          /*
970           * GLX_EXT_visual_info extension
971           */
972          case GLX_X_VISUAL_TYPE_EXT:
973             parselist++;
974             visual_type = *parselist++;
975             break;
976          case GLX_TRANSPARENT_TYPE_EXT:
977             parselist++;
978             trans_type = *parselist++;
979             break;
980          case GLX_TRANSPARENT_INDEX_VALUE_EXT:
981             parselist++;
982             trans_value = *parselist++;
983             break;
984          case GLX_TRANSPARENT_RED_VALUE_EXT:
985          case GLX_TRANSPARENT_GREEN_VALUE_EXT:
986          case GLX_TRANSPARENT_BLUE_VALUE_EXT:
987          case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
988 	    /* ignore */
989 	    parselist++;
990 	    parselist++;
991 	    break;
992 
993 	 case None:
994 	    break;
995 	 default:
996 	    /* undefined attribute */
997 	    return NULL;
998       }
999    }
1000 
1001    /*
1002     * Since we're only simulating the GLX extension this function will never
1003     * find any real GL visuals.  Instead, all we can do is try to find an RGB
1004     * or CI visual of appropriate depth.  Other requested attributes such as
1005     * double buffering, depth buffer, etc. will be associated with the X
1006     * visual and stored in the VisualTable[].
1007     */
1008    if (level==0) {
1009       /* normal color planes */
1010       if (rgb_flag) {
1011          /* Get an RGB visual */
1012          int min_rgb = min_red + min_green + min_blue;
1013          if (min_rgb>1 && min_rgb<8) {
1014             /* a special case to be sure we can get a monochrome visual */
1015             min_rgb = 1;
1016          }
1017          vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
1018       }
1019       else {
1020          /* Get a color index visual */
1021          vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
1022          accum_size = 0;
1023       }
1024    }
1025    else {
1026       /* over/underlay planes */
1027       vis = choose_x_overlay_visual( dpy, screen, level, trans_type,
1028                                      trans_value, min_ci, visual_type );
1029    }
1030 
1031    if (vis) {
1032       if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1033                             depth_size, stencil_size, accum_size, level ))
1034          return NULL;
1035    }
1036 
1037    return vis;
1038 }
1039 
1040 
1041 
1042 
glXCreateContext(Display * dpy,XVisualInfo * visinfo,GLXContext share_list,Bool direct)1043 GLXContext glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1044 			     GLXContext share_list, Bool direct )
1045 {
1046    XMesaVisual glxvis;
1047 
1048    /* Garbage collection */
1049    free_zombie_buffers();
1050 
1051    glxvis = find_glx_visual( dpy, visinfo );
1052    if (!glxvis) {
1053       /* This visual wasn't found with glXChooseVisual() */
1054       glxvis = create_glx_visual( dpy, visinfo );
1055       if (!glxvis) {
1056          /* unusable visual */
1057          return NULL;
1058       }
1059    }
1060    return (GLXContext) XMesaCreateContext( glxvis, (XMesaContext) share_list );
1061 }
1062 
1063 
1064 
glXMakeCurrent(Display * dpy,GLXDrawable drawable,GLXContext ctx)1065 Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1066 {
1067    if (ctx && drawable) {
1068       static GLXDrawable prev_drawable = 0;
1069       static XMesaBuffer prev_buffer = 0;
1070       XMesaBuffer buffer;
1071 
1072       if (drawable==prev_drawable) {
1073          buffer = prev_buffer;
1074       }
1075       else {
1076          buffer = find_buffer( dpy, drawable );
1077       }
1078       if (!buffer) {
1079          /* drawable must be a new window! */
1080          buffer = save_buffer( ctx->xm_visual, drawable, GL_FALSE, 0 );
1081          if (!buffer) {
1082             /* If this happens, increase MAX_BUFFERS and recompile */
1083             fprintf(stderr,"Mesa GLX error: too many windows!\n");
1084             return False;
1085          }
1086       }
1087       prev_drawable = drawable;
1088       prev_buffer = buffer;
1089 
1090       /* Now make current! */
1091       return (Bool) XMesaMakeCurrent( (XMesaContext) ctx, buffer );
1092    }
1093    else if (!ctx && !drawable) {
1094       /* release current context w/out assigning new one. */
1095       XMesaMakeCurrent( NULL, NULL );
1096       return True;
1097    }
1098    else {
1099       /* ctx XOR drawable is NULL, this is an error */
1100       return False;
1101    }
1102 }
1103 
1104 
1105 
glXCreateGLXPixmap(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap)1106 GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
1107                               Pixmap pixmap )
1108 {
1109    XMesaVisual v;
1110    XMesaBuffer b;
1111 
1112    v = find_glx_visual( dpy, visinfo );
1113    if (!v) {
1114       v = create_glx_visual( dpy, visinfo );
1115       if (!v) {
1116          /* unusable visual */
1117          return 0;
1118       }
1119    }
1120 
1121    b = save_buffer( v, pixmap, GL_TRUE, 0 );
1122    if (!b) {
1123       return 0;
1124    }
1125    return b->frontbuffer;
1126 }
1127 
1128 
1129 #ifdef GLX_MESA_pixmap_colormap
1130 
glXCreateGLXPixmapMESA(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap,Colormap cmap)1131 GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1132                                   Pixmap pixmap, Colormap cmap )
1133 {
1134    XMesaVisual v;
1135    XMesaBuffer b;
1136 
1137    v = find_glx_visual( dpy, visinfo );
1138    if (!v) {
1139       v = create_glx_visual( dpy, visinfo );
1140       if (!v) {
1141          /* unusable visual */
1142          return 0;
1143       }
1144    }
1145 
1146    b = save_buffer( v, pixmap, GL_TRUE, cmap );
1147    if (!b) {
1148       return 0;
1149    }
1150    return b->frontbuffer;
1151 }
1152 
1153 #endif
1154 
1155 
glXDestroyGLXPixmap(Display * dpy,GLXPixmap pixmap)1156 void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1157 {
1158    int i, j;
1159 
1160    for (i=0;i<NumBuffers;i++) {
1161       if (BufferList[i]->frontbuffer==pixmap) {
1162          XMesaDestroyBuffer( BufferList[i] );
1163 	 for (j=i+1;j<NumBuffers;j++) {
1164 	    BufferList[j-1] = BufferList[j];
1165 	 }
1166 	 NumBuffers--;
1167 	 return;
1168       }
1169    }
1170    fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1171 }
1172 
1173 
glXCopyContext(Display * dpy,GLXContext src,GLXContext dst,GLuint mask)1174 void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1175 		     GLuint mask )
1176 {
1177    XMesaContext xm_src, xm_dst;
1178    xm_src = (XMesaContext) src;
1179    xm_dst = (XMesaContext) dst;
1180    gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask );
1181 }
1182 
1183 
1184 
glXQueryExtension(Display * dpy,int * errorb,int * event)1185 Bool glXQueryExtension( Display *dpy, int *errorb, int *event )
1186 {
1187    /* Mesa's GLX isn't really an X extension but we try to act like one. */
1188    return True;
1189 }
1190 
1191 
glXDestroyContext(Display * dpy,GLXContext ctx)1192 void glXDestroyContext( Display *dpy, GLXContext ctx )
1193 {
1194    XMesaDestroyContext( (XMesaContext) ctx );
1195 
1196    /* Garbage collection */
1197    free_zombie_buffers();
1198 }
1199 
1200 
1201 
glXIsDirect(Display * dpy,GLXContext ctx)1202 Bool glXIsDirect( Display *dpy, GLXContext ctx )
1203 {
1204    /* This isn't true but... */
1205    return True;
1206 }
1207 
1208 
1209 
glXSwapBuffers(Display * dpy,GLXDrawable drawable)1210 void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1211 {
1212    static GLXDrawable prev_drawable = 0;
1213    static XMesaBuffer prev_buffer = 0;
1214 
1215    if (drawable==prev_drawable) {
1216       XMesaSwapBuffers( prev_buffer );
1217       return;
1218    }
1219 
1220    prev_drawable = drawable;
1221    prev_buffer = find_buffer( dpy, drawable );
1222    if (prev_buffer) {
1223       XMesaSwapBuffers( prev_buffer );
1224    }
1225    else {
1226       fprintf( stderr,
1227 	  "Warning: glXSwapBuffers drawable doesn't match current context\n");
1228    }
1229 }
1230 
1231 
1232 
glXQueryVersion(Display * dpy,int * maj,int * min)1233 Bool glXQueryVersion( Display *dpy, int *maj, int *min )
1234 {
1235    /* Return GLX version, not Mesa version */
1236    *maj = 1;
1237    *min = 1;
1238    return True;
1239 }
1240 
1241 
1242 
1243 /*
1244  * Query the GLX attributes of the given XVisualInfo.
1245  */
glXGetConfig(Display * dpy,XVisualInfo * visinfo,int attrib,int * value)1246 int glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1247 		  int attrib, int *value )
1248 {
1249    int visclass;
1250    XMesaVisual glxvis;
1251 
1252    glxvis = find_glx_visual( dpy, visinfo );
1253    if (!glxvis) {
1254       /* this visual wasn't obtained with glXChooseVisual */
1255       glxvis = create_glx_visual( dpy, visinfo );
1256       if (!glxvis) {
1257 	 /* this visual can't be used for GL rendering */
1258 	 if (attrib==GLX_USE_GL) {
1259 	    *value = (int) False;
1260 	    return 0;
1261 	 }
1262 	 else {
1263 	    /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1264 	    return GLX_BAD_VISUAL;
1265 	 }
1266       }
1267    }
1268 
1269    /* Get the visual class */
1270    visclass = visinfo->CLASS;
1271 
1272    switch(attrib) {
1273       case GLX_USE_GL:
1274          *value = (int) True;
1275 	 return 0;
1276       case GLX_BUFFER_SIZE:
1277 	 *value = visinfo->depth;
1278 	 return 0;
1279       case GLX_LEVEL:
1280 	 *value = glxvis->level;
1281 	 return 0;
1282       case GLX_RGBA:
1283 	 if (glxvis->gl_visual->RGBAflag) {
1284 	    *value = True;
1285 	 }
1286 	 else {
1287 	    *value = False;
1288 	 }
1289 	 return 0;
1290       case GLX_DOUBLEBUFFER:
1291 	 *value = (int) glxvis->gl_visual->DBflag;
1292 	 return 0;
1293       case GLX_STEREO:
1294 	 *value = (int) False;
1295 	 return 0;
1296       case GLX_AUX_BUFFERS:
1297 	 *value = (int) False;
1298 	 return 0;
1299       case GLX_RED_SIZE:
1300          if (visclass==DirectColor || visclass==TrueColor) {
1301             *value = bitcount( visinfo->visual->red_mask );
1302          }
1303          else {
1304             /* a crude approximation */
1305             *value = visinfo->depth;
1306          }
1307 	 return 0;
1308       case GLX_GREEN_SIZE:
1309          if (visclass==DirectColor || visclass==TrueColor) {
1310             *value = bitcount( visinfo->visual->green_mask );
1311          }
1312          else {
1313             *value = visinfo->depth;
1314          }
1315 	 return 0;
1316       case GLX_BLUE_SIZE:
1317          if (visclass==DirectColor || visclass==TrueColor) {
1318             *value = bitcount( visinfo->visual->blue_mask );
1319          }
1320          else {
1321             *value = visinfo->depth;
1322          }
1323 	 return 0;
1324       case GLX_ALPHA_SIZE:
1325          if (glxvis->gl_visual->FrontAlphaEnabled ||
1326              glxvis->gl_visual->BackAlphaEnabled) {
1327             *value = 8;
1328          }
1329          else {
1330             *value = 0;
1331          }
1332 	 return 0;
1333       case GLX_DEPTH_SIZE:
1334          *value = glxvis->gl_visual->DepthBits;
1335 	 return 0;
1336       case GLX_STENCIL_SIZE:
1337 	 *value = glxvis->gl_visual->StencilBits;
1338 	 return 0;
1339       case GLX_ACCUM_RED_SIZE:
1340       case GLX_ACCUM_GREEN_SIZE:
1341       case GLX_ACCUM_BLUE_SIZE:
1342       case GLX_ACCUM_ALPHA_SIZE:
1343 	 *value = glxvis->gl_visual->AccumBits;
1344 	 return 0;
1345 
1346       /*
1347        * GLX_EXT_visual_info extension
1348        */
1349       case GLX_X_VISUAL_TYPE_EXT:
1350          switch (glxvis->visinfo->CLASS) {
1351             case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
1352             case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
1353             case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
1354             case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
1355             case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
1356             case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
1357          }
1358          return 0;
1359       case GLX_TRANSPARENT_TYPE_EXT:
1360          if (glxvis->level==0) {
1361             /* normal planes */
1362             *value = GLX_NONE_EXT;
1363          }
1364          else if (glxvis->level>0) {
1365             /* overlay */
1366             if (glxvis->gl_visual->RGBAflag) {
1367                *value = GLX_TRANSPARENT_RGB_EXT;
1368             }
1369             else {
1370                *value = GLX_TRANSPARENT_INDEX_EXT;
1371             }
1372          }
1373          else if (glxvis->level<0) {
1374             /* underlay */
1375             *value = GLX_NONE_EXT;
1376          }
1377          return 0;
1378       case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1379          {
1380             int pixel = transparent_pixel( glxvis );
1381             if (pixel>=0) {
1382                *value = pixel;
1383             }
1384             /* else undefined */
1385          }
1386          return 0;
1387       case GLX_TRANSPARENT_RED_VALUE_EXT:
1388          /* undefined */
1389          return 0;
1390       case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1391          /* undefined */
1392          return 0;
1393       case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1394          /* undefined */
1395          return 0;
1396       case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1397          /* undefined */
1398          return 0;
1399 
1400       /*
1401        * Extensions
1402        */
1403       default:
1404 	 return GLX_BAD_ATTRIBUTE;
1405    }
1406 }
1407 
1408 
1409 
glXGetCurrentContext(void)1410 GLXContext glXGetCurrentContext( void )
1411 {
1412    return (GLXContext) XMesaGetCurrentContext();
1413 }
1414 
1415 
1416 
glXGetCurrentDrawable(void)1417 GLXDrawable glXGetCurrentDrawable( void )
1418 {
1419    XMesaBuffer b = XMesaGetCurrentBuffer();
1420    if (b) {
1421       return b->frontbuffer;
1422    }
1423    else {
1424       return 0;
1425    }
1426 }
1427 
1428 
glXWaitGL(void)1429 void glXWaitGL( void )
1430 {
1431    XMesaContext xmesa = XMesaGetCurrentContext();
1432    XMesaFlush( xmesa );
1433 }
1434 
1435 
1436 
glXWaitX(void)1437 void glXWaitX( void )
1438 {
1439    XMesaContext xmesa = XMesaGetCurrentContext();
1440    XMesaFlush( xmesa );
1441 }
1442 
1443 
1444 
1445 #define EXTENSIONS "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers"
1446 
1447 
1448 /* GLX 1.1 and later */
glXQueryExtensionsString(Display * dpy,int screen)1449 const char *glXQueryExtensionsString( Display *dpy, int screen )
1450 {
1451    static char *extensions = EXTENSIONS;
1452    return extensions;
1453 }
1454 
1455 
1456 
1457 /* GLX 1.1 and later */
glXQueryServerString(Display * dpy,int screen,int name)1458 const char *glXQueryServerString( Display *dpy, int screen, int name )
1459 {
1460    static char *extensions = EXTENSIONS;
1461    static char *vendor = "Brian Paul";
1462    static char *version = "1.1 Mesa 2.2";
1463 
1464    switch (name) {
1465       case GLX_EXTENSIONS:
1466          return extensions;
1467       case GLX_VENDOR:
1468 	 return vendor;
1469       case GLX_VERSION:
1470 	 return version;
1471       default:
1472          return NULL;
1473    }
1474 }
1475 
1476 
1477 
1478 /* GLX 1.1 and later */
glXGetClientString(Display * dpy,int name)1479 const char *glXGetClientString( Display *dpy, int name )
1480 {
1481    static char *extensions = EXTENSIONS;
1482    static char *vendor = "Brian Paul";
1483    static char *version = "1.1 Mesa 2.2";
1484 
1485    switch (name) {
1486       case GLX_EXTENSIONS:
1487          return extensions;
1488       case GLX_VENDOR:
1489 	 return vendor;
1490       case GLX_VERSION:
1491 	 return version;
1492       default:
1493          return NULL;
1494    }
1495 }
1496 
1497 
1498 
1499 /*
1500  * Release the depth, stencil, accum buffers attached to a window prior
1501  * to destroying the window.
1502  */
glXReleaseBuffersMESA(Display * dpy,Window w)1503 Bool glXReleaseBuffersMESA( Display *dpy, Window w )
1504 {
1505    GLint i, j;
1506 
1507    for (i=0;i<NumBuffers;i++) {
1508       if (BufferList[i]->frontbuffer==w) {
1509          XMesaDestroyBuffer( BufferList[i] );
1510 	 for (j=i+1;j<NumBuffers;j++) {
1511 	    BufferList[j-1] = BufferList[j];
1512 	 }
1513 	 NumBuffers--;
1514          return True;
1515       }
1516    }
1517    return False;
1518 }
1519 
1520 #endif
1521