1

我的情况是这样的。我编写了一个代码来检查一组窗口的内容是否符合交换条件(也就是说,在调整大小事件后,所有重绘都在所述窗口及其所有子窗口上成功执行)。如果满足条件,我对所述窗口及其所有子窗口执行 glXSwapBuffers 调用。我的目标是允许调整大小时无闪烁的系统。子窗口以平铺方式排列,并且不重叠。在他们之间,这个功能似乎起作用了。然而,我的问题出现在父母身上。在调整大小的某个时候,其内容会闪烁。到目前为止,这就是我已经实现的。

  1. 所有事件(例如 ConfigureNotify 或 Expose)都已根据需要进行压缩。
  2. 窗口 background_pixmap 设置为无。
  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 缓冲区时,它的执行并不是滞后的,因为一些发现的有关英特尔系统的错误似乎曾经暗示过一次。
  3. 交换后前缓冲区的图片输出显示大部分是黑色伪影(每次绘图之前我的窗口颜色总是被清除为其他颜色)。

关于为什么交换缓冲区,似乎没有交换缓冲区,是否还有其他合理的解释?我应该研究其他路线来实现无闪烁的重新调整大小吗?我读过一篇建议使用 WinGravity 的文章,但恐怕我还不太理解。

4

1 回答 1

0

如果您的窗口设置了背景像素图,那么在每个调整大小的步骤中,在实际的 OpenGL 重绘开始之前,它们都会被填充。这是闪烁的来源之一。另一个问题是 glXSwapBuffers 没有与垂直回溯同步。您可以使用 glXSwapInterval 进行设置。

因此,无闪烁调整大小需要做两件事:设置 nil 背景像素图并启用 glXSwapBuffers 同步到垂直回扫(交换间隔 1)。

于 2013-08-29T16:43:16.837 回答