mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
Desktop Linux GL apps (GLFW/LWJGL, glxgears, anything X11) create contexts through GLX, and MobileGL only spoke EGL - the two exported glX symbols were proc-address stubs that could resolve GL entry points but never produce a context. GLXImpl is the missing sibling of WGLImpl/CGLImpl: the same window-system-binding pattern, calling the internal MG_Impl::EGLImpl namespace directly. The surface covers exactly what GLFW 3.4 resolves via dlsym plus the legacy visual API: FBConfig enumeration mirrors the two EGLState configs (stencil-8 first so stencil-wanting choosers land on it), glXGetVisualFromFBConfig answers with the screen's default visual (falling back to any 24-bit TrueColor one), and glXCreateContextAttribsARB maps the ARB attribs onto EGL context attribs the way WGL's Ext_CreateContextAttribsARB does - profile mask only emitted for 3.2+ or an explicit profile request, since that bit is what keys MobileGL's relaxed-semantics compatibility mode. Legacy glXCreateContext/CreateNewContext hand out 3.3 compatibility contexts, matching wglCreateContext. Drawables follow the WGL HWND model: the GLXWindow is the X window itself, the EGL window surface is created lazily on first MakeCurrent and cached per XID, and the GLX layer owns size discovery per the platform-layer contract - it pushes changes through EGLImpl::ResizePlatformWindowSurface, polling XGetGeometry on MakeCurrent and on swaps throttled to 250ms so a fast-swapping app is not paying a server round trip per frame. libX11 is dlopen'd at runtime like everywhere else in the tree; Xlib.h is already in every TU via the vulkan include, so XVisualInfo gets an ABI mirror struct (Xutil.h needs the Bool and Status macros that Includes.h deliberately pops) and the caller's XFree pairs with our malloc. glXGetProcAddress now resolves glX names from the export table before falling through to the shared GL resolver, which previously returned nullptr for every glX extension entry point - GLFW requires glXCreateContextAttribsARB and glXSwapIntervalEXT to arrive that way. Verified with a smoke test replaying GLFW's exact call sequence (dlsym-only resolution, manual FBConfig filtering, 3.2 core forward-compatible context, glXCreateWindow, 60 swapped frames, clean glGetError) on both backends against the real NVIDIA driver, then with Minecraft 1.21.1, 1.21.4+Fabric+Sodium and 26.2-snapshot-6 reaching in-world rendering on both Espryt and Magma.
70 lines
3.4 KiB
C++
70 lines
3.4 KiB
C++
// MobileGL - MobileGL/MG_Impl/GLXImpl/GLXImpl.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include <Includes.h>
|
|
|
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
|
|
namespace MobileGL::MG_Impl::GLXImpl {
|
|
// GLX layered on MobileGL's own EGL, mirroring WGLImpl/CGLImpl. Handles are
|
|
// opaque to callers; XVisualInfo crosses the ABI as void* so this header
|
|
// needs no Xlib includes (Includes.h forward-declares Display/XID/Window).
|
|
using GLXFBConfigHandle = void*;
|
|
using GLXContextHandle = void*;
|
|
using GLXDrawableHandle = unsigned long; // XID
|
|
|
|
int QueryExtension(Display* dpy, int* errorBase, int* eventBase);
|
|
int QueryVersion(Display* dpy, int* major, int* minor);
|
|
const char* QueryExtensionsString(Display* dpy, int screen);
|
|
const char* GetClientString(Display* dpy, int name);
|
|
const char* QueryServerString(Display* dpy, int screen, int name);
|
|
|
|
GLXFBConfigHandle* GetFBConfigs(Display* dpy, int screen, int* nelements);
|
|
GLXFBConfigHandle* ChooseFBConfig(Display* dpy, int screen, const int* attribList, int* nelements);
|
|
int GetFBConfigAttrib(Display* dpy, GLXFBConfigHandle config, int attribute, int* value);
|
|
void* GetVisualFromFBConfig(Display* dpy, GLXFBConfigHandle config);
|
|
void* ChooseVisual(Display* dpy, int screen, int* attribList);
|
|
int GetConfig(Display* dpy, void* visualInfo, int attribute, int* value);
|
|
|
|
GLXContextHandle CreateContext(Display* dpy, void* visualInfo, GLXContextHandle share, int direct);
|
|
GLXContextHandle CreateNewContext(Display* dpy, GLXFBConfigHandle config, int renderType,
|
|
GLXContextHandle share, int direct);
|
|
GLXContextHandle CreateContextAttribsARB(Display* dpy, GLXFBConfigHandle config, GLXContextHandle share,
|
|
int direct, const int* attribList);
|
|
void DestroyContext(Display* dpy, GLXContextHandle context);
|
|
int MakeCurrent(Display* dpy, GLXDrawableHandle drawable, GLXContextHandle context);
|
|
int MakeContextCurrent(Display* dpy, GLXDrawableHandle draw, GLXDrawableHandle read,
|
|
GLXContextHandle context);
|
|
void SwapBuffers(Display* dpy, GLXDrawableHandle drawable);
|
|
|
|
GLXDrawableHandle CreateWindow(Display* dpy, GLXFBConfigHandle config, GLXDrawableHandle window,
|
|
const int* attribList);
|
|
void DestroyWindow(Display* dpy, GLXDrawableHandle window);
|
|
|
|
GLXContextHandle GetCurrentContext();
|
|
GLXDrawableHandle GetCurrentDrawable();
|
|
GLXDrawableHandle GetCurrentReadDrawable();
|
|
Display* GetCurrentDisplay();
|
|
int IsDirect(Display* dpy, GLXContextHandle context);
|
|
void WaitGL();
|
|
void WaitX();
|
|
int QueryContext(Display* dpy, GLXContextHandle context, int attribute, int* value);
|
|
void QueryDrawable(Display* dpy, GLXDrawableHandle drawable, int attribute, unsigned int* value);
|
|
|
|
void SwapIntervalEXT(Display* dpy, GLXDrawableHandle drawable, int interval);
|
|
int SwapIntervalMESA(unsigned int interval);
|
|
int GetSwapIntervalMESA();
|
|
int SwapIntervalSGI(int interval);
|
|
|
|
// Name -> exported glX entry point (table lives with the exports).
|
|
void* GetGLXEntryPoint(const char* name);
|
|
} // namespace MobileGL::MG_Impl::GLXImpl
|
|
|
|
#endif // __linux__ && !__ANDROID__
|