calling glReadPixels from another thread

I am trying to call glReadPixels from a thread that is not my rendering thread and I get no data. I understand it’s because the two threads don’t have the same rendering context. I have tried sharing my rendering context but it is not allowed. All I need to do is access my frame buffer from another thread and I don’t want to manually copy the buffer between the threads. Anyone have any suggestions?

Thanks in advance

You can pass pointer to memory area from second thread to the thead which own the context, and let the first thread read pixels for you, in such way you’ll avoid the unnecessary copy operation. I think your paralelism will not hurt from this, as actually you don’t want to read framebuffer data anytime, but just when frame is rendered.

This would work, but I would still have to read the frame buffer in my rendering thread. I want o avoid this because I am rendering on the whole screen and the glReadPixels call greatly reduces my frame rate.

In any case you can not render something while you read back data, so I doubt that it is possible to gain some performance win from fact that you read from second thread while rendering thread stall and waiting for second thread finish the reading…

What do you mean with :

Originally posted by cloza:
I have tried sharing my rendering context but it is not allowed.
What prevents you from sharing your contexts ? What OS, gl window manager do you use ? What languages ?

I meant I tried using the same rendering context for my second thread by using glMakeCurrent and I got a error because it was already in use. My code is in C++ on Windows. I am not using straight openGL. I am using a commercial rendering package that is built on openGL.

There should have a function in order to create your context that allows you to specify another variable for a second shared context.

Under linux / glx:

GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext share_list, Bool direct); 

Sorry, but I don’t know for your commercial product. But there should have almost the same function just because I can see ‘glMakeCurrent’ that looks like glXMakeCurrent and if I remember well wglMakeCurrent too.
You can surely find further documentation about opengl and multithreading on this website.

Hope this helps.

It’s not possible.

A single context can’t be current in multiple threads.
“Objects” can be shared between multiple contexts. But glReadPixels is certainly not an object …

I’ve found a way to do it but it will only work under Windows. Here’s the code:

// create a DC for the screen and create     
// a memory DC compatible with screen DC
HDC hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hMemDC = CreateCompatibleDC(hScrDC);

// create a bitmap compatible with the screen DC
HBITMAP hBitmap = CreateCompatibleBitmap(hScrDC, width, height);

// select new bitmap into memory DC
(HBITMAP*)SelectObject(hMemDC, hBitmap);
// copy pixel data from screen DC to memory DC 
BitBlt(hMemDC, origX, origY, width, height, hScrDC, srcOrigX, srcOrigY, SRCCOPY);

BITMAP bmp;
// get updated bitmap back
GetObject(hBitmap, sizeof(BITMAP), &bmp);
			
BITMAPINFO bi;
// get pixel data in RGB format
// bi struct specifies the format data
// pdata will hold pixel data
GetDIBits(hMemDC, hBitmap, 0, height, pdata, &bi, DIB_RGB_COLORS);
						
  

pdata holds raw RGB so it can be written to bitmap or AVI file. It can be run in another thread or from another application because it uses the screens pixel data.

Thanks for your sharing ! And you’re right, this will work only under Windows and strangely it has nothing to do with wgl.