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