2016-08-19 22 views
1

XCB 및 OpenGL을 사용하는 응용 프로그램이 있습니다. 처음에는, 나는 다음과 같은 속성을 가지는 프레임 버퍼 구성을 선택합니다 GLX 애니메이션이 예상보다 느립니다.

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

내가 고정 된 시간 (초)을 지속하도록되어 간단한 애니메이션을 실행하지만, 화면에 보여주는 것은 5 초에 대해 (더 오래 걸립니다). 로그를 추가하여 진행의 가치를 보여 주면 실제 루프가 1 초만 지속된다는 것을 알게되었습니다.

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

무엇이 실제로 일어나고 있는지 잘 모르겠습니다. 각 반복마다 가정합니다. glXSwapBuffers()은 드로잉을 위해 OpenGL 명령을 대기열에 추가하고 대부분 루프가 끝나면 아직 실행되지 않습니다.

usleep()의 매개 변수를 조정하면 애니메이션이 부드럽게 처리되지 않거나 애니메이션이 훨씬 느려지는 것 외에는 아무런 효과가 없습니다. 단일 버퍼링으로 전환하면 문제가 사라집니다 (그러나 단일 버퍼링과 관련된 문제가 발생합니다).

내가 제대로하고있는 것 같지 않지만 무슨 생각을 모르겠다.

답변

2

glXSwapBuffers의 정확한 타이밍 동작은 각 구현에 대해 열려 있습니다. NVIDIA와 fglrx는 V-Sync (V-Sync가 활성화 된 경우)까지 glXSwapBuffers를 차단하도록 선택하면 Mesa와 Intel은 명령 대기열에 더 이상 적합하지 않은 다음 호출에서 차단하여 차단합니다. V 싱크가 유지되기 전에 버퍼에 저장됩니다.

그러나 애니메이션의 정확한 길이가 원하는 경우 프레임을 일정하게하고 지연을 수행하는 루프 은 작동하지 않습니다.. 대신 가능한 한 빨리 다시 그리기해야하며 드로잉 속도를 제한하기 위해 지연 만 사용해야합니다. 애니메이션은 고정 된 타임 스텝 대신 실제 그리기 반복 사이에 경과 된 실제 시간만큼 진행되어야합니다 (이는 그림보다 훨씬 빠른 속도이지만 고정 된 시간 단계를 사용해야하는 게임 루프와는 대조적입니다).

마지막으로 중요한 것은 입니다.은 애니메이션 제어에 gettimeofday을 사용하면 안됩니다. gettimeofday은 벽 시계 시간을보고합니다.이 시간은 점프하거나, 천천히 또는 뒤로 움직일 수 있습니다. 대신 고정밀 타이머를 사용하십시오 (clock_gettime(CLOCK_MONOTONIC, …)).

+0

지연을 사용하여 드로잉 속도를 제한하고 있습니다. 'timer_progress()'는'start'와'draw()'가 그 값을 사용하고 나서 경과 된 시간을 반환합니다. – martinkunev