2016-04-27 2 views
1

Je me demande si je pourrais attraper l'événement vsync écran par n'importe quel descripteur de fichier et [sélectionnez | sondage | l'épouser.GLX événement Vsync

Normalement, si je ne me trompe pas, glXSwapBuffers() ne bloque pas le processus pour que je puisse faire quelque chose comme:

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(); 
     } 
    } 
} 

Je pourrais alors je pourrais trig tout état de cause quel que soit lorsque l'événement se produit et vsync évitez en même temps l'effet de déchirure dans le cas où j'utilise uniquement la fonction de dessin X et éventuellement GL pour vsync.

Est-ce que libdrm pouvait m'aider? la question plus générale est:

Alors, quel fd dois-je utiliser pour attraper l'événement vsync et comment faire en sorte que shur sur ce fd que l'événement qui s'est passé est un événement vsync?

+0

Notez que je veux le rendre monothreaded. Je pourrais faire un processus séparé qui agit comme un serveur auquel je pourrais me connecter et envoyer une requête "réveille-moi quand vsync s'est passé", ce processus pourrait bloquer un glfinish et ensuite envoyer quelque chose via une socket ou pipe ou autre, je le ferais évitez-le aussi. –

+0

Pourquoi voulez-vous exactement cela? Serait-ce un cas de [le problème XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? – davmac

+0

Je crée ma propre bibliothèque/API, je veux avoir un seul point de synchronisation pour tous les événements d'un processus. –

Répondre

1

Il semble que vous puissiez utiliser l'API libdrm pour voir les événements vsync. Voir this blog entry, et en particulier this example code. Un commentaire du code explique comment cela fonctionne:

/* (...) 
* 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. 
* (...) 
*/ 

Vous devez configurer un gestionnaire d'événements en page flip pour être informé lorsqu'un vsync se produit, qui sera appelée par la méthode drmHandleEvent (à partir libdrm) que vous peut appeler quand il y a une activité sur le descripteur de fichier drm. Toutefois, la mise en correspondance de tout cela dans un client X peut s'avérer difficile ou impossible. Il peut être que vous pouvez ouvrir le périphérique drm vous-même et juste écouter les événements vsync (sans tenter de définir le mode etc), mais cela pourrait également s'avérer impossible. Code Pertinent:

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. 

Le problème est qu'un événement page flip ne semble être générée si vous avez effectivement émis une demande de page flip (échange de tampon). On peut supposer que ce serait le serveur X qui a émis de telles demandes, mais il ne signale même pas nécessairement qu'il veut être averti lorsque la séquence de synchronisation (vsync) se produit réellement (c'est-à-dire utilise le drapeau DRM_MODE_PAGE_FLIP_EVENT).

Il y a aussi la difficulté d'ouvrir le dispositif de DRI correct (? /dev/dri/card0 ou /dev/dri/card1 ou ...)

Compte tenu de la difficulté/manque de fiabilité/inapplicabilité général de tout ce qui précède, la solution la plus simple est probablement:

  1. Utilisez un thread séparé pour attendre vsync en utilisant les appels GL standards. Selon this page on the OpenGL wiki vous devez utiliser glXSwapIntervalEXT(1) pour activer vsync, puis glXSwapBuffers et glFinish pour vous assurer que la retrace verticale se produit réellement.
  2. Ensuite, informez le thread principal que la retrace verticale s'est produite. Vous pouvez le faire en envoyant des données à un canal ou, sur Linux, utilisez un eventfd.

Mise à jour:

Vous pouvez être en mesure d'utiliser le GLX_INTEL_swap_event extension:

Accepté par le paramètre de glXSelectEvent et est retourné dans le paramètre de glXGetSelectedEvent:

GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000

Retourné dans le domaine d'un "échange complet" événement:

GLX_EXCHANGE_COMPLETE_INTEL 0x8180
GLX_COPY_COMPLETE_INTEL 0x8181
GLX_FLIP_COMPLETE_INTEL 0x8182

...

Un client peut demander à recevoir échange complet GLX événements sur une fenêtre. Lorsqu'un événement est reçu, l'appelant peut déterminer le type d'échange en vérifiant le champ event_type.

Cela signifie que, si l'extension est pris en charge, vous pouvez recevoir des notifications d'échange (qui correspondent à retraçage vertical si vsync est activé) par l'intermédiaire d'événements réguliers X, que vous voyez sur le descripteur de fichier de connexion X.

+0

J'ai déjà vu ce blog et ce code, j'ai essayé de lancer des modeset tels quels, il m'a dit "drm device/dev/dri/card0 ne supporte pas les buffers stupides". J'ai seulement/dev/dri/card0. Je n'ai pas encore essayé le côté drm pour le moment, je me demandais si c'était possible via les extensions X11 ... –

+0

@LewisAnesa vous n'avez pas besoin de tampons stupides. Vous n'avez pas besoin de mapper un tampon du tout; vous avez juste besoin de recevoir des événements (événement page flip). La seule question ouverte est de savoir si ces événements seront effectivement livrés. – davmac

+0

Oui, je vais continuer ces recherches après le travail (fuseau horaire français), peut-être activer v-sync via glXSwapIntervalEXT (1) induit ces événements à être livrés par dri device ..? Je n'ai vu aucun document pour libdrm comme la documentation xlib, si vous voyez quelque chose, n'hésitez pas à partager. –