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