#+build windows package opengl_backend import "core:log" import win32 "core:sys/windows" import gl "vendor:OpenGL" import bk ".." GL_Context :: struct { hwnd: win32.HWND, hdc: win32.HDC, gl_ctx: win32.HGLRC, width: u32, height: u32, } create_gl_context :: proc( surface: bk.Surface_Desc, width, height: u32, title: cstring, ) -> ( GL_Context, bool, ) { if surface.kind != .Win32 || surface.win32.hwnd == nil { log.error("gpu/opengl: Windows OpenGL backend requires Win32 surface") return {}, false } hwnd := win32.HWND(surface.win32.hwnd) hdc := win32.GetDC(hwnd) if hdc == nil { log.error("gpu/opengl: GetDC failed") return {}, false } pfd := win32.PIXELFORMATDESCRIPTOR { nSize = size_of(win32.PIXELFORMATDESCRIPTOR), nVersion = 1, dwFlags = win32.PFD_DRAW_TO_WINDOW | win32.PFD_SUPPORT_OPENGL | win32.PFD_DOUBLEBUFFER, iPixelType = win32.PFD_TYPE_RGBA, cColorBits = 32, cDepthBits = 24, cStencilBits = 8, iLayerType = win32.PFD_MAIN_PLANE, } pixel_format := win32.ChoosePixelFormat(hdc, &pfd) if pixel_format == 0 || !win32.SetPixelFormat(hdc, pixel_format, &pfd) { log.error("gpu/opengl: failed to set Win32 pixel format") win32.ReleaseDC(hwnd, hdc) return {}, false } dummy := win32.wglCreateContext(hdc) if dummy == nil || !win32.wglMakeCurrent(hdc, dummy) { log.error("gpu/opengl: failed to create WGL bootstrap context") if dummy != nil do win32.wglDeleteContext(dummy) win32.ReleaseDC(hwnd, hdc) return {}, false } gl.load_up_to(4, 5, win32.gl_set_proc_address) win32.wglCreateContextAttribsARB = auto_cast win32.wglGetProcAddress( "wglCreateContextAttribsARB", ) if win32.wglCreateContextAttribsARB == nil { log.error("gpu/opengl: WGL_ARB_create_context unavailable") win32.wglMakeCurrent(nil, nil) win32.wglDeleteContext(dummy) win32.ReleaseDC(hwnd, hdc) return {}, false } attribs := [?]c_int { win32.CONTEXT_MAJOR_VERSION_ARB, 4, win32.CONTEXT_MINOR_VERSION_ARB, 5, win32.CONTEXT_PROFILE_MASK_ARB, win32.CONTEXT_CORE_PROFILE_BIT_ARB, 0, } gl_ctx := win32.wglCreateContextAttribsARB(hdc, nil, &attribs[0]) win32.wglMakeCurrent(nil, nil) win32.wglDeleteContext(dummy) if gl_ctx == nil || !win32.wglMakeCurrent(hdc, gl_ctx) { log.error("gpu/opengl: failed to create WGL 4.5 core context") if gl_ctx != nil do win32.wglDeleteContext(gl_ctx) win32.ReleaseDC(hwnd, hdc) return {}, false } gl.load_up_to(4, 5, win32.gl_set_proc_address) return {hwnd = hwnd, hdc = hdc, gl_ctx = gl_ctx, width = width, height = height}, true } destroy_gl_context :: proc(ctx: ^GL_Context) { if ctx == nil || ctx.hdc == nil do return win32.wglMakeCurrent(nil, nil) if ctx.gl_ctx != nil do win32.wglDeleteContext(ctx.gl_ctx) if ctx.hwnd != nil do win32.ReleaseDC(ctx.hwnd, ctx.hdc) ctx^ = {} } make_gl_context_current :: proc(ctx: ^GL_Context) -> bool { if ctx == nil || ctx.hdc == nil || ctx.gl_ctx == nil do return false return win32.wglMakeCurrent(ctx.hdc, ctx.gl_ctx) } swap_gl_context :: proc(ctx: ^GL_Context) -> bool { if ctx == nil || ctx.hdc == nil do return false return win32.SwapBuffers(ctx.hdc) } resize_gl_context :: proc(ctx: ^GL_Context, width, height: u32) { if ctx == nil do return ctx.width = width ctx.height = height } gl_context_set_proc_address :: proc(p: rawptr, name: cstring) { win32.gl_set_proc_address(p, name) }