如何获取有关OpenGL上下文的尽可能多的信息

您好世界,感谢您抽出宝贵时间阅读本文!

我正在用GTK2 / 3 + OpenGL编写一个程序,我运行了两个版本的程序:

  • (a)GTK + 2 + GtkGlext扩展 – >效果很好!
  • (b)GTK + 3 + LibX11 – >工作正常!

一切看起来都很好,除了(a)中的渲染明显快于(b)中的渲染……而且我不知道为什么。 以下是用于创建OpenGL上下文的代码部分的一些示例:

  • (一个)

    // To create the context, and the associated GtkWidget GdkGLConfig * glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); GtkWidget * drawing_area = gtk_drawing_area_new (); gtk_widget_set_gl_capability (drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); g_signal_connect (G_OBJECT (drawing_area), "expose-event", G_CALLBACK (on_expose), data); // And later on to draw using the OpenGL context: gboolean on_expose (GtkWidget * widg, GdkEvent * event, gpointer data) { GdkGLContext * glcontext = gtk_widget_get_gl_context (widg); GdkGLDrawable * gldrawable = gtk_widget_get_gl_drawable (widg); if (gdk_gl_drawable_gl_begin (gldrawable, glcontext)) { // OpenGL instructions to draw here ! gdk_gl_drawable_swap_buffers (view -> gldrawable); gdk_gl_drawable_gl_end (view -> gldrawable); } return TRUE; } 
  • (b)中

     // To create the GtkWidget GtkWidget * drawing_area = gtk_drawing_area_new (); // Next line is required to avoid background flickering gtk_widget_set_double_buffered (drawing_area, FALSE); g_signal_connect (G_OBJECT (drawing_area), "realize", G_CALLBACK(on_realize), data); g_signal_connect (G_OBJECT (drawing_area), "draw", G_CALLBACK(on_expose), data); // To create the OpenGL context GLXContext glcontext; G_MODULE_EXPORT void on_realize (GtkWidget * widg, gpointer data) { GdkWindow * xwin = gtk_widget_get_window (widg); GLint attr_list[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None}; XVisualInfo * visualinfo = glXChooseVisual (GDK_WINDOW_XDISPLAY (xwin), gdk_screen_get_number (gdk_window_get_screen (xwin)), attr_list); glcontext = glXCreateContext (GDK_WINDOW_XDISPLAY (xwin), visualinfo, NULL, TRUE); xfree (visualinfo); } // To Draw using the OpenGL context G_MODULE_EXPORT gboolean on_expose (GtkWidget * widg, cairo_t * cr, gpointer data) { GdkWindow * win = gtk_widget_get_window (widg); if (glXMakeCurrent (GDK_WINDOW_XDISPLAY (xwin), GDK_WINDOW_XID (xwin), glcontext)) { // OpenGL instructions to draw here ! glXSwapBuffers (GDK_WINDOW_XDISPLAY (win), GDK_WINDOW_XID (win)); } return TRUE; } 

试图理解为什么(a)比(b)下载GtkGLext库的源代码更快,读取它们,并发现命令与调用X11完全相同。 现在我的想法是(b)中的以下行

 gtk_widget_set_double_buffered (drawing_area, FALSE); 

搞乱渲染,然后我无能为力……或者OpenGL上下文之间存在差异,这可能解释了我注意到的行为,如果我按照这个方向进行跟进,我需要比较两者尽可能详细的上下文……到目前为止,我选择了一些似乎是获取某些信息的最常用方法:

 OpenGL Version : 3.0 Mesa 12.0.3 OpenGL Vendor : nouveau OpenGL Renderer : Gallium 0.4 on NVCF OpenGL Shading Version : 1.30 Color Bits (R,G,B,A) : 8, 8, 8, 0 Depth Bits : 24 Stencil Bits : 0 Max. Lights Allowed : 8 Max. Texture Size : 16384 Max. Clipping Planes : 8 Max. Modelview Matrix Stacks : 32 Max. Projection Matrix Stacks : 32 Max. Attribute Stacks : 16 Max. Texture Stacks : 10 Total number of OpenGL Extensions : 227 Extensions list: N°1 : GL_AMD_conservative_depth N°2 : GL_AMD_draw_buffers_blend ... 

但是这两种背景都给出了完全相同的信息……

感谢您已经到达那里……现在我的问题是:

有没有办法输出尽可能多的关于OpenGL上下文的信息,以及如何?

我欢迎任何其他关于我在做什么的建议!

S.

PS:我正在使用GtkGLArea Widget for GTK3,但是如上所述,我还没有。

[编辑]一些OpenGL指令:

 // OpenGL instructions to draw here ! glLoadIdentity (); glPushMatrix (); // d is the depth ... calculated somewhere else glTranslated (0.0, 0.0, -d); // Skipping the rotation part for clarity, I am using a quaternion rotate_camera (); // r, g, b and a are GLFloat values glClearColor (r,g,b,a); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDisable (GL_LIGHTING); int i; // nbds is the number of chemical bonds GLfloat * lineVertices; // This is "roughly" what I do to draw chemical bonds, to give you an idea for (i=0; i<nbds;i++) { // get_bonds (i) gives backs a 6 float array lineVertices = get_bonds(i); glPushMatrix(); glLineWidth (1.0); glEnableClientState (GL_VERTEX_ARRAY); glVertexPointer (3, GL_FLOAT, 0, lineVertices); glDrawArrays (GL_LINES, 0, 2); glDisableClientState (GL_VERTEX_ARRAY); glPopMatrix(); } glEnable (GL_LIGHTING); 

[/编辑]

感谢您的建议,“ApiTrace”的想法令人惊叹,我不仅发现了一个很棒的工具,而且还帮助我找到了一些关于我的问题的线索。 使用ApiTrace:

  1. 我检查了我的程序的两个版本(a)和(b)都使用了完全相同的OpenGL上下文…具有很好的细节和易用性我必须添加…因此错误不是来自上下文初始化。
  2. 我发现在版本(b)中,渲染比在版本(a)中更频繁地完成5次…对于同一帧,意味着5次!

我的目标唯一合乎逻辑的结论是版本2和3之间GTK +信号的差异,在我的程序版本(a)中我使用了expose-event而在版本(b)中我使用了draw事件(新信号用于GtkDrawingArea )…显然,此时版本2和版本3之间GTK +库的行为存在一些差异……我正在努力寻找解决方法…我将编辑此答案以提供更多信息。

[编辑]你好世界,回答我自己的问题,希望能帮助别人避免我犯的同样错误。 要重新绘制我正在使用的OpenGL窗口:

 void update (GtkWidget * plot) { gtk_widget_hide (plot); gtw_widget_show (plot); } 

相反,我应该一直在使用:

 gtk_widget_queue_draw (plot); 

所有问题都解决了![/编辑]