c - 手动控制 GTK 小部件重绘滴答率

标签 c opengl gtk gtk3

出于测试目的,我真的希望能够手动控制 GTK3 应用程序的帧刷新率。放慢速度很容易,我只是在渲染函数中 sleep 。不过,我能达到的最大帧速率是显示器的刷新率 60Hz。

我发现我可以使用 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
}

最佳答案

我发现了一个强制立即重新绘制的技巧:

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。

我这样做还没有遇到任何问题,但这似乎适用于包含多个 GtkWidget 的窗口。我还没有尝试过重叠的小部件,但我怀疑这里唯一的解决方案是重新绘制任何重叠的小部件。

关于c - 手动控制 GTK 小部件重绘滴答率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34497652/

相关文章:

c - 下载GTK之后,为什么我的编译器给我这些错误?

Javascript GTK 绑定(bind)

c - 关于如何对这一行进行编程的建议

c - 从 C 文件中读取数字

c++ - 如何在 OpenGL 中使用 vector 和结构上传顶点数据?

c++ - 即使 QFilterKey 匹配,QRenderPassFilter 也会隐藏平面网格

c# - OSx 单声道 gtk Hello World 。 Gtk.Container 抛出异常

c - 尝试在 C 中打印 ascii 表示

c - Slab缓存分配没有预定义函数的结构堆栈

c++ - glDrawArrays 奇怪地绘制数组