OpenGL 3.0 context

“Great” news : OpenGL 3.0 is out! Well, after skimming over the new specs there’s really no new stuff – besindes of some manufacturer specific extensions going EXT or ARB and the deprecated markings sig. NVIDIA announced full GL3.0 support on G80 series with driver version 181.00+ so I tried to play around with the new context type – here’s some code 🙂

#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094

typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList);

void GLWindow::CreateGL() {
    if(m_hWnd == NULL) {
        throw std::exception("Window handle cannot be NULL");
    }    // If we have no window, we cannot continue

    // If any of the following steps fail, we shutdown any OpenGL elements that have been started and exit
    if (!(m_hDC=GetDC(m_hWnd))) {                        // Retrieve the Device Context for this window
        ShutdownGL();
        throw std::exception("Could not get window Device Context");
    }

    //Create the PixelFormatDescriptor, which describes to OpenGL the pixel properties such as depth, color, and alpha channels
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof(PIXELFORMATDESCRIPTOR) );
    pfd.nVersion = 1;                                                                // The PFD version, always 1
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;        // The properties of the PFD, in this case OpenGL support and double buffering
    pfd.iPixelType = PFD_TYPE_RGBA;                                                    // The type of Pixels we're dealing with
    pfd.cColorBits = m_displaySettings.colorBits;                                    // The color depth of the window
    pfd.cAlphaBits = m_displaySettings.alphaBits;                                    // The alpha depth of the window
    pfd.cDepthBits = m_displaySettings.depthBits;                                    // The number of bits to use for the depth buffer
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);                                        // The size of this structure

    int pixelFormat;
    if (!(pixelFormat = ChoosePixelFormat(m_hDC,&pfd))) {
        ShutdownGL();
        throw std::exception("Could not find a suitable Pixel Format");
    }

    if(!SetPixelFormat(m_hDC,pixelFormat,&pfd)) {            // Set the format of the Device Context
        ShutdownGL();
        throw std::exception("Could not set the Pixel Format");
    }

    // NV GL 3.0
    HGLRC tempContext = NULL;
    if(!(tempContext = wglCreateContext(m_hDC))) {                    // Bind the render context for drawing
        ShutdownGL();
        throw std::exception("Could not create temp. Render Context");
    }

    if(!wglMakeCurrent(m_hDC, tempContext)) {                    // Bind the render context for drawing
        wglDeleteContext(tempContext);
        ShutdownGL();
        throw std::exception("Could not make temp. Render Context current");
    }

    int attribs[] = {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,//we want a 3.0 context
        WGL_CONTEXT_MINOR_VERSION_ARB, 0,//and it shall be forward compatible so that we can only use up to date functionality
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        0 //zero indicates the end of the array
    };

    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; //pointer to the method
    wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");

    if(wglCreateContextAttribsARB == NULL) { //OpenGL 3.0 is not supported
        // Bind the render context for drawing
        wglDeleteContext(tempContext);
        ShutdownGL();
        throw std::exception("Cannot get Proc Adress for GL 3.0 CreateContextAttribs");
    }

    if (!(m_hRC=wglCreateContextAttribsARB(m_hDC,0, attribs))) {
        wglDeleteContext(tempContext);
        ShutdownGL();
        throw std::exception("Can't Create A GL 3.0 Rendering Context.");
    }
    wglDeleteContext(tempContext);

    if(!wglMakeCurrent(m_hDC,m_hRC)) { // Try To Activate The Rendering Context
        ShutdownGL();
        throw std::exception("Could not make Render Context current");
    }
}

The key is the PFNWGLCREATECONTEXTATTRIBSARBPROC function pointer that is supplied by the opengl dll (see its declation on line 5). Using this layout we can fetch the function using a casted wglGetProcAddress() to the new function “wglCreateContextAttribsARB”. So the difference with GL3.0 here is to use a different method when creating a GL-context. The former method would still create an GL2 context. Alternatively one may use a new version of a utility/ext wrapper (glut, glew, glext, etc.) which supplies the new function directly.

Here’s the complete test project: gl30context_sample_code.

Advertisements

2 thoughts on “OpenGL 3.0 context

  1. Hello;
    i’m developing an app that would use opengl 3 with wxwidget, but i have problem configuring it, so i was wondering if i can use your code.
    thanks

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s