views:

69

answers:

2

NOTE: Please read the whole thing before posting, you'll see why.

So I have an OpenGL/WinAPI application. I'm doing what you would expect, by doing cycles of handling messages, then rendering a frame, handling messages, rendering frame...

The trouble is, when I resize or move a window, the screen freezes, and it can look quite ugly. I know from previous expirements with OpenGL that limiting the number of messages to be processed between frames (either by number or time) does the trick. It seems windows is blocking my app whenever it moves/resizes the window. From expirimenting, I do know that putting the windows message handling into another thread and forgetting about it works quite well, and helps with the timing aswell.

My question is: Is there any better, less destructive, or non-threaded way of doing this? Is there any downside to what I am doing (besides the multithreading dramas). I would love to know if multithreading is avoidable.

Thanks, Alex

+3  A: 

When the user clicks on the non client areas of a window to move or size a window, DefwindowProc goes into a modal loop, so your game loop is no longer being executed - until the user cancels or finishes the modal operation.

There are window messages you can use to detect the start and end of modal operations: WM_ENTERSIZEMOVE for example.

The crux of the matter is, if your OpenGL window is not fullscreen, or it displays message boxes, then you cannot rely on a simple game loop to keep on rendering the game - you need to switch to a timer based renderer.

SetTimer can create a timer that will deliver WM_TIMER messages even when modal operations are in progress.

PS. A note on threading: OpenGL contexts are not thread safe and accessed must be serialized (manually by user code) if a context is shared across threads. Even if multiple contexts are used, access to the actual device is serialized too, so there is no performance benefit to be gained from multithreading an OpenGL based renderer - unless (ironically) you do a lot of CPU intensive work (and then something like OpenMP to parallelize loops would help there more than trying to design a higher level multi threaded rendering job dispatcher). Basically: stick to a single threaded renderer with OpenGL - it will perform better than almost any attempt at threading, and be far more predictable to.

PPS. For windowed OpenGL apps its probably also be better to abandon the traditional game-loop approach to rendering each frame, and rely on the RedrawWindow to dispatch WM_PAINT messages to the window: Painting inside a BeginPaint/EndPaint block means your applications rendering behaviour is much more predictable, and the DesktopWindowManager process can deal with its job of applying aero glass effects, and trying to implement vsync'ed updates of the desktop to the display much more efficiently.

Chris Becke
I think you misunderstood. Only one thread deals with OpenGL and it's context. The other is for windows handling.
Alexander Rafferty
Nope. I was just looking to be ... complete in my argument against multithreading OpenGL. A UI thread + OpenGl thread provides no performance benefits and simply means that activities that are serialized anyway, now have to be marshalled between threads. Plus, the UI thread is the one that the OS gives the foreground boost to. It makes no sense on any level to separate OpenGL rendering from the window thread.
Chris Becke
A: 

One idea as a workaround: Render into an FBO, blit the FBO into the window on each resize message (potentially scaling it), and re-render the FBO at the proper resolution when the message queue is empty.

This way you get predictable redraws with little artifacts and no threading.

eile