GTK and OpenGL without GTKGLExt
Carlos Pereira
jose.carlos.pereira at ist.utl.pt
Tue Apr 6 08:14:16 PDT 2010
Hi,
I wrote some code to build GTK / OpenGL applications that doesn't need
GTKGLExt or GTKGLArea libraries. The whole thing comes down to about
30-40 lines of C code.
I am posting this here because I would like very much to hear your
comments and suggestions: what mistakes am I doing? are there mem leaks?
how to make it more robust? how to make it even more simple? is this a
good ideia at all?
I tested this code on Ubuntu 9.10 x86 (GTK 2.18.3), with more than 30
windows open simultaneously, each one with a drawing area, sharing more
than 200 pre-compiled OpenGL lists, with more than 30 lights, creating
and removing windows on the fly, and everything seems to work fine.
A very simple working example can be found here: (I deliberately removed
all error checks, to make this example as simple and clear as possible.
For comparison, I included also the corresponding version with GTKGLExt):
http://www.gamgi.org/gtk_opengl.tar.gz
A big, under test, application can be found here:
http://www.gamgi.org/gamgi-all-0.14.7-exp.tar.gz
Essentially everything comes down to this: disable GTK double buffering
for drawing area and create a new OpenGL context:
#include <GL/glx.h>
#include <gdk/gdkx.h>
GtkWidget *area;
GdkVisual* visual;
GdkColormap *colormap;
GdkScreen *screen;
XVisualInfo *xvisual;
Colormap xcolormap;
Display *display;
Window root;
int xscreen;
int attributes[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, True, GLX_DEPTH_SIZE, 12, None };
area = gtk_drawing_area_new ();
gtk_widget_set_double_buffered (area, FALSE);
display = gdk_x11_get_default_xdisplay ();
xscreen = DefaultScreen (display);
screen = gdk_screen_get_default ();
xvisual = glXChooseVisual (display, xscreen, attributes);
visual = gdk_x11_screen_lookup_visual (screen, xvisual->visualid);
root = RootWindow (display, xscreen);
xcolormap = XCreateColormap (display, root, xvisual->visual, AllocNone);
colormap = gdk_x11_colormap_foreign_new (visual, xcolormap);
gtk_widget_set_colormap (area, colormap);
context = glXCreateContext (display, xvisual, NULL or previous context,
TRUE);
To set the context in GTK callbacks, use this:
GdkWindow *window = gtk_widget_get_window (area);
Display *display = gdk_x11_drawable_get_xdisplay (window);
int id = gdk_x11_drawable_get_xid (window);
if (glXMakeCurrent (display, id, context) == TRUE)
{
... OpenGL here ...
glXSwapBuffers (display, id);
}
My main question is, to create a GL context, I have to allocate
resources, that must be freed later. Which resources shall I free
myself, and when?
Currently I do this:
1) free XVisualInfo immediately after creating each GL context:
XFree (xvisual);
2) free XColormap and GdkColormap when the corresponding drawing area is
removed:
glXDestroyContext (display, context);
XFreeColormap (display, xcolormap);
g_object_unref (G_OBJECT (colormap));
3) question: shall I free the X and GDK visuals in the end, when
removing the last GL context (before closing the application)?
XFree (xvisual);
g_object_unref (G_OBJECT (visual));
I am not a X or GTK expert, so I would like to hear your comments on
this... if this is not the right place to ask, then my apologies...
Thank you very much!
Carlos
More information about the xorg
mailing list