[wgl] Keep dummy window/context around for gl context creation, and don't reload wgl functions every time
This commit is contained in:
parent
64d7b31e5c
commit
5ac512c15e
|
@ -20,17 +20,94 @@
|
||||||
WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \
|
||||||
|
|
||||||
//NOTE: wgl function pointers declarations
|
//NOTE: wgl function pointers declarations
|
||||||
|
|
||||||
#define WGL_PROC(type, name) _cat3_(PFN, type, PROC) name = 0;
|
#define WGL_PROC(type, name) _cat3_(PFN, type, PROC) name = 0;
|
||||||
WGL_PROC_LIST
|
WGL_PROC_LIST
|
||||||
#undef WGL_PROC
|
#undef WGL_PROC
|
||||||
|
|
||||||
//NOTE: wgl loader
|
//NOTE: wgl loader
|
||||||
static void wgl_load_procs()
|
|
||||||
|
typedef struct wgl_dummy_context
|
||||||
{
|
{
|
||||||
|
bool init;
|
||||||
|
HWND hWnd;
|
||||||
|
HDC hDC;
|
||||||
|
HGLRC glContext;
|
||||||
|
|
||||||
|
} wgl_dummy_context;
|
||||||
|
|
||||||
|
static wgl_dummy_context __mgWGLDummyContext = {0};
|
||||||
|
|
||||||
|
static void wgl_init()
|
||||||
|
{
|
||||||
|
if(!__mgWGLDummyContext.init)
|
||||||
|
{
|
||||||
|
//NOTE: create a dummy window
|
||||||
|
WNDCLASS windowClass = {.style = CS_OWNDC,
|
||||||
|
.lpfnWndProc = DefWindowProc,
|
||||||
|
.hInstance = GetModuleHandleW(NULL),
|
||||||
|
.lpszClassName = "wgl_helper_window_class",
|
||||||
|
.hCursor = LoadCursor(0, IDC_ARROW)};
|
||||||
|
|
||||||
|
if(!RegisterClass(&windowClass))
|
||||||
|
{
|
||||||
|
//TODO: error
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
__mgWGLDummyContext.hWnd = CreateWindow("wgl_helper_window_class",
|
||||||
|
"dummy",
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
0, 0, 100, 100,
|
||||||
|
0, 0, windowClass.hInstance, 0);
|
||||||
|
|
||||||
|
if(!__mgWGLDummyContext.hWnd)
|
||||||
|
{
|
||||||
|
//TODO: error
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
__mgWGLDummyContext.hDC = GetDC(__mgWGLDummyContext.hWnd);
|
||||||
|
|
||||||
|
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
||||||
|
{
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
1,
|
||||||
|
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
|
||||||
|
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
|
||||||
|
32, // Colordepth of the framebuffer.
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
24, // Number of bits for the depthbuffer
|
||||||
|
8, // Number of bits for the stencilbuffer
|
||||||
|
0, // Number of Aux buffers in the framebuffer.
|
||||||
|
PFD_MAIN_PLANE,
|
||||||
|
0,
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
int pixelFormat = ChoosePixelFormat(__mgWGLDummyContext.hDC, &pixelFormatDesc);
|
||||||
|
SetPixelFormat(__mgWGLDummyContext.hDC, pixelFormat, &pixelFormatDesc);
|
||||||
|
|
||||||
|
__mgWGLDummyContext.glContext = wglCreateContext(__mgWGLDummyContext.hDC);
|
||||||
|
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
||||||
|
|
||||||
|
//NOTE(martin): now load WGL extension functions
|
||||||
#define WGL_PROC(type, name) name = (_cat3_(PFN, type, PROC))wglGetProcAddress( #name );
|
#define WGL_PROC(type, name) name = (_cat3_(PFN, type, PROC))wglGetProcAddress( #name );
|
||||||
WGL_PROC_LIST
|
WGL_PROC_LIST
|
||||||
#undef WGL_PROC
|
#undef WGL_PROC
|
||||||
|
|
||||||
|
__mgWGLDummyContext.init = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wglMakeCurrent(__mgWGLDummyContext.hDC, __mgWGLDummyContext.glContext);
|
||||||
|
}
|
||||||
|
quit:;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef WGL_PROC_LIST
|
#undef WGL_PROC_LIST
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,61 +254,7 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||||
if(windowData)
|
if(windowData)
|
||||||
{
|
{
|
||||||
//NOTE: create a dummy window
|
wgl_init();
|
||||||
WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
|
||||||
.lpfnWndProc = WinProc,
|
|
||||||
.hInstance = GetModuleHandleW(NULL),
|
|
||||||
.lpszClassName = "HelperWindowClass",
|
|
||||||
.hCursor = LoadCursor(0, IDC_ARROW)};
|
|
||||||
|
|
||||||
if(!RegisterClass(&windowClass))
|
|
||||||
{
|
|
||||||
//TODO: error
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND helperWindowHandle = CreateWindow("HelperWindowClass", "Test Window",
|
|
||||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
||||||
800, 600,
|
|
||||||
0, 0, windowClass.hInstance, 0);
|
|
||||||
|
|
||||||
if(!helperWindowHandle)
|
|
||||||
{
|
|
||||||
//TODO: error
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE(martin): create a dummy OpenGL context, to be able to load extensions
|
|
||||||
HDC dummyDC = GetDC(helperWindowHandle);
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
|
||||||
{
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
1,
|
|
||||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
|
|
||||||
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
|
|
||||||
32, // Colordepth of the framebuffer.
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
24, // Number of bits for the depthbuffer
|
|
||||||
8, // Number of bits for the stencilbuffer
|
|
||||||
0, // Number of Aux buffers in the framebuffer.
|
|
||||||
PFD_MAIN_PLANE,
|
|
||||||
0,
|
|
||||||
0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
int pixelFormat = ChoosePixelFormat(dummyDC, &pixelFormatDesc);
|
|
||||||
SetPixelFormat(dummyDC, pixelFormat, &pixelFormatDesc);
|
|
||||||
|
|
||||||
HGLRC dummyGLContext = wglCreateContext(dummyDC);
|
|
||||||
wglMakeCurrent(dummyDC, dummyGLContext);
|
|
||||||
|
|
||||||
//NOTE(martin): now load WGL extension functions
|
|
||||||
wgl_load_procs();
|
|
||||||
|
|
||||||
//NOTE(martin): create a child window for the surface
|
//NOTE(martin): create a child window for the surface
|
||||||
WNDCLASS childWindowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
WNDCLASS childWindowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
||||||
|
@ -258,7 +281,27 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
childWindowClass.hInstance,
|
childWindowClass.hInstance,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
//NOTE(martin): now create the true pixel format and gl context
|
//NOTE(martin): create the pixel format and gl context
|
||||||
|
PIXELFORMATDESCRIPTOR pixelFormatDesc =
|
||||||
|
{
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
1,
|
||||||
|
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
|
||||||
|
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
|
||||||
|
32, // Colordepth of the framebuffer.
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
24, // Number of bits for the depthbuffer
|
||||||
|
8, // Number of bits for the stencilbuffer
|
||||||
|
0, // Number of Aux buffers in the framebuffer.
|
||||||
|
PFD_MAIN_PLANE,
|
||||||
|
0,
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
int pixelFormatAttrs[] = {
|
int pixelFormatAttrs[] = {
|
||||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||||
|
@ -271,6 +314,7 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
|
|
||||||
HDC hDC = GetDC(childWindow);
|
HDC hDC = GetDC(childWindow);
|
||||||
u32 numFormats = 0;
|
u32 numFormats = 0;
|
||||||
|
int pixelFormat = 0;
|
||||||
|
|
||||||
wglChoosePixelFormatARB(hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats);
|
wglChoosePixelFormatARB(hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats);
|
||||||
|
|
||||||
|
@ -286,7 +330,7 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||||
0};
|
0};
|
||||||
|
|
||||||
HGLRC glContext = wglCreateContextAttribsARB(hDC, dummyGLContext, contextAttrs);
|
HGLRC glContext = wglCreateContextAttribsARB(hDC, __mgWGLDummyContext.glContext, contextAttrs);
|
||||||
|
|
||||||
if(!glContext)
|
if(!glContext)
|
||||||
{
|
{
|
||||||
|
@ -295,11 +339,6 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
printf("error: %i\n", error);
|
printf("error: %i\n", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: destroy dummy context and dummy window
|
|
||||||
wglMakeCurrent(hDC, 0);
|
|
||||||
wglDeleteContext(dummyGLContext);
|
|
||||||
DestroyWindow(helperWindowHandle);
|
|
||||||
|
|
||||||
//NOTE: make gl context current
|
//NOTE: make gl context current
|
||||||
wglMakeCurrent(hDC, glContext);
|
wglMakeCurrent(hDC, glContext);
|
||||||
wglSwapIntervalEXT(1);
|
wglSwapIntervalEXT(1);
|
||||||
|
@ -317,12 +356,10 @@ mg_surface mg_wgl_surface_create_for_window(mp_window window)
|
||||||
surface->interface.setFrame = mg_wgl_surface_set_frame;
|
surface->interface.setFrame = mg_wgl_surface_set_frame;
|
||||||
surface->interface.getHidden = mg_wgl_surface_get_hidden;
|
surface->interface.getHidden = mg_wgl_surface_get_hidden;
|
||||||
surface->interface.setHidden = mg_wgl_surface_set_hidden;
|
surface->interface.setHidden = mg_wgl_surface_set_hidden;
|
||||||
//TODO: get/set frame/hidden
|
|
||||||
|
|
||||||
surface->hWnd = childWindow;
|
surface->hWnd = childWindow;
|
||||||
surface->hDC = hDC;
|
surface->hDC = hDC;
|
||||||
surface->glContext = glContext;
|
surface->glContext = glContext;
|
||||||
|
|
||||||
surface->contentsScaling = contentsScaling;
|
surface->contentsScaling = contentsScaling;
|
||||||
|
|
||||||
mg_gl_load_gl43(&surface->api, mg_wgl_get_proc);
|
mg_gl_load_gl43(&surface->api, mg_wgl_get_proc);
|
||||||
|
|
7
todo.txt
7
todo.txt
|
@ -12,7 +12,7 @@ Overview
|
||||||
[ ] Baked fonts?
|
[ ] Baked fonts?
|
||||||
|
|
||||||
[x] Allow different versions of GL/GLES to co-exist
|
[x] Allow different versions of GL/GLES to co-exist
|
||||||
[>] Allow selecting version of GL/GLES context when creating surface
|
[/] Allow selecting version of GL/GLES context when creating surface
|
||||||
- pass/set attributes when creating surface?
|
- pass/set attributes when creating surface?
|
||||||
|
|
||||||
[ ] Check that we can make GLES and GL surfaces co-exist in the app
|
[ ] Check that we can make GLES and GL surfaces co-exist in the app
|
||||||
|
@ -24,10 +24,11 @@ Overview
|
||||||
[/] Automatic surface resizing
|
[/] Automatic surface resizing
|
||||||
[/] Keep dummy window/dummy context around for gl context creation, and don't reload wgl functions every time
|
[/] Keep dummy window/dummy context around for gl context creation, and don't reload wgl functions every time
|
||||||
|
|
||||||
[!] Sort out gles contents scaling for high dpi on osx
|
|
||||||
[!] win32 surfaces: only register surface child window once?
|
|
||||||
[!] Make linking with libEGL optional, even if EGL backend is compiled in milepost?
|
[!] Make linking with libEGL optional, even if EGL backend is compiled in milepost?
|
||||||
[!] Bundle examples with their own resources?? (e.g. avoiding clashes in metal libs files in bin directory)
|
[!] Bundle examples with their own resources?? (e.g. avoiding clashes in metal libs files in bin directory)
|
||||||
|
|
||||||
|
[!] Sort out gles contents scaling for high dpi on osx
|
||||||
|
[!] win32 surfaces: only register surface child window once?
|
||||||
[!] Fix canvas shader precision issue on OSX
|
[!] Fix canvas shader precision issue on OSX
|
||||||
[!] Fix canvas perf issue on OSX
|
[!] Fix canvas perf issue on OSX
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue