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