2015-12-28 105 views
0

出于测试目的,我真的很想能够手动控制我的GTK3应用程序的帧刷新率。慢下来很容易,我只是睡在渲染功能。但是,我可以实现的最大帧速率是我的显示器60Hz的刷新率。手动控制GTK小部件重绘打勾速率

我发现,我可以添加一个不封顶更新插槽插使用gdk_threads_add_idle主循环,但即使我称之为gtk_gl_area_queue_render这个函数实际渲染功能只能运行在我的显示器的刷新率内。

有没有办法强制重新渲染是“立即”的要求?我试过手动调用渲染槽,这会导致重新渲染函数立即被调用,但它根本不会更新屏幕。

void update_auto(gpointer user_data) 
{ 
    // ... do some update stuff 
    // somehow get the appropriate GtkGLArea from user_data 
    GtkGLArea* area = get_area(user_data); 
    gtk_gl_area_queue_render(area); 
    // capped at 60Hz 
} 

void update_manual(gpointer user_data) 
{ 
    // ... do some update stuff 
    // somehow get the appropriate GtkGLArea from user_data 
    GtkGLArea* area = get_area(user_data); 
    gtk_gl_area_make_current(area); 
    render(area,gtk_gl_area_get_context(area), user_data); 
    // even though render was called, screen never updates 
} 

void render(GtkGLArea* area, GdkGLContext* context, gpointer user_data) 
{ 
    // ... render 
} 

void setup_widget() 
{ 
    // ... some init stuff 
    // only one of these is used at a time 
#if TEST_FLAG == 0 
    gdk_threads_add_idle(update_manual, user_data); 
#elif TEST_FLAG == 1 
    gdk_threads_add_idle(update_auto, user_data); 
#elif TEST_FLAG == 2 
    gtk_widget_add_tick_callback((GtkWidget*) area, update_auto, user_data, NULL); 
#else 
    gtk_widget_add_tick_callback((GtkWidget*) area, update_manual, user_data, NULL); 
#endif 
} 
+0

渲染速度比显示器的刷新速度还要快吗? –

+0

我现在的一个原因是性能测试。我感兴趣的是渲染循环中的各种代码更改如何影响性能,我宁愿不必使用足够大的场景来显着减慢渲染循环。我也想调试一些不规则的框架口吃问题,在较大的场景发生。 – helloworld922

+0

也许渲染引擎*不会更快地刷新。我不知道这是否适用于LED/LCD显示器,但是旧的CRT刷新是在反激期完成的,以创建平滑的帧过渡。 –

回答

0

我发现一个黑客迫使立即重新抽签:

GtkGLArea扩展GtkWidget类,这样我就可以使用绘图功能立即重新绘制。

// inside update 
// get the proper clipping so we don't draw over other widgets 
GtkAllocation reg; 
gtk_widget_get_allocation((GtkWidget*)area, &reg); 
cairo_region_t *creg = cairo_region_create_rectangle(&reg); 
cairo_t *cr = gdk_cairo_create(gtk_widget_get_window((GtkWidget*)area)); 
gdk_cairo_region(cr, creg); 
cairo_clip(cr); 

gtk_widget_draw((GtkWidget*)area, cr); 
cairo_destroy(cr); 
cairo_region_destroy(creg); 

然后我就可以使用,如果需要,gdk_threads_add_idle函数会很乐意尽可能快地调用更新功能。

即使没有使用gdk_threads_add_idle,我已经注意到即使使用这种方法与gtk_widget_add_tick_callback也具有明显更一致的帧速率。在我注意到帧率在15/30/60 fps之间零星跳跃之前,似乎表明它缺少一两个重绘更新周期。这个问题现在已经完全消失了,我得到了一个近乎恒定的N fps,其中N被限制在60,适用于小场景。

我还没有遇到任何问题,但这样做,但这似乎与Windows不止包含一个单一的GtkWidget。我没有尝试重叠的小部件,但我怀疑这里唯一的解决方案是也重绘任何重叠的小部件。