Multithreading with One Context

Hi all,

So I know there’s been some discussion about multithreading using multiple contexts, etc. I have a bit of an interesting situation. I know the application I’m writing is less-efficient, but that’s not the point. We’re mainly using OpenGL as just a visualization of what the parallelization code is doing in the app. So here’s what I’m trying to do:

I have an OpenGL window that displays the Mandelbrot set, which it first must compute. The computation is done in parallel, row by row, but an arbitrary number of threads. I need the threads to be able to draw to the same window, same viewport, etc, so you can see the work that each thread has completed so far.

For now I’m just trying to get this working on Windows, but eventually it will need to work on Linux, as well. I’ve used GLUT to create and initialize the window, and I’m trying to use either one or multiple contexts (trying both ways) to let the threads take turns drawing to the window. Here’s a basic outline (which isn’t working in multi-threaded mode yet):


Render (called from within display callback):
clear window
deviceContext := wglGetCurrentDC()
threadContext := wglCreateContext(deviceContext)
[begin parallel section]
for each row assigned to thread
    compute pixel values for row
    obtain write lock
        wglMakeCurrent(deviceContext, threadContext)
        for each pixel in row
            glColor3*(color)
            glRecti(...)
        end for
        wglMakeCurrent(NULL, NULL)
        glFlush()
    release lock
end for
wglDeleteContext(threadContext)

The other way I’ve tried this is to let each thread have its own context (created within the parallel section), but it had the exact same result, which was that only a single large rectangle gets drawn (1/4 the size of the window) in the upper-right corner.

I would do a makeCurrent( 0,0 ) before the parallel section. I’m not sure if the created context is current automatically. Do the glFlush before makecurrent( 0, 0 ).

Otherwise the code looks valid.

I would also use glDrawPixels or a textured quad to get the pixels on screen.

OK, I tried those recommendations, and now it just renders the four corners of a rectangle (the same rectangle as before, 1/4 the size of the viewport). When I comment out ONLY the parallelization parts (OpenMP pragmas) and the wglMakeCurrent calls, then it renders correctly. When I leave the parallel pragmas in but render with only one thread, then it also renders correctly. So something is up with the wglMakeCurrent calls.