// MobileGL - MobileGL/MG_State/EGLState/Core.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 #include namespace MobileGL { namespace MG_State { namespace EGLState { class EGLContext { public: using EGLDisplayHandle = ::EGLDisplay; using EGLConfigHandle = ::EGLConfig; using EGLSurfaceHandle = ::EGLSurface; using EGLContextHandle = ::EGLContext; using EGLSyncHandle = ::EGLSync; using EGLImageHandle = ::EGLImage; EGLContext() = default; // Error void SetError(EGLint errorCode); EGLint ConsumeError(); // API void SetBoundAPI(EGLenum api); EGLenum GetBoundAPI() const; // Display EGLDisplayHandle GetDisplay(NativeDisplayType nativeDisplay); EGLDisplayHandle GetPlatformDisplay(EGLenum platform, void* nativeDisplay); Bool ValidateDisplay(EGLDisplayHandle display) const; Bool IsDisplayInitialized(EGLDisplayHandle display) const; Bool InitializeDisplay(EGLDisplayHandle display, EGLint* major, EGLint* minor); Bool TerminateDisplay(EGLDisplayHandle display); // Config Bool ChooseConfig(EGLDisplayHandle display, const EGLint* attribList, EGLConfigHandle* configs, EGLint configSize, EGLint* numConfig); Bool GetConfigs(EGLDisplayHandle display, EGLConfigHandle* configs, EGLint configSize, EGLint* numConfig); Bool ValidateConfig(EGLConfigHandle config) const; Bool ValidateConfigOnDisplay(EGLDisplayHandle display, EGLConfigHandle config) const; Bool GetConfigAttrib(EGLDisplayHandle display, EGLConfigHandle config, EGLint attribute, EGLint* value) const; // Context EGLContextHandle CreateContext(EGLDisplayHandle display, EGLConfigHandle config, EGLContextHandle shareCtx, const EGLint* attribList); Bool DestroyContext(EGLDisplayHandle display, EGLContextHandle context); Bool QueryContext(EGLDisplayHandle display, EGLContextHandle context, EGLint attribute, EGLint* value) const; Bool ValidateContext(EGLContextHandle context) const; Bool ValidateContextOnDisplay(EGLDisplayHandle display, EGLContextHandle context) const; // Surface EGLSurfaceHandle CreateWindowSurface(EGLDisplayHandle display, EGLConfigHandle config, NativeWindowType window, const EGLint* attribList); EGLSurfaceHandle CreatePbufferSurface(EGLDisplayHandle display, EGLConfigHandle config, const EGLint* attribList); EGLSurfaceHandle CreatePixmapSurface(EGLDisplayHandle display, EGLConfigHandle config, EGLNativePixmapType pixmap, const EGLint* attribList); EGLSurfaceHandle CreatePbufferFromClientBuffer(EGLDisplayHandle display, EGLenum bufferType, EGLClientBuffer buffer, EGLConfigHandle config, const EGLint* attribList); EGLSurfaceHandle CreatePlatformWindowSurface(EGLDisplayHandle display, EGLConfigHandle config, void* nativeWindow, const EGLAttrib* attribList); EGLSurfaceHandle CreatePlatformPixmapSurface(EGLDisplayHandle display, EGLConfigHandle config, void* nativePixmap, const EGLAttrib* attribList); Bool DestroySurface(EGLDisplayHandle display, EGLSurfaceHandle surface); Bool QuerySurface(EGLDisplayHandle display, EGLSurfaceHandle surface, EGLint attribute, EGLint* value) const; Bool ValidateSurface(EGLSurfaceHandle surface) const; Bool ValidateSurfaceOnDisplay(EGLDisplayHandle display, EGLSurfaceHandle surface) const; Bool SwapInterval(EGLDisplayHandle display, EGLint interval); // Current Bool MakeCurrent(EGLDisplayHandle display, EGLSurfaceHandle draw, EGLSurfaceHandle read, EGLContextHandle context); void ReleaseThread(); EGLContextHandle GetCurrentContext() const; EGLDisplayHandle GetCurrentDisplay() const; EGLSurfaceHandle GetCurrentSurface(EGLint readdraw) const; // Sync EGLSyncHandle CreateSync(EGLDisplayHandle display, EGLenum type, const EGLAttrib* attribList); Bool DestroySync(EGLDisplayHandle display, EGLSyncHandle sync); EGLint ClientWaitSync(EGLDisplayHandle display, EGLSyncHandle sync, EGLint flags, EGLTime timeout); Bool GetSyncAttrib(EGLDisplayHandle display, EGLSyncHandle sync, EGLint attribute, EGLAttrib* value) const; Bool WaitSync(EGLDisplayHandle display, EGLSyncHandle sync, EGLint flags) const; // Image EGLImageHandle CreateImage(EGLDisplayHandle display, EGLContextHandle context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib* attribList); Bool DestroyImage(EGLDisplayHandle display, EGLImageHandle image); private: enum class SurfaceType { Window, Pbuffer, Pixmap, PbufferFromClientBuffer, PlatformWindow, PlatformPixmap }; struct DisplayLookupKey { Uint64 NativeDisplayKey = 0; EGLenum Platform = EGL_NONE; Bool operator==(const DisplayLookupKey& rhs) const; }; struct DisplayLookupHasher { SizeT operator()(const DisplayLookupKey& key) const; }; struct DisplayObject { Uint64 NativeDisplayKey = 0; EGLenum Platform = EGL_NONE; Bool Initialized = false; EGLint MajorVersion = 1; EGLint MinorVersion = 5; EGLint SwapInterval = 1; Vector Configs; }; struct ConfigObject { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLint ConfigId = 1; EGLint RedSize = 8; EGLint GreenSize = 8; EGLint BlueSize = 8; EGLint AlphaSize = 8; EGLint DepthSize = 24; EGLint StencilSize = 8; EGLint SurfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_PIXMAP_BIT; EGLint RenderableType = EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT; EGLint MinSwapInterval = 0; EGLint MaxSwapInterval = 4; EGLint NativeVisualId = 0; }; struct ContextObject { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLConfigHandle Config = nullptr; EGLContextHandle SharedContext = nullptr; EGLenum ClientAPI = EGL_OPENGL_API; EGLint ClientVersion = 1; EGLint MajorVersion = 1; EGLint MinorVersion = 0; }; struct SurfaceObject { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLConfigHandle Config = nullptr; SurfaceType Type = SurfaceType::Window; Uint64 NativeHandleKey = 0; EGLClientBuffer ClientBuffer = nullptr; EGLenum BufferType = EGL_NONE; EGLint Width = 0; EGLint Height = 0; EGLint TextureFormat = EGL_NO_TEXTURE; EGLint TextureTarget = EGL_NO_TEXTURE; EGLint MipmapLevel = 0; EGLint MipmapTexture = EGL_FALSE; EGLint RenderBuffer = EGL_BACK_BUFFER; EGLint SwapBehavior = EGL_BUFFER_DESTROYED; }; struct SyncObject { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLenum Type = EGL_SYNC_FENCE; EGLenum Condition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE; EGLenum Status = EGL_SIGNALED; }; struct ImageObject { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLContextHandle Context = nullptr; EGLenum Target = EGL_NONE; EGLClientBuffer Buffer = nullptr; }; struct ThreadCurrentState { EGLDisplayHandle Display = EGL_NO_DISPLAY; EGLSurfaceHandle DrawSurface = EGL_NO_SURFACE; EGLSurfaceHandle ReadSurface = EGL_NO_SURFACE; EGLContextHandle Context = nullptr; }; template static HandleType EncodeHandle(Uint64 rawHandle) { return reinterpret_cast(static_cast(rawHandle)); } template static Uint64 ToNativeKey(NativeType nativeHandle) { if constexpr (std::is_pointer_v) { return static_cast(reinterpret_cast(nativeHandle)); } else { return static_cast(nativeHandle); } } static std::thread::id CurrentThreadKey(); EGLDisplayHandle GetOrCreateDisplay(Uint64 nativeDisplayKey, EGLenum platform); EGLConfigHandle CreateDefaultConfig(EGLDisplayHandle display); DisplayObject* TryGetDisplay(EGLDisplayHandle display); const DisplayObject* TryGetDisplay(EGLDisplayHandle display) const; const ConfigObject* TryGetConfig(EGLConfigHandle config) const; const ContextObject* TryGetContext(EGLContextHandle context) const; const SurfaceObject* TryGetSurface(EGLSurfaceHandle surface) const; const SyncObject* TryGetSync(EGLSyncHandle sync) const; const ImageObject* TryGetImage(EGLImageHandle image) const; void ReleaseDisplayObjects(EGLDisplayHandle display); void ReleaseThreadUnlocked(const std::thread::id& threadKey); private: mutable std::recursive_mutex m_mutex; Uint64 m_nextDisplayHandle = 1; Uint64 m_nextConfigHandle = 1; Uint64 m_nextSurfaceHandle = 1; Uint64 m_nextContextHandle = 1; Uint64 m_nextSyncHandle = 1; Uint64 m_nextImageHandle = 1; UnorderedMap m_displayLookup; UnorderedMap m_displays; UnorderedMap m_configs; UnorderedMap m_surfaces; UnorderedMap m_contexts; UnorderedMap m_syncs; UnorderedMap m_images; UnorderedMap m_threadErrors; UnorderedMap m_threadBoundAPI; UnorderedMap m_threadCurrents; UnorderedMap m_contextOwners; }; } // namespace EGLState extern UniquePtr pEGLContext; } // namespace MG_State } // namespace MobileGL