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