Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't I have WGL_ARB_create_context extension?

Tags:

c++

opengl

I'm executing the following code to create a core-profile OpenGL context.

Specifically, I am:

  1. Creating a dummy window
  2. Using this dummy window to request an OpenGL context (I assume it would be hardware accelerated, but I'm not sure that would even matter)
  3. Using this OpenGL context to load OpenGL function pointers
  4. With these function pointers, I then attempt to use wglCreateContextAttribsARB to create second context specifically with a core profile in a second window.

Code:

WNDCLASSW wcDummy = {0};
wcDummy.lpfnWndProc     = +[](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){return DefWindowProcW(hWnd, message, wParam, lParam);};
wcDummy.hInstance       = GetModuleHandle(0);
wcDummy.hbrBackground   = (HBRUSH)(COLOR_BACKGROUND);
wcDummy.lpszClassName   = L"Dummy";
wcDummy.style           = CS_OWNDC;

if(!RegisterClassW(&wcDummy))
{
    get_and_print_error();
    return false;
}

HWND windowDummy = CreateWindowW(wcDummy.lpszClassName, title.c_str(), WS_DISABLED, 0, 0, 640, 480, 0, 0, wcDummy.hInstance, NULL);
if(windowDummy == NULL)
{
    get_and_print_error();
    return false;
}

PIXELFORMATDESCRIPTOR pfdDummy =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    32,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    24,
    8,
    0, 0, 0, 0, 0, 0
};

HDC dummyDrawingContext = GetDC(windowDummy);

INT pixelFormatDummy = ChoosePixelFormat(dummyDrawingContext, &pfdDummy);
SetPixelFormat(dummyDrawingContext, pixelFormatDummy, &pfdDummy);

HGLRC dummyContext = wglCreateContext(dummyDrawingContext);
wglMakeCurrent(dummyDrawingContext, dummyContext);

if(wglGetCurrentContext() != NULL)
{
    load_gl_functions();
}
else
    return false;

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;

GLint64 numExtensions;
glGetInteger64v(GL_NUM_EXTENSIONS, &numExtensions);
std::cout << "Available Extensions:\n";
for(GLint64 i = 0; i < numExtensions; ++i)
{
    const GLubyte* extensionName = glGetStringi(GL_EXTENSIONS, i);

    std::cout << "\n\t" << (const char*)extensionName;

    if(std::strcmp((const char*)extensionName, "WGL_ARB_create_context") == 0)
    {
        wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
    }
}
std::cout << std::endl;

wglDeleteContext(dummyContext);
DestroyWindow(windowDummy);

WNDCLASSW wc = {0};
wc.lpfnWndProc      = Window::WndProc;
wc.hInstance        = GetModuleHandle(0);
wc.hbrBackground    = (HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName    = title.c_str();
wc.style = CS_OWNDC;

if(!RegisterClassW(&wc))
{
    get_and_print_error();
    return false;
}

HWND window = CreateWindowW(wc.lpszClassName, title.c_str(), WS_OVERLAPPED|WS_VISIBLE|WS_SYSMENU ,0,0,640,480,0,0,wc.hInstance,this);
if(window == NULL)
{
    get_and_print_error();
    return false;
}

PIXELFORMATDESCRIPTOR pfd =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    32,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    24,
    8,
    0, 0, 0, 0, 0, 0
};

HDC m_drawingContext = GetDC(window);

INT pixelFormat = ChoosePixelFormat(m_drawingContext, &pfd);
SetPixelFormat(m_drawingContext, pixelFormat, &pfd);

const GLint attribList[] =
{
    WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
    WGL_CONTEXT_MINOR_VERSION_ARB, 4,
    WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
    0
};

m_glRenderContext = wglCreateContextAttribsARB(m_drawingContext, 0, attribList);

wglMakeCurrent(m_drawingContext, m_glRenderContext);

if(wglGetCurrentContext() != NULL)
{
    load_gl_functions();
}
else
    return false;

const GLubyte* driver = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);

std::wcout << "Device:       " << std::wstring(convert_gl_string_to_win32_string(driver)) << std::endl;
std::wcout << "GL Version:   " << std::wstring(convert_gl_string_to_win32_string(version)) << std::endl;
std::wcout << "GLSL Version: " << std::wstring(convert_gl_string_to_win32_string(glslVersion)) << std::endl;
std::wcout << std::endl;

The problem is that the WGL_ARB_create_context extension does not exist.

However, if I forget about checking the list of extensions, i.e. forgo the loop and simply:

wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");

I end up with a function pointer and everything works correctly.

Why does my list of available extensions not provide the WGL_ARB_create_context string, even though the extension exists?

EDIT I have an AMD Radeon HD 7900 seriesY

like image 922
NeomerArcana Avatar asked Dec 23 '22 14:12

NeomerArcana


2 Answers

Why does my list of available extensions not provide the WGL_ARB_create_context string, even though the extension exists?

Because WGL extensions are not required to be advertised via the GL extension strings. There is the WGL_ARB_extension_string extension which controls the advertisement of WGL extensions. Quoting from that spec:

Applications should call wglGetProcAddress to see whether or not wglGetExtensionsStringARB is supported. If it is supported then it can be used to determine which WGL extensions are supported by the device.

So, to not create any recursive issue, the function pointer is guaranteed to be valid if it is non-NULL.

If you wonder why some WGL extensions are still in the GL extension string: THis is a legacy thing once more. Quoting issue 1 from that extenstion spec again:

Note that extensions that were previously advertised via glGetString(e.g., the swap interval extension) should continue to be advertised there so existing applications don't break. They should also be advertised via wglGetExtensionsStringARB so new applications can make one call to find out which WGL extensions are supported.

Side note:

Your GL extension query mechanism using glGetStringi will only work beginning with GL 3.0. Both glGetInteger64v and glGetStringi might not be available, and this code will most likely just crash if run on some older GPU, or when falling back to Microsoft's GL 1.1 renderer.

like image 154
derhass Avatar answered Feb 12 '23 12:02

derhass


The reason why the extension WGL_ARB_create_context is not in the list of supported extensions is because it is technically not an OpenGL extension but a WGL extension. glGetStringi only returns OpenGL extensions but not WGL ones1.

To query WGL extensions, the WGL_ARB_extensions_string extension has to be used which provides the wglGetExtensionsStringARB method. The only way to check whether this extension is available is to query the address of wglGetExtensionsStringARB and see whether it returns 0.

Applications should call wglGetProcAddress to see whether or not wglGetExtensionsStringARB is supported.

Note, that if you only want to know whether WGL_ARB_create_context it is easier to query the address of wglCreateContextARB and check that result.


1 There are a few exceptions due to historical reasons. The extension descriptions states:

Note that extensions that were previously advertised via glGetString (e.g., the swap interval extension) should continue to be advertised there so existing applications don't break. They should also be advertised via wglGetExtensionsStringARB so new applications can make one call to find out which WGL extensions are supported.

like image 20
BDL Avatar answered Feb 12 '23 14:02

BDL