2016-08-19 9 views
1

Ich habe eine Anwendung mit XCB und openGL. Zu Beginn wähle ich eine Framebuffer-Konfiguration mit den folgenden Attributen:GLX Animation langsamer als erwartet

const int attributes[] = {GLX_BUFFER_SIZE, 32, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, True, GLX_RENDER_TYPE, GLX_RGBA_BIT, None}; 
fb_configs = glXChooseFBConfig(display, screen_index, attributes, &fb_configs_count); 

Ich betreiben eine einfache Animation, die angeblich eine feste Dauer (1 s) dauern, aber es auf dem Bildschirm dauert viel länger, zeige (ca. 5 s). Nach dem Hinzufügen von Protokollen, um den Wert des Fortschritts anzuzeigen, fand ich heraus, dass die tatsächliche Schleife nur 1s dauert.

struct timeval start; // start time of the animation 
gettimeofday(&start, 0); 

while (1) 
{ 
    double progress = timer_progress(&start); 
    if (progress > 1.0) 
     break; // end the animation 

    draw(progress); 
    glXSwapBuffers(display, drawable); 

    xcb_generic_event_t *event = xcb_poll_for_event(connection); 
    if (!event) 
    { 
     usleep(1000); 
     continue; 
    } 

    switch (event->response_type & ~0x80) 
    { 
    case XCB_EXPOSE: 
    default: 
     free(event); 
     continue; 
    } 
} 

Ich bin nicht sicher, was wirklich los ist. Ich nehme an, dass bei jeder Iteration glXSwapBuffers() die OpenGL-Befehle für das Zeichnen in die Warteschlange gestellt werden und die meisten davon noch ausgeführt werden müssen, wenn die Schleife vorbei ist.

Die Optimierung des Parameters usleep() hat keinen anderen Effekt, als die Animation weniger weich zu machen oder die Animation viel langsamer zu machen. Das Problem verschwindet, wenn ich zu einer einzelnen Pufferung umschalte (aber ich bekomme die Probleme, die mit einer einzelnen Pufferung verbunden sind).

Es scheint, dass ich etwas nicht richtig mache, aber ich habe keine Ahnung was.

Antwort

2

Das genaue Timing-Verhalten von glXSwapBuffers bleibt für jede Implementierung offen. NVidia und fglrx entscheiden sich dafür, glXSwapBuffers bis V-Sync zu blockieren (wenn V-Sync aktiviert ist), entscheiden sich Mesa und Intel dafür, sofort zurückzukehren und beim nächsten Aufruf zu blockieren, der nicht mehr in die Befehlswarteschlange passen würde Puffer vor V-Sync werden hochgehalten.

Wenn Ihr Wunsch jedoch eine genaue Länge für Ihre Animation ist, dann wird eine Schleife mit einer festen Anzahl von Frames und die Durchführung von Verzögerungen nicht funktionieren. Stattdessen sollten Sie so schnell wie möglich neu zeichnen (und Verzögerungen verwenden, um Ihre Zeichenrate zu begrenzen). Die Animation sollte um die tatsächliche Zeit, die zwischen den tatsächlichen Zeichenwiederholungen anstelle eines festen Zeitschritts verstrichen ist, fortgeschritten sein (dies steht im Gegensatz zu Spielschleifen, die tatsächlich einen festen Zeitschritt verwenden sollten, wenn auch mit einer viel schnelleren Geschwindigkeit als das Zeichnen).

Schließlich müssen Sie nicht verwenden gettimeofday für die Steuerung von Animationen. gettimeofday meldet die Wanduhrzeit, die springen, verlangsamen oder hochlaufen oder sogar rückwärts laufen kann. Verwenden Sie stattdessen hochpräzise Timer (clock_gettime(CLOCK_MONOTONIC, …)).

+0

Ich verwende Verzögerungen nur, um die Ziehgeschwindigkeit zu begrenzen. 'timer_progress()' gibt die Zeit zurück, die seit 'start' vergangen ist und' draw() 'verwendet diesen Wert. – martinkunev

Verwandte Themen