我的情况是这样的。我编写了一个代码来检查一组窗口的内容是否符合交换条件(也就是说,在调整大小事件后,所有重绘都在所述窗口及其所有子窗口上成功执行)。如果满足条件,我对所述窗口及其所有子窗口执行 glXSwapBuffers 调用。我的目标是允许调整大小时无闪烁的系统。子窗口以平铺方式排列,并且不重叠。在他们之间,这个功能似乎起作用了。然而,我的问题出现在父母身上。在调整大小的某个时候,其内容会闪烁。到目前为止,这就是我已经实现的。
- 所有事件(例如 ConfigureNotify 或 Expose)都已根据需要进行压缩。
- 窗口 background_pixmap 设置为无。
- 了解每当生成 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() 读取缓冲区内容,然后将其输出为图像。要读取哪个缓冲区由传递给函数的参数确定。我从输出图片中发现的是这个。
- RedrawWindowFromBuffer() 后后台缓冲区的图片输出是预期的。
- 交换后的后台缓冲区的图片输出按预期填充了清除的颜色。因此,当 glReadPixel 被调用用于 Front 缓冲区时,它的执行并不是滞后的,因为一些发现的有关英特尔系统的错误似乎曾经暗示过一次。
- 交换后前缓冲区的图片输出显示大部分是黑色伪影(每次绘图之前我的窗口颜色总是被清除为其他颜色)。
关于为什么交换缓冲区,似乎没有交换缓冲区,是否还有其他合理的解释?我应该研究其他路线来实现无闪烁的重新调整大小吗?我读过一篇建议使用 WinGravity 的文章,但恐怕我还不太理解。