如何使用 GLFW 轮询 libdispatch 块中的事件


关于

如何用 libdispatch 使用 GLUT 的答案?,我现在改用 GLFW —

以下代码设置一个窗口,设置一个计时器来轮询事件,并随着时间的推移对呈现更新进行排队:

#include <dispatch/dispatch.h>
#include <GL/glfw.h>
float t=0;
int main(void)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        glfwInit();
        glfwDisable(GLFW_AUTO_POLL_EVENTS);
        glfwOpenWindow(320,200,8,8,8,8,8,0,GLFW_WINDOW);
    });
    // Periodically process window events --- this isn't working.
    dispatch_source_t windowEventTimer;
    windowEventTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    uint64_t nanoseconds = 100 * NSEC_PER_MSEC;
    dispatch_source_set_timer(windowEventTimer, dispatch_time(DISPATCH_TIME_NOW, nanoseconds), nanoseconds, 0);
    dispatch_source_set_event_handler(windowEventTimer, ^{
        glfwPollEvents();
    });
    dispatch_resume(windowEventTimer);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(int i=0;i<200;++i)
        {
            // Enqueue a rendering update.
            dispatch_async(dispatch_get_main_queue(), ^{
                glClearColor (0.2f, 0.2f, 0.4f, 1.0f);
                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glColor3f (1.0, 0.7, 0.7); 
                glBegin( GL_LINES );
                    glVertex3f(0,0,0);
                    glVertex3f(t+=0.02,.1,0);
                glEnd();
                glfwSwapBuffers();
            });
            // Wait a bit, to simulate complex calculations.
            sleep(1);
        }
    });
    dispatch_main();
}

动画按预期更新,但窗口框架不绘制,并且窗口不响应事件。

挖掘 GLFW 源代码,我想我发现了问题:GLFW 创建的 Cocoa 窗口的运行循环需要从线程 0 执行,但 GLFW 不能确保_glfwPlatformPollEvents()发生在线程 0 上。 (关于在 0 以外的线程上执行 Cocoa GUI 的此问题报告了相同的症状。

解决方法是使用 CoreFoundation 用于从CFRunLoop内部处理主 libdispatch 队列的相同私有接口。

如果我用这个替换上面代码中的dispatch_main()调用:

while(1)
{
    _dispatch_main_queue_callback_4CF(NULL);
    usleep(10000);
}

。它按预期工作 — 窗口框架绘制,窗口处理事件。


为了改善这种令人讨厌的情况,我:

  • 提交功能请求以使其成为公共 libdispatch API
  • 请求更新 GLFW 文档以提及 Mac 事件需要哪个线程。

最新更新