Blitting a window with OpenGL

I am trying to take a screen capture of a window (not fullscreen) with some OpenGL rendering on part of it.

When I capture it with BitBlt from the DC of the window, the part where OpenGL is supposed to reside is just blank, or garbage. It works fine with DirectX (as expected).

Is this a known issue? This is needed for research and I would like to know if we can expect it to be solved or is just a feature?

Thanks.

Edit: Windows 7. 186.81 NVIDIA 9800 M GTS

glReadPixels will do.

This can be any application running OpenGL in some way. I don’t have the source code to the application I’m trying to capture the screen of and it needs to be application-independent.

I don’t have the source code to the application I’m trying to capture the screen of

Then there’s no much that can be done.

This is needed for research and I would like to know if we can expect it to be solved or is just a feature?

It’s not a feature; it’s simply an unintended consequence of different rendering mechanisms conflicting.

Yeah but the DWM in Windows 7 captures the window thumbnails properly. I’m trying to understand when it actually does the capturing so that I can probably emulate it somehow?

Start here

http://msdn.microsoft.com/en-us/library/ms646304(VS.85).aspx

and follow the link to SendInput etc.

This enables you to send a print screen (VK_SNAPSHOT) and copy to the clipboard…

This won’t work for fullscreen applications though. AFAIK, the only reliable way is to inject yourself into the process, hook wglSwapBuffers and do a readback with glReadPixels.

There are tutorials detailing this process on the net.

Yes but the window may not be always on the foreground.

Are you accessing the RC properly? bit-depth, stencil bit resolution, all that? If you’re getting it blank or all garbage maybe you’re not looking at the correct memory position/accessing it properly. Using OpenGL will require some thinking as it isn’t a magic library like DirectX is, it’s designed for real programmers to use, not Visual Basic newbies.

You are lovely :slight_smile:
No, I’m not using OpenGL at all. What I’m trying to achieve is to capture a screenshot of the window that is running OpenGL. The window may be in the background too so Print Screen manually or automatically doesn’t work.

What I’m trying to achieve is to capture a screenshot of the window that is running OpenGL.

This is not possible, under the parameters you have outlined above.

The window may be in the background too so Print Screen manually or automatically doesn’t work.

If the window is not even visible, you cannot get a screen shot of it. The pixels not in view fail the pixel ownership test, so they may not have valid pixel data. So even if you could somehow get access to the OpenGL framebuffer from another process, the framebuffer would contain partial garbage data.

If you have Windows 7 (because I haven’t tested it on Vista), open up a windowed OpenGL application, put it on the background and you will still be able to see it playing in the thumbnail (when you keep your mouse over the taskbar) or even Flip 3D view. And I checked it, flip 3D doesn’t bring a window to the front.

Programatically, you can register the thumbnail through dwmRegisterThumbnail, and you can have it drawn on another window, live, even if the OpenGL window is on the background.

The problem with registering thumbnail is that you can’t do image processing on it. That is why I’m looking for a way to capture it from the DC. Someone suggested hooking into the swap buffers call and that is the most reasonable solution so far but it is way too complicated and there is no time.

>> Someone suggested hooking into the swap buffers call and that is the most reasonable solution so far but it is way too complicated and there is no time.

What if the call is to wglSwapLayerBuffers instead of SwapBuffers ?

P.S. Isn’t there an ethical issue here or at least the specter of copyright infringement? Is there content presentable on a PC that we as users shouldn’t have direct access to?

It was the wglSwapLayerBuffers, yes.
DLL injection or hooking into an application to monitor the messages is allowed.

My point was that there are ways to thwart the hooking mechanism so I wouldn’t rely on it as a screen grabbing panacea.

Incidentally I didn’t mean to imply that you were engaged in something unscrupulous; just adding a bit of fodder for discussion… (no takers i see)

For the largest part, dll-injection is how applications like FRAPS (or Taksi or whatever) work. While it’s probably possible to code an app in such a way such as to thwart typical grabbing attempts, there only so many ways to present a rendering. Hooking wglSwapBuffers will probably handle >90% of current OpenGL applications.

Do you know if wglSwapBuffers is used once for each GL window or is it a replacement for GDI to include GL as well?

On the thwarting of things I know only that if I load my procs directly from opengl32.dll (after setting the pixel format on my dc) and call wglSwapLayerBuffer a hook is a no show…

Also it is quite interesting how DWM can get it in real time.

On the thwarting of things I know only that if I load my procs directly from opengl32.dll (after setting the pixel format on my dc) and call wglSwapLayerBuffer a hook is a no show…

Not if I route you through my faux opengl32.dll. :wink:

Also it is quite interesting how DWM can get it in real time.

That’s one of the benefits of controlling the compositor and driver architecture. In fact, the screenshots are always available in real time to the compositor, but mere mortals don’t have access to that part of the OS.