2

I am trying to create a library where it's possible to create a OpenGL context with GTK3 which gets rendered automatically or with 1 function call (something similar to a swap-buffers function). I was looking at the source code of GtkGLArea, which seems to have the following order of execution:

  1. A new GtkGLArea is created with the superclass GtkWidget.
  2. When the realize signal of the superclass is captured, a GdkGLContext is created and a realize signal is given to the user. The user is supposed to put the initial OpenGL functions in a function passed to this signal.
  3. The draw signal of the superclass is also captured, some OpenGL initialization code is called for binding the framebuffer (or texture) and the renderbuffer. The buffers are created if they don't exist. After this the render signal is given where the user is supposed to put the rendering OpenGL code. Finally the gdk_cairo_draw_from_gl function is called to draw the renderbuffer (or texture) on the Cairo context of the superclass passed through the draw signal.

For the user it basically comes down to this:

void realize(GtkGLarea *area){
    // OpenGL initialization functions
}
gboolean render(GtkGLArea *area, GdkGLContext *context){
    // OpenGL rendering functions
    return TRUE;
}

// Init functions, setup a GTK window
GtkWidget *gl_area = gtk_gl_area_new();
g_signal_connect(gl_area, "realize", G_CALLBACK(realize), NULL);
g_signal_connect(gl_area, "render", G_CALLBACK(render), NULL);
// Add gl_area to the window and display the window

But that's not what I want, what I want is this:

// Init functions, setup a GTK window
// Setup a OpenGL context on the GTK window
// OpenGL initialization functions
while(1){ // Main loop
    if(gtk_events_pending()){
        gtk_main_iteration();
    } 
    // OpenGL rendering functions
    swapBuffers();
}

What would be the best way to achieve this? I tried this (unsuccessfully) by simulating the functions called around the signals, and by using a GdkGLContext created on a GdkWindow taken from a GtkDrawingArea.

These are the options which I can imagine as solutions now:

  • Create a custom GTK3 class extending GtkWidget and using GdkGLContext and somehow track when the drawing signal is called so the appropriate OpenGL functions are called around that signal.
  • Find a way to ignore the whole GTK3 part and try to use the underlying Xlib functions to create a OpenGL context through X11 (which isn't portable at all).
  • Use a evil hack with threads and setjmp and longjmp to enter and exit the signals from the swapBuffers function.

None of these "solutions" are really appealing to me, is the thing I want impossible, or am I just missing some information?

tversteeg
  • 4,717
  • 10
  • 42
  • 77
  • It wouldn't seem like it should be possible, because having an endless loop will block the GUI, which you don't want. I believe the GTK way is an elegant way to achieve the purpose of using the GtkGlArea. – oldtechaa May 19 '16 at 17:29
  • @oldtechaa I agree with you that the GTK way is a more elegant way, unfortunately that's not possible for me. For the rest of the GUI I already have a endless loop without blocking the GUI (as shown in the edit I made). I can't change this setup. – tversteeg May 20 '16 at 14:26
  • I hope I understand your goal, but couldn't you do it the GTK way, then also call your render function from your loop when you need to redraw? – oldtechaa May 20 '16 at 14:32
  • @oldtechaa I wish I could do that, but I really have to stick to the format as described in the post – tversteeg May 21 '16 at 16:34
  • I'm saying to use your format, but also set up your own `realize` and `render` functions, which you can then call from inside your loop. Really, if you still can't do that, then you probably should be using multiple threads. [Here](https://stackoverflow.com/questions/30607429/gtk3-and-multithreading-replacing-deprecated-functions) is one good discussion of multithreading; I'm sure you'll find plenty more if you want to go that route. – oldtechaa May 21 '16 at 22:56

0 Answers0