c - glXSwapbuffers 似乎没有交换(?)

标签 c opengl x11 double-buffering glx

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

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

哪个...应该服务,内容总是在调用 swap 之前恢复。可悲的是,它在实现中并没有出现。从上面的代码中,我为了调试目的做了一些调整,输出缓冲区中的内容如下。

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 buffer 时,它的执行不会像一些已发现的关于英特尔系统的错误似乎曾经暗示过的那样。
  3. 交换后前缓冲区的图片输出显示大部分为黑色伪影(我的窗口的颜色总是在每次绘制之前清除为其他颜色)。

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

最佳答案

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

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

关于c - glXSwapbuffers 似乎没有交换(?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18516426/

相关文章:

java - 关于 EBO 如何工作的一些说明(元素数组缓冲区)

c++ - 图形硬件上的最近邻搜索

r - 在服务器上运行 R 时,如何从 emacs ess 启动 x 窗口?

java - Java 中的工作区又名桌面

c++ - 如何为 32 位位图生成单色位掩码

c - 哪个更快 : bitshift vs switch

c - glPopMatrix() 大喊 "unsupported texture format in setup_hardware_state"

清除带有桌面背景像素的 X11 窗口,并在其上放置带有透明像素的 XImage?

c - Raspberry PI 中的幂函数

c - 如何在 C 语言的#define 宏中用字符串常量替换函数名