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