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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22
23 #include <string.h>
24
25 #include "gdkglx.h"
26 #include "gdkglprivate-x11.h"
27 #include "gdkgloverlay-x11.h"
28 #include "gdkglconfig-x11.h"
29
30 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
31 #include <gdk/gdkscreen.h>
32 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
33
34 #ifdef HAVE_LIBXMU
35
36 #include <X11/Xatom.h> /* for XA_RGB_DEFAULT_MAP atom */
37
38 #ifdef HAVE_XMU_STDCMAP_H
39 #include <Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
40 #else
41 #include <X11/Xmu/StdCmap.h> /* for XmuLookupStandardColormap */
42 #endif
43
44 #endif /* HAVE_LIBXMU */
45
46 static void gdk_gl_config_impl_x11_class_init (GdkGLConfigImplX11Class *klass);
47 static void gdk_gl_config_impl_x11_finalize (GObject *object);
48
49 static gpointer parent_class = NULL;
50
51 GType
gdk_gl_config_impl_x11_get_type(void)52 gdk_gl_config_impl_x11_get_type (void)
53 {
54 static GType type = 0;
55
56 if (!type)
57 {
58 static const GTypeInfo type_info = {
59 sizeof (GdkGLConfigImplX11Class),
60 (GBaseInitFunc) NULL,
61 (GBaseFinalizeFunc) NULL,
62 (GClassInitFunc) gdk_gl_config_impl_x11_class_init,
63 (GClassFinalizeFunc) NULL,
64 NULL, /* class_data */
65 sizeof (GdkGLConfigImplX11),
66 0, /* n_preallocs */
67 (GInstanceInitFunc) NULL
68 };
69
70 type = g_type_register_static (GDK_TYPE_GL_CONFIG,
71 "GdkGLConfigImplX11",
72 &type_info, 0);
73 }
74
75 return type;
76 }
77
78 static void
gdk_gl_config_impl_x11_class_init(GdkGLConfigImplX11Class * klass)79 gdk_gl_config_impl_x11_class_init (GdkGLConfigImplX11Class *klass)
80 {
81 GObjectClass *object_class = G_OBJECT_CLASS (klass);
82
83 GDK_GL_NOTE_FUNC_PRIVATE ();
84
85 parent_class = g_type_class_peek_parent (klass);
86
87 object_class->finalize = gdk_gl_config_impl_x11_finalize;
88 }
89
90 static void
gdk_gl_config_impl_x11_finalize(GObject * object)91 gdk_gl_config_impl_x11_finalize (GObject *object)
92 {
93 GdkGLConfigImplX11 *impl = GDK_GL_CONFIG_IMPL_X11 (object);
94
95 GDK_GL_NOTE_FUNC_PRIVATE ();
96
97 XFree (impl->xvinfo);
98
99 g_object_unref (G_OBJECT (impl->colormap));
100
101 G_OBJECT_CLASS (parent_class)->finalize (object);
102 }
103
104 /*
105 * Get standard RGB colormap
106 */
107
108 #ifdef HAVE_GDK_X11_COLORMAP_FOREIGN_NEW
109
110 static GdkColormap *
gdk_gl_config_get_std_rgb_colormap(GdkScreen * screen,XVisualInfo * xvinfo,gboolean is_mesa_glx)111 gdk_gl_config_get_std_rgb_colormap (GdkScreen *screen,
112 XVisualInfo *xvinfo,
113 gboolean is_mesa_glx)
114 {
115 GdkDisplay *display;
116 Display *xdisplay;
117 int screen_num;
118 Window xroot_window;
119 Status status;
120 Colormap xcolormap = None;
121 XStandardColormap *standard_cmaps;
122 int i, num_cmaps;
123 GdkVisual *visual;
124
125 GDK_GL_NOTE_FUNC_PRIVATE ();
126
127 display = gdk_screen_get_display (screen);
128 xdisplay = GDK_DISPLAY_XDISPLAY (display);
129 screen_num = xvinfo->screen;
130 xroot_window = RootWindow (xdisplay, screen_num);
131
132 /*
133 * (ripped from GLUT)
134 * Hewlett-Packard supports a feature called "HP Color Recovery".
135 * Mesa has code to use HP Color Recovery. For Mesa to use this feature,
136 * the atom _HP_RGB_SMOOTH_MAP_LIST must be defined on the root window AND
137 * the colormap obtainable by XGetRGBColormaps for that atom must be set on
138 * the window. If that colormap is not set, the output will look stripy.
139 */
140
141 if (is_mesa_glx &&
142 xvinfo->visual->class == TrueColor &&
143 xvinfo->depth == 8)
144 {
145 Atom xa_hp_cr_maps;
146
147 GDK_GL_NOTE (MISC,
148 g_message (" -- Try to find a standard RGB colormap with HP Color Recovery"));
149
150 xa_hp_cr_maps = gdk_x11_get_xatom_by_name_for_display (display,
151 "_HP_RGB_SMOOTH_MAP_LIST");
152
153 status = XGetRGBColormaps (xdisplay, xroot_window,
154 &standard_cmaps, &num_cmaps,
155 xa_hp_cr_maps);
156 if (status)
157 {
158 for (i = 0; i < num_cmaps; i++)
159 {
160 if (standard_cmaps[i].visualid == xvinfo->visualid)
161 {
162 xcolormap = standard_cmaps[i].colormap;
163 break;
164 }
165 }
166
167 XFree (standard_cmaps);
168
169 if (xcolormap != None)
170 {
171 GDK_GL_NOTE (MISC,
172 g_message (" -- Colormap: standard RGB with HP Color Recovery"));
173
174 visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
175 return gdk_x11_colormap_foreign_new (visual, xcolormap);
176 }
177 }
178 }
179
180 #if defined(HAVE_LIBXMU) && !defined(_DISABLE_STANDARD_RGB_CMAP)
181
182 /*
183 * (ripped from GLUT)
184 * Solaris 2.4 and 2.5 have a bug in their XmuLookupStandardColormap
185 * implementations. Please compile your Solaris 2.4 or 2.5 version of
186 * GtkGLExt with -D_DISABLE_STANDARD_RGB_CMAP to work around this bug.
187 * The symptom of the bug is that programs will get a BadMatch error
188 * from XCreateWindow when creating a window because Solaris 2.4 and 2.5
189 * create a corrupted RGB_DEFAULT_MAP property. Note that this workaround
190 * prevents colormap sharing between applications, perhaps leading
191 * unnecessary colormap installations or colormap flashing. Sun fixed
192 * this bug in Solaris 2.6.
193 */
194
195 if (!_gdk_gl_config_no_standard_colormap)
196 {
197 GDK_GL_NOTE (MISC,
198 g_message (" -- Try to find a standard RGB colormap"));
199
200 status = XmuLookupStandardColormap (xdisplay, screen_num,
201 xvinfo->visualid, xvinfo->depth,
202 XA_RGB_DEFAULT_MAP,
203 False, True);
204 if (status)
205 {
206 status = XGetRGBColormaps (xdisplay, xroot_window,
207 &standard_cmaps, &num_cmaps,
208 XA_RGB_DEFAULT_MAP);
209 if (status)
210 {
211 for (i = 0; i < num_cmaps; i++)
212 {
213 if (standard_cmaps[i].visualid == xvinfo->visualid)
214 {
215 xcolormap = standard_cmaps[i].colormap;
216 break;
217 }
218 }
219
220 XFree (standard_cmaps);
221
222 if (xcolormap != None)
223 {
224 GDK_GL_NOTE (MISC, g_message (" -- Colormap: standard RGB"));
225
226 visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
227 return gdk_x11_colormap_foreign_new (visual, xcolormap);
228 }
229 }
230 }
231 }
232
233 #endif /* defined(HAVE_LIBXMU) && !defined(_DISABLE_STANDARD_RGB_CMAP) */
234
235 return NULL;
236 }
237
238 #endif /* HAVE_GDK_X11_COLORMAP_FOREIGN_NEW */
239
240 /*
241 * Setup colormap.
242 */
243
244 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
245
246 static GdkColormap *
gdk_gl_config_setup_colormap(GdkScreen * screen,XVisualInfo * xvinfo,gboolean is_rgba,gboolean is_mesa_glx)247 gdk_gl_config_setup_colormap (GdkScreen *screen,
248 XVisualInfo *xvinfo,
249 gboolean is_rgba,
250 gboolean is_mesa_glx)
251 {
252 GdkColormap *colormap;
253 GdkVisual *visual;
254 GdkGLOverlayInfo overlay_info;
255 gboolean overlay_supported;
256
257 GDK_GL_NOTE_FUNC_PRIVATE ();
258
259 if (is_rgba)
260 {
261 /*
262 * For RGBA mode.
263 */
264
265 /* Try default colormap. */
266
267 colormap = gdk_screen_get_default_colormap (screen);
268 visual = gdk_colormap_get_visual (colormap);
269 if (GDK_VISUAL_XVISUAL (visual)->visualid == xvinfo->visualid)
270 {
271 GDK_GL_NOTE (MISC, g_message (" -- Colormap: screen default"));
272 g_object_ref (G_OBJECT (colormap));
273 return colormap;
274 }
275
276 /* Try standard RGB colormap. */
277
278 #ifdef HAVE_GDK_X11_COLORMAP_FOREIGN_NEW
279 colormap = gdk_gl_config_get_std_rgb_colormap (screen, xvinfo, is_mesa_glx);
280 if (colormap)
281 return colormap;
282 #endif /* HAVE_GDK_X11_COLORMAP_FOREIGN_NEW */
283
284 /* New colormap. */
285
286 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new"));
287 visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
288 colormap = gdk_colormap_new (visual, FALSE);
289 return colormap;
290
291 }
292 else
293 {
294 /*
295 * For color index mode.
296 */
297
298 visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
299
300 overlay_supported = _gdk_x11_gl_overlay_get_info (visual, &overlay_info);
301 if (overlay_supported &&
302 overlay_info.transparent_type == GDK_GL_OVERLAY_TRANSPARENT_PIXEL &&
303 overlay_info.value < (guint32) xvinfo->visual->map_entries)
304 {
305
306 /*
307 * On machines where zero (or some other value in the range
308 * of 0 through map_entries-1), BadAlloc may be generated
309 * when an AllocAll overlay colormap is allocated since the
310 * transparent pixel precludes all the cells in the colormap
311 * being allocated (the transparent pixel is pre-allocated).
312 * So in this case, use XAllocColorCells to allocate
313 * map_entries-1 pixels (that is, all but the transparent pixel).
314 */
315
316 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new"));
317 colormap = gdk_colormap_new (visual, FALSE);
318 }
319 else
320 {
321
322 /*
323 * If there is no transparent pixel or if the transparent
324 * pixel is outside the range of valid colormap cells (HP
325 * can implement their overlays this smart way since their
326 * transparent pixel is 255), we can AllocAll the colormap.
327 * See note above.
328 */
329
330 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new allocated writable"));
331 colormap = gdk_colormap_new (visual, TRUE);
332 }
333
334 return colormap;
335
336 }
337
338 /* not reached */
339 return NULL;
340 }
341
342 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
343
344 static GdkColormap *
gdk_gl_config_setup_colormap(GdkScreen * screen,XVisualInfo * xvinfo,gboolean is_rgba,gboolean is_mesa_glx)345 gdk_gl_config_setup_colormap (GdkScreen *screen,
346 XVisualInfo *xvinfo,
347 gboolean is_rgba,
348 gboolean is_mesa_glx)
349 {
350 GdkColormap *colormap;
351 GdkVisual *visual;
352 GdkGLOverlayInfo overlay_info;
353 gboolean overlay_supported;
354
355 GDK_GL_NOTE_FUNC_PRIVATE ();
356
357 if (is_rgba)
358 {
359 /*
360 * For RGBA mode.
361 */
362
363 /* Try default colormap. */
364
365 colormap = gdk_colormap_get_system ();
366 visual = gdk_colormap_get_visual (colormap);
367 if (GDK_VISUAL_XVISUAL (visual)->visualid == xvinfo->visualid)
368 {
369 GDK_GL_NOTE (MISC, g_message (" -- Colormap: system default"));
370
371 g_object_ref (G_OBJECT (colormap));
372 return colormap;
373 }
374
375 /* New colormap. */
376
377 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new"));
378
379 visual = gdkx_visual_get (xvinfo->visualid);
380 colormap = gdk_colormap_new (visual, FALSE);
381 return colormap;
382
383 }
384 else
385 {
386 /*
387 * For color index mode.
388 */
389
390 visual = gdkx_visual_get (xvinfo->visualid);
391
392 overlay_supported = _gdk_x11_gl_overlay_get_info (visual, &overlay_info);
393 if (overlay_supported &&
394 overlay_info.transparent_type == GDK_GL_OVERLAY_TRANSPARENT_PIXEL &&
395 overlay_info.value < xvinfo->visual->map_entries)
396 {
397
398 /*
399 * On machines where zero (or some other value in the range
400 * of 0 through map_entries-1), BadAlloc may be generated
401 * when an AllocAll overlay colormap is allocated since the
402 * transparent pixel precludes all the cells in the colormap
403 * being allocated (the transparent pixel is pre-allocated).
404 * So in this case, use XAllocColorCells to allocate
405 * map_entries-1 pixels (that is, all but the transparent pixel).
406 */
407
408 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new"));
409 colormap = gdk_colormap_new (visual, FALSE);
410 }
411 else
412 {
413
414 /*
415 * If there is no transparent pixel or if the transparent
416 * pixel is outside the range of valid colormap cells (HP
417 * can implement their overlays this smart way since their
418 * transparent pixel is 255), we can AllocAll the colormap.
419 * See note above.
420 */
421
422 GDK_GL_NOTE (MISC, g_message (" -- Colormap: new allocated writable"));
423 colormap = gdk_colormap_new (visual, TRUE);
424 }
425
426 return colormap;
427
428 }
429
430 /* not reached */
431 return NULL;
432 }
433
434 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
435
436 static void
gdk_gl_config_init_attrib(GdkGLConfig * glconfig)437 gdk_gl_config_init_attrib (GdkGLConfig *glconfig)
438 {
439 GdkGLConfigImplX11 *impl;
440 int value;
441
442 impl = GDK_GL_CONFIG_IMPL_X11 (glconfig);
443
444 #define _GET_CONFIG(__attrib) \
445 glXGetConfig (impl->xdisplay, impl->xvinfo, __attrib, &value)
446
447 /* RGBA mode? */
448 _GET_CONFIG (GLX_RGBA);
449 glconfig->is_rgba = value ? TRUE : FALSE;
450
451 /* Layer plane. */
452 _GET_CONFIG (GLX_LEVEL);
453 glconfig->layer_plane = value;
454
455 /* Double buffering is supported? */
456 _GET_CONFIG (GLX_DOUBLEBUFFER);
457 glconfig->is_double_buffered = value ? TRUE : FALSE;
458
459 /* Stereo is supported? */
460 _GET_CONFIG (GLX_STEREO);
461 glconfig->is_stereo = value ? TRUE : FALSE;
462
463 /* Number of aux buffers */
464 _GET_CONFIG (GLX_AUX_BUFFERS);
465 glconfig->n_aux_buffers = value;
466
467 /* Has alpha bits? */
468 _GET_CONFIG (GLX_ALPHA_SIZE);
469 glconfig->has_alpha = value ? TRUE : FALSE;
470
471 /* Has depth buffer? */
472 _GET_CONFIG (GLX_DEPTH_SIZE);
473 glconfig->has_depth_buffer = value ? TRUE : FALSE;
474
475 /* Has stencil buffer? */
476 _GET_CONFIG (GLX_STENCIL_SIZE);
477 glconfig->has_stencil_buffer = value ? TRUE : FALSE;
478
479 /* Has accumulation buffer? */
480 _GET_CONFIG (GLX_ACCUM_RED_SIZE);
481 glconfig->has_accum_buffer = value ? TRUE : FALSE;
482
483 /* Number of multisample buffers (not supported yet) */
484 glconfig->n_sample_buffers = 0;
485
486 #undef _GET_CONFIG
487 }
488
489 static GdkGLConfig *
gdk_gl_config_new_common(GdkScreen * screen,const int * attrib_list)490 gdk_gl_config_new_common (GdkScreen *screen,
491 const int *attrib_list)
492 {
493 GdkGLConfig *glconfig;
494 GdkGLConfigImplX11 *impl;
495
496 Display *xdisplay;
497 int screen_num;
498 XVisualInfo *xvinfo;
499 int is_rgba;
500
501 GDK_GL_NOTE_FUNC_PRIVATE ();
502
503 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
504 xdisplay = GDK_SCREEN_XDISPLAY (screen);
505 screen_num = GDK_SCREEN_XNUMBER (screen);
506 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
507 xdisplay = gdk_x11_get_default_xdisplay ();
508 screen_num = gdk_x11_get_default_screen ();
509 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
510
511 GDK_GL_NOTE (MISC, _gdk_x11_gl_print_glx_info (xdisplay, screen_num));
512
513 /*
514 * Find an OpenGL-capable visual.
515 */
516
517 GDK_GL_NOTE_FUNC_IMPL ("glXChooseVisual");
518
519 xvinfo = glXChooseVisual (xdisplay, screen_num, (int *) attrib_list);
520 if (xvinfo == NULL)
521 return NULL;
522
523 GDK_GL_NOTE (MISC,
524 g_message (" -- glXChooseVisual: screen number = %d", xvinfo->screen));
525 GDK_GL_NOTE (MISC,
526 g_message (" -- glXChooseVisual: visual id = 0x%lx", xvinfo->visualid));
527
528 /*
529 * Instantiate the GdkGLConfigImplX11 object.
530 */
531
532 glconfig = g_object_new (GDK_TYPE_GL_CONFIG_IMPL_X11, NULL);
533 impl = GDK_GL_CONFIG_IMPL_X11 (glconfig);
534
535 impl->xdisplay = xdisplay;
536 impl->screen_num = screen_num;
537 impl->xvinfo = xvinfo;
538
539 impl->screen = screen;
540
541 /* Using Mesa? */
542 if (strstr (glXQueryServerString (xdisplay, screen_num, GLX_VERSION), "Mesa"))
543 impl->is_mesa_glx = TRUE;
544 else
545 impl->is_mesa_glx = FALSE;
546
547 /*
548 * Get an appropriate colormap.
549 */
550
551 /* RGBA mode? */
552 glXGetConfig (xdisplay, xvinfo, GLX_RGBA, &is_rgba);
553
554 impl->colormap = gdk_gl_config_setup_colormap (impl->screen,
555 impl->xvinfo,
556 is_rgba,
557 impl->is_mesa_glx);
558
559 GDK_GL_NOTE (MISC,
560 g_message (" -- Colormap: visual id = 0x%lx",
561 GDK_VISUAL_XVISUAL (impl->colormap->visual)->visualid));
562
563 /*
564 * Init configuration attributes.
565 */
566
567 gdk_gl_config_init_attrib (glconfig);
568
569 return glconfig;
570 }
571
572 /**
573 * gdk_gl_config_new:
574 * @attrib_list: a list of attribute/value pairs. The last attribute must
575 * be GDK_GL_ATTRIB_LIST_NONE.
576 *
577 * Returns an OpenGL frame buffer configuration that match the specified
578 * attributes.
579 *
580 * attrib_list is a int array that contains the attribute/value pairs.
581 * Available attributes are:
582 * GDK_GL_USE_GL, GDK_GL_BUFFER_SIZE, GDK_GL_LEVEL, GDK_GL_RGBA,
583 * GDK_GL_DOUBLEBUFFER, GDK_GL_STEREO, GDK_GL_AUX_BUFFERS,
584 * GDK_GL_RED_SIZE, GDK_GL_GREEN_SIZE, GDK_GL_BLUE_SIZE, GDK_GL_ALPHA_SIZE,
585 * GDK_GL_DEPTH_SIZE, GDK_GL_STENCIL_SIZE, GDK_GL_ACCUM_RED_SIZE,
586 * GDK_GL_ACCUM_GREEN_SIZE, GDK_GL_ACCUM_BLUE_SIZE, GDK_GL_ACCUM_ALPHA_SIZE.
587 *
588 * Return value: the new #GdkGLConfig.
589 **/
590 GdkGLConfig *
gdk_gl_config_new(const int * attrib_list)591 gdk_gl_config_new (const int *attrib_list)
592 {
593 GdkScreen *screen;
594
595 GDK_GL_NOTE_FUNC ();
596
597 g_return_val_if_fail (attrib_list != NULL, NULL);
598
599 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
600 screen = gdk_screen_get_default ();
601 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
602 screen = NULL;
603 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
604
605 return gdk_gl_config_new_common (screen, attrib_list);
606 }
607
608 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
609
610 /**
611 * gdk_gl_config_new_for_screen:
612 * @screen: target screen.
613 * @attrib_list: a list of attribute/value pairs. The last attribute must
614 * be GDK_GL_ATTRIB_LIST_NONE.
615 *
616 * Returns an OpenGL frame buffer configuration that match the specified
617 * attributes.
618 *
619 * Return value: the new #GdkGLConfig.
620 **/
621 GdkGLConfig *
gdk_gl_config_new_for_screen(GdkScreen * screen,const int * attrib_list)622 gdk_gl_config_new_for_screen (GdkScreen *screen,
623 const int *attrib_list)
624 {
625 GDK_GL_NOTE_FUNC ();
626
627 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
628 g_return_val_if_fail (attrib_list != NULL, NULL);
629
630 return gdk_gl_config_new_common (screen, attrib_list);
631 }
632
633 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
634
635 /*
636 * XVisualInfo returned by this function should be freed by XFree ().
637 */
638 static XVisualInfo *
gdk_x11_gl_get_xvinfo(Display * xdisplay,int screen_num,VisualID xvisualid)639 gdk_x11_gl_get_xvinfo (Display *xdisplay,
640 int screen_num,
641 VisualID xvisualid)
642 {
643 XVisualInfo xvinfo_template;
644 XVisualInfo *xvinfo_list;
645 int nitems_return;
646
647 GDK_GL_NOTE_FUNC_PRIVATE ();
648
649 xvinfo_template.visualid = xvisualid;
650 xvinfo_template.screen = screen_num;
651
652 xvinfo_list = XGetVisualInfo (xdisplay,
653 VisualIDMask | VisualScreenMask,
654 &xvinfo_template,
655 &nitems_return);
656
657 /* Returned XVisualInfo needs to be unique */
658 g_assert (xvinfo_list != NULL && nitems_return == 1);
659
660 return xvinfo_list;
661 }
662
663 static GdkGLConfig *
gdk_x11_gl_config_new_from_visualid_common(GdkScreen * screen,VisualID xvisualid)664 gdk_x11_gl_config_new_from_visualid_common (GdkScreen *screen,
665 VisualID xvisualid)
666 {
667 GdkGLConfig *glconfig;
668 GdkGLConfigImplX11 *impl;
669
670 Display *xdisplay;
671 int screen_num;
672 XVisualInfo *xvinfo;
673 int is_rgba;
674
675 GDK_GL_NOTE_FUNC_PRIVATE ();
676
677 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
678 xdisplay = GDK_SCREEN_XDISPLAY (screen);
679 screen_num = GDK_SCREEN_XNUMBER (screen);
680 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
681 xdisplay = gdk_x11_get_default_xdisplay ();
682 screen_num = gdk_x11_get_default_screen ();
683 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
684
685 GDK_GL_NOTE (MISC,
686 g_message (" -- GLX_VENDOR : %s",
687 glXGetClientString (xdisplay, GLX_VENDOR)));
688 GDK_GL_NOTE (MISC,
689 g_message (" -- GLX_VERSION : %s",
690 glXGetClientString (xdisplay, GLX_VERSION)));
691 GDK_GL_NOTE (MISC,
692 g_message (" -- GLX_EXTENSIONS : %s",
693 glXGetClientString (xdisplay, GLX_EXTENSIONS)));
694
695 /*
696 * Get XVisualInfo.
697 */
698
699 xvinfo = gdk_x11_gl_get_xvinfo (xdisplay, screen_num, xvisualid);
700 if (xvinfo == NULL)
701 return NULL;
702
703 GDK_GL_NOTE (MISC,
704 g_message (" -- gdk_x11_gl_get_xvinfo: screen number = %d", xvinfo->screen));
705 GDK_GL_NOTE (MISC,
706 g_message (" -- gdk_x11_gl_get_xvinfo: visual id = 0x%lx", xvinfo->visualid));
707
708 /*
709 * Instantiate the GdkGLConfigImplX11 object.
710 */
711
712 glconfig = g_object_new (GDK_TYPE_GL_CONFIG_IMPL_X11, NULL);
713 impl = GDK_GL_CONFIG_IMPL_X11 (glconfig);
714
715 impl->xdisplay = xdisplay;
716 impl->screen_num = screen_num;
717 impl->xvinfo = xvinfo;
718
719 impl->screen = screen;
720
721 /* Using Mesa? */
722 if (strstr (glXQueryServerString (xdisplay, screen_num, GLX_VERSION), "Mesa"))
723 impl->is_mesa_glx = TRUE;
724 else
725 impl->is_mesa_glx = FALSE;
726
727 /*
728 * Get an appropriate colormap.
729 */
730
731 /* RGBA mode? */
732 glXGetConfig (xdisplay, xvinfo, GLX_RGBA, &is_rgba);
733
734 impl->colormap = gdk_gl_config_setup_colormap (impl->screen,
735 impl->xvinfo,
736 is_rgba,
737 impl->is_mesa_glx);
738
739 GDK_GL_NOTE (MISC,
740 g_message (" -- Colormap: visual id = 0x%lx",
741 GDK_VISUAL_XVISUAL (impl->colormap->visual)->visualid));
742
743 /*
744 * Init configuration attributes.
745 */
746
747 gdk_gl_config_init_attrib (glconfig);
748
749 return glconfig;
750 }
751
752 /**
753 * gdk_x11_gl_config_new_from_visualid:
754 * @xvisualid: visual ID.
755 *
756 * Creates #GdkGLConfig from given visual ID that specifies the OpenGL-capable
757 * visual.
758 *
759 * Return value: the new #GdkGLConfig.
760 **/
761 GdkGLConfig *
gdk_x11_gl_config_new_from_visualid(VisualID xvisualid)762 gdk_x11_gl_config_new_from_visualid (VisualID xvisualid)
763 {
764 GdkScreen *screen;
765
766 GDK_GL_NOTE_FUNC ();
767
768 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
769 screen = gdk_screen_get_default ();
770 #else /* GDKGLEXT_MULTIHEAD_SUPPORT */
771 screen = NULL;
772 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
773
774 return gdk_x11_gl_config_new_from_visualid_common (screen, xvisualid);
775 }
776
777 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
778
779 /**
780 * gdk_x11_gl_config_new_from_visualid_for_screen:
781 * @screen: target screen.
782 * @xvisualid: visual ID.
783 *
784 * Creates #GdkGLConfig from given visual ID that specifies the OpenGL-capable
785 * visual.
786 *
787 * Return value: the new #GdkGLConfig.
788 **/
789 GdkGLConfig *
gdk_x11_gl_config_new_from_visualid_for_screen(GdkScreen * screen,VisualID xvisualid)790 gdk_x11_gl_config_new_from_visualid_for_screen (GdkScreen *screen,
791 VisualID xvisualid)
792 {
793 GDK_GL_NOTE_FUNC ();
794
795 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
796
797 return gdk_x11_gl_config_new_from_visualid_common (screen, xvisualid);
798 }
799
800 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
801
802 /**
803 * gdk_gl_config_get_screen:
804 * @glconfig: a #GdkGLConfig.
805 *
806 * Gets #GdkScreen.
807 *
808 * Return value: the #GdkScreen.
809 **/
810 GdkScreen *
gdk_gl_config_get_screen(GdkGLConfig * glconfig)811 gdk_gl_config_get_screen (GdkGLConfig *glconfig)
812 {
813 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
814
815 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->screen;
816 }
817
818 /**
819 * gdk_gl_config_get_attrib:
820 * @glconfig: a #GdkGLConfig.
821 * @attribute: the attribute to be returned.
822 * @value: returns the requested value.
823 *
824 * Gets information about a OpenGL frame buffer configuration.
825 *
826 * Return value: TRUE if it succeeded, FALSE otherwise.
827 **/
828 gboolean
gdk_gl_config_get_attrib(GdkGLConfig * glconfig,int attribute,int * value)829 gdk_gl_config_get_attrib (GdkGLConfig *glconfig,
830 int attribute,
831 int *value)
832 {
833 GdkGLConfigImplX11 *impl;
834 int ret;
835
836 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), FALSE);
837
838 impl = GDK_GL_CONFIG_IMPL_X11 (glconfig);
839
840 ret = glXGetConfig (impl->xdisplay, impl->xvinfo, attribute, value);
841
842 return (ret == Success);
843 }
844
845 /**
846 * gdk_gl_config_get_colormap:
847 * @glconfig: a #GdkGLConfig.
848 *
849 * Gets the #GdkColormap that is appropriate for the OpenGL frame buffer
850 * configuration.
851 *
852 * Return value: the appropriate #GdkColormap.
853 **/
854 GdkColormap *
gdk_gl_config_get_colormap(GdkGLConfig * glconfig)855 gdk_gl_config_get_colormap (GdkGLConfig *glconfig)
856 {
857 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
858
859 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->colormap;
860 }
861
862 /**
863 * gdk_gl_config_get_visual:
864 * @glconfig: a #GdkGLConfig.
865 *
866 * Gets the #GdkVisual that is appropriate for the OpenGL frame buffer
867 * configuration.
868 *
869 * Return value: the appropriate #GdkVisual.
870 **/
871 GdkVisual *
gdk_gl_config_get_visual(GdkGLConfig * glconfig)872 gdk_gl_config_get_visual (GdkGLConfig *glconfig)
873 {
874 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
875
876 return gdk_colormap_get_visual (GDK_GL_CONFIG_IMPL_X11 (glconfig)->colormap);
877 }
878
879 /**
880 * gdk_gl_config_get_depth:
881 * @glconfig: a #GdkGLConfig.
882 *
883 * Gets the color depth of the OpenGL-capable visual.
884 *
885 * Return value: number of bits per pixel
886 **/
887 gint
gdk_gl_config_get_depth(GdkGLConfig * glconfig)888 gdk_gl_config_get_depth (GdkGLConfig *glconfig)
889 {
890 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), 0);
891
892 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->xvinfo->depth;
893 }
894
895 /**
896 * gdk_x11_gl_config_get_xdisplay:
897 * @glconfig: a #GdkGLConfig.
898 *
899 * Gets X Display.
900 *
901 * Return value: pointer to the Display.
902 **/
903 Display *
gdk_x11_gl_config_get_xdisplay(GdkGLConfig * glconfig)904 gdk_x11_gl_config_get_xdisplay (GdkGLConfig *glconfig)
905 {
906 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
907
908 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->xdisplay;
909 }
910
911 /**
912 * gdk_x11_gl_config_get_screen_number:
913 * @glconfig: a #GdkGLConfig.
914 *
915 * Gets X screen number.
916 *
917 * Return value: the screen number.
918 **/
919 int
gdk_x11_gl_config_get_screen_number(GdkGLConfig * glconfig)920 gdk_x11_gl_config_get_screen_number (GdkGLConfig *glconfig)
921 {
922 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), 0);
923
924 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->screen_num;
925 }
926
927 /**
928 * gdk_x11_gl_config_get_xvinfo:
929 * @glconfig: a #GdkGLConfig.
930 *
931 * Gets XVisualInfo data.
932 *
933 * Return value: pointer to the XVisualInfo data.
934 **/
935 XVisualInfo *
gdk_x11_gl_config_get_xvinfo(GdkGLConfig * glconfig)936 gdk_x11_gl_config_get_xvinfo (GdkGLConfig *glconfig)
937 {
938 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
939
940 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->xvinfo;
941 }
942
943 /**
944 * gdk_x11_gl_config_is_mesa_glx:
945 * @glconfig: a #GdkGLConfig.
946 *
947 * Returns whether the server's GLX entension is Mesa.
948 *
949 * Return value: TRUE if Mesa GLX, FALSE otherwise.
950 **/
951 gboolean
gdk_x11_gl_config_is_mesa_glx(GdkGLConfig * glconfig)952 gdk_x11_gl_config_is_mesa_glx (GdkGLConfig *glconfig)
953 {
954 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), FALSE);
955
956 return GDK_GL_CONFIG_IMPL_X11 (glconfig)->is_mesa_glx;
957 }
958