Thursday, March 25, 2010

Windows 7 and OpenGL

I've recently been writing some OpenGL code under Windows 7 x64. This has been rather disappointing for me. I hadn't written any OpenGL code in a while, and my first few attempts didn't seem to work at all. Nothing I drew showed up at all -- even something as simple as clearing the background just wouldn't work!

After several attempts (and a bit of head-scratching) I accidentally resized the window - and suddenly, what I had drawn all showed up. A bit more testing showed that quite a bit of the time, resizing the window or minimizing and re-displaying the window would get it to draw correctly. Knowing that these invalidate the window and force it to be redrawn, I added a quick hack to set a timer when the window was initialized, and responded to the timer by invalidating the window. This helped quite a bit -- sometimes things still didn't show up correctly, but at least they usually did, though I sometimes had to wait a second or two before (for example) the content scaled correctly after I resized the window. One other detail bothered me a bit: my code seemed slow and sluggish -- in fact, my old laptop (still running Windows XP, because it only has 512M of RAM) seemed faster than my desktop, despite much slower hardware in general.

This got to me thinking back over things I'd heard when Windows Vista was new, about how it composed an images of the windows being displayed and displayed them all via Direct3D. That made me wonder, so after a little looking, I found the control panel where I could turn that off ("Performance Information and Tools"). With "Enable desktop composition" turned off, suddenly all my OpenGL code worked beautifully! Everything displayed perfectly every time, and it was fast!

Based on this, I did a bit of looking and added a couple of lines of code to automatically disable desktop compositing while my OpenGL program was running. During initialization, it calls:


DWM_hack = S_OK != DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);


and during shutdown, it does:


DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
::RedrawWindow(NULL,
NULL,
NULL,
RDW_INVALIDATE | RDW_UPDATENOW);


The "DWM_hack" is a Boolean that controls whether to set the timer that invalidates the window -- so if we can't disable compositing for some reason, we'll still set the timer, and at least get mediocre results instead of things mostly failing completely. I'm not sure whether the call to RedraWindow is really necessary -- at first I didn't include it, but once I ran into the desktop being left incompletely drawn after it exited, which this is intended to prevent. It probably shouldn't really be necessary, but then nothing in this entire post should be necessary.

So, if you're trying to write OpenGL for a recent version of Windows, and things are slow and/or not working dependably, this might be one way to make the code work.

Introduction

In case anybody decides to read this, I guess I'll start by introducing myself and what kinds of things I'll talk about, so you'll have some idea of whether you might want to read what I I write.

This blog is more or less a counterpoint to StackOverflow. StackOverflow is (intentionally) designed as a question and answer forum for programmers. Much of its design actively discourages extended discussion. Given the number of extended discussions that turn into arguments and outright flamewars in some cases, that was almost certainly a sensible decision, and I generally agree with it.

Nonetheless, there are times that a more extended discussion is in order as well. Being a blog tends to reduce flamewars a bit, simply because I'm not in the habit of flaming myself (and let's face it: given the number of blogs around, chances are pretty good nobody else will ever even read this, not to mention getting upset about it).

Anyway, that leads us to this blog. StackOverflow deals well with questions of fact (e.g. how do I move a window to a different monitor under Windows 7?), but relatively poorly with questions where the answer involves things like balancing a number of competing goals. I'm at least hoping that this forum will give me more opportunity for the latter. While it's certainly true that programming requires a great deal of factual knowledge (enough that StackOverflow has a lot of activity) it's also true that (at least to me) most of the really interesting questions in programming involve judgment, not just facts.

Speaking of judgment, my judgment tells me that this is getting too long, so I should shut up for now.