Mike Weir
Mike Weir

Reputation: 3189

Multiple windows with shared context

I currently have an implementation that works on all video cards except Mobile Intel GM45. Unfortunately, when I attempt to call wglMakeCurrent(sDC, sRC); on said video card, it crashes completely. I do not have physical access to this video card.

In my method, I'm re-using the same sRC based off the first sDC.

Now, I've read that "if both windows use the same pixelformat, use 1 GL context for both windows" ( http://www.opengl.org/wiki/Platform_specifics:_Windows#Multiple_Windows ) that you can do this with a single context and multiple windows (DCs) and as stated, my implementation works fine on all other video cards.

static HDC sDC = NULL;
static HGLRC sRC = NULL;
static HWND sOldWindow = NULL;

void GfxReset(HWND newWindow) {
    if (sCurrentWindow != newWindow) {
         if (sDC) {
            AssertWGL(wglMakeCurrent(sDC, NULL));
            AssertWGL(ReleaseDC(sCurrentWindow, sDC));
        }

        sDC = GetDC(newWindow);
        Assert(sDC);

        PrepareDC(sDC);

        //Create the render context.
        if (!sRC) {
            sRC = wglCreateContext(sDC);
            Assert(sRC);
        }

        AssertWGL(wglMakeCurrent(sDC, sRC)); // CRASH (not assertion)

        sCurrentWindow = newWindow;
    }
}

static void PrepareDC(HDC hDC) {
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 16;
    pfd.cStencilBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;
    int format = ChoosePixelFormat(hDC, &pfd);
    Assert(format);
    Assert(SetPixelFormat(hDC, format, &pfd));
}

I know that I could implement this using multiple contexts and using wglShareLists. I do not want to take this route due to having to refactor much code with respect to asset loading and whatnot.

Is there a way to implement multiple windows in OpenGL using a single context to greatly simplify texture creation. Otherwise, I would have to be aware of all the windows in my application and have those wglShareLists be pre-applied before I started to load textures, correct?

EDIT: I also tried to implement wglCreateContextAttribsARB in the following way: http://www.opengl.org/wiki/Tutorial%3a_OpenGL_3.1_The_First_Triangle_%28C%2B%2B/Win%29 however, the driver crashes on the call itself.

Upvotes: 3

Views: 1634

Answers (1)

datenwolf
datenwolf

Reputation: 162317

First off, let me tell you how great it is, that you aim for context reuse. However if you need to work around driver bugs (this is, what you're running into, what you do must never crash the program. worst case just produce an error), then well, work around it using wglShareLists.

It's perfectly fine to merge two context's namespaces, as long as there are no object ID collisions. Which means, that your primary context can already be loaded with textures and assets, as long as the context you're merging the namespace into is "virgin". Then all the existing assets of the "older" context will appear in the new one as well.


Something I noticed about your code: You wrote: wglMakeCurrent(sDC, NULL) which suggests you have the conception, that a OpenGL RC was somehow "bound" to a drawable DC. This is not what happens. The association is actually beween contexts and thread. The recommended call would be wglMakeCurrent(NULL, NULL), and quite frankly, I don't even know if the result of a wglMakeCurrent(<someDC not NULL>, NULL) is actually defined. Maybe that's actually the cause of your trouble.

Upvotes: 1

Related Questions