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