2016-04-27 13 views
1

Мне интересно, могу ли я поймать событие vsync на экране любым файловым дескриптором и [select | опрос | Эволюция.Событие GLX Vsync

Обычно, если я прав, glXSwapBuffers() не блокирует процесс, так что я мог бы сделать что-то вроде:

int init() { 
    create epollfd; 
    add Xconnection number to it; 
    add some other fd like socket timer tty etc... 
    possibly add a vsync fd like dri/card0 or fb0 or other??? 
    return epollfd; 
} 

main() { 
    int run = 1; 
    int epollfd = init(); 

    while(run) { 
     epoll_wait(epollfd, ...) { 

     if(trigedfd = socket) { 
      do network computing; 
     } 

     if(trigedfd = timer) { 
      do physics computing; 
     } 

     if(trigedfd = tty) { 
      do electronic communications; 
     } 

     if(trigedfd = Xconnection number) { 
      switch(Xevent) { 
       case key event: 
        do key computing; 
       case mouse event: 
        do mouse computing; 
       case vsync???: 
        do GL computings; 
        glXSwapBuffers(); 
      } 
     } 

     if(trigedfd = dri/card0 or fb0 or other???) { 
      do GL computings; 
      glXSwapBuffers(); 
     } 
    } 
} 

Так что я мог тогда я мог бы аккуратный любое событие, независимо, когда VSync событие произойдет и избегайте эффекта разрыва в тот же момент, когда я использую только функцию рисования X и, возможно, GL для vsync.

Может ли libdrm помочь мне? тем более общий вопрос:

Так что же мне нужно использовать, чтобы поймать событие vsync и как сделать shure на этом fd, что событие, которое произошло, - это событие vsync?

+0

Обратите внимание, что я хочу сделать это monothreaded. Я мог бы сделать отдельный процесс, который будет действовать как сервер, к которому я мог бы подключиться, и отправить запрос «разбудить меня, когда произошел vsync», этот процесс может блокироваться на glFinish, а затем отправлять что-то через сокет или канал или что угодно, я бы избегайте этого. –

+0

Почему именно вы этого хотите? Это может быть случай [проблема XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? – davmac

+0

Я создаю свою собственную библиотеку/api, я хочу иметь только одну точку синхронизации для всех входящих событий процесса. –

ответ

1

Похоже, вы можете использовать API libdrm для просмотра событий vsync. См. this blog entry, и в частности this example code. Комментарий от кода объясняет, как это работает:

/* (...) 
* The DRM_MODE_PAGE_FLIP_EVENT flag tells drmModePageFlip() to send us a 
* page-flip event on the DRM-fd when the page-flip happened. The last argument 
* is a data-pointer that is returned with this event. 
* (...) 
*/ 

Вам нужно создать обработчик страниц флип событий, чтобы получить уведомление, когда происходит VSync, которая будет называться методом drmHandleEvent (от libdrm), который вам может вызывать, когда есть активность в дескрипторе файла drm.

Однако сопоставление всего этого с X-клиентом может оказаться трудным или невозможным. может быть в том, что вы можете открыть устройство drm самостоятельно и просто прослушать события vsync (не пытаясь установить режим и т. Д.), Но это также может оказаться невозможным. Код Соответствующий:

drmEventContext ev; 
memset(&ev, 0, sizeof(ev)); 
ev.version = DRM_EVENT_CONTEXT_VERSION; 
ev.page_flip_handler = modeset_page_flip_event; 

// When file descriptor input is available: 
drmHandleEvent(fd, &ev); 
// If above works, "modeset_page_flip_event" will be called on vertical refresh. 

Проблема заключается в том, что событие страницы флипа только кажется, генерируется, если вы на самом деле издали (буфер подкачку) запрос страницы флипа. Предположительно, это был бы X-сервер, который выдавал такие запросы, но даже не обязательно указывает, что он хочет получать уведомление, когда фактически происходит vsync (т. Е. Использует флаг DRM_MODE_PAGE_FLIP_EVENT).

Там также трудность открытия правильного устройства DRI (? /dev/dri/card0 или /dev/dri/card1 или ...)

Учитывая сложность/ненадежность/общая unworkability всех выше, самым простым решением является, вероятно,:

  1. Используйте отдельный поток, чтобы ждать vsync, используя стандартные вызовы GL. В соответствии с this page on the OpenGL wiki вы должны использовать glXSwapIntervalEXT(1), чтобы включить vsync, затем glXSwapBuffers и glFinish, чтобы убедиться, что на самом деле происходит вертикальное обратное прохождение.
  2. Затем сообщите основной теме, что произошла вертикальная обратная передача. Вы можете сделать это, отправив данные в канал или, в Linux, используйте eventfd.

Update:

Вы можете быть в состоянии использовать GLX_INTEL_swap_event extension:

Принято параметром glXSelectEvent и возвращается в параметре glXGetSelectedEvent:

GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000

Возврат в поле "своп полного" событие:

GLX_EXCHANGE_COMPLETE_INTEL 0x8180
GLX_COPY_COMPLETE_INTEL 0x8181
GLX_FLIP_COMPLETE_INTEL 0x8182

...

клиент может попросить, чтобы получить полный своп GLX события в окне. Когда событие получено, вызывающий может определить, какой тип свопа произошел, проверив поле event_type.

Это означает, что, если расширение поддерживается, то вы можете получить своп уведомление (которые соответствуют вертикальной развертке, если VSync включена) с помощью регулярного X событий, которые вы увидите на файловом дескрипторе соединения X.

+0

Я уже видел этот блог и код, я попытался запустить режим, как есть, он сказал мне: «drm device/dev/dri/card0 не поддерживает немые буферы». У меня только/dev/dri/card0. Я не пробовал больше на стороне drm на данный момент, мне было интересно, что это возможно с помощью расширений X11 ... –

+0

@LewisAnesa вам не нужны немые буферы. Вам вообще не нужно отображать буфер; вам просто нужно получать события (событие флип страницы). Единственный открытый вопрос: действительно ли эти события будут доставлены. – davmac

+0

Да, я продолжу эти исследования после работы (французский часовой пояс), возможно, активируя v-sync через glXSwapIntervalEXT (1), побуждает это событие доставляться устройством dri ..? Я не видел документов для libdrm, таких как документация xlib, если вы что-то видите, не стесняйтесь делиться. –