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 "gdkglpixmap-x11.h"
26
27 static gboolean gdk_gl_pixmap_impl_x11_make_context_current (GdkGLDrawable *draw,
28 GdkGLDrawable *read,
29 GdkGLContext *glcontext);
30 static gboolean gdk_gl_pixmap_impl_x11_is_double_buffered (GdkGLDrawable *gldrawable);
31 static void gdk_gl_pixmap_impl_x11_swap_buffers (GdkGLDrawable *gldrawable);
32 /*
33 static gboolean gdk_gl_pixmap_impl_x11_gl_begin (GdkGLDrawable *draw,
34 GdkGLDrawable *read,
35 GdkGLContext *glcontext);
36 */
37 static void gdk_gl_pixmap_impl_x11_gl_end (GdkGLDrawable *gldrawable);
38 static GdkGLConfig *gdk_gl_pixmap_impl_x11_get_gl_config (GdkGLDrawable *gldrawable);
39
40 static void gdk_gl_pixmap_impl_x11_class_init (GdkGLPixmapImplX11Class *klass);
41 static void gdk_gl_pixmap_impl_x11_finalize (GObject *object);
42 static void gdk_gl_pixmap_impl_x11_gl_drawable_interface_init (GdkGLDrawableClass *iface);
43
44 static gpointer parent_class = NULL;
45
46 GType
gdk_gl_pixmap_impl_x11_get_type(void)47 gdk_gl_pixmap_impl_x11_get_type (void)
48 {
49 static GType type = 0;
50
51 if (!type)
52 {
53 static const GTypeInfo type_info = {
54 sizeof (GdkGLPixmapImplX11Class),
55 (GBaseInitFunc) NULL,
56 (GBaseFinalizeFunc) NULL,
57 (GClassInitFunc) gdk_gl_pixmap_impl_x11_class_init,
58 (GClassFinalizeFunc) NULL,
59 NULL, /* class_data */
60 sizeof (GdkGLPixmapImplX11),
61 0, /* n_preallocs */
62 (GInstanceInitFunc) NULL
63 };
64 static const GInterfaceInfo gl_drawable_interface_info = {
65 (GInterfaceInitFunc) gdk_gl_pixmap_impl_x11_gl_drawable_interface_init,
66 (GInterfaceFinalizeFunc) NULL,
67 NULL /* interface_data */
68 };
69
70 type = g_type_register_static (GDK_TYPE_GL_PIXMAP,
71 "GdkGLPixmapImplX11",
72 &type_info, 0);
73 g_type_add_interface_static (type,
74 GDK_TYPE_GL_DRAWABLE,
75 &gl_drawable_interface_info);
76 }
77
78 return type;
79 }
80
81 static void
gdk_gl_pixmap_impl_x11_class_init(GdkGLPixmapImplX11Class * klass)82 gdk_gl_pixmap_impl_x11_class_init (GdkGLPixmapImplX11Class *klass)
83 {
84 GObjectClass *object_class = G_OBJECT_CLASS (klass);
85
86 GDK_GL_NOTE_FUNC_PRIVATE ();
87
88 parent_class = g_type_class_peek_parent (klass);
89
90 object_class->finalize = gdk_gl_pixmap_impl_x11_finalize;
91 }
92
93 void
_gdk_gl_pixmap_destroy(GdkGLPixmap * glpixmap)94 _gdk_gl_pixmap_destroy (GdkGLPixmap *glpixmap)
95 {
96 GdkGLPixmapImplX11 *impl = GDK_GL_PIXMAP_IMPL_X11 (glpixmap);
97 Display *xdisplay;
98
99 GDK_GL_NOTE_FUNC_PRIVATE ();
100
101 if (impl->is_destroyed)
102 return;
103
104 xdisplay = GDK_GL_CONFIG_XDISPLAY (impl->glconfig);
105
106 if (impl->glxpixmap == glXGetCurrentDrawable ())
107 {
108 glXWaitGL ();
109
110 GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
111 glXMakeCurrent (xdisplay, None, NULL);
112 }
113
114 GDK_GL_NOTE_FUNC_IMPL ("glXDestroyGLXPixmap");
115 glXDestroyGLXPixmap (xdisplay, impl->glxpixmap);
116
117 impl->glxpixmap = None;
118
119 impl->is_destroyed = TRUE;
120 }
121
122 static void
gdk_gl_pixmap_impl_x11_finalize(GObject * object)123 gdk_gl_pixmap_impl_x11_finalize (GObject *object)
124 {
125 GdkGLPixmapImplX11 *impl = GDK_GL_PIXMAP_IMPL_X11 (object);
126
127 GDK_GL_NOTE_FUNC_PRIVATE ();
128
129 _gdk_gl_pixmap_destroy (GDK_GL_PIXMAP (object));
130
131 g_object_unref (G_OBJECT (impl->glconfig));
132
133 G_OBJECT_CLASS (parent_class)->finalize (object);
134 }
135
136 static void
gdk_gl_pixmap_impl_x11_gl_drawable_interface_init(GdkGLDrawableClass * iface)137 gdk_gl_pixmap_impl_x11_gl_drawable_interface_init (GdkGLDrawableClass *iface)
138 {
139 GDK_GL_NOTE_FUNC_PRIVATE ();
140
141 iface->create_new_context = _gdk_x11_gl_context_new;
142 iface->make_context_current = gdk_gl_pixmap_impl_x11_make_context_current;
143 iface->is_double_buffered = gdk_gl_pixmap_impl_x11_is_double_buffered;
144 iface->swap_buffers = gdk_gl_pixmap_impl_x11_swap_buffers;
145 iface->wait_gl = _gdk_gl_drawable_impl_x11_wait_gl;
146 iface->wait_gdk = _gdk_gl_drawable_impl_x11_wait_gdk;
147 iface->gl_begin = gdk_gl_pixmap_impl_x11_make_context_current;
148 iface->gl_end = gdk_gl_pixmap_impl_x11_gl_end;
149 iface->get_gl_config = gdk_gl_pixmap_impl_x11_get_gl_config;
150 iface->get_size = _gdk_gl_pixmap_get_size;
151 }
152
153 /**
154 * gdk_gl_pixmap_new:
155 * @glconfig: a #GdkGLConfig.
156 * @pixmap: the #GdkPixmap to be used as the rendering area.
157 * @attrib_list: this must be set to NULL or empty (first attribute of None).
158 *
159 * Creates an off-screen rendering area.
160 * attrib_list is currently unused. This must be set to NULL or empty
161 * (first attribute of None). See GLX 1.3 spec.
162 *
163 * Return value: the new #GdkGLPixmap.
164 **/
165 GdkGLPixmap *
gdk_gl_pixmap_new(GdkGLConfig * glconfig,GdkPixmap * pixmap,const int * attrib_list)166 gdk_gl_pixmap_new (GdkGLConfig *glconfig,
167 GdkPixmap *pixmap,
168 const int *attrib_list)
169 {
170 GdkGLPixmap *glpixmap;
171 GdkGLPixmapImplX11 *impl;
172
173 Display *xdisplay;
174 XVisualInfo *xvinfo;
175 Pixmap xpixmap;
176 GLXPixmap glxpixmap;
177
178 Window root_return;
179 int x_return, y_return;
180 unsigned int width_return, height_return;
181 unsigned int border_width_return;
182 unsigned int depth_return;
183
184 GdkGL_GLX_MESA_pixmap_colormap *mesa_ext;
185
186 GDK_GL_NOTE_FUNC ();
187
188 g_return_val_if_fail (GDK_IS_GL_CONFIG_IMPL_X11 (glconfig), NULL);
189 g_return_val_if_fail (GDK_IS_PIXMAP (pixmap), NULL);
190
191 xdisplay = GDK_GL_CONFIG_XDISPLAY (glconfig);
192 xvinfo = GDK_GL_CONFIG_XVINFO (glconfig);
193
194 /*
195 * Get X Pixmap.
196 */
197
198 xpixmap = GDK_DRAWABLE_XID (GDK_DRAWABLE (pixmap));
199
200 /*
201 * Check depth of the X pixmap.
202 */
203
204 if (!XGetGeometry (xdisplay, xpixmap,
205 &root_return,
206 &x_return, &y_return,
207 &width_return, &height_return,
208 &border_width_return,
209 &depth_return))
210 return NULL;
211
212 if (depth_return != (unsigned int) xvinfo->depth)
213 return NULL;
214
215 /*
216 * Create GLXPixmap.
217 */
218
219 mesa_ext = gdk_gl_get_GLX_MESA_pixmap_colormap (glconfig);
220 if (mesa_ext)
221 {
222 /* If GLX_MESA_pixmap_colormap is supported. */
223
224 GDK_GL_NOTE_FUNC_IMPL ("glXCreateGLXPixmapMESA");
225
226 glxpixmap = mesa_ext->glXCreateGLXPixmapMESA (xdisplay,
227 xvinfo,
228 xpixmap,
229 GDK_GL_CONFIG_XCOLORMAP (glconfig));
230 }
231 else
232 {
233 GDK_GL_NOTE_FUNC_IMPL ("glXCreateGLXPixmap");
234
235 glxpixmap = glXCreateGLXPixmap (xdisplay,
236 xvinfo,
237 xpixmap);
238 }
239
240 if (glxpixmap == None)
241 return NULL;
242
243 /*
244 * Instantiate the GdkGLPixmapImplX11 object.
245 */
246
247 glpixmap = g_object_new (GDK_TYPE_GL_PIXMAP_IMPL_X11, NULL);
248 impl = GDK_GL_PIXMAP_IMPL_X11 (glpixmap);
249
250 glpixmap->drawable = GDK_DRAWABLE (pixmap);
251 g_object_add_weak_pointer (G_OBJECT (glpixmap->drawable),
252 (gpointer *) &(glpixmap->drawable));
253
254 impl->glxpixmap = glxpixmap;
255
256 impl->glconfig = glconfig;
257 g_object_ref (G_OBJECT (impl->glconfig));
258
259 impl->is_destroyed = FALSE;
260
261 return glpixmap;
262 }
263
264 static gboolean
gdk_gl_pixmap_impl_x11_make_context_current(GdkGLDrawable * draw,GdkGLDrawable * read,GdkGLContext * glcontext)265 gdk_gl_pixmap_impl_x11_make_context_current (GdkGLDrawable *draw,
266 GdkGLDrawable *read,
267 GdkGLContext *glcontext)
268 {
269 GdkGLConfig *glconfig;
270 GLXPixmap glxpixmap;
271 GLXContext glxcontext;
272
273 g_return_val_if_fail (GDK_IS_GL_PIXMAP_IMPL_X11 (draw), FALSE);
274 g_return_val_if_fail (GDK_IS_GL_CONTEXT_IMPL_X11 (glcontext), FALSE);
275
276 glconfig = GDK_GL_PIXMAP_IMPL_X11 (draw)->glconfig;
277 glxpixmap = GDK_GL_PIXMAP_IMPL_X11 (draw)->glxpixmap;
278 glxcontext = GDK_GL_CONTEXT_GLXCONTEXT (glcontext);
279
280 if (glxpixmap == None || glxcontext == NULL)
281 return FALSE;
282
283 #ifdef GDKGLEXT_MULTIHEAD_SUPPORT
284 GDK_GL_NOTE (MISC,
285 g_message (" -- Pixmap: screen number = %d",
286 GDK_SCREEN_XNUMBER (gdk_drawable_get_screen (GDK_DRAWABLE (draw)))));
287 #endif /* GDKGLEXT_MULTIHEAD_SUPPORT */
288 GDK_GL_NOTE (MISC,
289 g_message (" -- Pixmap: visual id = 0x%lx",
290 GDK_VISUAL_XVISUAL (gdk_drawable_get_visual (GDK_DRAWABLE (draw)))->visualid));
291
292 GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
293
294 if (!glXMakeCurrent (GDK_GL_CONFIG_XDISPLAY (glconfig), glxpixmap, glxcontext))
295 {
296 g_warning ("glXMakeCurrent() failed");
297 _gdk_gl_context_set_gl_drawable (glcontext, NULL);
298 /* currently unused. */
299 /* _gdk_gl_context_set_gl_drawable_read (glcontext, NULL); */
300 return FALSE;
301 }
302
303 _gdk_gl_context_set_gl_drawable (glcontext, draw);
304 /* currently unused. */
305 /* _gdk_gl_context_set_gl_drawable_read (glcontext, read); */
306
307 if (_GDK_GL_CONFIG_AS_SINGLE_MODE (glconfig))
308 {
309 /* We do this because we are treating a double-buffered frame
310 buffer as a single-buffered frame buffer because the system
311 does not appear to export any suitable single-buffered
312 visuals (in which the following are necessary). */
313 glDrawBuffer (GL_FRONT);
314 glReadBuffer (GL_FRONT);
315 }
316
317 GDK_GL_NOTE (MISC, _gdk_gl_print_gl_info ());
318
319 return TRUE;
320 }
321
322 static gboolean
gdk_gl_pixmap_impl_x11_is_double_buffered(GdkGLDrawable * gldrawable)323 gdk_gl_pixmap_impl_x11_is_double_buffered (GdkGLDrawable *gldrawable)
324 {
325 g_return_val_if_fail (GDK_IS_GL_PIXMAP_IMPL_X11 (gldrawable), FALSE);
326
327 return gdk_gl_config_is_double_buffered (GDK_GL_PIXMAP_IMPL_X11 (gldrawable)->glconfig);
328 }
329
330 static void
gdk_gl_pixmap_impl_x11_swap_buffers(GdkGLDrawable * gldrawable)331 gdk_gl_pixmap_impl_x11_swap_buffers (GdkGLDrawable *gldrawable)
332 {
333 Display *xdisplay;
334 GLXPixmap glxpixmap;
335
336 g_return_if_fail (GDK_IS_GL_PIXMAP_IMPL_X11 (gldrawable));
337
338 xdisplay = GDK_GL_CONFIG_XDISPLAY (GDK_GL_PIXMAP_IMPL_X11 (gldrawable)->glconfig);
339 glxpixmap = GDK_GL_PIXMAP_IMPL_X11 (gldrawable)->glxpixmap;
340
341 if (glxpixmap == None)
342 return;
343
344 GDK_GL_NOTE_FUNC_IMPL ("glXSwapBuffers");
345
346 glXSwapBuffers (xdisplay, glxpixmap);
347 }
348
349 /*
350 static gboolean
351 gdk_gl_pixmap_impl_x11_gl_begin (GdkGLDrawable *draw,
352 GdkGLDrawable *read,
353 GdkGLContext *glcontext)
354 {
355 return gdk_gl_pixmap_impl_x11_make_context_current (draw, read, glcontext);
356 }
357 */
358
359 static void
gdk_gl_pixmap_impl_x11_gl_end(GdkGLDrawable * gldrawable)360 gdk_gl_pixmap_impl_x11_gl_end (GdkGLDrawable *gldrawable)
361 {
362 /* do nothing */
363 }
364
365 static GdkGLConfig *
gdk_gl_pixmap_impl_x11_get_gl_config(GdkGLDrawable * gldrawable)366 gdk_gl_pixmap_impl_x11_get_gl_config (GdkGLDrawable *gldrawable)
367 {
368 g_return_val_if_fail (GDK_IS_GL_PIXMAP_IMPL_X11 (gldrawable), NULL);
369
370 return GDK_GL_PIXMAP_IMPL_X11 (gldrawable)->glconfig;
371 }
372
373 /**
374 * gdk_x11_gl_pixmap_get_glxpixmap:
375 * @glpixmap: a #GdkGLPixmap.
376 *
377 * Gets GLXPixmap.
378 *
379 * Return value: the GLXPixmap.
380 **/
381 GLXPixmap
gdk_x11_gl_pixmap_get_glxpixmap(GdkGLPixmap * glpixmap)382 gdk_x11_gl_pixmap_get_glxpixmap (GdkGLPixmap *glpixmap)
383 {
384 g_return_val_if_fail (GDK_IS_GL_PIXMAP_IMPL_X11 (glpixmap), None);
385
386 return GDK_GL_PIXMAP_IMPL_X11 (glpixmap)->glxpixmap;
387 }
388