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