【问题标题】:glXSwapbuffers appear not to have swapped (?)glXSwapbuffers 似乎没有交换(?)
【发布时间】:2013-08-29 16:34:46
【问题描述】:

我的情况是这样的。我编写了一个代码来检查一组窗口的内容是否符合交换条件(也就是说,在调整大小事件后,所有重绘都在所述窗口及其所有子窗口上成功执行)。如果满足条件,我对所述窗口及其所有子窗口执行 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 的文章,但恐怕我还不太理解。

【问题讨论】:

    标签: c opengl x11 double-buffering glx


    【解决方案1】:

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

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

    【讨论】:

    • 背景像素图已经设置为无,所以我想我可以尝试设置垂直回扫。有没有办法检查它当前是否正在实施?有人说这取决于司机来决定。有人说要设置opengl环境,然后当然还有glXSwapInterval。我曾经检查过我的 NVDia 设置以允许垂直回溯,但我不确定它是否真的起作用,因为窗口仍然继续闪烁。
    • @S.Aymerich:说实话,我认为您将事情严重过度复杂化了。保持简单和直截了当:一旦你完成了对窗口的绘制,只需调用 glXSwapBuffers 即可。无论如何你都应该重绘,不要担心性能。
    • 曾经这样做过,@datenwolf。可悲的事实是,在执行任何调整大小事件时(无论是在其兄弟姐妹上还是在其父级上),子窗口的显示都会受到很大影响。
    • 如果您有多个子窗口而不是子窗口,我建议使用一个大的 OpenGL 窗口,并使用 glViewport + glScissor(并启用 GL_SCISSOR_TEST)将其划分为多个图块。更轻松。
    • 是的,这些子窗口也是使用 opengl 绘制的。虽然使用 glViewport 绘制到一个大窗口的不同部分可能更容易(我相信这是 Blender 对他们所做的),但为我的每个子窗口或它们的根选择的视觉样式不一定相同.因此,决定将系统实现为单独的子窗口。在对 swap_group 进行简短阅读后,我可能需要该扩展,但如果它没有得到广泛支持,我表示怀疑。
    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2012-06-12
    • 2011-10-01
    • 2017-10-24
    • 2015-08-26
    相关资源
    最近更新 更多