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