C 在GtkGLArea信号之外调用OpenGL函数
我正在尝试创建一个库,在这个库中,可以使用GTK3创建OpenGL上下文,该上下文可以自动渲染,也可以使用1个函数调用(类似于交换缓冲区函数)。我正在查看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
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
跟踪调用绘图信号的时间,以便围绕该信号调用相应的OpenGL函数GdkGLContext
- 找到一种忽略整个GTK3部分的方法,并尝试使用底层Xlib函数通过X11(根本不可移植)创建OpenGL上下文
- 使用带有线程的邪恶黑客和
和setjmp
来输入和退出swapBuffers函数的信号longjmp
这些“解决方案”中没有一个真正吸引我,我想要的是不可能的,还是我只是缺少了一些信息?这似乎不应该是可能的,因为有一个无休止的循环会阻塞GUI,这是你不想要的。我相信GTK方式是达到使用GtkGlArea目的的一种优雅方式。@oldtechaa我同意你的观点,GTK方式是一种更优雅的方式,不幸的是,这对我来说是不可能的。对于GUI的其余部分,我已经有了一个无止境的循环,而不会阻塞GUI(如我所做的编辑所示)。我无法更改此设置。我希望我理解你的目标,但你不能用GTK的方式,然后在需要重新绘制时从循环中调用渲染函数吗?@oldtechaa我希望我可以这样做,但我真的必须坚持帖子中描述的格式,我要使用你的格式,还可以设置自己的
realize
和render
函数,然后可以从循环内部调用这些函数。实际上,如果您仍然不能做到这一点,那么您可能应该使用多个线程。是对多线程的一个很好的讨论;如果你想走那条路,我相信你会找到更多的。