使用GdkFrameClock将GtkDrawingArea与屏幕刷新率同步

use*_*ser 4 gtk screen vsync gdk gtk3

背景

我想使用来将小部件的更新同步到屏幕刷新率GdkFrameClock。这是为了在LCD屏幕之外进行视觉刺激响应测量(因此,对于信号的纯度,需要尽可能接近精确的帧同步)。

我已经阅读了该类的文档,但是范围有限。我缺少对GdkFrameClock在GTK世界中的位置的一些总体了解。仔细阅读GitHub上GTK源代码树中的演示对我来说是徒劳的。

假设可以,如何使用(假设开罗)GdkFrameClock的屏幕表示更新GtkDrawingArea与屏幕刷新率同步?

如果不能,目的是GdkFrameClock什么?

Tri*_*dle 5

我没有GdkFrameClock生气,只是做了一些测试,但以下内容似乎很容易并且对我有用:

  1. 调用gtk_widget_add_tick_callback(),传递要在每次刷新时运行的函数
  2. 大约每秒60次(或适合您的系统),您的回调将被调用
  3. 完成后,从回调中调用gtk_widget_remove_tick_callback()或返回FALSE以停止接收更新。

在第2步中,您将传递GdkFrameClock使用中的消息,因此可以调用gdk_frame_clock_get_frame_time()以获得确切的帧时间戳,或使用gdk_frame_clock_get_timings()GdkFrameTimingsAPI进行更多有趣的事情。

下面的Vala代码(很容易转换为D,我敢肯定:-)证明了这一点:

private static bool on_frame_tick(Gtk.Widget widget, Gdk.FrameClock frame_clock)
{
    print("Got frame tick with timestamp %lld\n", frame_clock.get_frame_time());

    return true; // Keep going
}

void main(string[] args)
{
    Gtk.init(ref args);

    var w = new Gtk.Window(Gtk.WindowType.TOPLEVEL);
    w.add_tick_callback(on_frame_tick, null);
    w.show_all();

    Gtk.main();
}
Run Code Online (Sandbox Code Playgroud)

请注意,根据docs,您需要在处理程序中调用gtk_widget_queue_draw()(或queue_draw_area())以获取它,以使GTK实际执行重绘。这将依次调用draw()相关小部件的功能。

因此,我要做的是将帧时序信息保存在我的tick回调中,调用queue_redraw(),然后在draw()实现中使用保存的时序信息GtkDrawingArea