glXSwapbuffers, похоже, не поменялись местами (?)

Моя ситуация такая. Я написал код, который проверил группу окон, если их содержимое можно поменять местами или нет (то есть все перерисовки успешно выполняются в указанном окне и всех его дочерних элементах после изменения размера). Если условия будут выполнены, я выполнил вызов glXSwapBuffers для указанного окна и всех его дочерних элементов. Моя цель состояла в том, чтобы создать систему мерцания при изменении размера. Дочерние окна были расположены в виде плитки и не перекрываются. Между ними появилась функция для работы. Моя проблема, однако, возникает с родителем. Когда-то во время изменения размера его содержимое мерцает. Пока что это то, что я реализовал.

  1. Все события, такие как ConfigureNotify или Expose, уже сжаты по мере необходимости.
  2. Окно background_pixmap установлено как None.
  3. Понимание того, что всякий раз, когда генерируется событие Expose, фоновое содержимое окна теряется. После каждой перерисовки я сохраняю копию готовой перерисовки в своем собственном выделенном буфере. (Ни растровое изображение, ни fbo, но пока этого достаточно.)

Моя логика для каждого вызова glXSwapBuffers() заключается в следующем.

void window_swap( Window *win ) {
    Window *child;
    if ( win ) {
        for ( child=win->child; child; child=child->next )
            window_swap( child );

        if ( isValidForSwap( win ) ) {
            glXMakeCurrent( dpy, win->drawable, win->ctx );
            glDrawBuffer( GL_BACK );
            RedrawWindowFromBuffer( win, win->backing_store );
            glXSwapBuffers( dpy, win->drawable );
        }
    }
}

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

void window_swap( Window *win ) {
    if ( win ) {
        if ( isValidForSwap( win ) ) {

            glXMakeCurrent( dpy, win->drawable, win->ctx );

            glDrawBuffer( GL_BACK );
            OutputWindowBuffer( "back.jpg", GL_BACK );
            RedrawWindowFromBuffer( win, win->backing_store );

            glXSwapBuffers( dpy, win->drawable );

            glDrawBuffer( GL_BACK );
            glClearColor( 1.0, 1.0, 1.0, 1.0 );
            glClear( GL_COLOR_BUFFER_BIT );

            OutputWindowBuffer( "front_after.jpg", GL_FRONT );
            OutputWindowBuffer( "back_after.jpg", GL_BACK );
        }
    }
}

Функция OutputWindowBuffer() использует стандартную glReadPixel(), чтобы прочитать содержимое буфера и затем вывести его как изображение. Какой буфер должен быть прочитан, определяется параметром, переданным в функцию. Что я обнаружил с выходной картинкой, так это.

  1. Вывод изображения из заднего буфера после RedrawWindowFromBuffer() соответствует ожидаемому.
  2. Вывод изображения из заднего буфера после замены заполнен очищенным цветом, как и ожидалось. Таким образом, дело не в том, что glReadPixel может отставать в своем исполнении, когда он вызывался для буфера Front, как однажды обнаружила некоторая обнаруженная ошибка в системе Intel.
  3. Вывод изображения из переднего буфера после замены показывает в основном черные артефакты (цвет моего окна всегда очищается до другого цвета перед каждым рисунком).

Есть ли другие правдоподобные объяснения относительно того, почему замена буфера, кажется, не меняет местами буфер? Есть ли другие маршруты, которые я должен изучить, чтобы осуществить изменение размеров без мерцания? Я прочитал статью, в которой предлагается использовать WinGravity, но, боюсь, пока не совсем понял.

1 ответ

Если у ваших окон установлен фоновый растровый рисунок, то на каждом шаге изменения размера они заполняются этим до того, как начнется фактическая перерисовка OpenGL. Это один из источников мерцания. Другая проблема заключается в том, что glXSwapBuffers не синхронизируется с вертикальным возвратом. Вы можете установить это используя glXSwapInterval.

Итак, две вещи, которые нужно сделать для изменения размера без мерцания: установить нулевое фоновое растровое изображение и включить glXSwapBuffers, синхронизированные с вертикальным возвратом (интервал обмена 1).

Другие вопросы по тегам