Как использовать GLFW для опроса событий в блоке libdispatch?
В продолжение ответа на вопрос Как использовать GLUT с libdispatch? Я сейчас использую 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();
}
Анимация обновляется, как и ожидалось, но рамка окна не прорисовывается, и окно не реагирует на события.
1 ответ
Пробираясь через источник GLFW, я думаю, что нашел проблему: runloop окна Какао, созданного GLFW, должен выполняться из потока 0, но GLFW не гарантирует, что _glfwPlatformPollEvents()
происходит в потоке 0. (По этому вопросу сообщалось об идентичных симптомах при выполнении графического интерфейса Какао в потоке, отличном от 0).
Обходной путь - использовать тот же закрытый интерфейс, который использует CoreFoundation для обработки основной очереди libdispatch изнутри CFRunLoop
,
Если я заменю dispatch_main()
позвоните в приведенный выше код с этим:
while(1)
{
_dispatch_main_queue_callback_4CF(NULL);
usleep(10000);
}
... работает как положено - оконная рамка рисует, а окно обрабатывает события.
Пытаясь улучшить эту хакерскую ситуацию, я: