I'm executing the following code to create a core-profile OpenGL context.
Specifically, I am:
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
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 notwglGetExtensionsStringARB
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 viawglGetExtensionsStringARB
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With