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