Search code examples
c++windowsopenglglewwgl

wglCreateContextAttribsARB returns NULL on capable hardware


I have a program which creates an OpenGL 4.0 context on a Windows machine. On my own computer, this code works - however, on my friend's computer, it does not. wglCreateContextAttribsARB returns NULL, even though my friend's Nvidia card supports OpenGL 4.4 and should be able to return a backwards-compatible context. Every other call does as expected.

This is the context creation code:

dc = GetDC(window::get());

PIXELFORMATDESCRIPTOR pfd = { 0 };
pfd.nSize = sizeof(pfd);
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;

int nPixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, nPixelFormat, &pfd);
HGLRC tempRC = wglCreateContext(dc);
wglMakeCurrent(dc, tempRC);
glewInit();

static const int attributes[] = {
    WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
    WGL_CONTEXT_MINOR_VERSION_ARB, 0,
    NULL
};

rc = wglCreateContextAttribsARB(dc, NULL, attributes);

if (rc == NULL) {
    abort();
}

wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempRC);
wglMakeCurrent(dc, rc);

glClearColor(0.2, 0.4, 0.6, 1.0);
glEnable(GL_DEPTH_TEST);
wglSwapIntervalEXT(1);

Another person had a similar problem and posted this question here. However, the thing that fixed the problem for them is not fixing the problem for me. I'm completely stumped.


Solution

  • Check the vendor string of your basic context. Also check whether other OpenGL programs are running correctly.

    There are a few things that can completely disable use of graphics acceleration, mostly related to mirror drivers (remote desktop, screen recording, etc).

    Also, some laptops have both integrated Intel1 graphics (iGPU) and discrete nVidia or AMD graphics (dGPU). Until the driver detects a game or benchmark running, the dGPU will be powered down to extend battery life.

    In C or C++, for nVidia, there's a relatively simple way to request the dGPU for your application:

    extern "C" { _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; }
    

    Unfortunately people are still searching for ways to do this for other hybrids, like AMD.


    1 AMD makes processors with iGPUs also, but their capabilities are more complete (if slow), and if there's also a dGPU present, they work together in a form of unbalanced CrossFire. I therefore assume that explicitly enabling the dGPU isn't necessary in such cases. If you have an AMD APU (combo CPU+iGPU) and nVidia dGPU, I have no idea what happens.