summaryrefslogtreecommitdiff
path: root/plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c')
-rw-r--r--plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c591
1 files changed, 591 insertions, 0 deletions
diff --git a/plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c b/plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c
new file mode 100644
index 00000000..5fc0be54
--- /dev/null
+++ b/plugins/gtkui/gtkglext-gtk3/gdk/x11/gdkglcontext-x11.c
@@ -0,0 +1,591 @@
+/* GdkGLExt - OpenGL Extension to GDK
+ * Copyright (C) 2002-2004 Naofumi Yasufuku
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gdk/gdk.h> /* for gdk_error_trap_(push|pop) () */
+
+#include "gdkglx.h"
+#include "gdkglprivate-x11.h"
+#include "gdkglconfig-x11.h"
+#include "gdkglwindow-x11.h"
+#include "gdkglcontext-x11.h"
+
+static void gdk_gl_context_insert (GdkGLContext *glcontext);
+static void gdk_gl_context_remove (GdkGLContext *glcontext);
+static GdkGLContext *gdk_gl_context_lookup (GLXContext glxcontext);
+
+static gboolean _gdk_x11_gl_context_impl_copy (GdkGLContext *glcontext,
+ GdkGLContext *src,
+ unsigned long mask);
+static GdkGLDrawable* _gdk_x11_gl_context_impl_get_gl_drawable (GdkGLContext *glcontext);
+static GdkGLConfig* _gdk_x11_gl_context_impl_get_gl_config (GdkGLContext *glcontext);
+static GdkGLContext* _gdk_x11_gl_context_impl_get_share_list (GdkGLContext *glcontext);
+static gboolean _gdk_x11_gl_context_impl_is_direct (GdkGLContext *glcontext);
+static int _gdk_x11_gl_context_impl_get_render_type (GdkGLContext *glcontext);
+static gboolean _gdk_x11_gl_context_impl_make_current (GdkGLContext *glcontext,
+ GdkGLDrawable *draw,
+ GdkGLDrawable *read);
+static GLXContext _gdk_x11_gl_context_impl_get_glxcontext (GdkGLContext *glcontext);
+
+G_DEFINE_TYPE (GdkGLContextImplX11, \
+ gdk_gl_context_impl_x11, \
+ GDK_TYPE_GL_CONTEXT_IMPL)
+
+static void
+gdk_gl_context_impl_x11_init (GdkGLContextImplX11 *self)
+{
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ self->glxcontext = NULL;
+ self->share_list = NULL;
+ self->is_direct = FALSE;
+ self->render_type = 0;
+ self->glconfig = NULL;
+ self->gldrawable = NULL;
+ self->gldrawable_read = NULL;
+ self->is_destroyed = 0;
+ self->is_foreign = 0;
+}
+
+void
+_gdk_gl_context_destroy (GdkGLContext *glcontext)
+{
+ GdkGLContextImplX11 *impl = GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl);
+ Display *xdisplay;
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (impl->is_destroyed)
+ return;
+
+ gdk_gl_context_remove (glcontext);
+
+ xdisplay = GDK_GL_CONFIG_XDISPLAY (impl->glconfig);
+
+ if (impl->glxcontext == glXGetCurrentContext ())
+ {
+ glXWaitGL ();
+
+ GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
+ glXMakeCurrent (xdisplay, None, NULL);
+ }
+
+ if (!impl->is_foreign)
+ {
+ GDK_GL_NOTE_FUNC_IMPL ("glXDestroyContext");
+ glXDestroyContext (xdisplay, impl->glxcontext);
+ impl->glxcontext = NULL;
+ }
+
+ if (impl->gldrawable != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable),
+ (gpointer *) &(impl->gldrawable));
+ impl->gldrawable = NULL;
+ }
+
+ /* currently unused. */
+ /*
+ if (impl->gldrawable_read != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable_read),
+ (gpointer *) &(impl->gldrawable_read));
+ impl->gldrawable_read = NULL;
+ }
+ */
+
+ impl->is_destroyed = TRUE;
+}
+
+static void
+gdk_gl_context_impl_x11_finalize (GObject *object)
+{
+ GdkGLContextImplX11 *impl = GDK_GL_CONTEXT_IMPL_X11 (object);
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ _gdk_gl_context_destroy (GDK_GL_CONTEXT (object));
+
+ g_object_unref (G_OBJECT (impl->glconfig));
+
+ if (impl->share_list != NULL)
+ g_object_unref (G_OBJECT (impl->share_list));
+
+ G_OBJECT_CLASS (gdk_gl_context_impl_x11_parent_class)->finalize (object);
+}
+
+static void
+gdk_gl_context_impl_x11_class_init (GdkGLContextImplX11Class *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ klass->get_glxcontext = _gdk_x11_gl_context_impl_get_glxcontext;
+
+ klass->parent_class.copy_gl_context_impl = _gdk_x11_gl_context_impl_copy;
+ klass->parent_class.get_gl_drawable = _gdk_x11_gl_context_impl_get_gl_drawable;
+ klass->parent_class.get_gl_config = _gdk_x11_gl_context_impl_get_gl_config;
+ klass->parent_class.get_share_list = _gdk_x11_gl_context_impl_get_share_list;
+ klass->parent_class.is_direct = _gdk_x11_gl_context_impl_is_direct;
+ klass->parent_class.get_render_type = _gdk_x11_gl_context_impl_get_render_type;
+ klass->parent_class.make_current = _gdk_x11_gl_context_impl_make_current;
+ klass->parent_class.make_uncurrent = NULL;
+
+ object_class->finalize = gdk_gl_context_impl_x11_finalize;
+}
+
+static GdkGLContextImpl *
+gdk_x11_gl_context_impl_new_common (GdkGLContext *glcontext,
+ GdkGLConfig *glconfig,
+ GdkGLContext *share_list,
+ int render_type,
+ GLXContext glxcontext,
+ gboolean is_foreign)
+{
+ GdkGLContextImpl *impl;
+ GdkGLContextImplX11 *x11_impl;
+
+ Display *xdisplay;
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ /*
+ * Instantiate the GdkGLContextImplX11 object.
+ */
+
+ impl = g_object_new (GDK_TYPE_GL_CONTEXT_IMPL_X11, NULL);
+ x11_impl = GDK_GL_CONTEXT_IMPL_X11 (impl);
+
+ x11_impl->glxcontext = glxcontext;
+
+ if (share_list != NULL && GDK_IS_GL_CONTEXT (share_list))
+ {
+ x11_impl->share_list = share_list;
+ g_object_ref (G_OBJECT (x11_impl->share_list));
+ }
+ else
+ {
+ x11_impl->share_list = NULL;
+ }
+
+ xdisplay = GDK_GL_CONFIG_XDISPLAY (glconfig);
+ x11_impl->is_direct = glXIsDirect (xdisplay, glxcontext) ? TRUE : FALSE;
+
+ x11_impl->render_type = render_type;
+
+ x11_impl->glconfig = glconfig;
+ g_object_ref (G_OBJECT (x11_impl->glconfig));
+
+ x11_impl->gldrawable = NULL;
+ x11_impl->gldrawable_read = NULL;
+
+ x11_impl->is_foreign = is_foreign;
+
+ x11_impl->is_destroyed = FALSE;
+
+ glcontext->impl = impl;
+
+ /*
+ * Insert into the GL context hash table.
+ */
+
+ gdk_gl_context_insert (glcontext);
+
+ return impl;
+}
+
+/*< private >*/
+GdkGLContextImpl *
+_gdk_x11_gl_context_impl_new (GdkGLContext *glcontext,
+ GdkGLDrawable *gldrawable,
+ GdkGLContext *share_list,
+ gboolean direct,
+ int render_type)
+{
+ GdkGLConfig *glconfig;
+ GdkGLContextImplX11 *share_impl = NULL;
+ GLXContext share_glxcontext = NULL;
+
+ Display *xdisplay;
+ XVisualInfo *xvinfo;
+ GLXContext glxcontext;
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ /*
+ * Create an OpenGL rendering context.
+ */
+
+ glconfig = gdk_gl_drawable_get_gl_config (gldrawable);
+
+ xdisplay = GDK_GL_CONFIG_XDISPLAY (glconfig);
+ xvinfo = GDK_GL_CONFIG_XVINFO (glconfig);
+
+ if (share_list != NULL && GDK_IS_GL_CONTEXT (share_list))
+ {
+ share_impl = GDK_GL_CONTEXT_IMPL_X11 (share_list->impl);
+ share_glxcontext = share_impl->glxcontext;
+ }
+
+ GDK_GL_NOTE_FUNC_IMPL ("glXCreateContext");
+
+ if (_gdk_gl_context_force_indirect)
+ {
+ GDK_GL_NOTE (MISC, g_message (" -- Force indirect"));
+
+ glxcontext = glXCreateContext (xdisplay,
+ xvinfo,
+ share_glxcontext,
+ False);
+ }
+ else
+ {
+ glxcontext = glXCreateContext (xdisplay,
+ xvinfo,
+ share_glxcontext,
+ (direct == TRUE) ? True : False);
+ }
+ if (glxcontext == NULL)
+ return NULL;
+
+ GDK_GL_NOTE (MISC,
+ g_message (" -- Context: screen number = %d", xvinfo->screen));
+ GDK_GL_NOTE (MISC,
+ g_message (" -- Context: visual id = 0x%lx", xvinfo->visualid));
+
+ /*
+ * Instantiate the GdkGLContextImplX11 object.
+ */
+
+ return gdk_x11_gl_context_impl_new_common (glcontext,
+ glconfig,
+ share_list,
+ render_type,
+ glxcontext,
+ FALSE);
+}
+
+GdkGLContextImpl *
+_gdk_x11_gl_context_impl_new_from_glxcontext (GdkGLContext *glcontext,
+ GdkGLConfig *glconfig,
+ GdkGLContext *share_list,
+ GLXContext glxcontext)
+{
+ GDK_GL_NOTE_FUNC ();
+
+ g_return_val_if_fail (GDK_IS_X11_GL_CONFIG (glconfig), NULL);
+ g_return_val_if_fail (glxcontext != NULL, NULL);
+
+ /*
+ * Instantiate the GdkGLContextImplX11 object.
+ */
+
+ return gdk_x11_gl_context_impl_new_common (glcontext,
+ glconfig,
+ share_list,
+ GDK_GL_RGBA_TYPE,
+ glxcontext,
+ TRUE);
+}
+
+static gboolean
+_gdk_x11_gl_context_impl_copy (GdkGLContext *glcontext,
+ GdkGLContext *src,
+ unsigned long mask)
+{
+ GLXContext dst_glxcontext, src_glxcontext;
+ GdkGLConfig *glconfig;
+
+ GDK_GL_NOTE_FUNC ();
+
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), FALSE);
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (src), FALSE);
+
+ dst_glxcontext = GDK_GL_CONTEXT_GLXCONTEXT (glcontext);
+ if (dst_glxcontext == NULL)
+ return FALSE;
+
+ src_glxcontext = GDK_GL_CONTEXT_GLXCONTEXT (src);
+ if (src_glxcontext == NULL)
+ return FALSE;
+
+ glconfig = GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->glconfig;
+
+ gdk_error_trap_push ();
+
+ glXCopyContext (GDK_GL_CONFIG_XDISPLAY (glconfig),
+ src_glxcontext, dst_glxcontext,
+ mask);
+
+ return gdk_error_trap_pop () == Success;
+}
+
+/*< private >*/
+void
+_gdk_x11_gl_context_impl_set_gl_drawable (GdkGLContext *glcontext,
+ GdkGLDrawable *gldrawable)
+{
+ GdkGLContextImplX11 *impl = GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl);
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (impl->gldrawable == gldrawable)
+ return;
+
+ if (impl->gldrawable != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable),
+ (gpointer *) &(impl->gldrawable));
+ impl->gldrawable = NULL;
+ }
+
+ if (gldrawable != NULL && GDK_IS_GL_DRAWABLE (gldrawable))
+ {
+ impl->gldrawable = gldrawable;
+ g_object_add_weak_pointer (G_OBJECT (impl->gldrawable),
+ (gpointer *) &(impl->gldrawable));
+ }
+}
+
+/*< private >*/
+/* currently unused. */
+/*
+void
+_gdk_gl_context_set_gl_drawable_read (GdkGLContext *glcontext,
+ GdkGLDrawable *gldrawable_read)
+{
+ GdkGLContextImplX11 *impl = GDK_GL_CONTEXT_IMPL_X11 (glcontext);
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (impl->gldrawable_read == gldrawable_read)
+ return;
+
+ if (impl->gldrawable_read != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (impl->gldrawable_read),
+ (gpointer *) &(impl->gldrawable_read));
+ impl->gldrawable_read = NULL;
+ }
+
+ if (gldrawable_read != NULL && GDK_IS_GL_DRAWABLE (gldrawable_read))
+ {
+ impl->gldrawable_read = gldrawable_read;
+ g_object_add_weak_pointer (G_OBJECT (impl->gldrawable_read),
+ (gpointer *) &(impl->gldrawable_read));
+ }
+}
+*/
+
+static GdkGLDrawable *
+_gdk_x11_gl_context_impl_get_gl_drawable (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), NULL);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->gldrawable;
+}
+
+static GdkGLConfig *
+_gdk_x11_gl_context_impl_get_gl_config (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), NULL);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->glconfig;
+}
+
+static GdkGLContext *
+_gdk_x11_gl_context_impl_get_share_list (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), NULL);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->share_list;
+}
+
+static gboolean
+_gdk_x11_gl_context_impl_is_direct (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), FALSE);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->is_direct;
+}
+
+static int
+_gdk_x11_gl_context_impl_get_render_type (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), 0);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->render_type;
+}
+
+static gboolean
+_gdk_x11_gl_context_impl_make_current (GdkGLContext *glcontext,
+ GdkGLDrawable *draw,
+ GdkGLDrawable *read)
+{
+ GdkGLWindow *glwindow;
+ GdkGLWindowImplX11 *x11_impl;
+ GdkGLConfig *glconfig;
+ GdkWindow *window;
+ Window glxwindow;
+ GLXContext glxcontext;
+
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), FALSE);
+ g_return_val_if_fail (GDK_IS_X11_GL_WINDOW (draw), FALSE);
+
+ glwindow = GDK_GL_WINDOW(draw);
+ x11_impl = GDK_GL_WINDOW_IMPL_X11 (glwindow->impl);
+ glconfig = x11_impl->glconfig;
+ window = gdk_gl_window_get_window(glwindow);
+ glxwindow = x11_impl->glxwindow;
+ glxcontext = GDK_GL_CONTEXT_GLXCONTEXT (glcontext);
+
+ if (glxwindow == None || glxcontext == NULL)
+ return FALSE;
+
+ GDK_GL_NOTE (MISC,
+ g_message (" -- Window: screen number = %d",
+ GDK_SCREEN_XNUMBER (gdk_window_get_screen (window))));
+ GDK_GL_NOTE (MISC,
+ g_message (" -- Window: visual id = 0x%lx",
+ GDK_VISUAL_XVISUAL (gdk_window_get_visual (window))->visualid));
+
+ GDK_GL_NOTE_FUNC_IMPL ("glXMakeCurrent");
+
+ if (!glXMakeCurrent (GDK_GL_CONFIG_XDISPLAY (glconfig), glxwindow, glxcontext))
+ {
+ g_warning ("glXMakeCurrent() failed");
+ _gdk_x11_gl_context_impl_set_gl_drawable (glcontext, NULL);
+ /* currently unused. */
+ /* _gdk_gl_context_set_gl_drawable_read (glcontext, NULL); */
+ return FALSE;
+ }
+
+ _gdk_x11_gl_context_impl_set_gl_drawable (glcontext, draw);
+ /* currently unused. */
+ /* _gdk_gl_context_set_gl_drawable_read (glcontext, read); */
+
+ if (_GDK_GL_CONFIG_AS_SINGLE_MODE (glconfig))
+ {
+ /* We do this because we are treating a double-buffered frame
+ buffer as a single-buffered frame buffer because the system
+ does not appear to export any suitable single-buffered
+ visuals (in which the following are necessary). */
+ glDrawBuffer (GL_FRONT);
+ glReadBuffer (GL_FRONT);
+ }
+
+ GDK_GL_NOTE (MISC, _gdk_gl_print_gl_info ());
+
+ return TRUE;
+}
+
+GdkGLContext *
+_gdk_x11_gl_context_impl_get_current (void)
+{
+ static GdkGLContext *current = NULL;
+ GLXContext glxcontext;
+
+ GDK_GL_NOTE_FUNC ();
+
+ glxcontext = glXGetCurrentContext ();
+
+ if (glxcontext == NULL)
+ return NULL;
+
+ if (current && GDK_GL_CONTEXT_GLXCONTEXT (current) == glxcontext)
+ return current;
+
+ current = gdk_gl_context_lookup (glxcontext);
+
+ return current;
+}
+
+GLXContext
+_gdk_x11_gl_context_impl_get_glxcontext (GdkGLContext *glcontext)
+{
+ g_return_val_if_fail (GDK_IS_X11_GL_CONTEXT (glcontext), NULL);
+
+ return GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl)->glxcontext;
+}
+
+/*
+ * GdkGLContext hash table.
+ */
+
+static GHashTable *gl_context_ht = NULL;
+
+static void
+gdk_gl_context_insert (GdkGLContext *glcontext)
+{
+ GdkGLContextImplX11 *impl;
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (gl_context_ht == NULL)
+ {
+ GDK_GL_NOTE (MISC, g_message (" -- Create GL context hash table."));
+
+ /* We do not know the storage type of GLXContext from the GLX
+ specification. We assume that it is a pointer as NULL values
+ are specified for this type---this is consistent with the SGI
+ and Mesa GLX implementations. */
+ gl_context_ht = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+ }
+
+ impl = GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl);
+
+ g_hash_table_insert (gl_context_ht, impl->glxcontext, glcontext);
+}
+
+static void
+gdk_gl_context_remove (GdkGLContext *glcontext)
+{
+ GdkGLContextImplX11 *impl;
+
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (gl_context_ht == NULL)
+ return;
+
+ impl = GDK_GL_CONTEXT_IMPL_X11 (glcontext->impl);
+
+ g_hash_table_remove (gl_context_ht, impl->glxcontext);
+
+ if (g_hash_table_size (gl_context_ht) == 0)
+ {
+ GDK_GL_NOTE (MISC, g_message (" -- Destroy GL context hash table."));
+ g_hash_table_destroy (gl_context_ht);
+ gl_context_ht = NULL;
+ }
+}
+
+static GdkGLContext *
+gdk_gl_context_lookup (GLXContext glxcontext)
+{
+ GDK_GL_NOTE_FUNC_PRIVATE ();
+
+ if (gl_context_ht == NULL)
+ return NULL;
+
+ return g_hash_table_lookup (gl_context_ht, glxcontext);
+}