简体   繁体   English

在Windows之间切换后无效的OpenGL绘图上下文

[英]Invalid OpenGL drawing context after switching between windows

I experience the following problem with an OpenGL application 'A' (written in C++): After switching to a different window 'B' (either a child window of the same application or a completely different application) and then switching back to 'A', all OpenGL rendering is confined to the area of 'A' that was covered by 'B'. 我在OpenGL应用程序'A'(用C ++编写)中遇到以下问题:切换到不同的窗口'B'(同一应用程序的子窗口或完全不同的应用程序)然后切换回'A' ,所有OpenGL渲染都局限于'B'覆盖的'A'区域。

  • the problem goes away after minimizing and re-maximizing window 'A' 最小化并重新最大化窗口'A'后问题消失了
  • the problem only occurs on a single windows 7 machine. 问题只发生在一台Windows 7机器上。 When testing on many other machines (both windows and Linux) everything works fine. 在许多其他机器(Windows和Linux)上进行测试时,一切正常。 Updating the graphics driver to the latest version also did not help. 将图形驱动程序更新到最新版本也没有帮助。

Is there an obvious coding error that would cause this behavior? 是否存在会导致此行为的明显编码错误?

What is a good way to go about debugging this type of error? 调试此类错误的好方法是什么?

There are a number of aspects that could impact repainting behaviour on Windows. 有许多方面可能会影响Windows上的重绘行为。 Given the few details in the question, I suggest checking the basics first: 鉴于问题中的一些细节,我建议首先检查基础知识:

  • First of all, on Windows, you need to create the OpenGL context window with these flags: WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN 首先,在Windows上,您需要使用以下标志创建OpenGL上下文窗口: WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN

  • In response to WM_ACTIVATE , you should be calling wglMakeCurrent() . 响应WM_ACTIVATE ,您应该调用wglMakeCurrent()

  • In response to WM_SIZE , you should be calling glViewport() . 为响应WM_SIZE ,您应该调用glViewport()

The behaviour will certainly vary by hardware, Windows version, and driver version. 行为肯定会因硬件,Windows版本和驱动程序版本而异。 All combinations will have their own quirks. 所有组合都有自己的怪癖。

the problem goes away after minimizing and re-maximizing window 'A' 最小化并重新最大化窗口'A'后问题消失了

This is forcing a repaint and a resize, so doesn't narrow down the problem very much. 这是强制重绘调整大小,因此不会非常缩小问题的范围。 For debugging, you could use WM_CHAR to get keyboard events, and use a hotkey to force a repaint (without all the other message flow). 对于调试,您可以使用WM_CHAR来获取键盘事件,并使用热键强制重新绘制(没有所有其他消息流)。 That would tell you if it's an activation issue. 这会告诉你它是否是激活问题。

...all OpenGL rendering is confined to the area of 'A' that was covered by 'B'. ...所有OpenGL渲染都局限于'B'覆盖的'A'区域。

If the rendering scaled down to the overlapped area, then the viewport is probably getting messed up, for example setting the viewport to the dirty rect during a repaint. 如果渲染缩小到重叠区域,则视口可能会混乱,例如在重绘期间将视口设置为脏矩形。

If the scaling is correct but you are only seeing a corner of the window being repainted, the behaviour you are seeing is the occluding window saves the backing buffer of the window behind, which repaints just the saved bits when it gets restored. 如果缩放是正确的,但您只是看到窗口的一角被重新绘制,那么您所看到的行为是遮挡窗口保存窗口的后备缓冲区,它会在恢复时重新绘制已保存的位。 This is obviously not sufficient for your repainting logic, and the clip flags affect this behaviour. 这显然不足以重新绘制逻辑,剪辑标志会影响此行为。

Another possibility is that the active GL context (of which there is only one per thread) is not getting switched to the newly activated window before the repaint event gets processed. 另一种可能性是,在处理重绘事件之前,活动的GL上下文(每个线程只有一个)不会切换到新激活的窗口。 The activate handling above would address this. 上面的激活处理将解决这个问题。

As for debugging strategies, I'd put some printf s in your event handlers (or use MessageSpy) so you can see the order of events. 至于调试策略,我会在您的事件处理程序(或使用MessageSpy)中放置一些printf ,以便您可以看到事件的顺序。 The fact that it is only a particular combination of hardware and software means that you may be relying on default behaviour that is slightly different between versions. 事实上,它只是硬件和软件的特定组合,这意味着您可能依赖于版本之间略有不同的默认行为。 Any more details you can supply would help narrow this down further. 您可以提供的任何更多细节将有助于进一步缩小范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM