1 /* GdkGLExt - OpenGL Extension to GDK
2 * Copyright (C) 2002-2004 Naofumi Yasufuku
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17 */
18
19 #include <string.h>
20
21 #ifdef __APPLE__
22 #include <mach-o/dyld.h>
23 #else /* __APPLE__ */
24 #include <gmodule.h>
25 #endif /* __APPLE__ */
26
27 #include "gdkglx.h"
28 #include "gdkglprivate-x11.h"
29 #include "gdkglconfig-x11.h"
30 #include "gdkglquery.h"
31
32 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
33 #include <gdk/gdkdisplay.h>
34 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
35
36 /**
37 * gdk_gl_query_extension:
38 *
39 * Indicates whether the window system supports the OpenGL extension
40 * (GLX, WGL, etc.).
41 *
42 * Return value: TRUE if OpenGL is supported, FALSE otherwise.
43 **/
44 gboolean
gdk_gl_query_extension(void)45 gdk_gl_query_extension (void)
46 {
47 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
48 return glXQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
49 NULL, NULL);
50 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
51 return glXQueryExtension (gdk_x11_get_default_xdisplay (),
52 NULL, NULL);
53 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
54 }
55
56 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
57
58 /**
59 * gdk_gl_query_extension_for_display:
60 * @display: the #GdkDisplay where the query is sent to.
61 *
62 * Indicates whether the window system supports the OpenGL extension
63 * (GLX, WGL, etc.).
64 *
65 * Return value: TRUE if OpenGL is supported, FALSE otherwise.
66 **/
67 gboolean
gdk_gl_query_extension_for_display(GdkDisplay * display)68 gdk_gl_query_extension_for_display (GdkDisplay *display)
69 {
70 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
71
72 return glXQueryExtension (GDK_DISPLAY_XDISPLAY (display),
73 NULL, NULL);
74 }
75
76 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
77
78 /**
79 * gdk_gl_query_version:
80 * @major: returns the major version number of the OpenGL extension.
81 * @minor: returns the minor version number of the OpenGL extension.
82 *
83 * Returns the version numbers of the OpenGL extension to the window system.
84 *
85 * In the X Window System, it returns the GLX version.
86 *
87 * In the Microsoft Windows, it returns the Windows version.
88 *
89 * Return value: FALSE if it fails, TRUE otherwise.
90 **/
91 gboolean
gdk_gl_query_version(int * major,int * minor)92 gdk_gl_query_version (int *major,
93 int *minor)
94 {
95 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
96 return glXQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
97 major, minor);
98 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
99 return glXQueryVersion (gdk_x11_get_default_xdisplay (),
100 major, minor);
101 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
102 }
103
104 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
105
106 /**
107 * gdk_gl_query_version_for_display:
108 * @display: the #GdkDisplay where the query is sent to.
109 * @major: returns the major version number of the OpenGL extension.
110 * @minor: returns the minor version number of the OpenGL extension.
111 *
112 * Returns the version numbers of the OpenGL extension to the window system.
113 *
114 * In the X Window System, it returns the GLX version.
115 *
116 * In the Microsoft Windows, it returns the Windows version.
117 *
118 * Return value: FALSE if it fails, TRUE otherwise.
119 **/
120 gboolean
gdk_gl_query_version_for_display(GdkDisplay * display,int * major,int * minor)121 gdk_gl_query_version_for_display (GdkDisplay *display,
122 int *major,
123 int *minor)
124 {
125 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
126
127 return glXQueryVersion (GDK_DISPLAY_XDISPLAY (display),
128 major, minor);
129 }
130
131 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
132
133 /*
134 * This code is based on __glutIsSupportedByGLX().
135 */
136
137 /**
138 * gdk_x11_gl_query_glx_extension:
139 * @glconfig: a #GdkGLConfig.
140 * @extension: name of GLX extension.
141 *
142 * Determines whether a given GLX extension is supported.
143 *
144 * Return value: TRUE if the GLX extension is supported, FALSE if not
145 * supported.
146 **/
147 gboolean
gdk_x11_gl_query_glx_extension(GdkGLConfig * glconfig,const char * extension)148 gdk_x11_gl_query_glx_extension (GdkGLConfig *glconfig,
149 const char *extension)
150 {
151 static const char *extensions = NULL;
152 const char *start;
153 char *where, *terminator;
154 int major, minor;
155
156 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), FALSE);
157
158 /* Extension names should not have spaces. */
159 where = strchr (extension, ' ');
160 if (where || *extension == '\0')
161 return FALSE;
162
163 if (extensions == NULL)
164 {
165 /* Be careful not to call glXQueryExtensionsString if it
166 looks like the server doesn't support GLX 1.1.
167 Unfortunately, the original GLX 1.0 didn't have the notion
168 of GLX extensions. */
169
170 glXQueryVersion (GDK_GL_CONFIG_XDISPLAY (glconfig),
171 &major, &minor);
172
173 if ((major == 1 && minor < 1) || (major < 1))
174 return FALSE;
175
176 extensions = glXQueryExtensionsString (GDK_GL_CONFIG_XDISPLAY (glconfig),
177 GDK_GL_CONFIG_SCREEN_XNUMBER (glconfig));
178 }
179
180 /* It takes a bit of care to be fool-proof about parsing
181 the GLX extensions string. Don't be fooled by
182 sub-strings, etc. */
183 start = extensions;
184 for (;;)
185 {
186 where = strstr (start, extension);
187 if (where == NULL)
188 break;
189
190 terminator = where + strlen (extension);
191
192 if (where == start || *(where - 1) == ' ')
193 if (*terminator == ' ' || *terminator == '\0')
194 {
195 GDK_GL_NOTE (MISC, g_message (" - %s - supported", extension));
196 return TRUE;
197 }
198
199 start = terminator;
200 }
201
202 GDK_GL_NOTE (MISC, g_message (" - %s - not supported", extension));
203
204 return FALSE;
205 }
206
207 /**
208 * gdk_gl_get_proc_address:
209 * @proc_name: function name.
210 *
211 * Returns the address of the OpenGL, GLU, or GLX function.
212 *
213 * Return value: the address of the function named by @proc_name.
214 **/
215
216 #ifdef __APPLE__
217
218 #define _GDK_GL_LIBGL_PATH "/usr/X11R6/lib/libGL.1.dylib"
219 #define _GDK_GL_LIBGLU_PATH "/usr/X11R6/lib/libGLU.1.dylib"
220
221 GdkGLProc
gdk_gl_get_proc_address(const char * proc_name)222 gdk_gl_get_proc_address (const char *proc_name)
223 {
224 typedef GdkGLProc (*__glXGetProcAddressProc) (const GLubyte *);
225 static __glXGetProcAddressProc glx_get_proc_address = (__glXGetProcAddressProc) -1;
226 const char *image_name;
227 static const struct mach_header *libgl_image = NULL;
228 static const struct mach_header *libglu_image = NULL;
229 NSSymbol symbol;
230 char *symbol_name;
231 GdkGLProc proc_address;
232
233 GDK_GL_NOTE_FUNC ();
234
235 if (strncmp ("glu", proc_name, 3) != 0)
236 {
237 /* libGL */
238
239 if (libgl_image == NULL)
240 {
241 image_name = g_getenv ("GDK_GL_LIBGL_PATH");
242 if (image_name == NULL)
243 image_name = _GDK_GL_LIBGL_PATH;
244
245 GDK_GL_NOTE (MISC, g_message (" - Add Mach-O image %s", image_name));
246
247 libgl_image = NSAddImage (image_name, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
248 if (libgl_image == NULL)
249 {
250 g_warning ("Cannot add Mach-O image %s", image_name);
251 return NULL;
252 }
253 }
254
255 if (glx_get_proc_address == (__glXGetProcAddressProc) -1)
256 {
257 /*
258 * Look up glXGetProcAddress () function.
259 */
260
261 symbol = NSLookupSymbolInImage (libgl_image,
262 "_glXGetProcAddress",
263 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
264 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
265 if (symbol == NULL)
266 {
267 symbol = NSLookupSymbolInImage (libgl_image,
268 "_glXGetProcAddressARB",
269 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
270 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
271 if (symbol == NULL)
272 {
273 symbol = NSLookupSymbolInImage (libgl_image,
274 "_glXGetProcAddressEXT",
275 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
276 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
277 }
278 }
279 GDK_GL_NOTE (MISC, g_message (" - glXGetProcAddress () - %s",
280 symbol ? "supported" : "not supported"));
281 if (symbol != NULL)
282 glx_get_proc_address = NSAddressOfSymbol (symbol);
283 else
284 glx_get_proc_address = NULL;
285 }
286
287 /* Try glXGetProcAddress () */
288
289 if (glx_get_proc_address != NULL)
290 {
291 proc_address = glx_get_proc_address (proc_name);
292 GDK_GL_NOTE (IMPL, g_message (" ** glXGetProcAddress () - %s",
293 proc_address ? "succeeded" : "failed"));
294 if (proc_address != NULL)
295 return proc_address;
296 }
297
298 /* Try Mach-O dyld */
299
300 symbol_name = g_strconcat ("_", proc_name, NULL);
301
302 symbol = NSLookupSymbolInImage (libgl_image,
303 symbol_name,
304 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
305 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
306 GDK_GL_NOTE (MISC, g_message (" - NSLookupSymbolInImage () - %s",
307 symbol ? "succeeded" : "failed"));
308
309 g_free (symbol_name);
310
311 if (symbol != NULL)
312 return NSAddressOfSymbol (symbol);
313 }
314 else
315 {
316 /* libGLU */
317
318 if (libglu_image == NULL)
319 {
320 image_name = g_getenv ("GDK_GL_LIBGLU_PATH");
321 if (image_name == NULL)
322 image_name = _GDK_GL_LIBGLU_PATH;
323
324 GDK_GL_NOTE (MISC, g_message (" - Add Mach-O image %s", image_name));
325
326 libglu_image = NSAddImage (image_name, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
327 if (libglu_image == NULL)
328 {
329 g_warning ("Cannot add Mach-O image %s", image_name);
330 return NULL;
331 }
332 }
333
334 symbol_name = g_strconcat ("_", proc_name, NULL);
335
336 symbol = NSLookupSymbolInImage (libglu_image,
337 symbol_name,
338 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
339 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
340 GDK_GL_NOTE (MISC, g_message (" - NSLookupSymbolInImage () - %s",
341 symbol ? "succeeded" : "failed"));
342
343 g_free (symbol_name);
344
345 if (symbol != NULL)
346 return NSAddressOfSymbol (symbol);
347 }
348
349 return NULL;
350 }
351
352 #else /* __APPLE__ */
353
354 GdkGLProc
gdk_gl_get_proc_address(const char * proc_name)355 gdk_gl_get_proc_address (const char *proc_name)
356 {
357 typedef GdkGLProc (*__glXGetProcAddressProc) (const GLubyte *);
358 static __glXGetProcAddressProc glx_get_proc_address = (__glXGetProcAddressProc) -1;
359 gchar *file_name;
360 GModule *module;
361 GdkGLProc proc_address = NULL;
362
363 GDK_GL_NOTE_FUNC ();
364
365 if (strncmp ("glu", proc_name, 3) != 0)
366 {
367 if (glx_get_proc_address == (__glXGetProcAddressProc) -1)
368 {
369 /*
370 * Look up glXGetProcAddress () function.
371 */
372
373 file_name = g_module_build_path (NULL, "GL");
374 GDK_GL_NOTE (MISC, g_message (" - Open %s", file_name));
375 module = g_module_open (file_name, G_MODULE_BIND_LAZY);
376 g_free (file_name);
377
378 if (module != NULL)
379 {
380 g_module_symbol (module, "glXGetProcAddress",
381 (gpointer) &glx_get_proc_address);
382 if (glx_get_proc_address == NULL)
383 {
384 g_module_symbol (module, "glXGetProcAddressARB",
385 (gpointer) &glx_get_proc_address);
386 if (glx_get_proc_address == NULL)
387 {
388 g_module_symbol (module, "glXGetProcAddressEXT",
389 (gpointer) &glx_get_proc_address);
390 }
391 }
392 GDK_GL_NOTE (MISC, g_message (" - glXGetProcAddress () - %s",
393 glx_get_proc_address ? "supported" : "not supported"));
394 g_module_close (module);
395 }
396 else
397 {
398 g_warning ("Cannot open %s", file_name);
399 glx_get_proc_address = NULL;
400 return NULL;
401 }
402 }
403
404 /* Try glXGetProcAddress () */
405
406 if (glx_get_proc_address != NULL)
407 {
408 proc_address = glx_get_proc_address (proc_name);
409 GDK_GL_NOTE (IMPL, g_message (" ** glXGetProcAddress () - %s",
410 proc_address ? "succeeded" : "failed"));
411 if (proc_address != NULL)
412 return proc_address;
413 }
414
415 /* Try g_module_symbol () */
416
417 /* libGL */
418 file_name = g_module_build_path (NULL, "GL");
419 GDK_GL_NOTE (MISC, g_message (" - Open %s", file_name));
420 module = g_module_open (file_name, G_MODULE_BIND_LAZY);
421 g_free (file_name);
422
423 if (module != NULL)
424 {
425 g_module_symbol (module, proc_name, (gpointer) &proc_address);
426 GDK_GL_NOTE (MISC, g_message (" - g_module_symbol () - %s",
427 proc_address ? "succeeded" : "failed"));
428 g_module_close (module);
429 }
430 else
431 {
432 g_warning ("Cannot open %s", file_name);
433 }
434
435 if (proc_address == NULL)
436 {
437 /* libGLcore */
438 file_name = g_module_build_path (NULL, "GLcore");
439 GDK_GL_NOTE (MISC, g_message (" - Open %s", file_name));
440 module = g_module_open (file_name, G_MODULE_BIND_LAZY);
441 g_free (file_name);
442
443 if (module != NULL)
444 {
445 g_module_symbol (module, proc_name, (gpointer) &proc_address);
446 GDK_GL_NOTE (MISC, g_message (" - g_module_symbol () - %s",
447 proc_address ? "succeeded" : "failed"));
448 g_module_close (module);
449 }
450 }
451 }
452 else
453 {
454 /* libGLU */
455 file_name = g_module_build_path (NULL, "GLU");
456 GDK_GL_NOTE (MISC, g_message (" - Open %s", file_name));
457 module = g_module_open (file_name, G_MODULE_BIND_LAZY);
458 g_free (file_name);
459
460 if (module != NULL)
461 {
462 g_module_symbol (module, proc_name, (gpointer) &proc_address);
463 GDK_GL_NOTE (MISC, g_message (" - g_module_symbol () - %s",
464 proc_address ? "succeeded" : "failed"));
465 g_module_close (module);
466 }
467 else
468 {
469 g_warning ("Cannot open %s", file_name);
470 }
471 }
472
473 return proc_address;
474 }
475
476 #endif /* __APPLE__ */
477
478 /*< private >*/
479 void
_gdk_x11_gl_print_glx_info(Display * xdisplay,int screen_num)480 _gdk_x11_gl_print_glx_info (Display *xdisplay,
481 int screen_num)
482 {
483 static gboolean done = FALSE;
484
485 if (!done)
486 {
487 g_message (" -- Server GLX_VENDOR : %s",
488 glXQueryServerString (xdisplay, screen_num, GLX_VENDOR));
489 g_message (" -- Server GLX_VERSION : %s",
490 glXQueryServerString (xdisplay, screen_num, GLX_VERSION));
491 g_message (" -- Server GLX_EXTENSIONS : %s",
492 glXQueryServerString (xdisplay, screen_num, GLX_EXTENSIONS));
493
494 g_message (" -- Client GLX_VENDOR : %s",
495 glXGetClientString (xdisplay, GLX_VENDOR));
496 g_message (" -- Client GLX_VERSION : %s",
497 glXGetClientString (xdisplay, GLX_VERSION));
498 g_message (" -- Client GLX_EXTENSIONS : %s",
499 glXGetClientString (xdisplay, GLX_EXTENSIONS));
500
501 done = TRUE;
502 }
503 }
504