Promote JUCE_OPENGL3 and openGL3_2 core context to Windows

Hi Roli team !
Thanks a lot for your last Juce 4.3 enhancements.
juce_opengl module seems to not have moved since a long time.

It could be great if Windows platforms users of this module could benefit of the JUCE_OPENGL3 and OpenGLVersion::openGL3_2 modern core context support.
This is already the case on OSX plateforms (juce_OpenGL_osx.h)

Here my juce_OpenGL_win32.h NativeContext class changes proposal to make it possible:

First of all the NativeContext constructor to take those macro and version enum in account:

NativeContext (Component& component,
const OpenGLPixelFormat& pixelFormat,
void* contextToShareWith,
bool /useMultisampling/,
OpenGLVersion version)
: context (nullptr)
{
dummyComponent = new DummyComponent (*this);
createNativeWindow (component);

        PIXELFORMATDESCRIPTOR pfd;
        initialisePixelFormatDescriptor (pfd, pixelFormat);
        const int pixFormat = ChoosePixelFormat (dc, &pfd);
        if (pixFormat != 0)
            SetPixelFormat (dc, pixFormat, &pfd);
        renderContext = wglCreateContext (dc);
        if (renderContext != 0)
        {
            makeActive();
            initialiseGLExtensions();
            const int wglFormat = wglChoosePixelFormatExtension (pixelFormat);
            deactivateCurrentContext();
#ifndef JUCE_OPENGL3 // D/Labs: enforce delete old context and create a new one according to specified version
            if (wglFormat != pixFormat && wglFormat != 0)
#endif  // JUCE_OPENGL3 D/Labs
            {
                // can't change the pixel format of a window, so need to delete the
                // old one and create a new one..
                releaseDC();
                nativeWindow = nullptr;
                createNativeWindow (component);
                if (SetPixelFormat (dc, wglFormat, &pfd))
                {
                    deleteRenderContext();
                    renderContext = createVersionnedContext(dc, (HGLRC)contextToShareWith, version); /* D/Labs */
                }
            }
#ifdef JUCE_OPENGL3 // D/Labs createVersionnedContext could manage context sharing
            if (version != openGL3_2)
#endif // JUCE_OPENGL3 
              if (contextToShareWith != nullptr) 
                  wglShareLists ((HGLRC) contextToShareWith, renderContext);
            component.getTopLevelComponent()->repaint();
            component.repaint();
        }
    }

Then the new function pointer initialization

    JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglChoosePixelFormatARB,  BOOL, (HDC, const int*, const FLOAT*, UINT, int*, UINT*))
    JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglSwapIntervalEXT,       BOOL, (int))
    JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglGetSwapIntervalEXT,    int, ())
    JUCE_DECLARE_WGL_EXTENSION_FUNCTION (wglCreateContextAttribsARB, HGLRC, (HDC, HGLRC, const int *)) /**D/Labs*/

    #undef JUCE_DECLARE_WGL_EXTENSION_FUNCTION

    void initialiseGLExtensions()
    {
        #define JUCE_INIT_WGL_FUNCTION(name)    name = (type_ ## name) OpenGLHelpers::getExtensionFunction (#name);
        JUCE_INIT_WGL_FUNCTION (wglChoosePixelFormatARB);
        JUCE_INIT_WGL_FUNCTION (wglSwapIntervalEXT);
        JUCE_INIT_WGL_FUNCTION (wglGetSwapIntervalEXT);
        JUCE_INIT_WGL_FUNCTION (wglCreateContextAttribsARB); /**D/Labs*/
        #undef JUCE_INIT_WGL_FUNCTION
    }

and the new createVersionnedContext method:

    HGLRC createVersionnedContext(HDC dc, HGLRC contextToShareWith, OpenGLVersion version) // D/Labs
    {
#ifdef JUCE_OPENGL3
      if (version == openGL3_2)
      {
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define WGL_CONTEXT_FLAGS_ARB 0x2094
        int attribs[64];
        int numAttribs = 0;

        attribs[numAttribs++] = WGL_CONTEXT_MAJOR_VERSION_ARB; attribs[numAttribs++] = 3;
        attribs[numAttribs++] = WGL_CONTEXT_MINOR_VERSION_ARB; attribs[numAttribs++] = 2;
        attribs[numAttribs++] = WGL_CONTEXT_PROFILE_MASK_ARB; attribs[numAttribs++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
        attribs[numAttribs++] = WGL_CONTEXT_FLAGS_ARB; attribs[numAttribs++] = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
#ifdef JUCE_DEBUG
          | WGL_CONTEXT_DEBUG_BIT_ARB
#endif //JUCE_DEBUG
          ;
        attribs[numAttribs++] = 0;
        HGLRC arbRC = wglCreateContextAttribsARB(dc, contextToShareWith, attribs);
        jassert(arbRC != NULL);
        return arbRC;
      }
      else
#endif // JUCE_OPENGL3
        return wglCreateContext (dc);
    }

Of course defines should be moved into juce_MissingGLDefinitions.h.
Note that in debug build, I create a debug GL context. May be juce::OpenGLPixelFormat should be extended to let choose this at runtime.

May be hard coded context version 3.2 should also be part of the juce::OpenGLPixelFormat structure.

Note that to be really core profile compliant, the following deprecated code

#if ! JUCE_ANDROID 
  glEnable (GL_TEXTURE_2D); 
#endif 

should be replaced by

#if ! JUCE_ANDROID && ! JUCE_OPENGL3
  glEnable (GL_TEXTURE_2D); 
#endif 

This can be found one one in juce_OpenGLContext.cpp, one time in juce_OpenGLFrameBuffer.cpp, two time in juce_OpenGLGraphicsContext.cpp

Note that for juce_opengl module DLL build, there is the following missing JUCE_API marco in
juce_OpenGLAppComponent.h line 37.
juce_OpenGLShaderProgram.h line 128
juce_OpenGLShaderProgram.h line 173

Last request: To be able to quickly create a modern OpenGL sandbox, It should be great that OpenGLAppComponent constructor have additional parameters let select the setContinuousRepainting with true by default and the OpenGLVersion with OpenGLContext::defaultGLVersion by default.

Thanks a lot for your concern about this long issue.
Keep me in touch if you need helps for similar patch on Linux platforms.
The best,

2 Likes

Is it because Vulkan is out than nobody is interested anymore about OpenGL enhancement ?

No, we do a lot of GL work! We’re just working through a lot of forum backlog right now, but will get to this!

Ha, its the price of the success !
I don’t want to rush you, and glad to know that.
Thanks for this.