Search code examples
c++openglglfwglew

Why am I not getting a forward compatible OpenGL context with GLFW?


To my knowledge, when I set these context constraints on GLFW:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

I should get the maximum available OpenGL context on the running machine, provided that it's above OpenGL 3.3. However, by using glGetString to get the OpenGL context version, I am finding that this is not the case. Everytime I query glGetString for the context version, I only get the major and minor versions I set with glfwWindowHint, nothing above. Keep in mind, my GPU supports OpenGL 4.5.

Another thing to note, when I set no constraints whatsoever, I do in fact get an OpenGL 4.5 context.

Here is the full source code, which seems to replicate the problem:

#define GLEW_STATIC

#include <iostream>

#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <glm\glm.hpp>

int main(int argc, char argv[])
{

    if (!glfwInit())
    {
        std::cerr  << "Failed to initialize GLFW 3.0.4" << std::endl;
        getchar();

        glfwTerminate();
        return -1;
    }

    std::cout << "Initialized GLFW 3.0.4" << std::endl;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* m_window = glfwCreateWindow(640, 480, "Koala", NULL, NULL);

    if (!m_window)
    {
        std::cerr  << "Failed to create OpenGL 3.3+ context" << std::endl;
        getchar();
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(m_window);

    std::cout << "Created OpenGL 3.3+ context" << std::endl;

    glewExperimental = GL_TRUE;

    if (glewInit() != GLEW_OK)
    {
        std::cerr << "Failed to initialize GLEW 1.11.0" << std::endl;
        getchar();
        glfwTerminate();
        return -1;
    }

    std::cout << "Initialized GLEW 1.11.0" << std::endl;

    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* version = glGetString(GL_VERSION);

    std::cout << "GPU: " << renderer << std::endl;
    std::cout << "OpenGL Version: " << version << std::endl;

    while (!glfwWindowShouldClose(m_window))
    {
        glfwSwapBuffers(m_window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;

}

Solution

  • I should get the maximum available OpenGL context on the running machine, provided that it's above OpenGL 3.3.

    That's not the way it is defined. From the GLFW documentation:

    The GLFW_CONTEXT_VERSION_MAJOR and GLFW_CONTEXT_VERSION_MINOR hints specify the client API version that the created context must be compatible with.

    For OpenGL, these hints are not hard constraints, as they don't have to match exactly, but glfwCreateWindow will still fail if the resulting OpenGL version is less than the one requested.

    While there is no way to ask the driver for a context of the highest supported version, most drivers provide this when you ask GLFW for a version 1.0 context.

    So "most drivers" would give you what you expected, but this is not guaranteed.

    The typical usage is that you specify the minimum version that supports all the features that your code uses. Then you don't care if you get exactly that version, or possibly a higher one. But you know that you will get a failure if the minimum version is not supported.

    If you want to dynamically test which version is supported, your best bet is probably to first specify the highest version you can take advantage of, and test the return value of glfwCreateWindow(). If it fails, reduce the version as long as it fails, and call glfwCreateWindow() again, until you reach the minimum version you can run with. Then you can keep track of which version succeeded, or the version reported by glGetString(GL_VERSION), and use that to decide at runtime which features you can use.