/*
- * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
+ * Copyright (C) 2009-2011 Andy Spencer <andy753421@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* algorithm for updating surface mesh the planet. The only thing GritsOpenGL
* can actually render on it's own is a wireframe of a sphere.
*
- * GritsOpenGL requires (at least) OpenGL 2.0.
+ * GritsOpenGL relies on #GtkGlExt and requires (at least) OpenGL 2.0.
*/
#include <config.h>
#include <string.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "grits-opengl.h"
#include "grits-util.h"
-#include "gtkgl.h"
#include "roam.h"
+static GdkGLConfig *glconfig;
+
// #define ROAM_DEBUG
/* Tessellation, "finding intersecting triangles" */
g_mutex_unlock(opengl->objects_lock);
#endif
- gtk_gl_end(GTK_WIDGET(opengl));
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(opengl));
+ gdk_gl_drawable_swap_buffers(gldrawable);
g_debug("GritsOpenGL: on_expose - end\n");
return FALSE;
return FALSE;
}
+static gboolean on_chained_event(GritsOpenGL *opengl, GdkEvent *event, gpointer _)
+{
+ _foreach_object(opengl, (GFunc)grits_object_event, event);
+ return FALSE;
+}
+
static gboolean _update_errors_cb(gpointer _opengl)
{
GritsOpenGL *opengl = _opengl;
static void on_realize(GritsOpenGL *opengl, gpointer _)
{
g_debug("GritsOpenGL: on_realize");
- gtk_gl_begin(GTK_WIDGET(opengl));
+
+ /* Start OpenGL */
+ GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(opengl));
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(opengl));
+ if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
+ g_assert_not_reached();
/* Connect signals and idle functions now that opengl is fully initialized */
gtk_widget_add_events(GTK_WIDGET(opengl), GDK_KEY_PRESS_MASK);
g_signal_connect(opengl, "rotation-changed", G_CALLBACK(on_view_changed), NULL);
g_signal_connect(opengl, "motion-notify-event", G_CALLBACK(on_motion_notify), NULL);
+ g_signal_connect_after(opengl, "key-press-event", G_CALLBACK(on_chained_event), NULL);
+ g_signal_connect_after(opengl, "key-release-event", G_CALLBACK(on_chained_event), NULL);
+ g_signal_connect_after(opengl, "button-press-event", G_CALLBACK(on_chained_event), NULL);
+ g_signal_connect_after(opengl, "button-release-event", G_CALLBACK(on_chained_event), NULL);
+ g_signal_connect_after(opengl, "motion-notify-event", G_CALLBACK(on_chained_event), NULL);
+
#ifndef ROAM_DEBUG
opengl->sm_source[0] = g_timeout_add_full(G_PRIORITY_HIGH_IDLE+30, 33, (GSourceFunc)on_idle, opengl, NULL);
opengl->sm_source[1] = g_timeout_add_full(G_PRIORITY_HIGH_IDLE+10, 500, (GSourceFunc)on_idle, opengl, NULL);
return link;
}
-static GritsObject *grits_opengl_remove(GritsViewer *_opengl, gpointer _link)
+static GritsObject *grits_opengl_remove(GritsViewer *_opengl, GritsObject *object)
{
g_assert(GRITS_IS_OPENGL(_opengl));
GritsOpenGL *opengl = GRITS_OPENGL(_opengl);
- GList *link = _link;
+ GList *link = object->ref;
g_mutex_lock(opengl->objects_lock);
- GritsObject *object = link->data;
/* Just unlink and free it, link->prev is assured */
link->prev->next = link->next;
if (link->next)
link->next->prev = link->prev;
g_mutex_unlock(opengl->objects_lock);
+ object->ref = NULL;
+ object->viewer = NULL;
g_free(link);
g_object_unref(object);
return object;
}
G_DEFINE_TYPE(GritsOpenGL, grits_opengl, GRITS_TYPE_VIEWER);
+void grits_init(int *argc, char ***argv)
+{
+ glconfig = gdk_gl_config_new_by_mode(
+ GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
+ GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
+ if (!glconfig) {
+ g_warning("Failed to create glconfig, unsupported:%s%s%s%s.",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA) ? "" : " RGBA",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_DEPTH) ? "" : " DEPTH",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_DOUBLE) ? "" : " DOUBLE",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_ALPHA) ? "" : " ALPHA");
+ }
+}
static void grits_opengl_init(GritsOpenGL *opengl)
{
g_debug("GritsOpenGL: init");
opengl->objects_lock = g_mutex_new();
opengl->sphere = roam_sphere_new(opengl);
opengl->sphere_lock = g_mutex_new();
- gtk_gl_enable(GTK_WIDGET(opengl));
+
+ /* Set OpenGL before "realize" */
+ if (!glconfig) {
+ g_warning("recreating glconfig");
+ glconfig = gdk_gl_config_new_by_mode(
+ GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
+ GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
+ }
+ if (!glconfig)
+ g_error("Failed to create glconfig, unsupported:%s%s%s%s.",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA) ? "" : " RGBA",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_DEPTH) ? "" : " DEPTH",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_DOUBLE) ? "" : " DEPTH",
+ gdk_gl_config_new_by_mode(GDK_GL_MODE_ALPHA) ? "" : " ALPHA");
+ if (!gtk_widget_set_gl_capability(GTK_WIDGET(opengl),
+ glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
+ g_error("GL lacks required capabilities");
+
+ /* Finish OpenGL init after it's realized */
g_signal_connect(opengl, "realize", G_CALLBACK(on_realize), NULL);
}
static void grits_opengl_dispose(GObject *_opengl)