mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
257 lines
13 KiB
C++
257 lines
13 KiB
C++
// 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;
|
|
};
|
|
|
|
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 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 UniquePtr<EGLState::EGLContext> pEGLContext;
|
|
} // namespace MG_State
|
|
} // namespace MobileGL
|