c++ - OpenGL 闪烁/损坏,窗口调整大小和 DWM 处于事件状态

标签 c++ windows opengl direct3d dwm

我有一个 wxWidgets 应用程序,它有许多子 opengl 窗口。我正在使用我自己的 GL Canvas 类,而不是 wx 类。窗口共享它们的 OpenGL 上下文。 我不认为它是 wxwidgets 的事实在这里真的很重要。

opengl 窗口是一个窗口的子窗口,它们是彼此的兄弟窗口,包含在选项卡控件中。一种 MDI 风格的界面,但它不是 MDI 窗口。每个都可以单独调整大小。除非启用 Aero 并且 DWM 处于事件状态,否则一切正常。

调整任何窗口(甚至是 opengl 窗口)的大小会导致所有 opengl 窗口偶尔闪烁,并出现陈旧的后备存储 View ,其中包含当时屏幕上出现的任何非 opengl 垃圾。这只发生在启用 Aero 的情况下。

我很确定这是 DWM 实际上在其绘图表面后备存储中没有 opengl 内容,并且窗口没有在正确的时刻重新绘制。

我已经尝试了很多方法来解决这个问题,我确实有一个解决方案,但它不是很好,它涉及将带有 glReadPixels 的帧缓冲区读取到 DIB 中,然后在我的 onPaint 例程中将其传送到绘图 DC。仅当 DWM 处于事件状态时才启用此解决方法,但我宁愿根本不必这样做,因为它会稍微损害性能(但在功能强大的系统上并不算太糟糕 - 场景是相对简单的 3d 图)。也不建议将 GDI 和 opengl 混合使用,但令人惊讶的是,这种方法很有效。我现在可以忍受它,但我宁愿不必。无论如何,如果我想截取子窗口的屏幕截图,我仍然必须在 WM_PRINT 中执行此操作,我看不到解决方法。

有人知道更好的解决方案吗?

在有人问之前,我肯定会做到以下几点:

  • 窗口类有 CS_OWNDC
  • WM_ERASEBACKGROUND 什么都不做并返回 TRUE。
  • 双缓冲已启用。
  • Windows 具有 WS_CLIPSIBLINGS 和 WS_CLIPCHILDREN 窗口样式。
  • 在我的 resize 事件处理程序中,我立即重新绘制窗口。

我试过了:

  • 在像素格式描述符中设置 PFD_SUPPORT_COMPOSITION。
  • 不在绘图处理程序中使用 wxPaintDC 并调用 ::ValidateRect(hwnd, NULL) 代替。
  • 处理 WM_NCPAINT 并排除客户区
  • 通过 DWM API 禁用 NC 绘制
  • 在绘制事件中排除客户区
  • 在缓冲区交换前后调用 glFlush 和/或 glFinish。
  • 在每次绘制事件时使窗口无效(作为测试!) - 仍然 闪烁!
  • 不使用共享的 GL 上下文。
  • 禁用双缓冲。
  • 写入 GL_FRONT_AND_BACK

禁用 DWM 不是一种选择。

据我所知,如果您在 OpenGL 上使用 Direct3D,这甚至是一个问题,尽管我没有对此进行测试,因为它代表了很多工作。

最佳答案

这是一个远射,但我刚刚自己解决了同样的问题。

出现长镜头部分是因为我们正在对围绕我们的 OpenGL 窗口的无标题组框的轮廓进行所有者绘制(即,制作一个漂亮的小边框),这可能无法描述您的情况。

我们发现问题是这样的:

我们一直在使用 RoundRect() 调用(带有 HOLLOW_BRUSH)来绘制组框的轮廓。将其更改为 MoveToEx() 和 LineTo() 调用以确保仅绘制线条并且在组框内没有任何操作可以防止 GDI 尝试意外地重绘控件的全部内容。无效逻辑可能存在差异(或者我们在加载预期的空心画笔时遇到了错误)。我们仍在调查中。

-诺埃尔

关于c++ - OpenGL 闪烁/损坏,窗口调整大小和 DWM 处于事件状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10615272/

相关文章:

c++ - 我如何判断 OSX 程序是否正在调试器中运行?

c++ - C 和 C++ 中静态变量存储在哪里?

c++ - 使用 Qt 捕获 SQL 错误

c++ - Levenshtein Edit Distance 不计算编辑距离

windows - Bamboo远程构建代理安装nodejs后找不到powershell.exe

java - Spring 安全 java.lang.IllegalArgumentException : Non-hex character in input

windows - 我可以通过什么方式在Windows中使用Winsock2中定义的AF_UNIX

OpenGL:基向量如何在内存中布局

c++ - OpenGL 3+ 黑屏 - C++

python - 为什么只有一半的预期输出使用纹理坐标环绕模式,来自 SB OpenGL 的示例