4
\$\begingroup\$

There is a VC ++ Win32 project. It connected the library sdl, follows CreateWindowW I have written

 SDL_Window* w = SDL_CreateWindowFrom(hWnd);
 //  SDL_WindowFlags(SDL_WINDOW_OPENGL);
   SDL_GLContext glcontext = SDL_GL_CreateContext(w);
   if (glcontext == NULL)OutputDebugString("null");

But my glcontext == NULL and SDL_GetError returns The specified window isn't an OpenGL window

But if I use SDL_CreateWindow, context turns out successfully

Even after the creation of the window using

static PIXELFORMATDESCRIPTOR pfd = {
       sizeof(PIXELFORMATDESCRIPTOR), // strcut size 
       1,                              // Version number
       PFD_DRAW_TO_WINDOW |    // Flags, draw to a window,
       PFD_SUPPORT_OPENGL, // use OpenGL
       PFD_TYPE_RGBA,          // RGBA pixel values
       24,                     // 24-bit color
       0, 0, 0,                // RGB bits & shift sizes.
       0, 0, 0,                // Don't care about them
       0, 0,                   // No alpha buffer info
       0, 0, 0, 0, 0,          // No accumulation buffer
       32,                     // 32-bit depth buffer
       0,                      // No stencil buffer
       0,                      // No auxiliary buffers
       PFD_MAIN_PLANE,         // Layer type
       0,                      // Reserved (must be 0)
       0,                      // No layer mask
       0,                      // No visible mask
       0                       // No damage mask
   };



   // Did We Get A Device Context?
   hDC = GetDC(hWnd);

   PixelFormat = ChoosePixelFormat(hDC, &pfd);

   SetPixelFormat(hDC, PixelFormat, &pfd);

   // Are We Able To Get A Rendering Context?
   hRC = wglCreateContext(hDC);

   // Try To Activate The Rendering Context
   wglMakeCurrent(hDC, hRC);
   ReleaseDC(hWnd, hDC);
   ShowWindow(hWnd, nCmdShow);


   SDL_InitSubSystem(SDL_INIT_VIDEO);


   SDL_Window* w = SDL_CreateWindowFrom(hWnd);
   SDL_GLContext glcontext = SDL_GL_CreateContext(w);
   if (glcontext == NULL)OutputDebugString("null");

Can not get context. How correctly get the context?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

According to this thread it seems that creating OpenGL contexts from foreign windows isn't currently supported in SDL.

We can either always set the OPENGL flag for foreign windows, allowing you to try to create a context and let it fail if it's not compatible, or we can add a new API, something like SDL_CreateOpenGLWindowFrom()

According to various different threads it seems that there is no OpenGL initialization code in SDL_CreateWindowFrom, so OpenGL context initialization won't work with that method. If you are building your own SDL binaries, you might want to consider modifying the SDL_CreateWindowFrom function by adding the correct SDL_WINDOW_OPENGL flag to the correct place in that method. It seems to be what people experiencing this same problem have done.

Why are you not using SDL for window creation? Letting SDL handle the windowing makes it easier for you to develop, and it will also make your project more cross-platform. When you create the window using SDL_CreateWindow(), just remember to pass in the SDL_WINDOW_OPENGL flag to the creation, and then you should be able to create your OpenGL context just fine.

\$\endgroup\$
6
  • \$\begingroup\$ Because I want to use OpenGL with Win32 GUI \$\endgroup\$
    – Ni55aN
    Commented Oct 24, 2015 at 9:25
  • \$\begingroup\$ Okay. In that case, you have two good options IMHO: You either modify SDL to initialize OpenGL in SDL_CreateWindowFrom or you ask SDL to create the window, and get the window handle from SDL, and perform your GUI on that handle. \$\endgroup\$
    – user35344
    Commented Oct 24, 2015 at 12:00
  • \$\begingroup\$ But how can I add Win32 GUI to the SDL window? \$\endgroup\$
    – Ni55aN
    Commented Oct 24, 2015 at 12:40
  • \$\begingroup\$ Let's continue this discussion in the GDSE chat to keep the comment section more clean. \$\endgroup\$
    – user35344
    Commented Oct 24, 2015 at 12:46
  • \$\begingroup\$ You actually did answer the question, but not sure if SDL_WINDOW_OPENGL is enough to make it compatible. My SDL_GL_CreateContext now just crash. \$\endgroup\$ Commented Feb 25, 2016 at 7:19
3
\$\begingroup\$

So I made it here looking for help on this, and actually managed to get the idea for a fix. Not sure if too late to help anyone who posted here though but there it goes anyway :)

After diving in SDL 2.0.3's source, I found out that one can first create a "dummy" OpenGL window which SDL will look up at when setting up the foreign window. To make this work, you need to set the SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT hint to point at the dummy window before calling SDL_CreateWindowFrom - more info on that here (https://wiki.libsdl.org/SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT).

After creating the foreign window, you might want to destroy the dummy, but that will make SDL_GL_CreateContext crash when called, since SDL keeps track of how many OpenGL windows have been created in order to unload the GL library when all are gone, but won't increase the ref count when creating a foreign OpenGL window. There are 2 fixes for this:

  • Just keep the dummy window alive and hidden during the whole execution (simplest approach, and probably the best)
  • Add the refcount increase to SDL (which was my choice)

If you want to go the latter way you would need to make the block starting at line 354 in file src/video/windows/SDL_windowswindow.c look like this:

// If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well
if (otherWindow->flags & SDL_WINDOW_OPENGL)
{
    window->flags |= SDL_WINDOW_OPENGL;
    if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
        return -1;
    }
    else
    {
        SDL_GL_LoadLibrary(NULL);
    }
}

And here's my code for creating the foreign window:

SDL_Window* pSampleWin = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);

char sBuf[32];
sprintf_s<32>(sBuf, "%p", pSampleWin);

SDL_SetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, sBuf);
mpWindow = SDL_CreateWindowFrom(aInitVars.mpExternalWindowHandle);
SDL_SetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, nullptr);

SDL_DestroyWindow(pSampleWin);  

Note: I haven't dealt with releasing the library reference here, might be worth looking into.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .