Created
November 17, 2023 04:44
-
-
Save stillwwater/b5f8c659979fb6f9657239b833432d54 to your computer and use it in GitHub Desktop.
Create a modern OpenGL context on Windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Initializes an OpenGL device context for a given window. | |
void | |
gl_create_context(HWND hwnd) | |
{ | |
HDC hdc; | |
HGLRC hglrc; | |
int pfd_index; | |
PIXELFORMATDESCRIPTOR pfd, device_pfd; | |
// in order to load a modern opengl context we first need to load an old | |
// opengl using a dummy window and use it to query the extension to load a | |
// modern context. | |
WNDCLASSA wndclass = {0}; | |
wndclass.lpfnWndProc = DefWindowProcA; | |
wndclass.hInstance = GetModuleHandleA(NULL); | |
wndclass.lpszClassName = "WNDWGLLOADER"; | |
RegisterClassA(&wndclass); | |
HWND glwnd = CreateWindowA("WNDWGLLOADER", "", | |
CS_OWNDC, 0, 0, 0, 0, NULL, NULL, wndclass.hInstance, NULL); | |
if (!glwnd) { | |
fprintf(stderr, "Failed to create dummy GL window (0x%lX)", GetLastError()); | |
} | |
ZeroMemory(&pfd, sizeof(pfd)); | |
// we're doing this again later, for now all we care about is a PFD that | |
// supports opengl | |
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); | |
pfd.nVersion = 1; | |
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; | |
pfd.iPixelType = PFD_TYPE_RGBA; | |
pfd.cColorBits = 32; | |
pfd.cAlphaBits = 8; | |
pfd.cDepthBits = 24; | |
pfd.cStencilBits = 8; | |
pfd.iLayerType = PFD_MAIN_PLANE; | |
hdc = GetDC(glwnd); | |
pfd_index = ChoosePixelFormat(hdc, &pfd); | |
DescribePixelFormat(hdc, pfd_index, sizeof(device_pfd), &device_pfd); | |
if (!SetPixelFormat(hdc, pfd_index, &device_pfd)) { | |
fprintf(stderr, "Failed to find a suitable pixel format for the graphics context (0x%lX).", GetLastError()); | |
} | |
// create opengl device context for the current window | |
hglrc = wglCreateContext(hdc); | |
if (!wglMakeCurrent(hdc, hglrc)) { | |
fprintf(stderr, "Failed to create an opengl context (0x%lX).", GetLastError()); | |
} | |
// load the extensions we need in order to load the real context | |
wglCreateContextAttribsARB = (wglCreateContextAttribsARB_t *)wglGetProcAddress("wglCreateContextAttribsARB"); | |
wglChoosePixelFormatARB = (wglChoosePixelFormatARB_t *)wglGetProcAddress("wglChoosePixelFormatARB"); | |
wglSwapIntervalEXT = (wglSwapIntervalEXT_t *)wglGetProcAddress("wglSwapIntervalEXT"); | |
if (!wglCreateContextAttribsARB || !wglChoosePixelFormatARB) { | |
fprintf(stderr, "Failed to load opengl extensions"); | |
} | |
wglMakeCurrent(hdc, 0); | |
wglDeleteContext(hglrc); | |
ReleaseDC(glwnd, hdc); | |
DestroyWindow(glwnd); | |
if (wglSwapIntervalEXT) | |
wglSwapIntervalEXT(1); | |
opengl32_dll = LoadLibraryA("opengl32.dll"); | |
if (!opengl32_dll) { | |
fprintf(stderr, "Missing opengl32.dll (0x%lX)", GetLastError()); | |
} | |
// do it for real this time | |
hdc = GetDC(hwnd); | |
ZeroMemory(&pfd, sizeof pfd); | |
int pf_attribs[] = { | |
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, | |
WGL_SUPPORT_OPENGL_ARB, GL_TRUE, | |
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, | |
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, | |
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, | |
WGL_COLOR_BITS_ARB, 32, | |
WGL_DEPTH_BITS_ARB, 24, | |
WGL_STENCIL_BITS_ARB, 8, | |
0, | |
}; | |
int context_attribs[] = { | |
WGL_CONTEXT_MAJOR_VERSION_ARB, MV_MIN_GL_MAJOR_VERSION, | |
WGL_CONTEXT_MINOR_VERSION_ARB, MV_MIN_GL_MINOR_VERSION, | |
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, | |
0, | |
} ; | |
UINT n_formats; | |
wglChoosePixelFormatARB(hdc, pf_attribs, NULL, 1, &pfd_index, &n_formats); | |
if (n_formats == 0) { | |
fprintf(stderr, "No suitable pixel format returned by wglChoosePixelFormatARB."); | |
} | |
DescribePixelFormat(hdc, pfd_index, sizeof(pfd), &pfd); | |
if (!SetPixelFormat(hdc, pfd_index, &pfd)) { | |
fprintf(stderr, "Failed to find a suitable pixel format for the graphics context (0x%lX).", GetLastError()); | |
} | |
hglrc = wglCreateContextAttribsARB(hdc, 0, context_attribs); | |
if (!wglMakeCurrent(hdc, hglrc)) { | |
fprintf(stderr, "Failed to create an opengl context (0x%lX).", GetLastError()); | |
} | |
ReleaseDC(hwnd, hdc); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment