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