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