3

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.

Mike Weir
  • 2,858
  • 1
  • 26
  • 44

1 Answers1

1

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.

datenwolf
  • 149,702
  • 12
  • 167
  • 273
  • I've tried both with two NULLs and one NULL. In all code I've found that referenced driver bugs, the less risky solution was actually providing the RC. I don't quite understand your actual answer though, in terms of application. I understand what you're explaining of course. – Mike Weir Jul 25 '14 at 13:30
  • @PhoenixX_2: Due to your question I was re-reading the specification for glXMakeCurrent and wglMakeCurrent once again. And it seems that there's a discrepancy between their semantics: glXMakeCurrent wants to be called `glXMakeCurrent(None, NULL)` for detaching the OpenGL context from the thread, while the documentation for `wglMakeCurrent` hints at, that it expects a DC handle for its first argument. Interesting. – datenwolf Jul 25 '14 at 14:50
  • Regardless, I tried both methods and it didn't work :P. – Mike Weir Jul 26 '14 at 12:04
  • @PhoenixX_2: Well, then congratualtions: You probably found a driver bug. Time to write a bug report… – datenwolf Jul 26 '14 at 13:26
  • I'm about to lose 100 points for a bounty that will go to you for an answer you have yet to answer. Can you please at least flush out your answer. Perhaps a suggestion for off screen buffer or an actual implementation suggestion. Again, I got nothing from this answer and it doesn't answer the question. Sorry to come off this way. – Mike Weir Aug 13 '14 at 17:11
  • @PhoenixX_2: Hmm, I could hack some example code. What exactly should it do? Context reuse and graceful fallback to context sharing if a blacklisted driver is detected? – datenwolf Aug 13 '14 at 18:07
  • Any of that sounds like it could be of use :). Thanks! – Mike Weir Aug 13 '14 at 23:33
  • @PhoenixX_2: Just wanted to let you know, that I didn't forget you. I just have to shave some Yak to make this a fully self contained, fully working example. I just finished creating the two windows and with context creation / reuse branches. Still lacks some demo on the use of the same texture but separate FBO for each window though. You can see the code here (part of my wglarb library, as a test case) https://github.com/datenwolf/wglarb/blob/test_shared/test/shared.c – once the example is done, I'll paste the code into my answer. – datenwolf Aug 18 '14 at 11:09
  • Don't feel too pressured - I can't award the bounty any longer, and I will likely take an offscreen buffer approach and just blit to the window that's needed at the time. Lame, but seems to be my best chance of getting around this driver bug. – Mike Weir Aug 19 '14 at 00:54
  • @PhoenixX_2: Out of curiosity: You mention that the driver crashes on the call to wglCreateContextAttribsARB – which is odd. Could you please have a look at my *wglarb* library and try to build and run the *layered* test program? *wglarb* is a little wrapper that takes care of all the Yak-shaving involved when one wants to use the *wgl…Attribs* functions. And I'm quite positive it's one of the few codes doing that, that is thread safe (and getting also other things right). I haven't fleshed out the build system though; you'll probably have to tinker with the Makefile or create a VS solution. – datenwolf Aug 19 '14 at 09:19