mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat|Fix] (MG_State/EGLState|MG_Backend|MG_Impl/EGLImpl): Initial implemention of EGL API.
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
// 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 <Includes.h>
|
||||
#include <type_traits>
|
||||
|
||||
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 = default;
|
||||
};
|
||||
|
||||
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<EGLConfigHandle> 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 <typename HandleType>
|
||||
static HandleType EncodeHandle(Uint64 rawHandle) {
|
||||
return reinterpret_cast<HandleType>(static_cast<SizeT>(rawHandle));
|
||||
}
|
||||
|
||||
template <typename NativeType>
|
||||
static Uint64 ToNativeKey(NativeType nativeHandle) {
|
||||
if constexpr (std::is_pointer_v<NativeType>) {
|
||||
return static_cast<Uint64>(reinterpret_cast<SizeT>(nativeHandle));
|
||||
} else {
|
||||
return static_cast<Uint64>(nativeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
static Optional<EGLint> ParseAttribValue(const EGLint* attribList, EGLint attrib);
|
||||
static Optional<EGLAttrib> ParseAttribValue(const EGLAttrib* attribList, EGLint attrib);
|
||||
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<DisplayLookupKey, EGLDisplayHandle, DisplayLookupHasher> m_displayLookup;
|
||||
UnorderedMap<EGLDisplayHandle, DisplayObject> m_displays;
|
||||
UnorderedMap<EGLConfigHandle, ConfigObject> m_configs;
|
||||
UnorderedMap<EGLSurfaceHandle, SurfaceObject> m_surfaces;
|
||||
UnorderedMap<EGLContextHandle, ContextObject> m_contexts;
|
||||
UnorderedMap<EGLSyncHandle, SyncObject> m_syncs;
|
||||
UnorderedMap<EGLImageHandle, ImageObject> m_images;
|
||||
|
||||
UnorderedMap<std::thread::id, EGLint> m_threadErrors;
|
||||
UnorderedMap<std::thread::id, EGLenum> m_threadBoundAPI;
|
||||
UnorderedMap<std::thread::id, ThreadCurrentState> m_threadCurrents;
|
||||
UnorderedMap<EGLContextHandle, std::thread::id> m_contextOwners;
|
||||
};
|
||||
} // namespace EGLState
|
||||
|
||||
extern EGLState::EGLContext* pEGLContext;
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
Reference in New Issue
Block a user