[grits] Switch from GtkGLExt to internal OpenGL handling
- From: Andy Spencer <andys src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grits] Switch from GtkGLExt to internal OpenGL handling
- Date: Fri, 17 Jun 2011 05:20:39 +0000 (UTC)
commit 07448c519e963bae1cfde4f1ff353478dd28136c
Author: Andy Spencer <andy753421 gmail com>
Date: Tue Jun 7 08:43:32 2011 +0000
Switch from GtkGLExt to internal OpenGL handling
GtkGLExt has many problems:
- It's code is bloated and convoluted
- It doesn't work on Win32
- It doesn't work with gtk+-3.0
- The last release was in early 2006
Using our own lets us fix these issues and should be easier to maintain
than trying to figure out the GtkGLExt mess, or waiting for someone else
to fix it.
configure.ac | 13 +++-
examples/plugin/teapot.c | 4 +-
src/Makefile.am | 13 ++-
src/grits-opengl.c | 28 +------
src/grits-test.c | 2 -
src/grits.pc.in | 6 +-
src/gtkgl.c | 190 ++++++++++++++++++++++++++++++++++++++++++++
src/gtkgl.h | 33 ++++++++
src/objects/grits-volume.c | 1 -
src/plugins/Makefile.am | 2 +
src/plugins/elev.c | 1 -
src/plugins/env.c | 1 -
src/plugins/test.c | 1 -
13 files changed, 255 insertions(+), 40 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 953029a..5a1623c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,7 +25,7 @@ GTK_DOC_CHECK(1.9)
# Check for required packages
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.14 gobject-2.0 gthread-2.0)
PKG_CHECK_MODULES(CAIRO, cairo)
-PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.16 gtkglext-1.0)
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.16)
PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.26)
# Test for Windows vs. Unix
@@ -40,6 +40,17 @@ fi
AM_CONDITIONAL([WIN32], test "$WIN32" = "yes")
AM_CONDITIONAL([NOTWIN32], test "$WIN32" = "no")
+# Configure GL flags
+if test "$WIN32" = yes; then
+ GL_CFLAGS=""
+ GL_LIBS="-lglu32 -lopengl32"
+else
+ GL_CFLAGS=""
+ GL_LIBS="-lGL -lGLU"
+fi
+AC_SUBST([GL_CFLAGS])
+AC_SUBST([GL_LIBS])
+
# Output
AC_CONFIG_FILES([
Makefile
diff --git a/examples/plugin/teapot.c b/examples/plugin/teapot.c
index 60c52f4..2a1201d 100644
--- a/examples/plugin/teapot.c
+++ b/examples/plugin/teapot.c
@@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gtk/gtkgl.h>
#include <GL/gl.h>
+#include <GL/glut.h>
#include <grits.h>
@@ -59,7 +59,7 @@ static void expose(GritsCallback *callback, GritsOpenGL *opengl, gpointer _teapo
glRotatef(teapot->rotation, 1, 1, 0);
glColor4f(0.9, 0.9, 0.7, 1.0);
glDisable(GL_CULL_FACE);
- gdk_gl_draw_teapot(TRUE, 0.25);
+ glutSolidTeapot(2.5);
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cb7454..e9b536d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,8 @@
SUBDIRS = data objects . plugins
AM_CFLAGS = -Wall --std=gnu99 -I$(top_srcdir)/src
-AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(SOUP_CFLAGS)
-AM_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(SOUP_LIBS)
+AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(GL_CFLAGS) $(SOUP_CFLAGS)
+AM_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(GL_LIBS) $(SOUP_LIBS)
AM_LDFLAGS = --as-needed -no-undefined
BUILT_SOURCES = grits-marshal.c grits-marshal.h
@@ -35,6 +35,7 @@ libgrits_la_SOURCES = grits.h \
grits-marshal.c grits-marshal.h \
grits-util.c grits-util.h \
roam.c roam.h \
+ gtkgl.c gtkgl.h \
gpqueue.c gpqueue.h
libgrits_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DPKGDATADIR="\"$(dots)$(datadir)/$(GRITS_SUBDIR)\"" \
@@ -47,10 +48,12 @@ libgrits_la_LDFLAGS = $(AM_LDFLAGS) \
# Demo program
if WIN32
-AM_LDFLAGS += -mwindows
-dots = ..
+AM_CPPFLAGS += -DUSE_WGL
+AM_LDFLAGS += -mwindows
+dots = ..
else
-BINLDFLAGS = -static
+AM_CPPFLAGS += -DUSE_GLX
+BINLDFLAGS = -static
endif
bin_PROGRAMS = grits-demo
diff --git a/src/grits-opengl.c b/src/grits-opengl.c
index d8eda27..b1316fc 100644
--- a/src/grits-opengl.c
+++ b/src/grits-opengl.c
@@ -24,7 +24,7 @@
* 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 relies on #GtkGlExt and requires (at least) OpenGL 2.0.
+ * GritsOpenGL requires (at least) OpenGL 2.0.
*/
#include <config.h>
@@ -32,12 +32,12 @@
#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"
// #define ROAM_DEBUG
@@ -206,8 +206,7 @@ static gboolean on_expose(GritsOpenGL *opengl, GdkEventExpose *event, gpointer _
g_mutex_unlock(opengl->objects_lock);
#endif
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(opengl));
- gdk_gl_drawable_swap_buffers(gldrawable);
+ gtk_gl_end(GTK_WIDGET(opengl));
g_debug("GritsOpenGL: on_expose - end\n");
return FALSE;
@@ -271,12 +270,7 @@ static gboolean on_idle(GritsOpenGL *opengl)
static void on_realize(GritsOpenGL *opengl, gpointer _)
{
g_debug("GritsOpenGL: on_realize");
-
- /* 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();
+ gtk_gl_begin(GTK_WIDGET(opengl));
/* Connect signals and idle functions now that opengl is fully initialized */
gtk_widget_add_events(GTK_WIDGET(opengl), GDK_KEY_PRESS_MASK);
@@ -454,19 +448,7 @@ static void grits_opengl_init(GritsOpenGL *opengl)
opengl->objects_lock = g_mutex_new();
opengl->sphere = roam_sphere_new(opengl);
opengl->sphere_lock = g_mutex_new();
-
- /* Set OpenGL before "realize" */
- GdkGLConfig *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");
- if (!gtk_widget_set_gl_capability(GTK_WIDGET(opengl),
- glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
- g_error("GL lacks required capabilities");
- g_object_unref(glconfig);
-
- /* Finish OpenGL init after it's realized */
+ gtk_gl_enable(GTK_WIDGET(opengl));
g_signal_connect(opengl, "realize", G_CALLBACK(on_realize), NULL);
}
static void grits_opengl_dispose(GObject *_opengl)
diff --git a/src/grits-test.c b/src/grits-test.c
index 67e299d..5be869b 100644
--- a/src/grits-test.c
+++ b/src/grits-test.c
@@ -17,7 +17,6 @@
#include <config.h>
#include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
#include <gdk/gdkkeysyms.h>
#include "grits.h"
@@ -69,7 +68,6 @@ int main(int argc, char **argv)
g_thread_init(NULL);
gdk_threads_init();
gtk_init(&argc, &argv);
- gtk_gl_init(&argc, &argv);
prefs = grits_prefs_new(NULL, NULL);
plugins = grits_plugins_new(g_getenv("GRITS_PLUGIN_PATH"), prefs);
diff --git a/src/grits.pc.in b/src/grits.pc.in
index 541f222..da0ea6a 100644
--- a/src/grits.pc.in
+++ b/src/grits.pc.in
@@ -6,6 +6,6 @@ includedir= includedir@
Name: Grits
Description: Grits is a Virtual Globe library
Version: @VERSION@
-Requires: gmodule-2.0 gtk+-2.0 gtkglext-1.0 libsoup-2.4
-Libs: -L${libdir} -lgrits
-Cflags: -I${includedir}/grits
+Requires: gmodule-2.0 gtk+-2.0 libsoup-2.4
+Libs: -L${libdir} -lgrits @GL_LIBS@
+Cflags: -I${includedir}/grits @GL_CFLAGS@
diff --git a/src/gtkgl.c b/src/gtkgl.c
new file mode 100644
index 0000000..9a2909a
--- /dev/null
+++ b/src/gtkgl.c
@@ -0,0 +1,190 @@
+#include <gtk/gtk.h>
+
+/***************************
+ * GtkGlExt implementation *
+ ***************************/
+#if defined(USE_GTKGLEXT)
+#include <gtk/gtkgl.h>
+void gtk_gl_enable(GtkWidget *widget)
+{
+ GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
+ GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
+ GDK_GL_MODE_ALPHA | GDK_GL_MODE_DOUBLE);
+ gtk_widget_set_gl_capability(widget,
+ glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
+}
+
+void gtk_gl_begin(GtkWidget *widget)
+{
+ GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
+ gdk_gl_drawable_gl_begin(gldrawable, glcontext);
+}
+
+void gtk_gl_end(GtkWidget *widget)
+{
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
+ gdk_gl_drawable_swap_buffers(gldrawable);
+ gdk_gl_drawable_gl_end(gldrawable);
+}
+
+void gtk_gl_disable(GtkWidget *widget)
+{
+}
+
+
+/**********************
+ * X11 implementation *
+ **********************/
+#elif defined(USE_GLX)
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+void gtk_gl_enable(GtkWidget *widget)
+{
+ g_debug("GtkGl: enable");
+ GdkScreen *screen = gdk_screen_get_default();
+ Display *xdisplay = GDK_SCREEN_XDISPLAY(screen);
+ gint nscreen = GDK_SCREEN_XNUMBER(screen);
+
+ /* Create context */
+ int attribs[] = {GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GLX_DEPTH_SIZE, 1,
+ None};
+ XVisualInfo *xvinfo = glXChooseVisual(xdisplay, nscreen, attribs);
+ GLXContext context = glXCreateContext(xdisplay, xvinfo, NULL, False);
+ g_object_set_data(G_OBJECT(widget), "glcontext", context);
+
+ /* Fix up colormap */
+ GdkVisual *visual = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid);
+ GdkColormap *cmap = gdk_colormap_new(visual, FALSE);
+ gtk_widget_set_colormap(widget, cmap);
+
+ /* Disable GTK double buffering */
+ gtk_widget_set_double_buffered(widget, FALSE);
+}
+
+void gtk_gl_begin(GtkWidget *widget)
+{
+ g_debug("GtkGl: begin");
+ Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
+ Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
+ GLXContext context = g_object_get_data(G_OBJECT(widget), "glcontext");
+ glXMakeCurrent(xdisplay, xwindow, context);
+}
+
+void gtk_gl_end(GtkWidget *widget)
+{
+ g_debug("GtkGl: end");
+ Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
+ Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
+ glXSwapBuffers(xdisplay, xwindow);
+}
+
+void gtk_gl_disable(GtkWidget *widget)
+{
+ g_debug("GtkGl: disable");
+ Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
+ GLXContext context = g_object_get_data(G_OBJECT(widget), "glcontext");
+ glXDestroyContext(xdisplay, context);
+}
+
+
+/************************
+ * Win32 implementation *
+ ************************/
+#elif defined(USE_WGL)
+#include <windows.h>
+#include <gdk/gdkwin32.h>
+static void on_realize(GtkWidget *widget, gpointer _)
+{
+ g_debug("GtkGl: on_realize");
+ gdk_window_ensure_native(gtk_widget_get_window(widget));
+ gtk_widget_set_double_buffered(widget, FALSE);
+
+ HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
+ HDC hDC = GetDC(hwnd);
+
+ PIXELFORMATDESCRIPTOR pfd = {
+ .nSize = sizeof(pfd),
+ .nVersion = 1,
+ .dwFlags = PFD_DRAW_TO_WINDOW
+ | PFD_SUPPORT_OPENGL
+ | PFD_DOUBLEBUFFER,
+ //.dwFlags = PFD_SUPPORT_OPENGL
+ // | PFD_DRAW_TO_WINDOW,
+ .iPixelType = PFD_TYPE_RGBA,
+ .cColorBits = 24,
+ .cAlphaBits = 8,
+ .cDepthBits = 32,
+ .iLayerType = PFD_MAIN_PLANE,
+ };
+ int pf = ChoosePixelFormat(hDC, &pfd);
+ if (pf == 0)
+ g_error("GtkGl: ChoosePixelFormat failed");
+ if (!SetPixelFormat(hDC, pf, &pfd))
+ g_error("GtkGl: SetPixelFormat failed");
+ HGLRC hRC = wglCreateContext(hDC);
+ if (hRC == NULL)
+ g_error("GtkGl: wglCreateContext failed");
+ g_object_set_data(G_OBJECT(widget), "glcontext", hRC);
+}
+
+void gtk_gl_enable(GtkWidget *widget)
+{
+ g_debug("GtkGl: enable");
+ g_signal_connect(widget, "realize", G_CALLBACK(on_realize), NULL);
+}
+
+void gtk_gl_begin(GtkWidget *widget)
+{
+ g_debug("GtkGl: begin");
+ HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
+ HDC hDC = GetDC(hwnd);
+ HGLRC hRC = g_object_get_data(G_OBJECT(widget), "glcontext");
+ if (!wglMakeCurrent(hDC, hRC))
+ g_error("GtkGl: wglMakeCurrent failed");
+}
+
+void gtk_gl_end(GtkWidget *widget)
+{
+ g_debug("GtkGl: end");
+ HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
+ HDC hDC = GetDC(hwnd);
+ if (!SwapBuffers(hDC))
+ g_error("GtkGl: SwapBuffers failed");
+}
+
+void gtk_gl_disable(GtkWidget *widget)
+{
+ g_debug("GtkGl: disable");
+ HGLRC hRC = g_object_get_data(G_OBJECT(widget), "glcontext");
+ wglDeleteContext(hRC);
+}
+
+
+
+/**************************
+ * Mac OSX implementation *
+ **************************/
+#elif defined(USE_CGL)
+void gtk_gl_enable(GtkWidget *widget) { }
+void gtk_gl_begin(GtkWidget *widget) { }
+void gtk_gl_end(GtkWidget *widget) { }
+void gtk_gl_disable(GtkWidget *widget) { }
+
+
+/****************************
+ * Undefined implementation *
+ ****************************/
+#else
+#warning "Unimplemented GtkGl"
+void gtk_gl_enable(GtkWidget *widget) { }
+void gtk_gl_begin(GtkWidget *widget) { }
+void gtk_gl_end(GtkWidget *widget) { }
+void gtk_gl_disable(GtkWidget *widget) { }
+#endif
diff --git a/src/gtkgl.h b/src/gtkgl.h
new file mode 100644
index 0000000..174fc76
--- /dev/null
+++ b/src/gtkgl.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_GL_H__
+#define __GTK_GL_H__
+
+/* Call before widget is realized */
+void gtk_gl_enable(GtkWidget *widget);
+
+/* Call at the start of "expose" */
+void gtk_gl_begin(GtkWidget *widget);
+
+/* Call at the end of "expose-event" */
+void gtk_gl_end(GtkWidget *widget);
+
+/* Call when done to cleanup data */
+void gtk_gl_disable(GtkWidget *widget);
+
+#endif
diff --git a/src/objects/grits-volume.c b/src/objects/grits-volume.c
index be08279..0ec7fb9 100644
--- a/src/objects/grits-volume.c
+++ b/src/objects/grits-volume.c
@@ -30,7 +30,6 @@
#include <math.h>
#include <glib.h>
#include <GL/gl.h>
-#include <gdk/gdkgl.h>
#include "grits-volume.h"
/* Drawing */
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 0052a59..e5c17dd 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -14,10 +14,12 @@ map_la_SOURCES = map.c map.h
env_la_SOURCES = env.c env.h
test_la_SOURCES = test.c test.h
+if NOTWIN32
noinst_LTLIBRARIES = teapot.la
teapot_la_SOURCES = \
$(top_srcdir)/examples/plugin/teapot.c \
$(top_srcdir)/examples/plugin/teapot.h
+endif
test:
( cd ../; make test )
diff --git a/src/plugins/elev.c b/src/plugins/elev.c
index e99b326..57813ab 100644
--- a/src/plugins/elev.c
+++ b/src/plugins/elev.c
@@ -25,7 +25,6 @@
* greyscale elevation overlay on the planets surface.
*/
-#include <gtk/gtkgl.h>
#include <glib/gstdio.h>
#include <GL/gl.h>
diff --git a/src/plugins/env.c b/src/plugins/env.c
index 3a1f324..a22ad0b 100644
--- a/src/plugins/env.c
+++ b/src/plugins/env.c
@@ -25,7 +25,6 @@
*/
#include <math.h>
-#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <grits.h>
diff --git a/src/plugins/test.c b/src/plugins/test.c
index d917092..c051806 100644
--- a/src/plugins/test.c
+++ b/src/plugins/test.c
@@ -23,7 +23,6 @@
* for how to create a plugin.
*/
-#include <gtk/gtkgl.h>
#include <GL/gl.h>
#include <GL/glu.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]