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



您好,感谢您花时间阅读本文!

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

  • (a) GTK+2 + gtkext扩展->工作很棒!
  • (b) GTK+3 + LibX11 ->工作正常!

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

  • (a)

    // 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)快,我下载了gtkgleext库的源代码,阅读它们,并发现这些命令与对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:我正在为GTK3使用GtkGLArea小部件,但正如这里所说的,我还没有。

[EDIT]一些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上下文…我必须补充的是……因此错误不是来自context初始化。
  2. 我发现在版本(b)中渲染完成了5次,比版本(a)更频繁…即同一帧5次!

我唯一的逻辑结论是版本2和3之间的GTK+信号的差异,在我的程序的版本(a)中,我使用expose-event,而在版本(b)中,我使用draw事件(GtkDrawingArea的新信号)…显然,GTK+库在版本2和3之间的行为有一些不同……我正在想办法绕过它……我将编辑这个答案以提供进一步的信息。

[编辑]Hello world,回答我自己的问题,希望能帮助别人避免和我犯同样的错误。为了重新绘制我的OpenGL窗口,我使用:

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

我应该用:

gtk_widget_queue_draw (plot);

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

最新更新