Desktop screen capture

I’m trying to achieve a desktop screen capture in opengl.
I’ve read in a few places that it’s supposed to be possible by creating a full screen invisible window and then using glReadPixels.
I’m a bit of a beginner with opengl so I may be missing something simple but I can’t figure out how to do this, or any examples on how to achieve this or whether this is even the right approach.
I’d be happy for some guidance in how to achieve this.

Thanks

glReadBuffer(GL_FRONT);
glReadPixels(…);

This should be enough, I think. You might need to do single-buffering (no double-buffering).

You definitely have to go offscreen if you running your program under Windows. Because if you running on-screen, you have to make sure the window is not partially or fully covered by another one: in this case, the pixel ownership test is taken into account and you will get garbage in the covered part of your image.

see figure 4.1 page 202 of OpenGL spec 2.1, chapter 4 “Per-Fragment Operations and the framebuffer”:

http://www.opengl.org/registry/doc/glspec21.20061201.pdf

They are many approaches to initialize an offscreen window depending on the capabilities of your OpenGL implementation and the operating system you are using.

Going from best to worst:

  1. If framebuffer object is supported, go for it. This is flexible and hardware accelerated and it works within an existing OpenGL context.

If not, you will have to go with older solutions:

  1. go with pbuffer (usually hardware accelerated), but you have to create a special pbuffer context.

  2. if not, go with pixmap on Unix (glx) or DIB (device-independent bitmap) on Windows, both are software and slow:

ref for DIB: http://www.mesa3d.org/brianp/sig97/offscrn.htm#wgl

  1. or if you are using Mesa, use OSMesa (OS stands for Off Screen), software and slow, but you don’t have to use ReadPixel because you are giving color buffer to Mesa.

ref: http://mesa3d.org/osmesa.html

@overlay : Unless I am mistaken, the OP wants to screenshot the desktop, not the opengl graphics. So offscreen rendering will not help.

Why would you want to use OpenGL to get a screenshot of the desktop? Doesn’t the OS provide an API to do exactly that?

ZbufferR: you are right :slight_smile:

Yes, indeed, I want to grab the desktop, not a specific application.
The reason to do it with opengl is twofold.

  1. I want to post process the data in opengl (glsl actually). If I grab it using gdi I then have to copy the data to the card creating an i/o and cpu overhead

  2. Using gdi means using bitblt which doesn’t capture overlays and the mouse. I was hoping that using opengl may solve that (only testing will tell …). The other option is directx which I don’t like but if that is the only option I will use that.

From several forums it seems that I first need to create a full screen invisible opengl window. If there are no other suggestions I will be happy to learn how to do that (I managed to create a standard window or full screen mode but not an invisible one). I’m not sure if it’s a great option as it will probably grab mouse/keyboard events and such, but I will start with that.

Btw, iirc overlays at some time used to be composited onscreen only by the DAC (to the VGA port). Fortunately with Vista overlays are no longer used; still on Vista’s Aero generally apps don’t have access to the real front-buffer, afaik. So, expect these 2 oddities.

It looks like what is done in this example may be what I’m looking for in order to achieve my ends, anyone know how this type of thing can be done
http://coreytabaka.com/programming/cube-demo/
especially with the behavior when selecting transparent and always on top in the small taskbar icon

You actually want a window with transparent background.

Look at this recent thread then (Subwindow with transparent background):
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=258832#Post258832

I also have an example on my site:
http://www.dhpoware.com/demos/glLayeredWindows.html

Does this work also with Vista + Aero ?

Yes seems to work fine under Vista and Aero.

With glReadPixels() data is copied to system memory and you have to copy it back to “process” it with GLSL. So this point is irrelevant.

The last time I tried grabbing the desktop, all I needed to do was create a fullscreen window (if you want the full desktop, that is), don’t do glClear(), just a glReadPixels(). I don’t remember if it was the front or the back buffer, but I’m pretty sure it worked with double-buffering.

I found out the way of reading desktop content into a pixel buffer object (PBO) by using a transparent window, but the window is not in full-screen mode, it just have the size of the desktop and the WS_POPUP style. I don’t know anything about GLSL, but for my purpose I need to process this screenshot with CUDA, so the next step is to register and map this PBO to CUDA without any other copy operation, that’s precisely the advantage of using PBO: fast and asynchronous pixel data transfer from screen to PBO as openGL driver takes care of this operation by using DMA chip, and no need for copy back the data from RAM to GPU, just a mapping operation.

Perhaps GLSL also have interoperability with PBOs and having the image of desktop in such an object lead to fast processing.

@diaztula: I’m really interested in how you accomplished screen grabbing and storing it into a PBO. Could you place some code here or send me a pm?

forgive my offence,I don’t think you can achieve it by opengl. maybe desktop can be capture, but capturing overlay seems impossible, especially on vista with DWM on.

I think I have exactly same problem as OP.
My OpenGL application draws texture generated from Windows desktop.
I know how to capture the desktop before OpenGL is initialized, but how can I do after the initialization?
Is there any mechanism which will allow me to look what is “under the OpenGL window”?

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.