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