From 5250621c898f2edc18f6089ae01b62eb3aad0f23 Mon Sep 17 00:00:00 2001 From: Annas Amare Date: Fri, 17 Jul 2026 21:59:42 -0400 Subject: [PATCH 1/3] feat: expose active graphics context identity --- include/game_window.h | 43 +++++++++++++++++++++++++++++++++++ src/window_eglut.cpp | 9 +++++++- src/window_eglut.h | 2 ++ src/window_glfw.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++- src/window_glfw.h | 2 ++ src/window_sdl3.cpp | 33 +++++++++++++++++++++++++++ src/window_sdl3.h | 2 ++ 7 files changed, 142 insertions(+), 2 deletions(-) diff --git a/include/game_window.h b/include/game_window.h index ac63829..2157d2e 100644 --- a/include/game_window.h +++ b/include/game_window.h @@ -9,6 +9,43 @@ enum class GraphicsApi { OPENGL, OPENGL_ES2 }; + +enum class GraphicsClientApi { + UNKNOWN, + OPENGL, + OPENGL_ES +}; + +enum class GraphicsWindowSystem { + UNKNOWN, + GLFW, + SDL3, + EGLUT +}; + +enum class GraphicsContextProfile { + UNKNOWN, + CORE, + COMPATIBILITY, + ES +}; + +enum class GraphicsContextCreationApi { + UNKNOWN, + NATIVE, + EGL, + OSMESA +}; + +struct GraphicsContextInfo { + GraphicsWindowSystem windowSystem = GraphicsWindowSystem::UNKNOWN; + GraphicsClientApi clientApi = GraphicsClientApi::UNKNOWN; + int versionMajor = -1; + int versionMinor = -1; + int versionRevision = -1; + GraphicsContextProfile profile = GraphicsContextProfile::UNKNOWN; + GraphicsContextCreationApi creationApi = GraphicsContextCreationApi::UNKNOWN; +}; enum class KeyAction { PRESS, REPEAT, @@ -94,6 +131,12 @@ class GameWindow { virtual void makeCurrent(bool) = 0; + // Returns properties of the successfully created context. Call this while + // the context is current; implementations must not return request hints. + virtual GraphicsContextInfo getGraphicsContextInfo() const { + return {}; + } + virtual void setIcon(std::string const& iconPath) = 0; virtual void show() = 0; diff --git a/src/window_eglut.cpp b/src/window_eglut.cpp index 793623b..fd8b6d1 100644 --- a/src/window_eglut.cpp +++ b/src/window_eglut.cpp @@ -76,6 +76,13 @@ void EGLUTWindow::makeCurrent(bool active) { eglutMakeCurrent(active ? winId : -1); } +GraphicsContextInfo EGLUTWindow::getGraphicsContextInfo() const { + GraphicsContextInfo info; + info.windowSystem = GraphicsWindowSystem::EGLUT; + info.creationApi = GraphicsContextCreationApi::EGL; + return info; +} + void EGLUTWindow::show() { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); @@ -451,4 +458,4 @@ int EGLUTWindow::translateMeta(unsigned int meta) { mods |= KEY_MOD_NUMLOCK; } return mods; -} \ No newline at end of file +} diff --git a/src/window_eglut.h b/src/window_eglut.h index 02aab8f..7127f79 100644 --- a/src/window_eglut.h +++ b/src/window_eglut.h @@ -55,6 +55,8 @@ class EGLUTWindow : public WindowWithLinuxJoystick { void makeCurrent(bool active) override; + GraphicsContextInfo getGraphicsContextInfo() const override; + void show() override; void close() override; diff --git a/src/window_glfw.cpp b/src/window_glfw.cpp index 7e0a85b..d64bebb 100644 --- a/src/window_glfw.cpp +++ b/src/window_glfw.cpp @@ -66,6 +66,57 @@ void GLFWGameWindow::makeCurrent(bool c) { glfwMakeContextCurrent(c ? window : nullptr); } +GraphicsContextInfo GLFWGameWindow::getGraphicsContextInfo() const { + GraphicsContextInfo info; + info.windowSystem = GraphicsWindowSystem::GLFW; + + switch(glfwGetWindowAttrib(window, GLFW_CLIENT_API)) { + case GLFW_OPENGL_API: + info.clientApi = GraphicsClientApi::OPENGL; + break; + case GLFW_OPENGL_ES_API: + info.clientApi = GraphicsClientApi::OPENGL_ES; + break; + default: + break; + } + + info.versionMajor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR); + info.versionMinor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR); + info.versionRevision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION); + + if(info.clientApi == GraphicsClientApi::OPENGL_ES) { + info.profile = GraphicsContextProfile::ES; + } else { + switch(glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE)) { + case GLFW_OPENGL_CORE_PROFILE: + info.profile = GraphicsContextProfile::CORE; + break; + case GLFW_OPENGL_COMPAT_PROFILE: + info.profile = GraphicsContextProfile::COMPATIBILITY; + break; + default: + break; + } + } + + switch(glfwGetWindowAttrib(window, GLFW_CONTEXT_CREATION_API)) { + case GLFW_NATIVE_CONTEXT_API: + info.creationApi = GraphicsContextCreationApi::NATIVE; + break; + case GLFW_EGL_CONTEXT_API: + info.creationApi = GraphicsContextCreationApi::EGL; + break; + case GLFW_OSMESA_CONTEXT_API: + info.creationApi = GraphicsContextCreationApi::OSMESA; + break; + default: + break; + } + + return info; +} + GLFWGameWindow::~GLFWGameWindow() { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); @@ -508,4 +559,4 @@ int GLFWGameWindow::translateMeta(unsigned int meta) { mods |= KEY_MOD_NUMLOCK; } return mods; -} \ No newline at end of file +} diff --git a/src/window_glfw.h b/src/window_glfw.h index 9d81267..8991184 100644 --- a/src/window_glfw.h +++ b/src/window_glfw.h @@ -59,6 +59,8 @@ class GLFWGameWindow : public GameWindow { void makeCurrent(bool active) override; + GraphicsContextInfo getGraphicsContextInfo() const override; + double getRelativeScale() const; void setRelativeScale(); diff --git a/src/window_sdl3.cpp b/src/window_sdl3.cpp index 722ecb7..f24217a 100644 --- a/src/window_sdl3.cpp +++ b/src/window_sdl3.cpp @@ -63,6 +63,39 @@ void SDL3GameWindow::makeCurrent(bool c) { SDL_GL_MakeCurrent(window, c ? context : nullptr); } +GraphicsContextInfo SDL3GameWindow::getGraphicsContextInfo() const { + GraphicsContextInfo info; + info.windowSystem = GraphicsWindowSystem::SDL3; + int value = 0; + + if(SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &value)) { + info.versionMajor = value; + } + if(SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &value)) { + info.versionMinor = value; + } + if(SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &value)) { + switch(value) { + case SDL_GL_CONTEXT_PROFILE_ES: + info.clientApi = GraphicsClientApi::OPENGL_ES; + info.profile = GraphicsContextProfile::ES; + break; + case SDL_GL_CONTEXT_PROFILE_CORE: + info.clientApi = GraphicsClientApi::OPENGL; + info.profile = GraphicsContextProfile::CORE; + break; + case SDL_GL_CONTEXT_PROFILE_COMPATIBILITY: + info.clientApi = GraphicsClientApi::OPENGL; + info.profile = GraphicsContextProfile::COMPATIBILITY; + break; + default: + break; + } + } + + return info; +} + SDL3GameWindow::~SDL3GameWindow() { if(window) { SDL_DestroyWindow(window); diff --git a/src/window_sdl3.h b/src/window_sdl3.h index 38a74d1..e25f61f 100644 --- a/src/window_sdl3.h +++ b/src/window_sdl3.h @@ -44,6 +44,8 @@ class SDL3GameWindow : public GameWindow { void makeCurrent(bool active) override; + GraphicsContextInfo getGraphicsContextInfo() const override; + int getRelativeScale() const; void setRelativeScale(); From 688e1d526c6d7a9a12e4c6ccfc037719cc21d948 Mon Sep 17 00:00:00 2001 From: Annas Amare Date: Fri, 17 Jul 2026 23:38:02 -0400 Subject: [PATCH 2/3] feat: expose host EGL resolver --- include/game_window_manager.h | 7 ++++++- src/window_manager_eglut.cpp | 6 +++++- src/window_manager_eglut.h | 4 +++- src/window_manager_glfw.cpp | 6 +++++- src/window_manager_glfw.h | 4 +++- src/window_manager_glfw_fallback_eglut.cpp | 4 ++++ src/window_manager_glfw_fallback_eglut.h | 4 +++- src/window_manager_sdl3.cpp | 6 +++++- src/window_manager_sdl3.h | 4 +++- 9 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/game_window_manager.h b/include/game_window_manager.h index a6f3c7e..5f3c768 100644 --- a/include/game_window_manager.h +++ b/include/game_window_manager.h @@ -25,6 +25,11 @@ class GameWindowManager { virtual ProcAddrFunc getProcAddrFunc() = 0; + // Returns a resolver for host EGL entry points when the active window + // implementation uses EGL. This is separate from the guest GL resolver + // exposed to Minecraft and may be unavailable for native contexts. + virtual ProcAddrFunc getEglProcAddrFunc() { return nullptr; } + virtual std::shared_ptr createWindow(const std::string& title, int width, int height, GraphicsApi api) = 0; @@ -41,4 +46,4 @@ class GameWindowManager { } const std::shared_ptr& getErrorHandler() { return errorhandler; } -}; \ No newline at end of file +}; diff --git a/src/window_manager_eglut.cpp b/src/window_manager_eglut.cpp index 60f36ae..e3ea7bd 100644 --- a/src/window_manager_eglut.cpp +++ b/src/window_manager_eglut.cpp @@ -25,6 +25,10 @@ GameWindowManager::ProcAddrFunc EGLUTWindowManager::getProcAddrFunc() { return (GameWindowManager::ProcAddrFunc) eglGetProcAddress; } +GameWindowManager::ProcAddrFunc EGLUTWindowManager::getEglProcAddrFunc() { + return (GameWindowManager::ProcAddrFunc) eglGetProcAddress; +} + std::shared_ptr EGLUTWindowManager::createWindow(const std::string& title, int width, int height, GraphicsApi api) { return std::shared_ptr(new EGLUTWindow(title, width, height, api)); @@ -43,4 +47,4 @@ void EGLUTWindowManager::addGamePadMapping(const std::string &content) { std::shared_ptr GameWindowManager::createManager() { return std::shared_ptr(new EGLUTWindowManager()); } -#endif \ No newline at end of file +#endif diff --git a/src/window_manager_eglut.h b/src/window_manager_eglut.h index f0e91ea..d450f91 100644 --- a/src/window_manager_eglut.h +++ b/src/window_manager_eglut.h @@ -9,9 +9,11 @@ class EGLUTWindowManager : public GameWindowManager { ProcAddrFunc getProcAddrFunc() override; + ProcAddrFunc getEglProcAddrFunc() override; + std::shared_ptr createWindow(const std::string& title, int width, int height, GraphicsApi api) override; void addGamepadMappingFile(const std::string& path) override; void addGamePadMapping(const std::string &content) override; -}; \ No newline at end of file +}; diff --git a/src/window_manager_glfw.cpp b/src/window_manager_glfw.cpp index 6a7b1c8..dbaec2f 100644 --- a/src/window_manager_glfw.cpp +++ b/src/window_manager_glfw.cpp @@ -16,6 +16,10 @@ GameWindowManager::ProcAddrFunc GLFWWindowManager::getProcAddrFunc() { return (GameWindowManager::ProcAddrFunc) glfwGetProcAddress; } +GameWindowManager::ProcAddrFunc GLFWWindowManager::getEglProcAddrFunc() { + return (GameWindowManager::ProcAddrFunc) glfwGetProcAddress; +} + std::shared_ptr GLFWWindowManager::createWindow(const std::string& title, int width, int height, GraphicsApi api) { return std::shared_ptr(new GLFWGameWindow(title, width, height, api)); @@ -34,4 +38,4 @@ void GLFWWindowManager::addGamePadMapping(const std::string &content) { std::shared_ptr GameWindowManager::createManager() { return std::shared_ptr(new GLFWWindowManager()); } -#endif \ No newline at end of file +#endif diff --git a/src/window_manager_glfw.h b/src/window_manager_glfw.h index e76aca0..6faad13 100644 --- a/src/window_manager_glfw.h +++ b/src/window_manager_glfw.h @@ -9,9 +9,11 @@ class GLFWWindowManager : public GameWindowManager { ProcAddrFunc getProcAddrFunc() override; + ProcAddrFunc getEglProcAddrFunc() override; + std::shared_ptr createWindow(const std::string& title, int width, int height, GraphicsApi api) override; void addGamepadMappingFile(const std::string& path) override; void addGamePadMapping(const std::string &content) override; -}; \ No newline at end of file +}; diff --git a/src/window_manager_glfw_fallback_eglut.cpp b/src/window_manager_glfw_fallback_eglut.cpp index 23a1945..d6a0aa7 100644 --- a/src/window_manager_glfw_fallback_eglut.cpp +++ b/src/window_manager_glfw_fallback_eglut.cpp @@ -27,6 +27,10 @@ GameWindowManager::ProcAddrFunc GLFWFallbackEGLUTWindowManager::getProcAddrFunc( return manager->getProcAddrFunc(); } +GameWindowManager::ProcAddrFunc GLFWFallbackEGLUTWindowManager::getEglProcAddrFunc() { + return manager->getEglProcAddrFunc(); +} + std::shared_ptr GLFWFallbackEGLUTWindowManager::createWindow(const std::string& title, int width, int height, GraphicsApi api) { return manager->createWindow(title, width, height, api); diff --git a/src/window_manager_glfw_fallback_eglut.h b/src/window_manager_glfw_fallback_eglut.h index ace4f39..eb5293b 100644 --- a/src/window_manager_glfw_fallback_eglut.h +++ b/src/window_manager_glfw_fallback_eglut.h @@ -9,9 +9,11 @@ class GLFWFallbackEGLUTWindowManager : public GameWindowManager { ProcAddrFunc getProcAddrFunc() override; + ProcAddrFunc getEglProcAddrFunc() override; + std::shared_ptr createWindow(const std::string& title, int width, int height, GraphicsApi api) override; void addGamepadMappingFile(const std::string& path) override; void addGamePadMapping(const std::string &content) override; -}; \ No newline at end of file +}; diff --git a/src/window_manager_sdl3.cpp b/src/window_manager_sdl3.cpp index f04e230..496ea49 100644 --- a/src/window_manager_sdl3.cpp +++ b/src/window_manager_sdl3.cpp @@ -13,6 +13,10 @@ GameWindowManager::ProcAddrFunc SDL3WindowManager::getProcAddrFunc() { return (GameWindowManager::ProcAddrFunc) SDL_GL_GetProcAddress; } +GameWindowManager::ProcAddrFunc SDL3WindowManager::getEglProcAddrFunc() { + return (GameWindowManager::ProcAddrFunc) SDL_EGL_GetProcAddress; +} + std::shared_ptr SDL3WindowManager::createWindow(const std::string& title, int width, int height, GraphicsApi api) { return std::shared_ptr(new SDL3GameWindow(title, width, height, api)); @@ -45,4 +49,4 @@ void SDL3WindowManager::addGamePadMapping(const std::string &content) { // Define this window manager as the used one std::shared_ptr GameWindowManager::createManager() { return std::shared_ptr(new SDL3WindowManager()); -} \ No newline at end of file +} diff --git a/src/window_manager_sdl3.h b/src/window_manager_sdl3.h index 8b2fe8b..6d373db 100644 --- a/src/window_manager_sdl3.h +++ b/src/window_manager_sdl3.h @@ -9,9 +9,11 @@ class SDL3WindowManager : public GameWindowManager { ProcAddrFunc getProcAddrFunc() override; + ProcAddrFunc getEglProcAddrFunc() override; + std::shared_ptr createWindow(const std::string& title, int width, int height, GraphicsApi api) override; void addGamepadMappingFile(const std::string& path) override; void addGamePadMapping(const std::string &content) override; -}; \ No newline at end of file +}; From 5695e1aaed91c4bea43cfaf8d9081a3f3c593062 Mon Sep 17 00:00:00 2001 From: Annas Amare Date: Sat, 18 Jul 2026 00:01:27 -0400 Subject: [PATCH 3/3] fix: preserve graphics resolver function types --- include/game_window_manager.h | 2 +- src/window_manager_eglut.cpp | 11 ++++++++--- src/window_manager_glfw.cpp | 10 ++++++++-- src/window_manager_sdl3.cpp | 14 ++++++++++++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/game_window_manager.h b/include/game_window_manager.h index 5f3c768..f02fb2e 100644 --- a/include/game_window_manager.h +++ b/include/game_window_manager.h @@ -19,7 +19,7 @@ class GameWindowManager { static std::shared_ptr getManager(); - using AnyFunc = void* (*)(); + using AnyFunc = void (*)(); using ProcAddrFunc = AnyFunc (*)(const char*); diff --git a/src/window_manager_eglut.cpp b/src/window_manager_eglut.cpp index e3ea7bd..c04d765 100644 --- a/src/window_manager_eglut.cpp +++ b/src/window_manager_eglut.cpp @@ -10,8 +10,13 @@ #endif #include #include +#include -extern "C" void eglGetProcAddress(); +namespace { +GameWindowManager::AnyFunc resolveEglProcAddress(const char* name) { + return reinterpret_cast(eglGetProcAddress(name)); +} +} EGLUTWindowManager::EGLUTWindowManager() { char buf[PATH_MAX]; @@ -22,11 +27,11 @@ EGLUTWindowManager::EGLUTWindowManager() { } GameWindowManager::ProcAddrFunc EGLUTWindowManager::getProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) eglGetProcAddress; + return resolveEglProcAddress; } GameWindowManager::ProcAddrFunc EGLUTWindowManager::getEglProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) eglGetProcAddress; + return resolveEglProcAddress; } std::shared_ptr EGLUTWindowManager::createWindow(const std::string& title, int width, int height, diff --git a/src/window_manager_glfw.cpp b/src/window_manager_glfw.cpp index dbaec2f..bdd5b34 100644 --- a/src/window_manager_glfw.cpp +++ b/src/window_manager_glfw.cpp @@ -3,6 +3,12 @@ #include "joystick_manager_glfw.h" #include +namespace { +GameWindowManager::AnyFunc resolveGlfwProcAddress(const char* name) { + return reinterpret_cast(glfwGetProcAddress(name)); +} +} + GLFWWindowManager::GLFWWindowManager() { // To create a default mapping for not mapped Gamepads // to avoid subtracting heads from buttons again @@ -13,11 +19,11 @@ GLFWWindowManager::GLFWWindowManager() { } GameWindowManager::ProcAddrFunc GLFWWindowManager::getProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) glfwGetProcAddress; + return resolveGlfwProcAddress; } GameWindowManager::ProcAddrFunc GLFWWindowManager::getEglProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) glfwGetProcAddress; + return resolveGlfwProcAddress; } std::shared_ptr GLFWWindowManager::createWindow(const std::string& title, int width, int height, diff --git a/src/window_manager_sdl3.cpp b/src/window_manager_sdl3.cpp index 496ea49..e1ee10b 100644 --- a/src/window_manager_sdl3.cpp +++ b/src/window_manager_sdl3.cpp @@ -5,16 +5,26 @@ #include +namespace { +GameWindowManager::AnyFunc resolveSdlGlProcAddress(const char* name) { + return reinterpret_cast(SDL_GL_GetProcAddress(name)); +} + +GameWindowManager::AnyFunc resolveSdlEglProcAddress(const char* name) { + return reinterpret_cast(SDL_EGL_GetProcAddress(name)); +} +} + SDL3WindowManager::SDL3WindowManager() { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD); } GameWindowManager::ProcAddrFunc SDL3WindowManager::getProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) SDL_GL_GetProcAddress; + return resolveSdlGlProcAddress; } GameWindowManager::ProcAddrFunc SDL3WindowManager::getEglProcAddrFunc() { - return (GameWindowManager::ProcAddrFunc) SDL_EGL_GetProcAddress; + return resolveSdlEglProcAddress; } std::shared_ptr SDL3WindowManager::createWindow(const std::string& title, int width, int height,