OpenGL闪烁/损坏,窗口调整大小并且DWM处于活动状态

Pet*_*ete 25 c++ windows opengl direct3d dwm

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

opengl窗口是窗口的子窗口,它们是彼此的兄弟,包含在选项卡控件中.MDI样式界面的种类,但它不是MDI窗口..每个窗口都可以单独调整大小.除非启用Aero且DWM处于活动状态,否则一切都很可爱.

调整任何窗口(甚至不是opengl窗口)的大小会导致所有opengl窗口偶尔闪烁,其中包含一个陈旧的后备存储视图,其中包含屏幕上那个非opengl的垃圾.这仅在启用Aero时发生.

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

我已经尝试了很多东西来解决这个问题,我确实有一个解决方案,但它不是很好,并且需要将带有glReadPixels的帧缓冲区读入DIB,然后在我的onPaint例程中将其渲染到绘制DC.这种解决方法仅在DWM处于活动状态时才启用,但我根本不必这样做,因为它会稍微损害性能(但在功能强大的系统上也不会太糟糕 - 场景是相对简单的3d图形).也不推荐混合使用GDI和opengl,但这种方法令人惊讶.我现在可以忍受它,但我宁愿不必.如果我想截取子窗口的截图,我仍然需要在WM_PRINT中执行此操作,我没有看到解决方法.

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

在有人要求之前我肯定会做以下事情:

  • Window类有CS_OWNDC
  • WM_ERASEBACKGROUND不执行任何操作并返回TRUE.
  • 启用双缓冲.
  • Windows具有WS_CLIPSIBLINGS和WS_CLIPCHILDREN窗口样式.
  • 在我的resize事件处理程序中,我立即重新绘制窗口.

我试过了:

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

禁用DWM不是一种选择.

据我所知,如果你在OpenGL上使用Direct3D,这甚至是一个问题,虽然我没有测试过它,因为它代表了很多工作.

oki*_*gan 0

嗯,也许您遇到了同样的问题:如果您使用“新”MFC,它将使用选项卡和窗口拆分器创建和应用程序。

分离器有一些逻辑(我猜测透明窗口周围的某个地方并为分离绘制异或线)导致这种行为。卸下分离器以确认它可以解决您的问题。如果您需要拆分功能 - 放入不同的拆分器。

选项卡还允许停靠并再次拆分具有相同问题的窗口 - 删除/替换。

祝你好运,伊戈尔