PDA

View Full Version : Blitting a window with OpenGL



dogdemir
02-04-2010, 02:53 PM
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

ZbuffeR
02-04-2010, 03:12 PM
glReadPixels will do.

dogdemir
02-04-2010, 03:55 PM
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.

Alfonse Reinheart
02-04-2010, 04:19 PM
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.

dogdemir
02-04-2010, 06:21 PM
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?

mark ds
02-05-2010, 04:41 AM
Start here

http://msdn.microsoft.com/en-us/library/ms646304%28VS.85%29.aspx

and follow the link to SendInput etc.

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

Stephen A
02-05-2010, 09:44 AM
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.

dogdemir
02-05-2010, 11:39 AM
...This enables you to send a print screen (VK_SNAPSHOT) and copy to the clipboard...

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

dirk103
02-08-2010, 02:06 PM
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.

dogdemir
02-08-2010, 03:03 PM
You are lovely :)
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.

Alfonse Reinheart
02-08-2010, 03:46 PM
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.

dogdemir
02-08-2010, 03:57 PM
If the window is not even visible, you cannot get a screen shot of it.

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.

Brolingstanz
02-08-2010, 04:49 PM
>> 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?

dogdemir
02-08-2010, 05:57 PM
It was the wglSwapLayerBuffers, yes.
DLL injection or hooking into an application to monitor the messages is allowed.

Brolingstanz
02-08-2010, 06:20 PM
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)

Stephen A
02-09-2010, 10:18 AM
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.

dogdemir
02-09-2010, 11:51 AM
Do you know if wglSwapBuffers is used once for each GL window or is it a replacement for GDI to include GL as well?

Brolingstanz
02-09-2010, 02:51 PM
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....

dogdemir
02-09-2010, 03:15 PM
Also it is quite interesting how DWM can get it in real time.

Stephen A
02-09-2010, 07:43 PM
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. ;)


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.

dogdemir
02-10-2010, 11:14 AM
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....

What pixel format you set on DC? And why?

I'm still not convinced as to why it doesn't show up on regular screen capture. Does anyone know where does the common OpenGL implementation in Windows draws to? (obviously not the DC, but where) Because I believe that is where DWM captures the screen from, with OpenGL and it composites correctly and if I can figure that out, then there may be a better solution compared to injection.

And I don't want to modify every user's opengl dll. This project leads to a system for scientific visualization.

Brolingstanz
02-10-2010, 02:13 PM
>> What pixel format you set on DC? And why?

is this a trick question? I'm not very good at those... ;-)

dogdemir
02-10-2010, 02:20 PM
No :) I'm asking whether you need a special pixel format to write to your DC or what you meant by that. I just want to make sure I'm not missing anything.

Brolingstanz
02-10-2010, 02:36 PM
Nope, just a vanilla pfd.

As for whether you're missing anything, despite my honorary subtitle of OpenGL Pro, I'm really not qualified to make that determination. ;-)

dogdemir
02-10-2010, 04:54 PM
Turn DWM off and voila :)

DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);

So that took 2 weeks to figure out.

Brolingstanz
02-10-2010, 05:51 PM
OK, but I don't think you need to disable composition to take a screen shot.

dogdemir
02-10-2010, 11:51 PM
You need to if you are going to capture a window DC.