C 在GtkGLArea信号之外调用OpenGL函数

C 在GtkGLArea信号之外调用OpenGL函数,c,opengl,gtk3,cairo,gdk,C,Opengl,Gtk3,Cairo,Gdk,我正在尝试创建一个库,在这个库中,可以使用GTK3创建OpenGL上下文,该上下文可以自动渲染,也可以使用1个函数调用(类似于交换缓冲区函数)。我正在查看GtkGLArea的源代码,它的执行顺序如下: 使用超类GtkWidget创建一个新的GtkGLArea 捕获超类的realize信号时,会出现GdkGLContext 创建并向用户提供实现信号。用户应该将初始OpenGL函数放入传递给该信号的函数中 超类的draw信号也被捕获,一些OpenGL初始化代码被调用以绑定帧缓冲区(或纹理)和rend

我正在尝试创建一个库,在这个库中,可以使用GTK3创建OpenGL上下文,该上下文可以自动渲染,也可以使用1个函数调用(类似于交换缓冲区函数)。我正在查看
GtkGLArea
的源代码,它的执行顺序如下:

  • 使用超类
    GtkWidget
    创建一个新的
    GtkGLArea
  • 捕获超类的
    realize
    信号时,会出现
    GdkGLContext
    创建并向用户提供
    实现
    信号。用户应该将初始OpenGL函数放入传递给该信号的函数中
  • 超类的
    draw
    信号也被捕获,一些OpenGL初始化代码被调用以绑定帧缓冲区(或纹理)和renderbuffer。如果缓冲区不存在,则创建缓冲区。在这之后,
    渲染
    信号被给出,用户应该将渲染OpenGL代码放在哪里。最后,调用
    gdk\u cairo\u draw\u from\u gl
    函数,在通过
    draw
    信号的超类的cairo上下文上绘制renderbuffer(或纹理)
  • 对于用户来说,基本上可以归结为:

    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
    
    但那不是我想要的,我想要的是:

    // 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();
    }
    
    实现这一目标的最佳方式是什么?我通过模拟围绕信号调用的函数,并使用在取自
    GtkDrawingArea
    GdkWindow
    上创建的
    GdkGLContext
    尝试了这一点(未成功)

    以下是我现在可以想象的解决方案:

    • 创建一个自定义GTK3类,扩展
      GtkWidget
      并使用
      GdkGLContext
      跟踪调用绘图信号的时间,以便围绕该信号调用相应的OpenGL函数
    • 找到一种忽略整个GTK3部分的方法,并尝试使用底层Xlib函数通过X11(根本不可移植)创建OpenGL上下文
    • 使用带有线程的邪恶黑客和
      setjmp
      longjmp
      来输入和退出swapBuffers函数的信号

    这些“解决方案”中没有一个真正吸引我,我想要的是不可能的,还是我只是缺少了一些信息?

    这似乎不应该是可能的,因为有一个无休止的循环会阻塞GUI,这是你不想要的。我相信GTK方式是达到使用GtkGlArea目的的一种优雅方式。@oldtechaa我同意你的观点,GTK方式是一种更优雅的方式,不幸的是,这对我来说是不可能的。对于GUI的其余部分,我已经有了一个无止境的循环,而不会阻塞GUI(如我所做的编辑所示)。我无法更改此设置。我希望我理解你的目标,但你不能用GTK的方式,然后在需要重新绘制时从循环中调用渲染函数吗?@oldtechaa我希望我可以这样做,但我真的必须坚持帖子中描述的格式,我要使用你的格式,还可以设置自己的
    realize
    render
    函数,然后可以从循环内部调用这些函数。实际上,如果您仍然不能做到这一点,那么您可能应该使用多个线程。是对多线程的一个很好的讨论;如果你想走那条路,我相信你会找到更多的。