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 "gdkglprivate.h"
20 #include "gdkglconfig.h"
21 
22 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
23 #include <gdk/gdkscreen.h>
24 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
25 
26 gboolean _gdk_gl_config_no_standard_colormap = FALSE;
27 
28 static void gdk_gl_config_class_init (GdkGLConfigClass *klass);
29 static void gdk_gl_config_finalize   (GObject          *object);
30 
31 static gpointer parent_class = NULL;
32 
33 GType
gdk_gl_config_get_type(void)34 gdk_gl_config_get_type (void)
35 {
36   static GType type = 0;
37 
38   if (!type)
39     {
40       static const GTypeInfo type_info = {
41         sizeof (GdkGLConfigClass),
42         (GBaseInitFunc) NULL,
43         (GBaseFinalizeFunc) NULL,
44         (GClassInitFunc) gdk_gl_config_class_init,
45         (GClassFinalizeFunc) NULL,
46         NULL,                   /* class_data */
47         sizeof (GdkGLConfig),
48         0,                      /* n_preallocs */
49         (GInstanceInitFunc) NULL
50       };
51 
52       type = g_type_register_static (G_TYPE_OBJECT,
53                                      "GdkGLConfig",
54                                      &type_info, 0);
55     }
56 
57   return type;
58 }
59 
60 static void
gdk_gl_config_class_init(GdkGLConfigClass * klass)61 gdk_gl_config_class_init (GdkGLConfigClass *klass)
62 {
63   GObjectClass *object_class = G_OBJECT_CLASS (klass);
64 
65   GDK_GL_NOTE_FUNC_PRIVATE ();
66 
67   parent_class = g_type_class_peek_parent (klass);
68 
69   object_class->finalize = gdk_gl_config_finalize;
70 }
71 
72 static void
gdk_gl_config_finalize(GObject * object)73 gdk_gl_config_finalize (GObject *object)
74 {
75   GDK_GL_NOTE_FUNC_PRIVATE ();
76 
77   G_OBJECT_CLASS (parent_class)->finalize (object);
78 }
79 
80 static GdkGLConfig *
gdk_gl_config_new_ci(GdkScreen * screen,GdkGLConfigMode mode)81 gdk_gl_config_new_ci (GdkScreen       *screen,
82                       GdkGLConfigMode  mode)
83 {
84   GdkGLConfig *glconfig = NULL;
85   static const int buf_size_list[] = { 16, 12, 8, 4, 2, 1, 0 };
86   int list[32];
87   int n = 0;
88   int i;
89 
90   list[n++] = GDK_GL_BUFFER_SIZE;
91   list[n++] = 1;
92   if (mode & GDK_GL_MODE_DOUBLE)
93     {
94       list[n++] = GDK_GL_DOUBLEBUFFER;
95     }
96   if (mode & GDK_GL_MODE_STEREO)
97     {
98       list[n++] = GDK_GL_STEREO;
99     }
100   if (mode & GDK_GL_MODE_DEPTH)
101     {
102       list[n++] = GDK_GL_DEPTH_SIZE;
103       list[n++] = 1;
104     }
105   if (mode & GDK_GL_MODE_STENCIL)
106     {
107       list[n++] = GDK_GL_STENCIL_SIZE;
108       list[n++] = 1;
109     }
110   list[n] = GDK_GL_ATTRIB_LIST_NONE;
111 
112   /* from GLUT */
113   /* glXChooseVisual specify GLX_BUFFER_SIZE prefers the
114      "smallest index buffer of at least the specified size".
115      This would be reasonable if GLUT allowed the user to
116      specify the required buffe size, but GLUT's display mode
117      is too simplistic (easy to use?). GLUT should try to find
118      the "largest".  So start with a large buffer size and
119      shrink until we find a matching one that exists. */
120 
121   for (i = 0; buf_size_list[i]; i++)
122     {
123       /* XXX Assumes list[1] is where GDK_GL_BUFFER_SIZE parameter is. */
124       list[1] = buf_size_list[i];
125 
126 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
127       glconfig = gdk_gl_config_new_for_screen (screen, list);
128 #else  /* GDKGLEXT_MULTIHEAD_SUPPORT */
129       glconfig = gdk_gl_config_new (list);
130 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
131 
132       if (glconfig != NULL)
133         return glconfig;
134     }
135 
136   return NULL;
137 }
138 
139 static GdkGLConfig *
gdk_gl_config_new_rgb(GdkScreen * screen,GdkGLConfigMode mode)140 gdk_gl_config_new_rgb (GdkScreen       *screen,
141                        GdkGLConfigMode  mode)
142 {
143   int list[32];
144   int n = 0;
145 
146   list[n++] = GDK_GL_RGBA;
147   list[n++] = GDK_GL_RED_SIZE;
148   list[n++] = 1;
149   list[n++] = GDK_GL_GREEN_SIZE;
150   list[n++] = 1;
151   list[n++] = GDK_GL_BLUE_SIZE;
152   list[n++] = 1;
153   if (mode & GDK_GL_MODE_ALPHA)
154     {
155       list[n++] = GDK_GL_ALPHA_SIZE;
156       list[n++] = 1;
157     }
158   if (mode & GDK_GL_MODE_DOUBLE)
159     {
160       list[n++] = GDK_GL_DOUBLEBUFFER;
161     }
162   if (mode & GDK_GL_MODE_STEREO)
163     {
164       list[n++] = GDK_GL_STEREO;
165     }
166   if (mode & GDK_GL_MODE_DEPTH)
167     {
168       list[n++] = GDK_GL_DEPTH_SIZE;
169       list[n++] = 1;
170     }
171   if (mode & GDK_GL_MODE_STENCIL)
172     {
173       list[n++] = GDK_GL_STENCIL_SIZE;
174       list[n++] = 1;
175     }
176   if (mode & GDK_GL_MODE_ACCUM)
177     {
178       list[n++] = GDK_GL_ACCUM_RED_SIZE;
179       list[n++] = 1;
180       list[n++] = GDK_GL_ACCUM_GREEN_SIZE;
181       list[n++] = 1;
182       list[n++] = GDK_GL_ACCUM_BLUE_SIZE;
183       list[n++] = 1;
184       if (mode & GDK_GL_MODE_ALPHA)
185         {
186           list[n++] = GDK_GL_ACCUM_ALPHA_SIZE;
187           list[n++] = 1;
188         }
189     }
190   list[n] = GDK_GL_ATTRIB_LIST_NONE;
191 
192 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
193   return gdk_gl_config_new_for_screen (screen, list);
194 #else  /* GDKGLEXT_MULTIHEAD_SUPPORT */
195   return gdk_gl_config_new (list);
196 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
197 }
198 
199 static GdkGLConfig *
gdk_gl_config_new_by_mode_common(GdkScreen * screen,GdkGLConfigMode mode)200 gdk_gl_config_new_by_mode_common (GdkScreen       *screen,
201                                   GdkGLConfigMode  mode)
202 {
203   GdkGLConfig *glconfig;
204 
205 #define _GL_CONFIG_NEW_BY_MODE(__screen, __mode)        \
206   ( ((__mode) & GDK_GL_MODE_INDEX) ?                    \
207     gdk_gl_config_new_ci (__screen, __mode) :           \
208     gdk_gl_config_new_rgb (__screen, __mode) )
209 
210   glconfig = _GL_CONFIG_NEW_BY_MODE (screen, mode);
211   if (glconfig == NULL)
212     {
213       /* Fallback cases when can't get exactly what was asked for... */
214       if (!(mode & GDK_GL_MODE_DOUBLE))
215         {
216           /* If we can't find a single buffered visual, try looking
217              for a double buffered visual.  We can treat a double
218              buffered visual as a single buffered visual by changing
219              the draw buffer to GL_FRONT and treating any swap
220              buffers as no-ops. */
221           mode |= GDK_GL_MODE_DOUBLE;
222           glconfig = _GL_CONFIG_NEW_BY_MODE (screen, mode);
223           if (glconfig != NULL)
224             glconfig->as_single_mode = TRUE;
225         }
226     }
227 
228 #undef _GL_CONFIG_NEW_BY_MODE
229 
230   return glconfig;
231 }
232 
233 /**
234  * gdk_gl_config_new_by_mode:
235  * @mode: display mode bit mask.
236  *
237  * Returns an OpenGL frame buffer configuration that match the specified
238  * display mode.
239  *
240  * Return value: the new #GdkGLConfig.
241  **/
242 GdkGLConfig *
gdk_gl_config_new_by_mode(GdkGLConfigMode mode)243 gdk_gl_config_new_by_mode (GdkGLConfigMode mode)
244 {
245   GdkScreen *screen;
246 
247 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
248   screen = gdk_screen_get_default ();
249 #else  /* GDKGLEXT_MULTIHEAD_SUPPORT */
250   screen = NULL;
251 #endif
252 
253   return gdk_gl_config_new_by_mode_common (screen, mode);
254 }
255 
256 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
257 
258 /**
259  * gdk_gl_config_new_by_mode_for_screen:
260  * @screen: target screen.
261  * @mode: display mode bit mask.
262  *
263  * Returns an OpenGL frame buffer configuration that match the specified
264  * display mode.
265  *
266  * Return value: the new #GdkGLConfig.
267  **/
268 GdkGLConfig *
gdk_gl_config_new_by_mode_for_screen(GdkScreen * screen,GdkGLConfigMode mode)269 gdk_gl_config_new_by_mode_for_screen (GdkScreen       *screen,
270                                       GdkGLConfigMode  mode)
271 {
272   return gdk_gl_config_new_by_mode_common (screen, mode);
273 }
274 
275 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
276 
277 /**
278  * gdk_gl_config_get_layer_plane:
279  * @glconfig: a #GdkGLConfig.
280  *
281  * Gets the layer plane (level) of the frame buffer.
282  * Zero is the default frame buffer.
283  * Positive layer planes correspond to frame buffers that overlay the default
284  * buffer, and negative layer planes correspond to frame buffers that underlie
285  * the default frame buffer.
286  *
287  * Return value: layer plane.
288  **/
289 gint
gdk_gl_config_get_layer_plane(GdkGLConfig * glconfig)290 gdk_gl_config_get_layer_plane (GdkGLConfig *glconfig)
291 {
292   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), 0);
293 
294   return glconfig->layer_plane;
295 }
296 
297 /**
298  * gdk_gl_config_get_n_aux_buffers:
299  * @glconfig: a #GdkGLConfig.
300  *
301  * Gets the number of auxiliary color buffers.
302  *
303  * Return value: number of auxiliary color buffers.
304  **/
305 gint
gdk_gl_config_get_n_aux_buffers(GdkGLConfig * glconfig)306 gdk_gl_config_get_n_aux_buffers (GdkGLConfig *glconfig)
307 {
308   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), 0);
309 
310   return glconfig->n_aux_buffers;
311 }
312 
313 /**
314  * gdk_gl_config_get_n_sample_buffers:
315  * @glconfig: a #GdkGLConfig.
316  *
317  * Gets the number of multisample buffers.
318  *
319  * Return value: number of multisample buffers.
320  **/
321 gint
gdk_gl_config_get_n_sample_buffers(GdkGLConfig * glconfig)322 gdk_gl_config_get_n_sample_buffers (GdkGLConfig *glconfig)
323 {
324   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), 0);
325 
326   return glconfig->n_sample_buffers;
327 }
328 
329 /**
330  * gdk_gl_config_is_rgba:
331  * @glconfig: a #GdkGLConfig.
332  *
333  * Returns whether the configured frame buffer is RGBA mode.
334  *
335  * Return value: TRUE if the configured frame buffer is RGBA mode, FALSE
336  *               otherwise.
337  **/
338 gboolean
gdk_gl_config_is_rgba(GdkGLConfig * glconfig)339 gdk_gl_config_is_rgba (GdkGLConfig *glconfig)
340 {
341   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
342 
343   return glconfig->is_rgba;
344 }
345 
346 /**
347  * gdk_gl_config_is_double_buffered:
348  * @glconfig: a #GdkGLConfig.
349  *
350  * Returns whether the configuration supports the double-buffered visual.
351  *
352  * Return value: TRUE if the double-buffered visual is supported, FALSE
353  *               otherwise.
354  **/
355 gboolean
gdk_gl_config_is_double_buffered(GdkGLConfig * glconfig)356 gdk_gl_config_is_double_buffered (GdkGLConfig *glconfig)
357 {
358   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
359 
360   return (glconfig->is_double_buffered && (!glconfig->as_single_mode));
361 }
362 
363 /**
364  * gdk_gl_config_is_stereo:
365  * @glconfig: a #GdkGLConfig.
366  *
367  * Returns whether the configuration supports the stereo visual.
368  *
369  * Return value: TRUE if the stereo visual is supported, FALSE otherwise.
370  **/
371 gboolean
gdk_gl_config_is_stereo(GdkGLConfig * glconfig)372 gdk_gl_config_is_stereo (GdkGLConfig *glconfig)
373 {
374   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
375 
376   return glconfig->is_stereo;
377 }
378 
379 /**
380  * gdk_gl_config_has_alpha:
381  * @glconfig: a #GdkGLConfig.
382  *
383  * Returns whether the configured color buffer has alpha bits.
384  *
385  * Return value: TRUE if the color buffer has alpha bits, FALSE otherwise.
386  **/
387 gboolean
gdk_gl_config_has_alpha(GdkGLConfig * glconfig)388 gdk_gl_config_has_alpha (GdkGLConfig *glconfig)
389 {
390   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
391 
392   return glconfig->has_alpha;
393 }
394 
395 /**
396  * gdk_gl_config_has_depth_buffer:
397  * @glconfig: a #GdkGLConfig.
398  *
399  * Returns whether the configured frame buffer has depth buffer.
400  *
401  * Return value: TRUE if the frame buffer has depth buffer, FALSE otherwise.
402  **/
403 gboolean
gdk_gl_config_has_depth_buffer(GdkGLConfig * glconfig)404 gdk_gl_config_has_depth_buffer (GdkGLConfig *glconfig)
405 {
406   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
407 
408   return glconfig->has_depth_buffer;
409 }
410 
411 /**
412  * gdk_gl_config_has_stencil_buffer:
413  * @glconfig: a #GdkGLConfig.
414  *
415  * Returns whether the configured frame buffer has stencil buffer.
416  *
417  * Return value: TRUE if the frame buffer has stencil buffer, FALSE otherwise.
418  **/
419 gboolean
gdk_gl_config_has_stencil_buffer(GdkGLConfig * glconfig)420 gdk_gl_config_has_stencil_buffer (GdkGLConfig *glconfig)
421 {
422   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
423 
424   return glconfig->has_stencil_buffer;
425 }
426 
427 /**
428  * gdk_gl_config_has_accum_buffer:
429  * @glconfig: a #GdkGLConfig.
430  *
431  * Returns whether the configured frame buffer has accumulation buffer.
432  *
433  * Return value: TRUE if the frame buffer has accumulation buffer, FALSE
434  *               otherwise.
435  **/
436 gboolean
gdk_gl_config_has_accum_buffer(GdkGLConfig * glconfig)437 gdk_gl_config_has_accum_buffer (GdkGLConfig *glconfig)
438 {
439   g_return_val_if_fail (GDK_IS_GL_CONFIG (glconfig), FALSE);
440 
441   return glconfig->has_accum_buffer;
442 }
443