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 #include "gdkglx.h"
22 #include "gdkglprivate-x11.h"
23 #include "gdkglconfig-x11.h"
24 #include "gdkglcontext-x11.h"
25 #include "gdkglwindow-x11.h"
26
27 #include <gdk/gdkglquery.h>
28
29 static gboolean gdk_gl_window_impl_x11_make_context_current (GdkGLDrawable *draw,
30 GdkGLDrawable *read,
31 GdkGLContext *glcontext);
32 static gboolean gdk_gl_window_impl_x11_is_double_buffered (GdkGLDrawable *gldrawable);
33 static void gdk_gl_window_impl_x11_swap_buffers (GdkGLDrawable *gldrawable);
34 /*
35 static gboolean gdk_gl_window_impl_x11_gl_begin (GdkGLDrawable *draw,
36 GdkGLDrawable *read,
37 GdkGLContext *glcontext);
38 */
39 static void gdk_gl_window_impl_x11_gl_end (GdkGLDrawable *gldrawable);
40 static GdkGLConfig *gdk_gl_window_impl_x11_get_gl_config (GdkGLDrawable *gldrawable);
41
42 static void gdk_gl_window_impl_x11_class_init (GdkGLWindowImplX11Class *klass);
43 static void gdk_gl_window_impl_x11_finalize (GObject *object);
44 static void gdk_gl_window_impl_x11_gl_drawable_interface_init (GdkGLDrawableClass *iface);
45
46 static gpointer parent_class = NULL;
47
48 GType
gdk_gl_window_impl_x11_get_type(void)49 gdk_gl_window_impl_x11_get_type (void)
50 {
51 static GType type = 0;
52
53 if (!type)
54 {
55 static const GTypeInfo type_info = {
56 sizeof (GdkGLWindowImplX11Class),
57 (GBaseInitFunc) NULL,
58 (GBaseFinalizeFunc) NULL,
59 (GClassInitFunc) gdk_gl_window_impl_x11_class_init,
60 (GClassFinalizeFunc) NULL,
61 NULL, /* class_data */
62 sizeof (GdkGLWindowImplX11),
63 0, /* n_preallocs */
64 (GInstanceInitFunc) NULL
65 };
66 static const GInterfaceInfo gl_drawable_interface_info = {
67 (GInterfaceInitFunc) gdk_gl_window_impl_x11_gl_drawable_interface_init,
68 (GInterfaceFinalizeFunc) NULL,
69 NULL /* interface_data */
70 };
71
72 type = g_type_register_static (GDK_TYPE_GL_WINDOW,
73 "GdkGLWindowImplX11",
74 &type_info, 0);
75 g_type_add_interface_static (type,
76 GDK_TYPE_GL_DRAWABLE,
77 &gl_drawable_interface_info);
78 }
79
80 return type;
81 }
82
83 static void
gdk_gl_window_impl_x11_class_init(GdkGLWindowImplX11Class * klass)84 gdk_gl_window_impl_x11_class_init (GdkGLWindowImplX11Class *klass)
85 {
86 GObjectClass *object_class = G_OBJECT_CLASS (klass);
87
88 GDK_GL_NOTE_FUNC_PRIVATE ();
89
90 parent_class = g_type_class_peek_parent (klass);
91
92 object_class->finalize = gdk_gl_window_impl_x11_finalize;
93 }
94
95 void
_gdk_gl_window_destroy(GdkGLWindow * glwindow)96 _gdk_gl_window_destroy (GdkGLWindow *glwindow)
97 {
98 GdkGLWindowImplX11 *impl = GDK_GL_WINDOW_IMPL_X11 (glwindow);
99 Display *xdisplay;
100 GdkGL_GLX_MESA_release_buffers *mesa_ext;
101
102 GDK_GL_NOTE_FUNC_PRIVATE ();
103
104 if (impl->is_destroyed)
105 return;
106
107 xdisplay = GDK_GL_CONFIG_XDISPLAY (impl->glconfig);
108
109 if (impl->glxwindow == glXGetCurrentDrawable ())
110 {
111 glXWaitGL ();
112
113 GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
114 glXMakeCurrent (xdisplay, None, NULL);
115 }
116
117 /* If GLX_MESA_release_buffers is supported. */
118 mesa_ext = gdk_gl_get_GLX_MESA_release_buffers (impl->glconfig);
119 if (mesa_ext)
120 {
121 GDK_GL_NOTE_FUNC_IMPL ("glXReleaseBuffersMESA");
122 mesa_ext->glXReleaseBuffersMESA (xdisplay, impl->glxwindow);
123 }
124
125 impl->glxwindow = None;
126
127 impl->is_destroyed = TRUE;
128 }
129
130 static void
gdk_gl_window_impl_x11_finalize(GObject * object)131 gdk_gl_window_impl_x11_finalize (GObject *object)
132 {
133 GdkGLWindowImplX11 *impl = GDK_GL_WINDOW_IMPL_X11 (object);
134
135 GDK_GL_NOTE_FUNC_PRIVATE ();
136
137 _gdk_gl_window_destroy (GDK_GL_WINDOW (object));
138
139 g_object_unref (G_OBJECT (impl->glconfig));
140
141 G_OBJECT_CLASS (parent_class)->finalize (object);
142 }
143
144 static void
gdk_gl_window_impl_x11_gl_drawable_interface_init(GdkGLDrawableClass * iface)145 gdk_gl_window_impl_x11_gl_drawable_interface_init (GdkGLDrawableClass *iface)
146 {
147 GDK_GL_NOTE_FUNC_PRIVATE ();
148
149 iface->create_new_context = _gdk_x11_gl_context_new;
150 iface->make_context_current = gdk_gl_window_impl_x11_make_context_current;
151 iface->is_double_buffered = gdk_gl_window_impl_x11_is_double_buffered;
152 iface->swap_buffers = gdk_gl_window_impl_x11_swap_buffers;
153 iface->wait_gl = _gdk_gl_drawable_impl_x11_wait_gl;
154 iface->wait_gdk = _gdk_gl_drawable_impl_x11_wait_gdk;
155 iface->gl_begin = gdk_gl_window_impl_x11_make_context_current;
156 iface->gl_end = gdk_gl_window_impl_x11_gl_end;
157 iface->get_gl_config = gdk_gl_window_impl_x11_get_gl_config;
158 iface->get_size = _gdk_gl_window_get_size;
159 }
160
161 /*
162 * attrib_list is currently unused. This must be set to NULL or empty
163 * (first attribute of None). See GLX 1.3 spec.
164 */
165 /**
166 * gdk_gl_window_new:
167 * @glconfig: a #GdkGLConfig.
168 * @window: the #GdkWindow to be used as the rendering area.
169 * @attrib_list: this must be set to NULL or empty (first attribute of None).
170 *
171 * Creates an on-screen rendering area.
172 * attrib_list is currently unused. This must be set to NULL or empty
173 * (first attribute of None). See GLX 1.3 spec.
174 *
175 * Return value: the new #GdkGLWindow.
176 **/
177 GdkGLWindow *
gdk_gl_window_new(GdkGLConfig * glconfig,GdkWindow * window,const int * attrib_list)178 gdk_gl_window_new (GdkGLConfig *glconfig,
179 GdkWindow *window,
180 const int *attrib_list)
181 {
182 GdkGLWindow *glwindow;
183 GdkGLWindowImplX11 *impl;
184
185 /* GLXWindow glxwindow; */
186 Window glxwindow;
187
188 GDK_GL_NOTE_FUNC ();
189
190 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
191 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
192
193 /*
194 * Get X Window.
195 */
196
197 glxwindow = GDK_DRAWABLE_XID (GDK_DRAWABLE (window));
198
199 /*
200 * Instantiate the GdkGLWindowImplX11 object.
201 */
202
203 glwindow = g_object_new (GDK_TYPE_GL_WINDOW_IMPL_X11, NULL);
204 impl = GDK_GL_WINDOW_IMPL_X11 (glwindow);
205
206 glwindow->drawable = GDK_DRAWABLE (window);
207 g_object_add_weak_pointer (G_OBJECT (glwindow->drawable),
208 (gpointer *) &(glwindow->drawable));
209
210 impl->glxwindow = glxwindow;
211
212 impl->glconfig = glconfig;
213 g_object_ref (G_OBJECT (impl->glconfig));
214
215 impl->is_destroyed = FALSE;
216
217 return glwindow;
218 }
219
220 static gboolean
gdk_gl_window_impl_x11_make_context_current(GdkGLDrawable * draw,GdkGLDrawable * read,GdkGLContext * glcontext)221 gdk_gl_window_impl_x11_make_context_current (GdkGLDrawable *draw,
222 GdkGLDrawable *read,
223 GdkGLContext *glcontext)
224 {
225 GdkGLConfig *glconfig;
226 Window glxwindow;
227 GLXContext glxcontext;
228
229 g_return_val_if_fail (GDK_IS_GL_WINDOW_IMPL_X11 (draw), FALSE);
230 g_return_val_if_fail (GDK_IS_GL_CONTEXT_IMPL_X11 (glcontext), FALSE);
231
232 glconfig = GDK_GL_WINDOW_IMPL_X11 (draw)->glconfig;
233 glxwindow = GDK_GL_WINDOW_IMPL_X11 (draw)->glxwindow;
234 glxcontext = GDK_GL_CONTEXT_GLXCONTEXT (glcontext);
235
236 if (glxwindow == None || glxcontext == NULL)
237 return FALSE;
238
239 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
240 GDK_GL_NOTE (MISC,
241 g_message (" -- Window: screen number = %d",
242 GDK_SCREEN_XNUMBER (gdk_drawable_get_screen (GDK_DRAWABLE (draw)))));
243 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
244 GDK_GL_NOTE (MISC,
245 g_message (" -- Window: visual id = 0x%lx",
246 GDK_VISUAL_XVISUAL (gdk_drawable_get_visual (GDK_DRAWABLE (draw)))->visualid));
247
248 GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
249
250 if (!glXMakeCurrent (GDK_GL_CONFIG_XDISPLAY (glconfig), glxwindow, glxcontext))
251 {
252 g_warning ("glXMakeCurrent() failed");
253 _gdk_gl_context_set_gl_drawable (glcontext, NULL);
254 /* currently unused. */
255 /* _gdk_gl_context_set_gl_drawable_read (glcontext, NULL); */
256 return FALSE;
257 }
258
259 _gdk_gl_context_set_gl_drawable (glcontext, draw);
260 /* currently unused. */
261 /* _gdk_gl_context_set_gl_drawable_read (glcontext, read); */
262
263 if (_GDK_GL_CONFIG_AS_SINGLE_MODE (glconfig))
264 {
265 /* We do this because we are treating a double-buffered frame
266 buffer as a single-buffered frame buffer because the system
267 does not appear to export any suitable single-buffered
268 visuals (in which the following are necessary). */
269 glDrawBuffer (GL_FRONT);
270 glReadBuffer (GL_FRONT);
271 }
272
273 GDK_GL_NOTE (MISC, _gdk_gl_print_gl_info ());
274
275 return TRUE;
276 }
277
278 static gboolean
gdk_gl_window_impl_x11_is_double_buffered(GdkGLDrawable * gldrawable)279 gdk_gl_window_impl_x11_is_double_buffered (GdkGLDrawable *gldrawable)
280 {
281 g_return_val_if_fail (GDK_IS_GL_WINDOW_IMPL_X11 (gldrawable), FALSE);
282
283 return gdk_gl_config_is_double_buffered (GDK_GL_WINDOW_IMPL_X11 (gldrawable)->glconfig);
284 }
285
286 static void
gdk_gl_window_impl_x11_swap_buffers(GdkGLDrawable * gldrawable)287 gdk_gl_window_impl_x11_swap_buffers (GdkGLDrawable *gldrawable)
288 {
289 Display *xdisplay;
290 Window glxwindow;
291
292 g_return_if_fail (GDK_IS_GL_WINDOW_IMPL_X11 (gldrawable));
293
294 xdisplay = GDK_GL_CONFIG_XDISPLAY (GDK_GL_WINDOW_IMPL_X11 (gldrawable)->glconfig);
295 glxwindow = GDK_GL_WINDOW_IMPL_X11 (gldrawable)->glxwindow;
296
297 if (glxwindow == None)
298 return;
299
300 GDK_GL_NOTE_FUNC_IMPL ("glXSwapBuffers");
301
302 glXSwapBuffers (xdisplay, glxwindow);
303 }
304
305 /*
306 static gboolean
307 gdk_gl_window_impl_x11_gl_begin (GdkGLDrawable *draw,
308 GdkGLDrawable *read,
309 GdkGLContext *glcontext)
310 {
311 return gdk_gl_window_impl_x11_make_context_current (draw, read, glcontext);
312 }
313 */
314
315 static void
gdk_gl_window_impl_x11_gl_end(GdkGLDrawable * gldrawable)316 gdk_gl_window_impl_x11_gl_end (GdkGLDrawable *gldrawable)
317 {
318 /* do nothing */
319 }
320
321 static GdkGLConfig *
gdk_gl_window_impl_x11_get_gl_config(GdkGLDrawable * gldrawable)322 gdk_gl_window_impl_x11_get_gl_config (GdkGLDrawable *gldrawable)
323 {
324 g_return_val_if_fail (GDK_IS_GL_WINDOW_IMPL_X11 (gldrawable), NULL);
325
326 return GDK_GL_WINDOW_IMPL_X11 (gldrawable)->glconfig;
327 }
328
329 /**
330 * gdk_x11_gl_window_get_glxwindow:
331 * @glwindow: a #GdkGLWindow.
332 *
333 * Gets X Window.
334 *
335 * Return value: the Window.
336 **/
337 Window
gdk_x11_gl_window_get_glxwindow(GdkGLWindow * glwindow)338 gdk_x11_gl_window_get_glxwindow (GdkGLWindow *glwindow)
339 {
340 g_return_val_if_fail (GDK_IS_GL_WINDOW_IMPL_X11 (glwindow), None);
341
342 return GDK_GL_WINDOW_IMPL_X11 (glwindow)->glxwindow;
343 }
344