Как использовать 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();
}

Анимация обновляется как положено, но рамка окна не рисуется, и окно не реагирует на события.


person smokris    schedule 24.09.2012    source источник
comment
GLFW дает вам свободу управлять циклом обработки событий; вы отбросили эту свободу, сделав ее циклом. Вы не можете просто извергнуть некоторый код в libdispatch и ожидать, что все будет работать. Вы должны думать о том, что вы пытаетесь сделать. Но поскольку вы не сказали, чего вы пытаетесь достичь (помимо совместного использования OpenGL и libdispatch), мы не можем вам помочь. Что именно вы пытаетесь сделать с libdispatch и OpenGL?   -  person Nicol Bolas    schedule 24.09.2012
comment
Это не совсем проясняет ситуацию. Вы хотите, чтобы другие вещи были отправлены, пока это происходит? Как вы распределяете по потокам? И Т. Д.   -  person Nicol Bolas    schedule 24.09.2012
comment
Общая архитектура приложения слишком сложна, чтобы уложиться в 600 символов, которые у меня есть здесь, но в основном: у меня есть некоторый код, который выполняет сложные вычисления и обновления нечасто по сравнению с вертикальным обновлением. В конечном итоге я хотел бы, чтобы этот код, когда он будет выполнен с набором вычислений, поставил в очередь блок, который рисует новый контент в контексте GL, меняет местами двойной буфер, а затем возвращается. И я хотел бы, чтобы окно тем временем обрабатывало события (между тем, когда блоки перерисовки ставятся в очередь). Все это уже отлично работает, за исключением бита событий обработки окна.   -  person smokris    schedule 24.09.2012
comment
Мой вопрос заключался в попытке свести проблему к простейшей форме, которая демонстрировала проблему. Возможно, это было слишком просто, чтобы быть полезным. Я просто заменил вопрос, основываясь на вашем совете.   -  person smokris    schedule 24.09.2012


Ответы (1)


Копаясь в исходниках GLFW, я думаю, что нашел проблему: цикл выполнения окна Cocoa, созданный GLFW, должен выполняться из потока 0, но GLFW не гарантирует, что _glfwPlatformPollEvents() произойдет в потоке 0. (Идентичные симптомы были зарегистрированы в этот вопрос о выполнении Cocoa GUI в потоке, отличном от 0 .)

Обходной путь — использовать тот же закрытый интерфейс, который CoreFoundation использует для обработки основной очереди libdispatch из файла CFRunLoop.

Если я заменю вызов dispatch_main() в приведенном выше коде следующим:

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

... работает как положено — рамка окна рисуется, а окно обрабатывает события.


Пытаясь исправить эту хакерскую ситуацию, я:

person smokris    schedule 24.09.2012