Merge branch 'dev' into Feat/Backend-Direct-Vulkan

This commit is contained in:
2026-03-08 10:31:44 +08:00
89 changed files with 9838 additions and 7946 deletions
-2
View File
@@ -14,7 +14,6 @@ bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase, bugprone-inaccurate-erase,
bugprone-incorrect-roundings, bugprone-incorrect-roundings,
bugprone-integer-division, bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses, bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects, bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc, bugprone-misplaced-operator-in-strlen-in-alloc,
@@ -63,7 +62,6 @@ cert-str34-c,
cppcoreguidelines-interfaces-global-init, cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions, cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init, cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing, cppcoreguidelines-slicing,
google-default-arguments, google-default-arguments,
google-runtime-operator, google-runtime-operator,
+1
View File
@@ -233,6 +233,7 @@ set(SOURCE_FILES
MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp
MobileGL/MG_State/GLState/Core.cpp MobileGL/MG_State/GLState/Core.cpp
MobileGL/MG_State/EGLState/Core.cpp
MobileGL/MG_State/GLState/ErrorState/Error.cpp MobileGL/MG_State/GLState/ErrorState/Error.cpp
MobileGL/MG_State/GLState/BufferState/BufferState.cpp MobileGL/MG_State/GLState/BufferState/BufferState.cpp
MobileGL/MG_State/GLState/BufferState/BufferObject.cpp MobileGL/MG_State/GLState/BufferState/BufferObject.cpp
+5 -3
View File
@@ -10,6 +10,7 @@
#include "Config.h" #include "Config.h"
#include <MG_Backend/BackendObjects.h> #include <MG_Backend/BackendObjects.h>
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_State/EGLState/Core.h>
#include <MG_Impl/GLImpl/Texture/ProxyTexture.h> #include <MG_Impl/GLImpl/Texture/ProxyTexture.h>
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h> #include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
@@ -33,9 +34,10 @@ namespace MobileGL {
void Destroy() { void Destroy() {
MGLOG_I("MobileGL closing..."); MGLOG_I("MobileGL closing...");
glslang::FinalizeProcess(); glslang::FinalizeProcess();
delete MG_State::pGLContext; MG_State::pGLContext.reset();
delete MG_Impl::GLImpl::TextureImpl::pProxyTextureManager; MG_State::pEGLContext.reset();
delete MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo; MG_Impl::GLImpl::TextureImpl::pProxyTextureManager.reset();
MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo.reset();
MG_Util::Debug::Close(); MG_Util::Debug::Close();
// TODO: add and use Destroy functions for other subsystems // TODO: add and use Destroy functions for other subsystems
+126
View File
@@ -9,7 +9,133 @@
#include "BackendObject.h" #include "BackendObject.h"
namespace MobileGL::MG_Backend { namespace MobileGL::MG_Backend {
namespace {
Bool IsReleaseCurrentRequest(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
return dpy == EGL_NO_DISPLAY && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT;
}
std::thread::id CurrentThreadKey() {
return std::this_thread::get_id();
}
} // namespace
Bool BackendObject::InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (dpy == EGL_NO_DISPLAY) {
MGLOG_E("InitializeEGLDisplay failed: invalid EGLDisplay");
return false;
}
if (m_eglDisplayInitialized && m_eglDisplay != dpy) {
MGLOG_E("InitializeEGLDisplay failed: backend already bound to a different EGLDisplay");
return false;
}
m_eglDisplay = dpy;
m_eglDisplayInitialized = true;
if (major) {
*major = 1;
}
if (minor) {
*minor = 5;
}
return true;
}
Bool BackendObject::CreateEGLWindowSurface(const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_eglDisplayInitialized) {
MGLOG_E("CreateEGLWindowSurface failed: EGL display is not initialized");
return false;
}
if (handle.Backend == WindowBackend::Unknown || !handle.Handle) {
MGLOG_E("CreateEGLWindowSurface failed: invalid native window handle");
return false;
}
if (m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle) {
return true;
}
SetWindowHandle(handle);
if (!InitWindowSurface()) {
MGLOG_E("CreateEGLWindowSurface failed: backend InitWindowSurface failed");
return false;
}
m_eglWindowSurfaceInitialized = true;
m_eglCurrentThreads.clear();
m_backendCapabilitiesInitialized = false;
return true;
}
Bool BackendObject::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
const auto threadKey = CurrentThreadKey();
if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) {
m_eglCurrentThreads.erase(threadKey);
return true;
}
if (!m_eglDisplayInitialized || m_eglDisplay != dpy) {
MGLOG_E("MakeEGLCurrent failed: EGL display mismatch or not initialized");
return false;
}
if (!m_eglWindowSurfaceInitialized) {
MGLOG_E("MakeEGLCurrent failed: EGL window surface is not initialized");
return false;
}
if (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE || ctx == EGL_NO_CONTEXT) {
MGLOG_E("MakeEGLCurrent failed: draw/read/context is invalid");
return false;
}
if (!m_backendCapabilitiesInitialized) {
if (!InitCapabilities()) {
MGLOG_E("MakeEGLCurrent failed: InitCapabilities failed");
return false;
}
m_backendCapabilitiesInitialized = true;
}
m_eglCurrentThreads[threadKey] = true;
return true;
}
void BackendObject::ResetEGLRuntimeState() {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
m_eglWindowSurfaceInitialized = false;
m_backendCapabilitiesInitialized = false;
m_eglCurrentThreads.clear();
}
Bool BackendObject::SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_eglDisplayInitialized || m_eglDisplay != dpy) {
MGLOG_E("SwapEGLBuffers failed: EGL display mismatch or not initialized");
return false;
}
if (m_eglCurrentThreads.find(CurrentThreadKey()) == m_eglCurrentThreads.end()) {
MGLOG_E("SwapEGLBuffers failed: no current context attached");
return false;
}
if (!m_eglWindowSurfaceInitialized || draw == EGL_NO_SURFACE) {
MGLOG_E("SwapEGLBuffers failed: invalid draw surface");
return false;
}
const auto& backendFunctions = GetBackendFunctions();
if (!backendFunctions.Present) {
MGLOG_E("SwapEGLBuffers failed: backend Present function is null");
return false;
}
backendFunctions.Present();
return true;
}
void BackendObject::SetWindowHandle(const WindowHandle& handle) { void BackendObject::SetWindowHandle(const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
m_windowHandle = handle; m_windowHandle = handle;
} }
} // namespace MobileGL::MG_Backend } // namespace MobileGL::MG_Backend
+15 -2
View File
@@ -91,8 +91,13 @@ namespace MobileGL {
virtual ~BackendObject() = default; virtual ~BackendObject() = default;
virtual void Initialize() = 0; virtual void Initialize() = 0;
virtual void InitCapabilities() = 0; virtual Bool InitCapabilities() = 0;
virtual void InitWindowSurface() = 0; virtual Bool InitWindowSurface() = 0;
virtual Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor);
virtual Bool CreateEGLWindowSurface(const WindowHandle& handle);
virtual Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
virtual Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw);
void SetWindowHandle(const WindowHandle& handle); void SetWindowHandle(const WindowHandle& handle);
@@ -103,7 +108,15 @@ namespace MobileGL {
virtual BackendType GetBackendType() const = 0; virtual BackendType GetBackendType() const = 0;
protected: protected:
void ResetEGLRuntimeState();
mutable std::recursive_mutex m_eglStateMutex;
WindowHandle m_windowHandle; WindowHandle m_windowHandle;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
Bool m_eglDisplayInitialized = false;
Bool m_eglWindowSurfaceInitialized = false;
Bool m_backendCapabilitiesInitialized = false;
UnorderedMap<std::thread::id, Bool> m_eglCurrentThreads;
}; };
} // namespace MG_Backend } // namespace MG_Backend
} // namespace MobileGL } // namespace MobileGL
@@ -13,16 +13,24 @@
#include <format> #include <format>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
namespace {
Bool IsReleaseCurrentRequest(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
return dpy == EGL_NO_DISPLAY && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT;
}
} // namespace
BackendObject_DirectGLES::~BackendObject_DirectGLES() { BackendObject_DirectGLES::~BackendObject_DirectGLES() {
DestroyEGLContext(); DestroyEGLContext();
} }
void BackendObject_DirectGLES::InitWindowSurface() { Bool BackendObject_DirectGLES::InitWindowSurface() {
// Only use EGL for now // Only use EGL for now
auto nativeWindow = reinterpret_cast<NativeWindowType>(m_windowHandle.Handle); auto nativeWindow = reinterpret_cast<NativeWindowType>(m_windowHandle.Handle);
if (!DirectGLES::InitWindowSurface(nativeWindow)) { if (!DirectGLES::InitWindowSurface(nativeWindow)) {
MGLOG_E("Failed to initialize window surface for DirectGLES backend"); MGLOG_E("Failed to initialize window surface for DirectGLES backend");
return false;
} }
return true;
} }
void BackendObject_DirectGLES::Initialize() { void BackendObject_DirectGLES::Initialize() {
@@ -40,18 +48,65 @@ namespace MobileGL::MG_Backend::DirectGLES {
DirectGLES::SetGLESFuncsTable(m_GLESFunctions); DirectGLES::SetGLESFuncsTable(m_GLESFunctions);
} }
void BackendObject_DirectGLES::InitCapabilities() { Bool BackendObject_DirectGLES::InitCapabilities() {
if (!m_initialized) { if (!m_initialized) {
MGLOG_E("DirectGLES backend not initialized"); MGLOG_E("DirectGLES backend not initialized");
return; return false;
} }
if (!MG_Util::BackendLoader::FillInGLESCapabilities(m_GLESCapabilities, m_GLESFunctions)) { if (!MG_Util::BackendLoader::FillInGLESCapabilities(m_GLESCapabilities, m_GLESFunctions)) {
MGLOG_E("Failed to fill in GLES capabilities for DirectGLES backend"); MGLOG_E("Failed to fill in GLES capabilities for DirectGLES backend");
return; return false;
} }
DirectGLES::SetGLESCapabilities(m_GLESCapabilities); DirectGLES::SetGLESCapabilities(m_GLESCapabilities);
UpdateDynamicBackendParameters(); UpdateDynamicBackendParameters();
return true;
}
Bool BackendObject_DirectGLES::InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) {
if (!m_initialized) {
MGLOG_E("DirectGLES backend not initialized");
return false;
}
return BackendObject::InitializeEGLDisplay(dpy, major, minor);
}
Bool BackendObject_DirectGLES::CreateEGLWindowSurface(const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_initialized) {
MGLOG_E("DirectGLES backend not initialized");
return false;
}
if (handle.Backend != WindowBackend::Android || !handle.Handle) {
MGLOG_E("DirectGLES backend only supports Android native windows");
return false;
}
const Bool sameHandle =
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
if (sameHandle) {
return true;
}
if (m_eglWindowSurfaceInitialized) {
DestroyEGLContext();
ResetEGLRuntimeState();
}
return BackendObject::CreateEGLWindowSurface(handle);
}
Bool BackendObject_DirectGLES::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) {
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
}
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
}
Bool BackendObject_DirectGLES::SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) {
return BackendObject::SwapEGLBuffers(dpy, draw);
} }
const RendererInfo& BackendObject_DirectGLES::GetRendererInfo() const { const RendererInfo& BackendObject_DirectGLES::GetRendererInfo() const {
@@ -17,8 +17,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
~BackendObject_DirectGLES() override; ~BackendObject_DirectGLES() override;
void Initialize() override; void Initialize() override;
void InitCapabilities() override; Bool InitCapabilities() override;
void InitWindowSurface() override; Bool InitWindowSurface() override;
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override;
Bool CreateEGLWindowSurface(const WindowHandle& handle) override;
Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override;
Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
const RendererInfo& GetRendererInfo() const override; const RendererInfo& GetRendererInfo() const override;
String GetBackendAPIVersionString() const override; String GetBackendAPIVersionString() const override;
+146 -145
View File
@@ -8,6 +8,7 @@
#include "DirectGLES.h" #include "DirectGLES.h"
#include "EGL/egl.h" #include "EGL/egl.h"
#include "MG_Util/Types.h"
#include "Utils.h" #include "Utils.h"
#include "Managers.h" #include "Managers.h"
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -45,7 +46,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace DebugImpl { namespace DebugImpl {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
void ErrorLopper::Loop(std::function<void(GLenum)> func) { void ErrorLopper::Loop(const std::function<void(GLenum)>& func) {
GLenum err = g_GLESFuncs.glGetError(); GLenum err = g_GLESFuncs.glGetError();
while (err != GL_NO_ERROR) { while (err != GL_NO_ERROR) {
func(err); func(err);
@@ -68,14 +69,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
Clear(); Clear();
} }
#else #else
void ErrorLopper::Loop(std::function<void(GLenum)> func) {} void ErrorLopper::Loop(const std::function<void(GLenum)>& func) {}
void ErrorLopper::Clear() {} void ErrorLopper::Clear() {}
ErrorLopper::ErrorLopper() {} ErrorLopper::ErrorLopper() = default;
ErrorLopper::~ErrorLopper() {} ErrorLopper::~ErrorLopper() = default;
#endif #endif
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
OpenGLScopeMarker::OpenGLScopeMarker(String scopeName) { OpenGLScopeMarker::OpenGLScopeMarker(const String& scopeName) {
g_GLESFuncs.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, scopeName.c_str()); g_GLESFuncs.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, scopeName.c_str());
} }
@@ -83,7 +84,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glPopDebugGroup(); g_GLESFuncs.glPopDebugGroup();
} }
#else #else
OpenGLScopeMarker::OpenGLScopeMarker(String scopeName) {} OpenGLScopeMarker::OpenGLScopeMarker(const String& scopeName) {}
OpenGLScopeMarker::~OpenGLScopeMarker() {} OpenGLScopeMarker::~OpenGLScopeMarker() {}
#endif #endif
@@ -92,31 +93,28 @@ namespace MobileGL::MG_Backend::DirectGLES {
// TODO: deletion for deleted objects // TODO: deletion for deleted objects
namespace BufferImpl { namespace BufferImpl {
void CreateAndSyncBufferObject(SharedPtr<MG_State::GLState::BufferObject>& bufferObject) { void CreateAndSyncBufferObject(const SharedPtr<MG_State::GLState::BufferObject>& bufferObject) {
if (!(bufferObject->GetChangeBits() & BufferChangeBits::DirtyBit)) return; if (!(bufferObject->GetChangeBits() & BufferChangeBits::DirtyBit)) return;
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject); const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject.get());
SharedPtr<BackendBufferObject> backendBufferObject; Bool exist = (backendBufferIt != g_backendBufferObjects.end());
if (backendBufferIt == g_backendBufferObjects.end()) { auto& backendObj = exist ? backendBufferIt->second : g_backendBufferObjects.GetOrCreate(bufferObject);
backendBufferObject = MakeShared<BackendBufferObject>(); if (!exist) {
g_backendBufferObjects[bufferObject] = backendBufferObject; backendObj = MakeShared<BackendBufferObject>();
} else {
backendBufferObject = backendBufferIt->second;
} }
backendBufferObject->SyncToBackend(bufferObject); backendObj->SyncToBackend(bufferObject);
} }
void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) { void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendBufferObjects.CollectGarbageIfNeeded();
// All buffers we need are: // All buffers we need are:
// 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO) // 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO)
// PBO is not needed since it should be handled in frontend // PBO is not needed since it should be handled in frontend
// static Vector<SharedPtr<MG_State::GLState::BufferObject>> buffersToSync;
// buffersToSync.clear();
const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
if (!currentVAOObject) { if (!currentVAOObject) {
MGLOG_E("No VAO is currently bound, cannot sync necessary buffers."); MGLOG_E("No VAO is currently bound, cannot sync necessary buffers.");
@@ -126,7 +124,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// VBO // VBO
for (const auto& attrib : currentVAOObject->GetAllAttributes()) { for (const auto& attrib : currentVAOObject->GetAllAttributes()) {
if (!attrib.Enabled) continue; if (!attrib.Enabled) continue;
auto bufferObject = attrib.Buffer; auto& bufferObject = attrib.Buffer;
if (bufferObject) { if (bufferObject) {
CreateAndSyncBufferObject(bufferObject); CreateAndSyncBufferObject(bufferObject);
} }
@@ -134,7 +132,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// IBO // IBO
if (includeIBO) { if (includeIBO) {
auto possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject();
if (possibleIBO) { if (possibleIBO) {
CreateAndSyncBufferObject(possibleIBO); CreateAndSyncBufferObject(possibleIBO);
} }
@@ -142,7 +140,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Indirect Buffer Object // Indirect Buffer Object
if (includeIndirectBuffer) { if (includeIndirectBuffer) {
auto possibleIndirectBuffer = auto& possibleIndirectBuffer =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
if (possibleIndirectBuffer) { if (possibleIndirectBuffer) {
CreateAndSyncBufferObject(possibleIndirectBuffer); CreateAndSyncBufferObject(possibleIndirectBuffer);
@@ -153,7 +151,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto uboBindingPointCnt = MG_State::pGLContext->GetBufferBindingPointCount(BufferTarget::Uniform); auto uboBindingPointCnt = MG_State::pGLContext->GetBufferBindingPointCount(BufferTarget::Uniform);
for (SizeT i = 0; i < uboBindingPointCnt; ++i) { for (SizeT i = 0; i < uboBindingPointCnt; ++i) {
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i); auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i);
auto obj = point.GetBoundObject(); auto& obj = point.GetBoundObject();
if (obj) { if (obj) {
CreateAndSyncBufferObject(obj); CreateAndSyncBufferObject(obj);
} }
@@ -166,48 +164,49 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
auto currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); g_backendVertexArrayObjects.CollectGarbageIfNeeded();
auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
if (!currentVAOObject) { if (!currentVAOObject) {
MGLOG_E("No VAO is currently bound, cannot sync current VAO."); MGLOG_E("No VAO is currently bound, cannot sync current VAO.");
return; return;
} }
const auto& backendVAOIt = g_backendVertexArrayObjects.find(currentVAOObject); const auto& backendVAOIt = g_backendVertexArrayObjects.find(currentVAOObject.get());
SharedPtr<VertexArrayImpl::BackendVertexArrayObject> backendVAOObject; Bool exist = (backendVAOIt != g_backendVertexArrayObjects.end());
if (backendVAOIt == g_backendVertexArrayObjects.end()) { auto& backendObj = exist ? backendVAOIt->second : g_backendVertexArrayObjects.GetOrCreate(currentVAOObject);
backendVAOObject = MakeShared<VertexArrayImpl::BackendVertexArrayObject>(); if (!exist) {
g_backendVertexArrayObjects[currentVAOObject] = backendVAOObject; backendObj = MakeShared<VertexArrayImpl::BackendVertexArrayObject>();
} else {
backendVAOObject = backendVAOIt->second;
} }
backendVAOObject->SyncToBackend(currentVAOObject); backendObj->SyncToBackend(currentVAOObject);
} }
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
namespace TextureImpl { namespace TextureImpl {
SharedPtr<BackendTextureObject> SyncTextureObjectToBackend( SharedPtr<BackendTextureObject>& SyncTextureObjectToBackend(
SharedPtr<MG_State::GLState::ITextureObject>& textureObject) { const SharedPtr<MG_State::GLState::ITextureObject>& textureObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
const auto& backendTextureIt = g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = g_backendTextureObjects.find(textureObject.get());
SharedPtr<BackendTextureObject> backendTextureObject; Bool exist = (backendTextureIt != g_backendTextureObjects.end());
if (backendTextureIt == g_backendTextureObjects.end()) { auto& backendObj = exist ? backendTextureIt->second : g_backendTextureObjects.GetOrCreate(textureObject);
backendTextureObject = MakeShared<BackendTextureObject>(); if (!exist) {
g_backendTextureObjects[textureObject] = backendTextureObject; backendObj = MakeShared<BackendTextureObject>();
} else {
backendTextureObject = backendTextureIt->second;
} }
backendTextureObject->SyncTextureParamsToBackend(textureObject); backendObj->SyncTextureParamsToBackend(textureObject);
backendTextureObject->SyncBuiltinSamplerToBackend(textureObject); backendObj->SyncBuiltinSamplerToBackend(textureObject);
backendTextureObject->SyncMipmapsToBackend(textureObject); backendObj->SyncMipmapsToBackend(textureObject);
return backendTextureObject;
return backendObj;
} }
void SyncNeccessaryTextures() { void SyncNeccessaryTextures() {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendTextureObjects.CollectGarbageIfNeeded();
// All textures we need are: // All textures we need are:
// 1. textures bound to texture units (TODO: only sync ones that are used in current program) // 1. textures bound to texture units (TODO: only sync ones that are used in current program)
// 2. textures used in current FBO // 2. textures used in current FBO
@@ -216,7 +215,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (int index = 0; index < MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; ++index) { for (int index = 0; index < MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; ++index) {
auto& unit = MG_State::pGLContext->GetTextureUnitObject(index); auto& unit = MG_State::pGLContext->GetTextureUnitObject(index);
for (const auto& bindingSlot : unit.GetAllBindingSlots()) { for (const auto& bindingSlot : unit.GetAllBindingSlots()) {
auto textureObject = bindingSlot.GetBoundObject(); auto& textureObject = bindingSlot.GetBoundObject();
if (textureObject) { if (textureObject) {
SyncTextureObjectToBackend(textureObject); SyncTextureObjectToBackend(textureObject);
} }
@@ -228,7 +227,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (currentFBO) { if (currentFBO) {
for (const auto& attachment : currentFBO->GetAllAttachmentObjects()) { for (const auto& attachment : currentFBO->GetAllAttachmentObjects()) {
if (!attachment.IsTexture()) continue; if (!attachment.IsTexture()) continue;
auto textureObject = attachment.GetTexture(); auto& textureObject = attachment.GetTexture();
if (textureObject) { if (textureObject) {
SyncTextureObjectToBackend(textureObject); SyncTextureObjectToBackend(textureObject);
} }
@@ -242,16 +241,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendFramebufferObjects.CollectGarbageIfNeeded();
TextureImpl::g_backendTextureObjects.CollectGarbageIfNeeded();
RenderbufferImpl::g_backendRenderbufferObjects.CollectGarbageIfNeeded();
const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read}; const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read};
MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr;
for (auto target : fboTargets) { for (auto& target : fboTargets) {
auto slot = MG_State::pGLContext->GetFramebufferBindingSlot(target); auto& slot = MG_State::pGLContext->GetFramebufferBindingSlot(target);
auto version = slot.GetVersion(); auto version = slot.GetVersion();
if (version == g_fboBindVersions[SizeT(target)]) continue; if (version == g_fboBindVersions[SizeT(target)]) continue;
auto currentFBO = slot.GetBoundObject(); auto& currentFBO = slot.GetBoundObject();
if (!currentFBO) { if (!currentFBO) {
MGLOG_E("No FBO is currently bound, cannot sync current FBO."); MGLOG_E("No FBO is currently bound, cannot sync current FBO.");
@@ -263,21 +266,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
continue; continue;
} }
const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO);
SharedPtr<BackendFramebufferObject> backendFBOObject;
if (backendFBOIt == g_backendFramebufferObjects.end()) {
backendFBOObject = MakeShared<BackendFramebufferObject>();
g_backendFramebufferObjects[currentFBO] = backendFBOObject;
} else {
backendFBOObject = backendFBOIt->second;
}
if (currentFBO.get() == lastUpdatedFBO) { if (currentFBO.get() == lastUpdatedFBO) {
MGLOG_D("Draw FBO and read FBO are the same, skipping sync."); MGLOG_D("Draw FBO and read FBO are the same, skipping sync.");
} else { continue;
backendFBOObject->SyncToBackend(currentFBO, target);
} }
const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO.get());
Bool exist = (backendFBOIt != g_backendFramebufferObjects.end());
auto& backendObj = exist ? backendFBOIt->second : g_backendFramebufferObjects.GetOrCreate(currentFBO);
if (!exist) {
backendObj = MakeShared<BackendFramebufferObject>();
}
backendObj->SyncToBackend(currentFBO, target);
lastUpdatedFBO = currentFBO.get(); lastUpdatedFBO = currentFBO.get();
} }
} }
@@ -466,21 +467,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
auto currentProgram = MG_State::pGLContext->GetCurrentProgram(); g_backendProgramObjects.CollectGarbageIfNeeded();
SamplerImpl::g_backendSamplerObjects.CollectGarbageIfNeeded();
auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (!currentProgram || !currentProgram->GetLinkStatus()) { if (!currentProgram || !currentProgram->GetLinkStatus()) {
g_GLESFuncs.glUseProgram(0); g_GLESFuncs.glUseProgram(0);
return; return;
} }
const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram); const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram.get());
SharedPtr<BackendProgramObjectImpl> backendProgram; Bool exist = (backendProgramIt != g_backendProgramObjects.end());
if (backendProgramIt == g_backendProgramObjects.end()) { auto& backendObj = exist ? backendProgramIt->second : g_backendProgramObjects.GetOrCreate(currentProgram);
backendProgram = MakeShared<BackendProgramObjectImpl>(); if (!exist) {
g_backendProgramObjects[currentProgram] = backendProgram; backendObj = MakeShared<BackendProgramObjectImpl>();
backendProgram->SyncToBackend(currentProgram); backendObj->SyncToBackend(currentProgram);
} else { } else {
backendProgram = backendProgramIt->second; if (!backendObj->GetBackendProgramId()) {
if (!backendProgram->GetBackendProgramId()) { backendObj->SyncToBackend(currentProgram);
backendProgram->SyncToBackend(currentProgram);
} }
} }
} }
@@ -495,7 +498,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& currentFBO = slot.GetBoundObject(); const auto& currentFBO = slot.GetBoundObject();
if (currentFBO && currentFBO != MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { if (currentFBO && currentFBO != MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO); const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO.get());
if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) { if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) {
backendFBOIt->second->Bind(target); backendFBOIt->second->Bind(target);
} else { } else {
@@ -528,7 +531,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif #endif
const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray(); const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray();
if (currentVAO) { if (currentVAO) {
const auto& backendVAOIt = VertexArrayImpl::g_backendVertexArrayObjects.find(currentVAO); const auto& backendVAOIt = VertexArrayImpl::g_backendVertexArrayObjects.find(currentVAO.get());
if (backendVAOIt != VertexArrayImpl::g_backendVertexArrayObjects.end()) { if (backendVAOIt != VertexArrayImpl::g_backendVertexArrayObjects.end()) {
backendVAOIt->second->Bind(); backendVAOIt->second->Bind();
} }
@@ -556,7 +559,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertTextureTargetToString(target).c_str()); MG_Util::ConvertTextureTargetToString(target).c_str());
continue; continue;
} }
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue; if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue;
GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target); GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target);
@@ -566,7 +569,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Bind sampler object if necessary // Bind sampler object if necessary
const auto& samplerObject = textureUnit.GetSamplerObject(); const auto& samplerObject = textureUnit.GetSamplerObject();
if (samplerObject) { if (samplerObject) {
const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject.get());
if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) { if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) {
backendSamplerIt->second->Bind(unit); backendSamplerIt->second->Bind(unit);
} }
@@ -581,7 +584,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedNC("BindCurrentProgram", TRACY_ZONECOLOR_BACKEND); ZoneScopedNC("BindCurrentProgram", TRACY_ZONECOLOR_BACKEND);
#endif #endif
const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram); const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram.get());
if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) {
backendProgramIt->second->Use(); backendProgramIt->second->Use();
auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); auto backendProgramId = backendProgramIt->second->GetBackendProgramId();
@@ -623,11 +626,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Connect buffer to backend binding point // Connect buffer to backend binding point
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding); auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding);
auto bufferObj = point.GetBoundObject(); auto& bufferObj = point.GetBoundObject();
auto range = point.GetRange(); auto range = point.GetRange();
if (bufferObj) { if (bufferObj) {
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObj); const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObj.get());
if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) { if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) {
const auto& backendBufferObject = backendBufferIt->second; const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_UNIFORM_BUFFER); backendBufferObject->Bind(GL_UNIFORM_BUFFER);
@@ -635,9 +638,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding, g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId()); backendBufferObject->GetBackendBufferId());
} else { } else {
g_GLESFuncs.glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding, g_GLESFuncs.glBindBufferRange(
backendBufferObject->GetBackendBufferId(), GL_UNIFORM_BUFFER, lastUBOBinding, backendBufferObject->GetBackendBufferId(),
range.start, range.end - range.start); (GLintptr)range.start, (GLintptr)(range.end - range.start));
} }
} else { } else {
MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO."); MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO.");
@@ -660,18 +663,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
backendProgramIt->second->GetBackendProgramId(), name.c_str()); backendProgramIt->second->GetBackendProgramId(), name.c_str());
g_GLESFuncs.glUniform1i(locAtBackend, unit); g_GLESFuncs.glUniform1i(locAtBackend, unit);
auto samplerObject = MG_State::pGLContext->GetTextureUnitObject(unit).GetSamplerObject(); auto& samplerObject = MG_State::pGLContext->GetTextureUnitObject(unit).GetSamplerObject();
if (samplerObject) { if (samplerObject) {
const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); const auto& backendSamplerIt =
SharedPtr<SamplerImpl::BackendSamplerObject> backendSamplerObject; SamplerImpl::g_backendSamplerObjects.find(samplerObject.get());
if (backendSamplerIt == SamplerImpl::g_backendSamplerObjects.end()) { Bool exist = (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end());
backendSamplerObject = MakeShared<SamplerImpl::BackendSamplerObject>(); auto& backendObj = exist ? backendSamplerIt->second
SamplerImpl::g_backendSamplerObjects[samplerObject] = backendSamplerObject; : SamplerImpl::g_backendSamplerObjects.GetOrCreate(samplerObject);
} else { if (!exist) {
backendSamplerObject = backendSamplerIt->second; backendObj = MakeShared<SamplerImpl::BackendSamplerObject>();
} }
backendSamplerObject->SyncToBackend(samplerObject); backendObj->SyncToBackend(samplerObject);
} else { } else {
SamplerImpl::UnbindSampler(unit); SamplerImpl::UnbindSampler(unit);
} }
@@ -845,30 +848,29 @@ namespace MobileGL::MG_Backend::DirectGLES {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER
DebugImpl::OpenGLScopeMarker marker(__func__); DebugImpl::OpenGLScopeMarker marker(__func__);
#endif #endif
DebugImpl::ErrorLopper errorLopper;
TextureImpl::SyncNeccessaryTextures(); TextureImpl::SyncNeccessaryTextures();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
FramebufferImpl::SyncCurrentFBO(); FramebufferImpl::SyncCurrentFBO();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
RenderStateImpl::SyncRenderState(); RenderStateImpl::SyncRenderState();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
BindCurrentFBO(FramebufferTarget::Draw); BindCurrentFBO(FramebufferTarget::Draw);
BindCurrentFBO(FramebufferTarget::Read); BindCurrentFBO(FramebufferTarget::Read);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str()); dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str());
g_GLESFuncs.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); g_GLESFuncs.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} }
@@ -895,15 +897,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertTextureTargetToString(textureTarget).c_str()); MG_Util::ConvertTextureTargetToString(textureTarget).c_str());
} }
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
SharedPtr<TextureImpl::BackendTextureObject> backendTextureObject; Bool exist = (backendTextureIt != TextureImpl::g_backendTextureObjects.end());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) { auto& backendObj =
backendTextureObject = MakeShared<TextureImpl::BackendTextureObject>(); exist ? backendTextureIt->second : TextureImpl::g_backendTextureObjects.GetOrCreate(textureObject);
TextureImpl::g_backendTextureObjects[textureObject] = backendTextureObject; if (!exist) {
} else { backendObj = MakeShared<TextureImpl::BackendTextureObject>();
backendTextureObject = backendTextureIt->second;
} }
backendTextureObject->Bind(target, unit); backendObj->Bind(target, unit);
} }
return true; return true;
} }
@@ -953,15 +954,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
DebugImpl::ErrorLopper errorLopper; DebugImpl::ErrorLopper errorLopper;
MGLOG_D("%s: Backend", __func__); MGLOG_D("%s: Backend", __func__);
TextureImpl::SyncNeccessaryTextures(); TextureImpl::SyncNeccessaryTextures();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
FramebufferImpl::SyncCurrentFBO(); FramebufferImpl::SyncCurrentFBO();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
RenderStateImpl::SyncRenderState(); RenderStateImpl::SyncRenderState();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
if (!UpdateTextureBindingAtTarget(target)) return; if (!UpdateTextureBindingAtTarget(target)) return;
@@ -969,10 +970,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Bind necessary FBO and texture // Bind necessary FBO and texture
BindCurrentFBO(FramebufferTarget::Read); BindCurrentFBO(FramebufferTarget::Read);
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit(); Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit) const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject((Int)activeTextureUnit)
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)) .GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
.GetBoundObject(); .GetBoundObject();
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) { if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.", MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.",
textureObject ? textureObject->GetExternalIndex() : 0); textureObject ? textureObject->GetExternalIndex() : 0);
@@ -998,19 +999,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (!isDepthFormat) { if (!isDepthFormat) {
g_GLESFuncs.glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); g_GLESFuncs.glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} else { } else {
MGLOG_D("%s: Backend depth", __func__); MGLOG_D("%s: Backend depth", __func__);
g_GLESFuncs.glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type, g_GLESFuncs.glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type,
nullptr); nullptr);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
GLint currentTex = backendTextureIt->second->GetBackendTextureId(); auto currentTex = (GLint)backendTextureIt->second->GetBackendTextureId();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -1026,7 +1027,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height, g_GLESFuncs.glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height,
GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0), GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0),
GL_NEAREST); GL_NEAREST);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} }
@@ -1041,15 +1042,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("%s: Backend", __func__); MGLOG_D("%s: Backend", __func__);
TextureImpl::SyncNeccessaryTextures(); TextureImpl::SyncNeccessaryTextures();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
FramebufferImpl::SyncCurrentFBO(); FramebufferImpl::SyncCurrentFBO();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
RenderStateImpl::SyncRenderState(); RenderStateImpl::SyncRenderState();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -1057,11 +1058,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Bind necessary FBO and texture // Bind necessary FBO and texture
BindCurrentFBO(FramebufferTarget::Read); BindCurrentFBO(FramebufferTarget::Read);
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit(); auto activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit) const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit)
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)) .GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
.GetBoundObject(); .GetBoundObject();
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) { if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.", MGLOG_E("CopyTexSubImage2D: No backend texture found for texture %u.",
textureObject ? textureObject->GetExternalIndex() : 0); textureObject ? textureObject->GetExternalIndex() : 0);
@@ -1069,12 +1070,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
backendTextureIt->second->Bind(target, activeTextureUnit); backendTextureIt->second->Bind(target, activeTextureUnit);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
GLenum internalFormat; GLenum internalFormat;
g_GLESFuncs.glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&internalFormat); g_GLESFuncs.glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&internalFormat);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
auto mgInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); auto mgInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat);
@@ -1084,19 +1085,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (!isDepthFormat) { if (!isDepthFormat) {
g_GLESFuncs.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); g_GLESFuncs.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} else { } else {
MGLOG_D("%s: Backend depth", __func__); MGLOG_D("%s: Backend depth", __func__);
GLint currentTex = backendTextureIt->second->GetBackendTextureId(); auto currentTex = backendTextureIt->second->GetBackendTextureId();
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder(false); TempFBOBinder tempFBOBinder(false);
g_GLESFuncs.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level); g_GLESFuncs.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
if (g_GLESFuncs.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (g_GLESFuncs.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
@@ -1107,7 +1108,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBlitFramebuffer( g_GLESFuncs.glBlitFramebuffer(
x, y, x + width, y + height, xoffset, yoffset, xoffset + width, yoffset + height, x, y, x + width, y + height, xoffset, yoffset, xoffset + width, yoffset + height,
GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST); GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} }
@@ -1120,8 +1121,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto unitIndex = MG_State::pGLContext->GetActiveTextureUnit(); auto unitIndex = MG_State::pGLContext->GetActiveTextureUnit();
auto& unit = MG_State::pGLContext->GetTextureUnitObject(unitIndex); auto& unit = MG_State::pGLContext->GetTextureUnitObject(unitIndex);
auto& slot = unit.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target)); auto& slot = unit.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target));
auto texture = slot.GetBoundObject(); auto& texture = slot.GetBoundObject();
auto backendTexture = TextureImpl::SyncTextureObjectToBackend(texture); auto& backendTexture = TextureImpl::SyncTextureObjectToBackend(texture);
backendTexture->Bind(target, unitIndex); backendTexture->Bind(target, unitIndex);
g_GLESFuncs.glGenerateMipmap(target); g_GLESFuncs.glGenerateMipmap(target);
@@ -1184,7 +1185,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
PixelStoreParameters m_prevParams; PixelStoreParameters m_prevParams;
PixelStoreParameters QueryCurrentGLPixelStoreParams(Bool isUnpack) { static PixelStoreParameters QueryCurrentGLPixelStoreParams(Bool isUnpack) {
PixelStoreParameters p; PixelStoreParameters p;
if (!isUnpack) { if (!isUnpack) {
g_GLESFuncs.glGetIntegerv(GL_PACK_ALIGNMENT, (GLint*)&p.Alignment); g_GLESFuncs.glGetIntegerv(GL_PACK_ALIGNMENT, (GLint*)&p.Alignment);
@@ -1214,7 +1215,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return p; return p;
} }
void Sync(Bool isUnpack, const PixelStoreParameters& params) { static void Sync(Bool isUnpack, const PixelStoreParameters& params) {
if (!isUnpack) { if (!isUnpack) {
g_GLESFuncs.glPixelStorei(GL_PACK_ALIGNMENT, params.Alignment); g_GLESFuncs.glPixelStorei(GL_PACK_ALIGNMENT, params.Alignment);
g_GLESFuncs.glPixelStorei(GL_PACK_ROW_LENGTH, params.RowLength); g_GLESFuncs.glPixelStorei(GL_PACK_ROW_LENGTH, params.RowLength);
@@ -1271,7 +1272,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
// Handle PBO // Handle PBO
auto pixelPackBufferObject = auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
Bool usePBO; Bool usePBO;
GLuint prevPixelPackBuffer = 0; GLuint prevPixelPackBuffer = 0;
@@ -1279,7 +1280,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject); BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject);
MGLOG_D("ReadPixels: Using PBO %u", pixelPackBufferObject->GetExternalIndex()); MGLOG_D("ReadPixels: Using PBO %u", pixelPackBufferObject->GetExternalIndex());
usePBO = true; usePBO = true;
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject); const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject.get());
if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) { if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) {
MGLOG_E("ReadPixels: No backend buffer found for PBO %u.", MGLOG_E("ReadPixels: No backend buffer found for PBO %u.",
@@ -1299,8 +1300,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (usePBO) { if (usePBO) {
// pull back to client memory if PBO is used // pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory"); MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(
pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT); GL_PIXEL_PACK_BUFFER, 0, (GLsizeiptr)pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) { if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory"); MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize(); SizeT size = pixelPackBufferObject->GetSize();
@@ -1345,7 +1346,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("GetTexImage: SyncCurrentFBO()"); MGLOG_D("GetTexImage: SyncCurrentFBO()");
FramebufferImpl::SyncCurrentFBO(); FramebufferImpl::SyncCurrentFBO();
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit(); auto activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
MGLOG_D("GetTexImage: active texture unit = %u", activeTextureUnit); MGLOG_D("GetTexImage: active texture unit = %u", activeTextureUnit);
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit) const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit)
@@ -1355,7 +1356,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("GetTexImage: bound texture object = %p (name=%u)", textureObject.get(), MGLOG_D("GetTexImage: bound texture object = %p (name=%u)", textureObject.get(),
textureObject ? textureObject->GetExternalIndex() : 0); textureObject ? textureObject->GetExternalIndex() : 0);
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) { if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("GetTexImage: No backend texture found for texture %u.", MGLOG_E("GetTexImage: No backend texture found for texture %u.",
@@ -1383,14 +1384,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
MGLOG_D("GetTexImage: Applying TempPixelStoreParameterSync (PACK)"); MGLOG_D("GetTexImage: Applying TempPixelStoreParameterSync (PACK)");
TempPixelStoreParameterSync tempPackParamsSync(false); TempPixelStoreParameterSync tempPackParamsSync(false);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -1404,7 +1405,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()); auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
auto levelRange = textureMipmapObject->GetLevelRange(); auto& levelRange = textureMipmapObject->GetLevelRange();
MGLOG_D("GetTexImage: mipmap level range = [%d, %d)", levelRange.x(), levelRange.y()); MGLOG_D("GetTexImage: mipmap level range = [%d, %d)", levelRange.x(), levelRange.y());
if (level < levelRange.x() || level >= levelRange.y()) { if (level < levelRange.x() || level >= levelRange.y()) {
@@ -1421,7 +1422,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("GetTexImage: mip level %d size = %dx%d", level, size.x(), size.y()); MGLOG_D("GetTexImage: mip level %d size = %dx%d", level, size.x(), size.y());
// Handle PBO // Handle PBO
auto pixelPackBufferObject = auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject(); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
Bool usePBO; Bool usePBO;
GLuint prevPixelPackBuffer = 0; GLuint prevPixelPackBuffer = 0;
@@ -1429,7 +1430,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject); BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject);
MGLOG_D("GetTexImage: Using PBO %u", pixelPackBufferObject->GetExternalIndex()); MGLOG_D("GetTexImage: Using PBO %u", pixelPackBufferObject->GetExternalIndex());
usePBO = true; usePBO = true;
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject); const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject.get());
if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) { if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) {
MGLOG_E("GetTexImage: No backend buffer found for PBO %u.", MGLOG_E("GetTexImage: No backend buffer found for PBO %u.",
pixelPackBufferObject ? pixelPackBufferObject->GetExternalIndex() : 0); pixelPackBufferObject ? pixelPackBufferObject->GetExternalIndex() : 0);
@@ -1443,7 +1444,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("GetTexImage: Not using PBO"); MGLOG_D("GetTexImage: Not using PBO");
} }
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
MGLOG_D("GetTexImage: glReadPixels(0, 0, %d, %d, %s, %s, %p)", size.x(), size.y(), MGLOG_D("GetTexImage: glReadPixels(0, 0, %d, %d, %s, %s, %p)", size.x(), size.y(),
@@ -1451,14 +1452,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
pixels); pixels);
g_GLESFuncs.glReadPixels(0, 0, size.x(), size.y(), esFormat, esType, pixels); g_GLESFuncs.glReadPixels(0, 0, size.x(), size.y(), esFormat, esType, pixels);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
if (usePBO) { if (usePBO) {
// pull back to client memory if PBO is used // pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory"); MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(
pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT); GL_PIXEL_PACK_BUFFER, 0, (GLsizeiptr)pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) { if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory"); MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize(); SizeT size = pixelPackBufferObject->GetSize();
@@ -1479,7 +1480,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
MGLOG_D("GetTexImage: finished"); MGLOG_D("GetTexImage: finished");
+110 -105
View File
@@ -7,10 +7,6 @@
// End of Source File Header // End of Source File Header
#include "Managers.h" #include "Managers.h"
#include "MG_State/GLState/TextureState/TextureEnum.h"
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_State/GLState/TextureState/TextureState.h"
#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h"
#include "Utils.h" #include "Utils.h"
#include "DirectGLES.h" #include "DirectGLES.h"
@@ -18,6 +14,7 @@
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h> #include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
#include <MG_Util/Converters/MGToGL/BufferEnumConverter.h> #include <MG_Util/Converters/MGToGL/BufferEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h> #include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h> #include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
@@ -44,7 +41,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendBufferObject::SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) { void BackendBufferObject::SyncToBackend(const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -105,7 +102,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void BackendBufferObject::SyncToBackend_glBufferData( void BackendBufferObject::SyncToBackend_glBufferData(
SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) { const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -117,11 +114,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLenum usage = MG_Util::ConvertBufferUsageToGLEnum(stateBufferObject->GetUsage()); GLenum usage = MG_Util::ConvertBufferUsageToGLEnum(stateBufferObject->GetUsage());
Bind(); Bind();
g_GLESFuncs.glBufferData(TempBufferTarget, size, data, usage); g_GLESFuncs.glBufferData(TempBufferTarget, (GLsizeiptr)size, data, usage);
} }
void BackendBufferObject::SyncToBackend_glBufferSubData( void BackendBufferObject::SyncToBackend_glBufferSubData(
SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) { const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -130,7 +127,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const void* data = stateBufferObject->GetDataReadOnly()->data(); const void* data = stateBufferObject->GetDataReadOnly()->data();
// dirty range: [range.start, range.end) // dirty range: [range.start, range.end)
auto ranges = stateBufferObject->GetDirtyRanges(); auto& ranges = stateBufferObject->GetDirtyRanges();
if (ranges.empty()) { if (ranges.empty()) {
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId); MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
return; return;
@@ -138,20 +135,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (const auto& range : ranges) { for (const auto& range : ranges) {
Bind(); Bind();
g_GLESFuncs.glBufferSubData(TempBufferTarget, range.start, range.end - range.start, g_GLESFuncs.glBufferSubData(TempBufferTarget, (GLintptr)range.start,
(GLintptr)(range.end - range.start),
reinterpret_cast<const char*>(data) + range.start); reinterpret_cast<const char*>(data) + range.start);
} }
} }
void BackendBufferObject::SyncToBackend_glMapBufferRange( void BackendBufferObject::SyncToBackend_glMapBufferRange(
SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, Bool invalidate, Bool unsynchronized) { const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, Bool invalidate, Bool unsynchronized) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId); MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId);
MGLOG_D("Mapping buffer with ID: %u", m_backendBufferId); MGLOG_D("Mapping buffer with ID: %u", m_backendBufferId);
auto ranges = stateBufferObject->GetDirtyRanges(); auto& ranges = stateBufferObject->GetDirtyRanges();
if (ranges.empty()) { if (ranges.empty()) {
MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId); MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId);
return; return;
@@ -159,18 +157,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
SizeT minStart = ranges.GetOverallMinStart(); SizeT minStart = ranges.GetOverallMinStart();
SizeT maxEnd = ranges.GetOverallMaxEnd(); SizeT maxEnd = ranges.GetOverallMaxEnd();
Bind(); Bind();
void* mappedData = g_GLESFuncs.glMapBufferRange(TempBufferTarget, minStart, maxEnd - minStart, void* mappedData = g_GLESFuncs.glMapBufferRange(
(invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) | TempBufferTarget, (GLintptr)minStart, (GLintptr)(maxEnd - minStart),
(unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) | (invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) | (unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) |
GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
const void* data = stateBufferObject->GetDataReadOnly()->data(); const void* data = stateBufferObject->GetDataReadOnly()->data();
if (mappedData) { if (mappedData) {
MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId); MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId);
Memcpy(mappedData, reinterpret_cast<const char*>(data) + minStart, maxEnd - minStart); Memcpy(mappedData, reinterpret_cast<const char*>(data) + minStart, maxEnd - minStart);
// Explicitly flush the dirty ranges // Explicitly flush the dirty ranges
for (const auto& range : ranges) { for (const auto& range : ranges) {
g_GLESFuncs.glFlushMappedBufferRange(TempBufferTarget, range.start - minStart, g_GLESFuncs.glFlushMappedBufferRange(TempBufferTarget, (GLintptr)(range.start - minStart),
range.end - range.start); (GLintptr)(range.end - range.start));
} }
g_GLESFuncs.glUnmapBuffer(TempBufferTarget); g_GLESFuncs.glUnmapBuffer(TempBufferTarget);
} else { } else {
@@ -191,7 +189,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBindBuffer(target, m_backendBufferId); g_GLESFuncs.glBindBuffer(target, m_backendBufferId);
} }
UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>> g_backendBufferObjects; StateBackendObjectRegistry<MG_State::GLState::BufferObject, BackendBufferObject> g_backendBufferObjects;
BackendBufferObject* g_boundVertexBufferObject = nullptr; BackendBufferObject* g_boundVertexBufferObject = nullptr;
} // namespace BufferImpl } // namespace BufferImpl
@@ -209,22 +207,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendVertexArrayObject::Bind() { void BackendVertexArrayObject::Bind() const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_GLESFuncs.glBindVertexArray(m_backendVAOId); g_GLESFuncs.glBindVertexArray(m_backendVAOId);
} }
void BackendVertexArrayObject::BindAttributeBuffer(Uint index, inline void BindAttributeBuffer(const MG_State::GLState::VertexAttribute& attrib) {
const MG_State::GLState::VertexAttribute& attrib) {
const auto& bufferObject = attrib.Buffer; const auto& bufferObject = attrib.Buffer;
if (!bufferObject) { if (!bufferObject) {
MGLOG_W("Attribute has no bound buffer, skipping."); MGLOG_W("Attribute has no bound buffer, skipping.");
return; return;
} }
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObject); const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObject.get());
if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) { if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) {
MGLOG_E("No backend buffer found for attribute's buffer, cannot bind attribute."); MGLOG_E("No backend buffer found for attribute's buffer, cannot bind attribute.");
return; return;
@@ -234,7 +231,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
backendBufferObject->Bind(GL_ARRAY_BUFFER); backendBufferObject->Bind(GL_ARRAY_BUFFER);
} }
void BackendVertexArrayObject::SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject) { void BackendVertexArrayObject::SyncToBackend(
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -268,7 +266,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions[attribIndex].BufferVersion; m_syncedAttributeVersions[attribIndex].BufferVersion;
if (!needsSyncFormat && !needsSyncBuffer) continue; if (!needsSyncFormat && !needsSyncBuffer) continue;
BindAttributeBuffer(attribIndex, attrib); BindAttributeBuffer(attrib);
if (!attrib.IsInteger) { if (!attrib.IsInteger) {
g_GLESFuncs.glVertexAttribPointer( g_GLESFuncs.glVertexAttribPointer(
@@ -289,7 +287,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (currentIndexBufferVersion != m_syncedIndexBufferVersion) { if (currentIndexBufferVersion != m_syncedIndexBufferVersion) {
const auto& indexBufferBinding = stateVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); const auto& indexBufferBinding = stateVAOObject->GetIndexBufferBindingSlot().GetBoundObject();
if (indexBufferBinding) { if (indexBufferBinding) {
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(indexBufferBinding); const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(indexBufferBinding.get());
if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) { if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) {
const auto& backendBufferObject = backendBufferIt->second; const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_ELEMENT_ARRAY_BUFFER); backendBufferObject->Bind(GL_ELEMENT_ARRAY_BUFFER);
@@ -303,7 +301,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions = allAttributeVersions; m_syncedAttributeVersions = allAttributeVersions;
} }
UnorderedMap<SharedPtr<MG_State::GLState::VertexArrayObject>, SharedPtr<BackendVertexArrayObject>> StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects; g_backendVertexArrayObjects;
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
@@ -336,7 +334,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_boundTexturesCache[unit][targetN] = this; g_boundTexturesCache[unit][targetN] = this;
} }
Uint BackendTextureObject::GetBackendTextureId() { Uint BackendTextureObject::GetBackendTextureId() const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -344,7 +342,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void BackendTextureObject::SyncMipmapsToBackend( void BackendTextureObject::SyncMipmapsToBackend(
SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) { const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) {
if (!stateTextureObject) { if (!stateTextureObject) {
MGLOG_E("State texture object is null, cannot sync to backend."); MGLOG_E("State texture object is null, cannot sync to backend.");
return; return;
@@ -353,7 +351,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
DebugImpl::ErrorLopper errorLopper;
MGLOG_D("Syncing texture mipmaps with backend ID %u to backend for state ID %u", m_backendTextureId, MGLOG_D("Syncing texture mipmaps with backend ID %u to backend for state ID %u", m_backendTextureId,
stateTextureObject->GetExternalIndex()); stateTextureObject->GetExternalIndex());
@@ -381,7 +378,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
Bind(target); Bind(target);
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
const auto baseSize = stateTextureObject->GetBaseSize(); const auto baseSize = stateTextureObject->GetBaseSize();
@@ -414,7 +411,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
&glFormat, &glType); &glFormat, &glType);
const auto& uploadTargets = textureMipmapObject->GetUploadTargets(); const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
for (auto uploadTarget : uploadTargets) { for (auto& uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) { for (SizeT level = 0; level < mipmapCount; ++level) {
auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level); auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
@@ -429,22 +426,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData, levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData,
levelDirty ? "true" : "false"); levelDirty ? "true" : "false");
errorLopper.Clear(); DebugImpl::ErrorLopper::Clear();
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
auto textureTarget = stateTextureObject->GetTarget(); auto textureTarget = stateTextureObject->GetTarget();
// TODO: handle more texture types // TODO: handle more texture types
switch (textureTarget) { switch (textureTarget) {
case TextureTarget::Texture2D: case TextureTarget::Texture2D:
case TextureTarget::TextureCubeMap: { case TextureTarget::TextureCubeMap: {
g_GLESFuncs.glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat, g_GLESFuncs.glTexImage2D(
static_cast<GLsizei>(levelTexelSize.x()), glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType, static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
pData); 0, glFormat, glType, pData);
break; break;
} }
case TextureTarget::Texture3D: { case TextureTarget::Texture3D: {
g_GLESFuncs.glTexImage3D( g_GLESFuncs.glTexImage3D(
glUploadTarget, static_cast<GLint>(level), glInternalFormat, glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()), static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
static_cast<GLsizei>(levelTexelSize.z()), 0, glFormat, glType, pData); static_cast<GLsizei>(levelTexelSize.z()), 0, glFormat, glType, pData);
break; break;
@@ -454,8 +451,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertTextureTargetToString(textureTarget).c_str()); MG_Util::ConvertTextureTargetToString(textureTarget).c_str());
} }
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, glUploadTarget, DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__,
glInternalFormat, glFormat, glType, pData](GLenum err) { glUploadTarget, glInternalFormat, glFormat, glType,
pData](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, " MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, "
"type=%s, pixels=%p", "type=%s, pixels=%p",
func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(), func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(),
@@ -478,7 +476,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat,
&glFormat, &glType); &glFormat, &glType);
const auto& uploadTargets = textureMipmapObject->GetUploadTargets(); const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
for (auto uploadTarget : uploadTargets) { for (auto& uploadTarget : uploadTargets) {
for (SizeT level = 0; level < mipmapCount; ++level) { for (SizeT level = 0; level < mipmapCount; ++level) {
if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) { if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) {
continue; continue;
@@ -499,10 +497,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop(
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, [file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line,
}); MG_Util::ConvertGLEnumToString(err).c_str());
});
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0, g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()), static_cast<GLsizei>(texelSize.x()),
@@ -518,7 +517,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto* textureBufferObject = auto* textureBufferObject =
static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get()); static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get());
auto& slot = textureBufferObject->GetBufferBindingSlot(); auto& slot = textureBufferObject->GetBufferBindingSlot();
auto buffer = slot.GetBoundObject(); auto& buffer = slot.GetBoundObject();
auto bufferIndex = buffer->GetExternalIndex(); auto bufferIndex = buffer->GetExternalIndex();
currentTextureInfo.bufferExternalIndex = bufferIndex; currentTextureInfo.bufferExternalIndex = bufferIndex;
@@ -530,10 +529,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Need to sync texture buffer if not synced yet // Need to sync texture buffer if not synced yet
auto& backendBuffers = BufferImpl::g_backendBufferObjects; auto& backendBuffers = BufferImpl::g_backendBufferObjects;
SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject; SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject;
const auto& backendBufferIt = backendBuffers.find(buffer); const auto& backendBufferIt = backendBuffers.find(buffer.get());
if (backendBufferIt == backendBuffers.end()) { if (backendBufferIt == backendBuffers.end()) {
backendBufferObject = MakeShared<BufferImpl::BackendBufferObject>(); auto& backendBufferSlot = backendBuffers.GetOrCreate(buffer);
backendBuffers[buffer] = backendBufferObject; if (!backendBufferSlot) {
backendBufferSlot = MakeShared<BufferImpl::BackendBufferObject>();
}
backendBufferObject = backendBufferSlot;
} else { } else {
backendBufferObject = backendBufferIt->second; backendBufferObject = backendBufferIt->second;
} }
@@ -553,7 +555,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
THROW_UNIMPL_EXCEPTION; THROW_UNIMPL_EXCEPTION;
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -561,11 +563,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
void BackendTextureObject::SyncBuiltinSamplerToBackend( void BackendTextureObject::SyncBuiltinSamplerToBackend(
SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) { const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
DebugImpl::ErrorLopper errorLopper;
if (!stateTextureObject) { if (!stateTextureObject) {
MGLOG_E("State texture object is null, cannot sync to backend."); MGLOG_E("State texture object is null, cannot sync to backend.");
return; return;
@@ -594,7 +596,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
Bind(target); Bind(target);
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -607,28 +609,29 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glTexParameteri(target, glName, \ g_GLESFuncs.glTexParameteri(target, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \ MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
m_cacheSamplerParameters.internalName = samplerParams.internalName; \ m_cacheSamplerParameters.internalName = samplerParams.internalName; \
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, \ DebugImpl::ErrorLopper::Loop( \
t = MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)](GLenum err) { \ [file = __FILE__, line = __LINE__, func = __func__, \
MGLOG_D("%s(%s:%d) ES error %s, GL_TEXTURE_MIN_FILTER = %s", func, file, line, \ t = MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)](GLenum err) { \
MG_Util::ConvertGLEnumToString(err).c_str(), MG_Util::ConvertGLEnumToString(t).c_str()); \ MGLOG_D("%s(%s:%d) ES error %s, GL_TEXTURE_MIN_FILTER = %s", func, file, line, \
}); \ MG_Util::ConvertGLEnumToString(err).c_str(), MG_Util::ConvertGLEnumToString(t).c_str()); \
}); \
} }
if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter || if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter ||
m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) { m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) {
g_GLESFuncs.glTexParameteri( g_GLESFuncs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
target, GL_TEXTURE_MIN_FILTER, (GLint)MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.minFilter,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.minFilter, samplerParams.mipmapMode)); samplerParams.mipmapMode));
m_cacheSamplerParameters.minFilter = samplerParams.minFilter; m_cacheSamplerParameters.minFilter = samplerParams.minFilter;
m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode; m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode;
} }
if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) { if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) {
g_GLESFuncs.glTexParameteri( g_GLESFuncs.glTexParameteri(
target, GL_TEXTURE_MAG_FILTER, target, GL_TEXTURE_MAG_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None)); (GLint)MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None));
m_cacheSamplerParameters.magFilter = samplerParams.magFilter; m_cacheSamplerParameters.magFilter = samplerParams.magFilter;
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -645,18 +648,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod); g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
m_cacheSamplerParameters.maxLod = samplerParams.maxLod; m_cacheSamplerParameters.maxLod = samplerParams.maxLod;
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
#undef SYNC_TEX_SAMPLER_PARAM_IF_CHANGED #undef SYNC_TEX_SAMPLER_PARAM_IF_CHANGED
} }
void BackendTextureObject::SyncTextureParamsToBackend( void BackendTextureObject::SyncTextureParamsToBackend(
SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) { const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
DebugImpl::ErrorLopper errorLopper;
if (!stateTextureObject) { if (!stateTextureObject) {
MGLOG_E("State texture object is null, cannot sync to backend."); MGLOG_E("State texture object is null, cannot sync to backend.");
return; return;
@@ -683,7 +686,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
Bind(target); Bind(target);
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -696,14 +699,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, static_cast<GLint>(levelRange.x())); g_GLESFuncs.glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, static_cast<GLint>(levelRange.x()));
m_cacheLodRange.x() = levelRange.x(); m_cacheLodRange.x() = levelRange.x();
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
if (m_cacheLodRange.y() != levelRange.y()) { if (m_cacheLodRange.y() != levelRange.y()) {
g_GLESFuncs.glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(levelRange.y())); g_GLESFuncs.glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(levelRange.y()));
m_cacheLodRange.y() = levelRange.y(); m_cacheLodRange.y() = levelRange.y();
} }
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
@@ -720,7 +723,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED(a(), GL_TEXTURE_SWIZZLE_A); SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED(a(), GL_TEXTURE_SWIZZLE_A);
#undef SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED #undef SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED
m_cacheSwizzleParams = swizzleParams; m_cacheSwizzleParams = swizzleParams;
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} }
@@ -730,7 +733,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLfloat borderColorArray[4] = {borderColor.x(), borderColor.y(), borderColor.z(), borderColor.w()}; GLfloat borderColorArray[4] = {borderColor.x(), borderColor.y(), borderColor.z(), borderColor.w()};
g_GLESFuncs.glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColorArray); g_GLESFuncs.glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColorArray);
m_cacheBorderColor = borderColor; m_cacheBorderColor = borderColor;
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
} }
@@ -760,8 +763,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>, Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache; g_boundTexturesCache;
UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>> StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject> g_backendTextureObjects;
g_backendTextureObjects;
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {
@@ -778,7 +780,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendFramebufferObject::Bind(FramebufferTarget target) { void BackendFramebufferObject::Bind(FramebufferTarget target) const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -788,12 +790,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_backendFBOId); g_GLESFuncs.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_backendFBOId);
} }
Bool BackendFramebufferObject::SyncAttachmentObject( static Bool SyncAttachmentObject(GLenum glFBOTarget,
GLenum glFBOTarget, const MG_State::GLState::FramebufferAttachmentObject& attachmentObject, const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
GLenum glBackendAttachment) { GLenum glBackendAttachment) {
if (attachmentObject.IsTexture()) { if (attachmentObject.IsTexture()) {
const auto& textureObject = attachmentObject.GetTexture(); const auto& textureObject = attachmentObject.GetTexture();
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) { if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("%s: No backend texture found for FBO attachment, cannot bind texture.", __func__); MGLOG_E("%s: No backend texture found for FBO attachment, cannot bind texture.", __func__);
return false; return false;
@@ -807,11 +809,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
} else if (attachmentObject.IsRenderbuffer()) { } else if (attachmentObject.IsRenderbuffer()) {
const auto& renderbufferObject = attachmentObject.GetRenderbuffer(); const auto& renderbufferObject = attachmentObject.GetRenderbuffer();
const auto& backendRenderbufferIt = const auto& backendRenderbufferIt =
RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject); RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject.get());
SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject; SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject;
if (backendRenderbufferIt == RenderbufferImpl::g_backendRenderbufferObjects.end()) { if (backendRenderbufferIt == RenderbufferImpl::g_backendRenderbufferObjects.end()) {
backendRenderbufferObject = MakeShared<RenderbufferImpl::BackendRenderbufferObject>(); auto& backendRenderbufferSlot =
RenderbufferImpl::g_backendRenderbufferObjects[renderbufferObject] = backendRenderbufferObject; RenderbufferImpl::g_backendRenderbufferObjects.GetOrCreate(renderbufferObject);
if (!backendRenderbufferSlot) {
backendRenderbufferSlot = MakeShared<RenderbufferImpl::BackendRenderbufferObject>();
}
backendRenderbufferObject = backendRenderbufferSlot;
} else { } else {
backendRenderbufferObject = backendRenderbufferIt->second; backendRenderbufferObject = backendRenderbufferIt->second;
} }
@@ -824,8 +830,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
return true; return true;
} }
void BackendFramebufferObject::SyncToBackend(SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject, void BackendFramebufferObject::SyncToBackend(
FramebufferTarget asTarget) { const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject, FramebufferTarget asTarget) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -853,7 +859,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
std::fill(m_backendDrawBuffers, m_backendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, GL_NONE); std::fill(m_backendDrawBuffers, m_backendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, GL_NONE);
int nEffectiveBuffers = 0; int nEffectiveBuffers = 0;
for (GLint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS; ++i) { for (GLint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS; ++i) {
auto frontendBuf = stateDrawBuffers[i]; auto& frontendBuf = stateDrawBuffers[i];
if (frontendBuf == FramebufferAttachmentType::None) { if (frontendBuf == FramebufferAttachmentType::None) {
m_backendDrawBuffers[i] = GL_NONE; m_backendDrawBuffers[i] = GL_NONE;
continue; continue;
@@ -892,7 +898,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions(); const auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions();
for (SizeT i = 0; i < attachments.size(); ++i) { for (SizeT i = 0; i < attachments.size(); ++i) {
const auto& attachmentObject = attachments[i]; const auto& attachmentObject = attachments[i];
FramebufferAttachmentType frontendType = static_cast<FramebufferAttachmentType>(i); auto frontendType = static_cast<FramebufferAttachmentType>(i);
GLenum glBackendAttachment = GL_NONE; GLenum glBackendAttachment = GL_NONE;
if (frontendType >= FramebufferAttachmentType::Color0 && if (frontendType >= FramebufferAttachmentType::Color0 &&
frontendType <= FramebufferAttachmentType::Color31) frontendType <= FramebufferAttachmentType::Color31)
@@ -928,7 +934,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Verify that the backend object's name and parameters match the frontend attachment state // Verify that the backend object's name and parameters match the frontend attachment state
if (attachmentObject.IsTexture()) { if (attachmentObject.IsTexture()) {
const auto& textureObject = attachmentObject.GetTexture(); const auto& textureObject = attachmentObject.GetTexture();
auto backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); auto backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
MOBILEGL_ASSERT(backendTextureIt != TextureImpl::g_backendTextureObjects.end(), MOBILEGL_ASSERT(backendTextureIt != TextureImpl::g_backendTextureObjects.end(),
"No backend texture found while framebuffer reports texture attachment."); "No backend texture found while framebuffer reports texture attachment.");
GLuint backendTexId = backendTextureIt->second->GetBackendTextureId(); GLuint backendTexId = backendTextureIt->second->GetBackendTextureId();
@@ -944,7 +950,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
"Attachment texture level mismatch between GLES and state object."); "Attachment texture level mismatch between GLES and state object.");
} else if (attachmentObject.IsRenderbuffer()) { } else if (attachmentObject.IsRenderbuffer()) {
const auto& renderbufferObject = attachmentObject.GetRenderbuffer(); const auto& renderbufferObject = attachmentObject.GetRenderbuffer();
auto backendRboIt = RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject); auto backendRboIt =
RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject.get());
MOBILEGL_ASSERT( MOBILEGL_ASSERT(
backendRboIt != RenderbufferImpl::g_backendRenderbufferObjects.end(), backendRboIt != RenderbufferImpl::g_backendRenderbufferObjects.end(),
"No backend renderbuffer found while framebuffer reports renderbuffer attachment."); "No backend renderbuffer found while framebuffer reports renderbuffer attachment.");
@@ -975,14 +982,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
return glBackendReadBuffer; return glBackendReadBuffer;
} }
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>> StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects; g_backendFramebufferObjects;
Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions = {0}; Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions = {0};
} // namespace FramebufferImpl } // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
UnorderedMap<SharedPtr<MG_State::GLState::ProgramObject>, SharedPtr<BackendProgramObjectImpl>> StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl> g_backendProgramObjects;
g_backendProgramObjects;
BackendProgramObjectImpl::BackendProgramObjectImpl() { BackendProgramObjectImpl::BackendProgramObjectImpl() {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
@@ -1008,7 +1014,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendProgramObjectImpl::SyncToBackend(SharedPtr<MG_State::GLState::ProgramObject>& stateProgramObject) { void BackendProgramObjectImpl::SyncToBackend(
const SharedPtr<MG_State::GLState::ProgramObject>& stateProgramObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -1161,7 +1168,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("Program sync completed. backend ID %u", m_backendProgramId); MGLOG_D("Program sync completed. backend ID %u", m_backendProgramId);
} }
void BackendProgramObjectImpl::Use() { void BackendProgramObjectImpl::Use() const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -1184,7 +1191,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendSamplerObject::SyncToBackend(SharedPtr<MG_State::GLState::SamplerObject>& stateSamplerObject) { void BackendSamplerObject::SyncToBackend(
const SharedPtr<MG_State::GLState::SamplerObject>& stateSamplerObject) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -1210,22 +1218,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
#define SYNC_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \ #define SYNC_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \
if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \ if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \
g_GLESFuncs.glSamplerParameteri(m_backendSamplerId, glName, \ g_GLESFuncs.glSamplerParameteri(m_backendSamplerId, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \ (GLint)MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
m_cacheSamplerParameters.internalName = samplerParams.internalName; \ m_cacheSamplerParameters.internalName = samplerParams.internalName; \
} }
if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter || if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter ||
m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) { m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) {
g_GLESFuncs.glSamplerParameteri( g_GLESFuncs.glSamplerParameteri(m_backendSamplerId, GL_TEXTURE_MIN_FILTER,
m_backendSamplerId, GL_TEXTURE_MIN_FILTER, (GLint)MG_Util::ConvertSamplerFilterModeToGLEnum(
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.minFilter, samplerParams.mipmapMode)); samplerParams.minFilter, samplerParams.mipmapMode));
m_cacheSamplerParameters.minFilter = samplerParams.minFilter; m_cacheSamplerParameters.minFilter = samplerParams.minFilter;
m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode; m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode;
} }
if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) { if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) {
g_GLESFuncs.glSamplerParameteri( g_GLESFuncs.glSamplerParameteri(
m_backendSamplerId, GL_TEXTURE_MAG_FILTER, m_backendSamplerId, GL_TEXTURE_MAG_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None)); (GLint)MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None));
m_cacheSamplerParameters.magFilter = samplerParams.magFilter; m_cacheSamplerParameters.magFilter = samplerParams.magFilter;
} }
@@ -1256,7 +1264,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_boundSamplersCache[unit] = this; g_boundSamplersCache[unit] = this;
} }
Uint BackendSamplerObject::GetBackendSamplerId() { Uint BackendSamplerObject::GetBackendSamplerId() const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -1271,8 +1279,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> g_boundSamplersCache; Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> g_boundSamplersCache;
UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>> StateBackendObjectRegistry<MG_State::GLState::SamplerObject, BackendSamplerObject> g_backendSamplerObjects;
g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
namespace RenderbufferImpl { namespace RenderbufferImpl {
@@ -1287,7 +1294,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendRenderbufferObject::Bind() { void BackendRenderbufferObject::Bind() const {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
@@ -1334,9 +1341,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId); MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId);
} }
UnorderedMap<SharedPtr<MG_State::GLState::RenderbufferObject>, SharedPtr<BackendRenderbufferObject>> StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
g_backendRenderbufferObjects; g_backendRenderbufferObjects;
} // namespace RenderbufferImpl } // namespace RenderbufferImpl
namespace Utils {} // namespace Utils
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
+122 -34
View File
@@ -15,19 +15,113 @@
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
template <typename StateObject, typename BackendObject>
class StateBackendObjectRegistry {
public:
using StatePtr = SharedPtr<StateObject>;
using StateWeakPtr = std::weak_ptr<StateObject>;
using BackendPtr = SharedPtr<BackendObject>;
using BackendMap = UnorderedMap<StateObject*, BackendPtr>;
using StateRefMap = UnorderedMap<StateObject*, StateWeakPtr>;
using iterator = typename BackendMap::iterator;
using const_iterator = typename BackendMap::const_iterator;
BackendPtr& GetOrCreate(const StatePtr& stateObj) {
MOBILEGL_ASSERT(stateObj != nullptr, "State object must not be null");
auto* key = stateObj.get();
auto trackedStateIt = m_stateRefs.find(key);
if (trackedStateIt != m_stateRefs.end() && trackedStateIt->second.expired()) {
EraseByKey(key);
}
m_stateRefs[key] = stateObj;
return m_backendObjects[key];
}
iterator find(StateObject* stateObj) {
if (!IsAlive(stateObj)) {
EraseByKey(stateObj);
return m_backendObjects.end();
}
return m_backendObjects.find(stateObj);
}
const_iterator find(StateObject* stateObj) const {
return const_cast<StateBackendObjectRegistry*>(this)->find(stateObj);
}
iterator end() { return m_backendObjects.end(); }
const_iterator end() const { return m_backendObjects.end(); }
void CollectGarbageIfNeeded() {
++m_gcTick;
if (m_gcTick < kGCInterval) {
return;
}
CollectGarbage();
m_gcTick = 0;
}
void CollectGarbageNow() { CollectGarbage(); }
private:
bool IsAlive(StateObject* stateObj) const {
const auto trackedStateIt = m_stateRefs.find(stateObj);
if (trackedStateIt == m_stateRefs.end()) {
return false;
}
return !trackedStateIt->second.expired();
}
void EraseByKey(StateObject* stateObj) {
m_stateRefs.erase(stateObj);
m_backendObjects.erase(stateObj);
}
void CollectGarbage() {
if (m_isCollecting) {
return;
}
m_isCollecting = true;
Vector<StateObject*> staleKeys;
staleKeys.reserve(m_stateRefs.size());
for (const auto& [stateKey, stateWeakRef] : m_stateRefs) {
if (stateWeakRef.expired()) {
staleKeys.push_back(stateKey);
}
}
for (auto* stateKey : staleKeys) {
m_stateRefs.erase(stateKey);
m_backendObjects.erase(stateKey);
}
m_isCollecting = false;
}
private:
static constexpr Uint32 kGCInterval = 1024;
StateRefMap m_stateRefs;
BackendMap m_backendObjects;
Uint32 m_gcTick = 0;
Bool m_isCollecting = false;
};
namespace BufferImpl { namespace BufferImpl {
const GLenum TempBufferTarget = GL_ARRAY_BUFFER; const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
class BackendBufferObject { class BackendBufferObject {
public: public:
BackendBufferObject(); BackendBufferObject();
void SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend(const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
Uint GetBackendBufferId() { return m_backendBufferId; } Uint GetBackendBufferId() const { return m_backendBufferId; }
void Bind(GLenum target = TempBufferTarget); void Bind(GLenum target = TempBufferTarget);
private: private:
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend_glBufferData(const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend_glBufferSubData(const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glMapBufferRange(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, void SyncToBackend_glMapBufferRange(const SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject,
Bool invalidate = true, Bool unsynchronized = true); Bool invalidate = true, Bool unsynchronized = true);
Uint m_backendBufferId = 0; Uint m_backendBufferId = 0;
@@ -36,21 +130,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
}; };
extern BackendBufferObject* g_boundVertexBufferObject; extern BackendBufferObject* g_boundVertexBufferObject;
extern UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>> extern StateBackendObjectRegistry<MG_State::GLState::BufferObject, BackendBufferObject> g_backendBufferObjects;
g_backendBufferObjects;
} // namespace BufferImpl } // namespace BufferImpl
namespace VertexArrayImpl { namespace VertexArrayImpl {
class BackendVertexArrayObject { class BackendVertexArrayObject {
public: public:
BackendVertexArrayObject(); BackendVertexArrayObject();
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject); void SyncToBackend(const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
Uint GetBackendVertexArrayId() { return m_backendVAOId; } Uint GetBackendVertexArrayId() const { return m_backendVAOId; }
void Bind(); void Bind() const;
private: private:
void BindAttributeBuffer(Uint index, const MG_State::GLState::VertexAttribute& attrib);
Uint m_backendVAOId = 0; Uint m_backendVAOId = 0;
Bool m_isInitialized = false; Bool m_isInitialized = false;
Uint16 m_syncedIndexBufferVersion = 0; Uint16 m_syncedIndexBufferVersion = 0;
@@ -58,7 +149,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions; m_syncedAttributeVersions;
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::VertexArrayObject>, SharedPtr<BackendVertexArrayObject>> extern StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects; g_backendVertexArrayObjects;
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
@@ -92,11 +183,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
class BackendTextureObject { class BackendTextureObject {
public: public:
BackendTextureObject(); BackendTextureObject();
void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncMipmapsToBackend(const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncBuiltinSamplerToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncBuiltinSamplerToBackend(const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncTextureParamsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncTextureParamsToBackend(const SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target, Uint unit = TempTextureUnit); void Bind(GLenum target, Uint unit = TempTextureUnit);
Uint GetBackendTextureId(); Uint GetBackendTextureId() const;
private: private:
Uint m_backendTextureId = 0; Uint m_backendTextureId = 0;
@@ -113,7 +204,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
void ActivateTextureUnit(Uint unit); void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target); void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>> extern StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject>
g_backendTextureObjects; g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>, extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
@@ -125,13 +216,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
class BackendFramebufferObject { class BackendFramebufferObject {
public: public:
BackendFramebufferObject(); BackendFramebufferObject();
void SyncToBackend(SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject, void SyncToBackend(const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject,
FramebufferTarget asTarget); FramebufferTarget asTarget);
Uint GetBackendFramebufferId() { return m_backendFBOId; } Uint GetBackendFramebufferId() const { return m_backendFBOId; }
void Bind(FramebufferTarget target); void Bind(FramebufferTarget target) const;
bool SyncAttachmentObject(GLenum glFBOTarget,
const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
GLenum glBackendAttachment);
// FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index); // FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const; GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const;
@@ -159,7 +247,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0}; FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0};
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>> extern StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects; g_backendFramebufferObjects;
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions; extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
} // namespace FramebufferImpl } // namespace FramebufferImpl
@@ -169,8 +257,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
public: public:
BackendProgramObjectImpl(); BackendProgramObjectImpl();
~BackendProgramObjectImpl(); ~BackendProgramObjectImpl();
void SyncToBackend(SharedPtr<MG_State::GLState::ProgramObject>& stateProgramObject); void SyncToBackend(const SharedPtr<MG_State::GLState::ProgramObject>& stateProgramObject);
void Use(); void Use() const;
Uint GetBackendProgramId() const { return m_backendProgramId; } Uint GetBackendProgramId() const { return m_backendProgramId; }
Uint GetBackendGlobalUBOId() const { return m_backendGlobalUBOId; } Uint GetBackendGlobalUBOId() const { return m_backendGlobalUBOId; }
@@ -180,7 +268,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Bool m_isInitialized = false; Bool m_isInitialized = false;
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::ProgramObject>, SharedPtr<BackendProgramObjectImpl>> extern StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl>
g_backendProgramObjects; g_backendProgramObjects;
} // namespace PrgramImpl } // namespace PrgramImpl
@@ -188,9 +276,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
class BackendSamplerObject { class BackendSamplerObject {
public: public:
BackendSamplerObject(); BackendSamplerObject();
void SyncToBackend(SharedPtr<MG_State::GLState::SamplerObject>& stateSamplerObject); void SyncToBackend(const SharedPtr<MG_State::GLState::SamplerObject>& stateSamplerObject);
void Bind(Uint unit); void Bind(Uint unit);
Uint GetBackendSamplerId(); Uint GetBackendSamplerId() const;
private: private:
Uint m_backendSamplerId = 0; Uint m_backendSamplerId = 0;
@@ -203,7 +291,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache; g_boundSamplersCache;
extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>> extern StateBackendObjectRegistry<MG_State::GLState::SamplerObject, BackendSamplerObject>
g_backendSamplerObjects; g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
@@ -212,8 +300,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
public: public:
BackendRenderbufferObject(); BackendRenderbufferObject();
void SyncToBackend(const SharedPtr<MG_State::GLState::RenderbufferObject>& stateRBOObject); void SyncToBackend(const SharedPtr<MG_State::GLState::RenderbufferObject>& stateRBOObject);
Uint GetBackendRenderbufferId() { return m_backendRBOId; } Uint GetBackendRenderbufferId() const { return m_backendRBOId; }
void Bind(); void Bind() const;
private: private:
Uint m_backendRBOId = 0; Uint m_backendRBOId = 0;
@@ -223,7 +311,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Int m_cacheHeight = 0; Int m_cacheHeight = 0;
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::RenderbufferObject>, SharedPtr<BackendRenderbufferObject>> extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
g_backendRenderbufferObjects; g_backendRenderbufferObjects;
} // namespace RenderbufferImpl } // namespace RenderbufferImpl
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
-9
View File
@@ -19,10 +19,6 @@
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h> #include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl {} // namespace BufferImpl
namespace VertexArrayImpl {} // namespace VertexArrayImpl
namespace TextureImpl { namespace TextureImpl {
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat, void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
GLenum* outFormat, GLenum* outType) { GLenum* outFormat, GLenum* outType) {
@@ -36,9 +32,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
outInternalFormat, outFormat, outType); outInternalFormat, outFormat, outType);
} }
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl {} // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
String ProcessOutColorLocations(const String& glslCode) { String ProcessOutColorLocations(const String& glslCode) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
@@ -166,7 +159,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return GL_UNIFORM_BUFFER_BINDING; return GL_UNIFORM_BUFFER_BINDING;
case GL_FRAMEBUFFER: case GL_FRAMEBUFFER:
return GL_FRAMEBUFFER_BINDING;
case GL_DRAW_FRAMEBUFFER: case GL_DRAW_FRAMEBUFFER:
return GL_DRAW_FRAMEBUFFER_BINDING; return GL_DRAW_FRAMEBUFFER_BINDING;
case GL_READ_FRAMEBUFFER: case GL_READ_FRAMEBUFFER:
@@ -176,7 +168,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return GL_RENDERBUFFER_BINDING; return GL_RENDERBUFFER_BINDING;
case GL_VERTEX_ARRAY: case GL_VERTEX_ARRAY:
return GL_VERTEX_ARRAY_BINDING;
case GL_VERTEX_ARRAY_BINDING: case GL_VERTEX_ARRAY_BINDING:
return GL_VERTEX_ARRAY_BINDING; return GL_VERTEX_ARRAY_BINDING;
+3 -3
View File
@@ -14,15 +14,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace DebugImpl { namespace DebugImpl {
class ErrorLopper { class ErrorLopper {
public: public:
void Loop(std::function<void(GLenum)>); static void Loop(const std::function<void(GLenum)>&);
void Clear(); static void Clear();
ErrorLopper(); ErrorLopper();
~ErrorLopper(); ~ErrorLopper();
}; };
class OpenGLScopeMarker { class OpenGLScopeMarker {
public: public:
explicit OpenGLScopeMarker(String scopeName); explicit OpenGLScopeMarker(const String& scopeName);
~OpenGLScopeMarker(); ~OpenGLScopeMarker();
}; };
} // namespace DebugImpl } // namespace DebugImpl
@@ -11,28 +11,99 @@
#include "DirectVulkan.h" #include "DirectVulkan.h"
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
namespace {
Bool IsReleaseCurrentRequest(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
return dpy == EGL_NO_DISPLAY && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT;
}
} // namespace
BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default; BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default;
void BackendObject_DirectVulkan::InitWindowSurface() { Bool BackendObject_DirectVulkan::InitWindowSurface() {
if (!m_windowHandle.Handle) {
MGLOG_E("Cannot initialize DirectVulkan window surface: native window handle is null");
return false;
}
auto nativeWindow = reinterpret_cast<NativeWindowType>(m_windowHandle.Handle); auto nativeWindow = reinterpret_cast<NativeWindowType>(m_windowHandle.Handle);
pVulkanRenderer = MakeUnique<MG_Backend::DirectVulkan::VulkanRenderer>(nativeWindow); pVulkanRenderer = MakeUnique<MG_Backend::DirectVulkan::VulkanRenderer>(nativeWindow);
MOBILEGL_ASSERT(pVulkanRenderer != nullptr, "InitWindowSurface: VulkanRenderer creation failed"); MOBILEGL_ASSERT(pVulkanRenderer != nullptr, "InitWindowSurface: VulkanRenderer creation failed");
pVulkanRenderer->Initialize(); pVulkanRenderer->Initialize();
return true;
} }
void BackendObject_DirectVulkan::Initialize() { void BackendObject_DirectVulkan::Initialize() {
m_initialized = true; m_initialized = true;
} }
void BackendObject_DirectVulkan::InitCapabilities() { Bool BackendObject_DirectVulkan::InitCapabilities() {
if (!m_initialized) { if (!m_initialized) {
MGLOG_E("Cannot initialize capabilities before backend is initialized"); MGLOG_E("Cannot initialize capabilities before backend is initialized");
return; return false;
}
if (!pVulkanRenderer) {
MGLOG_E("Cannot initialize capabilities: Vulkan renderer has not been created");
return false;
} }
MG_Util::BackendLoader::FillInVulkanCapabilities(m_vulkanCaps, pVulkanRenderer->GetPhysicalDevice().properties); MG_Util::BackendLoader::FillInVulkanCapabilities(m_vulkanCaps, pVulkanRenderer->GetPhysicalDevice().properties);
UpdateDynamicBackendParameters(); UpdateDynamicBackendParameters();
return true;
}
Bool BackendObject_DirectVulkan::InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) {
if (!m_initialized) {
MGLOG_E("DirectVulkan backend not initialized");
return false;
}
return BackendObject::InitializeEGLDisplay(dpy, major, minor);
}
Bool BackendObject_DirectVulkan::CreateEGLWindowSurface(const WindowHandle& handle) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!m_initialized) {
MGLOG_E("DirectVulkan backend not initialized");
return false;
}
if (handle.Backend != WindowBackend::Android || !handle.Handle) {
MGLOG_E("DirectVulkan backend only supports Android native windows");
return false;
}
const Bool sameHandle =
m_eglWindowSurfaceInitialized && m_windowHandle.Backend == handle.Backend && m_windowHandle.Handle == handle.Handle;
if (sameHandle) {
return true;
}
if (m_eglWindowSurfaceInitialized || pVulkanRenderer) {
pVulkanRenderer.reset();
ResetEGLRuntimeState();
}
return BackendObject::CreateEGLWindowSurface(handle);
}
Bool BackendObject_DirectVulkan::MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (IsReleaseCurrentRequest(dpy, draw, read, ctx)) {
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
}
if (!pVulkanRenderer) {
MGLOG_E("DirectVulkan renderer is not initialized");
return false;
}
return BackendObject::MakeEGLCurrent(dpy, draw, read, ctx);
}
Bool BackendObject_DirectVulkan::SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) {
const std::lock_guard<std::recursive_mutex> lock(m_eglStateMutex);
if (!pVulkanRenderer) {
MGLOG_E("DirectVulkan renderer is not initialized");
return false;
}
return BackendObject::SwapEGLBuffers(dpy, draw);
} }
const RendererInfo& BackendObject_DirectVulkan::GetRendererInfo() const { const RendererInfo& BackendObject_DirectVulkan::GetRendererInfo() const {
@@ -17,8 +17,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
~BackendObject_DirectVulkan() override; ~BackendObject_DirectVulkan() override;
void Initialize() override; void Initialize() override;
void InitWindowSurface() override; Bool InitWindowSurface() override;
void InitCapabilities() override; Bool InitCapabilities() override;
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override;
Bool CreateEGLWindowSurface(const WindowHandle& handle) override;
Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override;
Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
const RendererInfo& GetRendererInfo() const override; const RendererInfo& GetRendererInfo() const override;
String GetBackendAPIVersionString() const override; String GetBackendAPIVersionString() const override;
@@ -1764,12 +1764,8 @@ void main() {
Bool VulkanRenderer::IsExtensionAlreadyEnabled(const Vector<const char*>& enabledExtensions, Bool VulkanRenderer::IsExtensionAlreadyEnabled(const Vector<const char*>& enabledExtensions,
const char* extensionName) { const char* extensionName) {
for (const char* enabledExtensionName : enabledExtensions) { return std::any_of(enabledExtensions.begin(), enabledExtensions.end(),
if (strcmp(enabledExtensionName, extensionName) == 0) { [&extensionName](const String& name) { return name == extensionName; });
return true;
}
}
return false;
} }
Bool VulkanRenderer::EnableOptionalDeviceExtension(const Vector<VkExtensionProperties>& availableExtensions, Bool VulkanRenderer::EnableOptionalDeviceExtension(const Vector<VkExtensionProperties>& availableExtensions,
+439 -93
View File
@@ -9,177 +9,451 @@
#include "EGLImpl.h" #include "EGLImpl.h"
#include "../GetProcAddress.h" #include "../GetProcAddress.h"
#include <MG_Backend/BackendObjects.h> #include <MG_Backend/BackendObjects.h>
#include <MG_State/EGLState/Core.h>
#include <type_traits>
namespace MobileGL::MG_Impl::EGLImpl { namespace MobileGL::MG_Impl::EGLImpl {
namespace {
using EGLStateContext = MG_State::EGLState::EGLContext;
EGLStateContext* GetState() {
if (!MG_State::pEGLContext) {
MGLOG_E("pEGLContext is null. MG_State may not be initialized.");
}
return MG_State::pEGLContext.get();
}
MG_Backend::BackendObject* GetBackendObject(EGLStateContext* state) {
auto* backendObject = MG_Backend::pActiveBackendObject.get();
if (!backendObject && state) {
state->SetError(EGL_NOT_INITIALIZED);
}
return backendObject;
}
MG_Backend::WindowBackend DetectWindowBackend() {
#if defined(ANDROID) || defined(__ANDROID__)
return MG_Backend::WindowBackend::Android;
#else
return MG_Backend::WindowBackend::Unknown;
#endif
}
template <typename NativeType>
Bool IsNullNativeHandle(NativeType nativeHandle) {
if constexpr (std::is_pointer_v<NativeType>) {
return nativeHandle == nullptr;
} else {
return nativeHandle == 0;
}
}
template <typename NativeType>
void* ToVoidHandle(NativeType nativeHandle) {
if constexpr (std::is_pointer_v<NativeType>) {
return reinterpret_cast<void*>(nativeHandle);
} else {
return reinterpret_cast<void*>(static_cast<SizeT>(nativeHandle));
}
}
} // namespace
EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window,
const EGLint* attrib_list) { const EGLint* attrib_list) {
MGLOG_D("EGLImpl::CreateWindowSurface called with window=%p", window); auto* state = GetState();
const auto& activeBackendObject = MG_Backend::pActiveBackendObject; if (!state) {
if (!activeBackendObject) { return EGL_NO_SURFACE;
}
if (!state->IsDisplayInitialized(dpy)) {
state->SetError(EGL_NOT_INITIALIZED);
return EGL_NO_SURFACE;
}
if (!state->ValidateConfigOnDisplay(dpy, config)) {
state->SetError(EGL_BAD_CONFIG);
return EGL_NO_SURFACE;
}
if (IsNullNativeHandle(window)) {
state->SetError(EGL_BAD_NATIVE_WINDOW);
return EGL_NO_SURFACE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
MGLOG_E("activeBackendObject not initialized!"); MGLOG_E("activeBackendObject not initialized!");
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
activeBackendObject->SetWindowHandle({MG_Backend::WindowBackend::Android, reinterpret_cast<void*>(window)});
activeBackendObject->InitWindowSurface(); const MG_Backend::WindowHandle windowHandle = {
return (EGLSurface)1; .Backend = DetectWindowBackend(),
.Handle = ToVoidHandle(window),
};
if (!backendObject->CreateEGLWindowSurface(windowHandle)) {
state->SetError(EGL_BAD_NATIVE_WINDOW);
return EGL_NO_SURFACE;
}
return state->CreateWindowSurface(dpy, config, window, attrib_list);
} }
EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface draw) { EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface draw) {
MGLOG_D("EGLImpl::SwapBuffers called with dpy=%p", dpy); auto* state = GetState();
if (!MG_Backend::gBackendFunctionsTable.Present) { if (!state) {
MGLOG_E("MG_Backend::gBackendFunctionsTable.Present not initialized!"); return EGL_FALSE;
}
if (!state->ValidateSurfaceOnDisplay(dpy, draw)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
MGLOG_E("activeBackendObject not initialized!");
return EGL_FALSE;
}
if (!backendObject->SwapEGLBuffers(dpy, draw)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE; return EGL_FALSE;
} }
MG_Backend::gBackendFunctionsTable.Present();
return EGL_TRUE; return EGL_TRUE;
} }
EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size,
EGLint* num_config) { EGLint* num_config) {
*num_config = 1; auto* state = GetState();
return EGL_TRUE; if (!state) {
return EGL_FALSE;
}
return state->ChooseConfig(dpy, attrib_list, configs, config_size, num_config) ? EGL_TRUE : EGL_FALSE;
} }
EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list) { EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list) {
return (EGLContext)1; auto* state = GetState();
if (!state) {
return EGL_NO_CONTEXT;
}
return state->CreateContext(dpy, config, shareCtx, attrib_list);
} }
EGLBoolean Initialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { EGLBoolean Initialize(EGLDisplay dpy, EGLint* major, EGLint* minor) {
if (major) *major = 1; auto* state = GetState();
if (minor) *minor = 5; if (!state) {
return EGL_FALSE;
}
if (!state->InitializeDisplay(dpy, major, minor)) {
return EGL_FALSE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
MGLOG_E("activeBackendObject not initialized!");
return EGL_FALSE;
}
if (!backendObject->InitializeEGLDisplay(dpy, major, minor)) {
state->SetError(EGL_NOT_INITIALIZED);
return EGL_FALSE;
}
return EGL_TRUE; return EGL_TRUE;
} }
EGLDisplay GetDisplay(NativeDisplayType display) { EGLDisplay GetDisplay(NativeDisplayType display) {
return (EGLDisplay)1; auto* state = GetState();
if (!state) {
return EGL_NO_DISPLAY;
}
return state->GetDisplay(display);
} }
EGLint GetError() { EGLint GetError() {
return EGL_SUCCESS; auto* state = GetState();
if (!state) {
return EGL_NOT_INITIALIZED;
}
return state->ConsumeError();
} }
EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
const auto& activeBackendObject = MG_Backend::pActiveBackendObject; auto* state = GetState();
if (!activeBackendObject) { if (!state) {
return EGL_FALSE;
}
const auto oldDisplay = state->GetCurrentDisplay();
const auto oldDraw = state->GetCurrentSurface(EGL_DRAW);
const auto oldRead = state->GetCurrentSurface(EGL_READ);
const auto oldContext = state->GetCurrentContext();
if (!state->MakeCurrent(dpy, draw, read, ctx)) {
return EGL_FALSE;
}
const Bool releaseCurrentRequest =
dpy == EGL_NO_DISPLAY && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT;
if (releaseCurrentRequest) {
if (auto* backendObject = MG_Backend::pActiveBackendObject.get()) {
(void)backendObject->MakeEGLCurrent(dpy, draw, read, ctx);
}
return EGL_TRUE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
MGLOG_E("activeBackendObject not initialized!"); MGLOG_E("activeBackendObject not initialized!");
state->MakeCurrent(oldDisplay, oldDraw, oldRead, oldContext);
return EGL_FALSE;
}
if (!backendObject->MakeEGLCurrent(dpy, draw, read, ctx)) {
state->SetError(EGL_BAD_ACCESS);
state->MakeCurrent(oldDisplay, oldDraw, oldRead, oldContext);
return EGL_FALSE; return EGL_FALSE;
} }
activeBackendObject->InitCapabilities();
return EGL_TRUE; return EGL_TRUE;
} }
EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx) { EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->DestroyContext(dpy, ctx) ? EGL_TRUE : EGL_FALSE;
} }
EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface) { EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->DestroySurface(dpy, surface) ? EGL_TRUE : EGL_FALSE;
} }
EGLBoolean Terminate(EGLDisplay dpy) { EGLBoolean Terminate(EGLDisplay dpy) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->TerminateDisplay(dpy) ? EGL_TRUE : EGL_FALSE;
} }
EGLBoolean ReleaseThread() { EGLBoolean ReleaseThread() {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
state->ReleaseThread();
return EGL_TRUE; return EGL_TRUE;
} }
EGLContext GetCurrentContext() { EGLContext GetCurrentContext() {
return (EGLContext)1; auto* state = GetState();
if (!state) {
return EGL_NO_CONTEXT;
}
return state->GetCurrentContext();
} }
EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) { EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) {
if (attribute == EGL_NATIVE_VISUAL_ID) { auto* state = GetState();
#if defined(ANDROID) if (!state) {
*value = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; return EGL_FALSE;
}
return state->GetConfigAttrib(dpy, config, attribute, value) ? EGL_TRUE : EGL_FALSE;
}
EGLBoolean BindAPI(EGLenum api) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
switch (api) {
case EGL_OPENGL_API:
case EGL_OPENGL_ES_API:
case EGL_OPENVG_API:
state->SetBoundAPI(api);
return EGL_TRUE; return EGL_TRUE;
#elif defined(__linux__) default:
*value = 0; state->SetError(EGL_BAD_PARAMETER);
return EGL_TRUE; return EGL_FALSE;
#elif defined(_WIN32) }
*value = 0; }
return EGL_TRUE;
#else EGLSurface GetCurrentSurface(EGLint readdraw) {
*value = 0; auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
return state->GetCurrentSurface(readdraw);
}
EGLBoolean QuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint* value) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->QuerySurface(display, surface, attribute, value) ? EGL_TRUE : EGL_FALSE;
}
char const* QueryString(EGLDisplay display, EGLint name) {
auto* state = GetState();
if (!state) {
return nullptr;
}
if (display != EGL_NO_DISPLAY && !state->ValidateDisplay(display)) {
state->SetError(EGL_BAD_DISPLAY);
return nullptr;
}
switch (name) {
case EGL_VENDOR:
return "MobileGL";
case EGL_VERSION:
return "1.5 MobileGL";
case EGL_CLIENT_APIS:
return "OpenGL OpenGL_ES";
case EGL_EXTENSIONS:
return "";
default:
state->SetError(EGL_BAD_PARAMETER);
return nullptr;
}
}
EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->SwapInterval(dpy, interval) ? EGL_TRUE : EGL_FALSE;
}
EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) {
auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
return state->CreatePbufferSurface(dpy, config, attrib_list);
}
EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
if (!state->ValidateSurfaceOnDisplay(dpy, surface)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER) {
state->SetError(EGL_BAD_PARAMETER);
return EGL_FALSE; return EGL_FALSE;
#endif
} }
return EGL_TRUE; return EGL_TRUE;
} }
EGLBoolean BindAPI(EGLenum api) {
return EGL_TRUE;
}
EGLSurface GetCurrentSurface(EGLint readdraw) {
return (EGLSurface)1;
}
EGLBoolean QuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint* value) {
return EGL_TRUE;
}
char const* QueryString(EGLDisplay display, EGLint name) {
return "";
}
EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval) {
return EGL_TRUE;
}
EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) {
return (EGLSurface)1;
}
EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
return EGL_TRUE;
}
EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
if (!state->ValidateSurfaceOnDisplay(dpy, surface)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER) {
state->SetError(EGL_BAD_PARAMETER);
return EGL_FALSE;
}
return EGL_TRUE; return EGL_TRUE;
} }
EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) {
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
if (!state->ValidateSurfaceOnDisplay(dpy, surface)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE;
}
if (IsNullNativeHandle(target)) {
state->SetError(EGL_BAD_NATIVE_PIXMAP);
return EGL_FALSE;
}
return EGL_TRUE; return EGL_TRUE;
} }
EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config,
const EGLint* attrib_list) { const EGLint* attrib_list) {
return (EGLSurface)1; auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
return state->CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
} }
EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap,
const EGLint* attrib_list) { const EGLint* attrib_list) {
return (EGLSurface)1; auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
return state->CreatePixmapSurface(dpy, config, pixmap, attrib_list);
} }
EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) {
if (num_config) { auto* state = GetState();
*num_config = 1; if (!state) {
return EGL_FALSE;
} }
if (configs && config_size > 0) { return state->GetConfigs(dpy, configs, config_size, num_config) ? EGL_TRUE : EGL_FALSE;
configs[0] = (EGLConfig)1;
}
return EGL_TRUE;
} }
EGLDisplay GetCurrentDisplay() { EGLDisplay GetCurrentDisplay() {
return (EGLDisplay)1; auto* state = GetState();
if (!state) {
return EGL_NO_DISPLAY;
}
return state->GetCurrentDisplay();
} }
EGLenum QueryAPI() { EGLenum QueryAPI() {
return EGL_OPENGL_API; auto* state = GetState();
if (!state) {
return EGL_OPENGL_API;
}
return state->GetBoundAPI();
} }
EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) { EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) {
if (value) { auto* state = GetState();
*value = 1; if (!state) {
return EGL_FALSE;
} }
return EGL_TRUE; return state->QueryContext(dpy, ctx, attribute, value) ? EGL_TRUE : EGL_FALSE;
} }
EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) {
return EGL_TRUE; (void)value;
auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
if (!state->ValidateSurfaceOnDisplay(dpy, surface)) {
state->SetError(EGL_BAD_SURFACE);
return EGL_FALSE;
}
switch (attribute) {
case EGL_MIPMAP_LEVEL:
case EGL_SWAP_BEHAVIOR:
case EGL_TEXTURE_FORMAT:
case EGL_TEXTURE_TARGET:
case EGL_MIPMAP_TEXTURE:
return EGL_TRUE;
default:
state->SetError(EGL_BAD_ATTRIBUTE);
return EGL_FALSE;
}
} }
EGLBoolean WaitClient() { EGLBoolean WaitClient() {
@@ -191,60 +465,132 @@ namespace MobileGL::MG_Impl::EGLImpl {
} }
EGLBoolean WaitNative(EGLint engine) { EGLBoolean WaitNative(EGLint engine) {
(void)engine;
return EGL_TRUE; return EGL_TRUE;
} }
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) { EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) {
return reinterpret_cast<EGLSync>(0x1); auto* state = GetState();
if (!state) {
return EGL_NO_SYNC;
}
return state->CreateSync(dpy, type, attrib_list);
} }
EGLBoolean DestroySync(void* dpy, void* sync) { EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->DestroySync(dpy, sync) ? EGL_TRUE : EGL_FALSE;
} }
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) { EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) {
return EGL_CONDITION_SATISFIED; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->ClientWaitSync(dpy, sync, flags, timeout);
} }
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) { EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) {
if (value) { auto* state = GetState();
*value = 1; if (!state) {
return EGL_FALSE;
} }
return EGL_TRUE; return state->GetSyncAttrib(dpy, sync, attribute, value) ? EGL_TRUE : EGL_FALSE;
} }
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
const EGLAttrib* attrib_list) { const EGLAttrib* attrib_list) {
return reinterpret_cast<EGLImage>(0x1); auto* state = GetState();
if (!state) {
return EGL_NO_IMAGE;
}
return state->CreateImage(dpy, ctx, target, buffer, attrib_list);
} }
EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) { EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->DestroyImage(dpy, image) ? EGL_TRUE : EGL_FALSE;
} }
EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list) { EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list) {
return reinterpret_cast<EGLDisplay>(0x1); (void)attrib_list;
auto* state = GetState();
if (!state) {
return EGL_NO_DISPLAY;
}
return state->GetPlatformDisplay(platform, native_display);
} }
EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window, EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window,
const EGLAttrib* attrib_list) { const EGLAttrib* attrib_list) {
return reinterpret_cast<EGLSurface>(0x1); auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
if (native_window == nullptr) {
state->SetError(EGL_BAD_NATIVE_WINDOW);
return EGL_NO_SURFACE;
}
if (!state->IsDisplayInitialized(dpy)) {
state->SetError(EGL_NOT_INITIALIZED);
return EGL_NO_SURFACE;
}
if (!state->ValidateConfigOnDisplay(dpy, config)) {
state->SetError(EGL_BAD_CONFIG);
return EGL_NO_SURFACE;
}
auto* backendObject = GetBackendObject(state);
if (!backendObject) {
MGLOG_E("activeBackendObject not initialized!");
return EGL_NO_SURFACE;
}
const MG_Backend::WindowHandle windowHandle = {
.Backend = DetectWindowBackend(),
.Handle = native_window,
};
if (!backendObject->CreateEGLWindowSurface(windowHandle)) {
state->SetError(EGL_BAD_NATIVE_WINDOW);
return EGL_NO_SURFACE;
}
return state->CreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
} }
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap, EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
const EGLAttrib* attrib_list) { const EGLAttrib* attrib_list) {
return reinterpret_cast<EGLSurface>(0x1); auto* state = GetState();
if (!state) {
return EGL_NO_SURFACE;
}
return state->CreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
} }
EGLBoolean WaitSync(void* dpy, void* sync, int flags) { EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) {
return EGL_TRUE; auto* state = GetState();
if (!state) {
return EGL_FALSE;
}
return state->WaitSync(dpy, sync, flags) ? EGL_TRUE : EGL_FALSE;
} }
__eglMustCastToProperFunctionPointerType GetProcAddress(const char* name) { __eglMustCastToProperFunctionPointerType GetProcAddress(const char* name) {
if (!name) {
return nullptr;
}
MGLOG_D("eglGetProcAddress(%s)", name); MGLOG_D("eglGetProcAddress(%s)", name);
void* proc = MG_Impl::GetProcAddress(name); void* proc = MG_Impl::GetProcAddress(name);
if (!proc) { if (!proc) {
MGLOG_W("Failed to get function: %s", (const char*)name); MGLOG_W("Failed to get function: %s", name);
return nullptr; return nullptr;
} }
return (__eglMustCastToProperFunctionPointerType)proc; return (__eglMustCastToProperFunctionPointerType)proc;
+2 -2
View File
@@ -48,7 +48,7 @@ namespace MobileGL::MG_Impl::EGLImpl {
EGLBoolean WaitGL(); EGLBoolean WaitGL();
EGLBoolean WaitNative(EGLint engine); EGLBoolean WaitNative(EGLint engine);
EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list); EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list);
EGLBoolean DestroySync(void* dpy, void* sync); EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync);
EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value); EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value);
EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
@@ -59,6 +59,6 @@ namespace MobileGL::MG_Impl::EGLImpl {
const EGLAttrib* attrib_list); const EGLAttrib* attrib_list);
EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap, EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap,
const EGLAttrib* attrib_list); const EGLAttrib* attrib_list);
EGLBoolean WaitSync(void* dpy, void* sync, int flags); EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
__eglMustCastToProperFunctionPointerType GetProcAddress(const char* name); __eglMustCastToProperFunctionPointerType GetProcAddress(const char* name);
} // namespace MobileGL::MG_Impl::EGLImpl } // namespace MobileGL::MG_Impl::EGLImpl
File diff suppressed because it is too large Load Diff
+18 -20
View File
@@ -9,24 +9,22 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); GLboolean IsBuffer(GLuint buffer);
GLboolean IsBuffer(GLuint buffer); void DeleteBuffers(GLsizei n, const GLuint* buffers);
void DeleteBuffers(GLsizei n, const GLuint* buffers); void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); GLboolean UnmapBuffer(GLenum target);
GLboolean UnmapBuffer(GLenum target); void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); void* MapBuffer(GLenum target, GLenum access);
void* MapBuffer(GLenum target, GLenum access); void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
GLsizeiptr size); void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data); void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage); void BindBuffer(GLenum target, GLuint buffer);
void BindBuffer(GLenum target, GLuint buffer); void GenBuffers(GLsizei n, GLuint* buffers);
void GenBuffers(GLsizei n, GLuint* buffers); void BindBufferBase(GLenum target, GLuint index, GLuint buffer);
void BindBufferBase(GLenum target, GLuint index, GLuint buffer); void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
} // namespace MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MobileGL
+87 -92
View File
@@ -13,105 +13,100 @@
#include <MG_Util/Converters/MGToGL/BufferEnumConverter.h> #include <MG_Util/Converters/MGToGL/BufferEnumConverter.h>
#include <MG_Util/Converters/MGToStr/BufferEnumConverter.h> #include <MG_Util/Converters/MGToStr/BufferEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::BufferImpl {
namespace BufferImpl { Bool ValidateBufferTarget(BufferTarget target) {
Bool ValidateBufferTarget(BufferTarget target) { if (target == BufferTarget::Unknown) {
if (target == BufferTarget::Unknown) { using namespace MG_Util;
using namespace MG_Util; String bufferTargetStr = ConvertBufferTargetToString(target);
String bufferTargetStr = ConvertBufferTargetToString(target); String glTargetStr = ConvertGLEnumToString(ConvertBufferTargetToGLEnum(target));
String glTargetStr = ConvertGLEnumToString(ConvertBufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl/BufferImpl", "ValidateBufferTarget",
std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false;
}
if (target == BufferTarget::Index && MG_State::pGLContext->GetBoundVertexArray() == nullptr) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl",
"ValidateBufferTarget",
"No vertex array object is bound."));
return false;
}
return true;
}
Bool ValidateBufferBindingPointTarget(BufferTarget target) {
if (target != BufferTarget::Uniform && target != BufferTarget::AtomicCounter &&
target != BufferTarget::TransformFeedback && target != BufferTarget::ShaderStorage) {
using namespace MG_Util;
String bufferTargetStr = ConvertBufferTargetToString(target);
String glTargetStr = ConvertGLEnumToString(ConvertBufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl/BufferImpl", "ValidateBufferTarget",
std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false;
}
return true;
}
Bool ValidateBufferName(Uint index, Bool allowZero) {
if (index == 0) {
if (allowZero) return true;
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl",
"ValidateBufferName",
"Buffer name 0 is not valid."));
return false;
}
Bool isValid = MG_State::pGLContext->ValidateBufferName(index);
if (isValid) return true;
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>(
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl", "ValidateBufferName", "MG_Impl/GLImpl/BufferImpl", "ValidateBufferTarget",
std::format("Buffer name {} is not valid.", index))); std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false; return false;
} }
Bool ValidateBufferUsage(BufferUsage usage) { if (target == BufferTarget::Index && MG_State::pGLContext->GetBoundVertexArray() == nullptr) {
if (usage != BufferUsage::Unknown) { MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
return true; MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl",
} "ValidateBufferTarget",
"No vertex array object is bound."));
return false;
}
return true;
}
Bool ValidateBufferBindingPointTarget(BufferTarget target) {
if (target != BufferTarget::Uniform && target != BufferTarget::AtomicCounter &&
target != BufferTarget::TransformFeedback && target != BufferTarget::ShaderStorage) {
using namespace MG_Util; using namespace MG_Util;
String bufferUsageStr = ConvertBufferUsageToString(usage); String bufferTargetStr = ConvertBufferTargetToString(target);
String glUsageStr = ConvertGLEnumToString(ConvertBufferUsageToGLEnum(usage)); String glTargetStr = ConvertGLEnumToString(ConvertBufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl/BufferImpl", "ValidateBufferTarget",
std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false;
}
return true;
}
Bool ValidateBufferName(Uint index, Bool allowZero) {
if (index == 0) {
if (allowZero) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl", "ValidateBufferName",
"Buffer name 0 is not valid."));
return false;
}
Bool isValid = MG_State::pGLContext->ValidateBufferName(index);
if (isValid) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl", "ValidateBufferName",
std::format("Buffer name {} is not valid.", index)));
return false;
}
Bool ValidateBufferUsage(BufferUsage usage) {
if (usage != BufferUsage::Unknown) {
return true;
}
using namespace MG_Util;
String bufferUsageStr = ConvertBufferUsageToString(usage);
String glUsageStr = ConvertGLEnumToString(ConvertBufferUsageToGLEnum(usage));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl/BufferImpl", "ValidateBufferUsage",
std::format("Usage {} ({}) is not one of the allowable values.", bufferUsageStr, glUsageStr)));
return false;
}
Bool ValidateBufferMappingAccess(Flags<BufferMappingAccessBit> accessBits) {
if (accessBits == BufferMappingAccessBit::Null) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl",
"ValidateBufferMappingAccess",
"Access bits cannot be null."));
return false;
}
const auto validBits = BufferMappingAccessBit::Read | BufferMappingAccessBit::Write |
BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer |
BufferMappingAccessBit::FlushExplicit | BufferMappingAccessBit::Unsynchronized |
BufferMappingAccessBit::Persistent | BufferMappingAccessBit::Coherent;
if ((accessBits & validBits) != accessBits) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl", "ValidateBufferMappingAccess",
"MG_Impl/GLImpl/BufferImpl", "ValidateBufferUsage", "Access bits cannot contain invalid flags."));
std::format("Usage {} ({}) is not one of the allowable values.", bufferUsageStr, glUsageStr)));
return false; return false;
} }
Bool ValidateBufferMappingAccess(Flags<BufferMappingAccessBit> accessBits) { return true;
if (accessBits == BufferMappingAccessBit::Null) { }
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum, } // namespace MobileGL::MG_Impl::GLImpl::BufferImpl
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl",
"ValidateBufferMappingAccess",
"Access bits cannot be null."));
return false;
}
const auto validBits = BufferMappingAccessBit::Read | BufferMappingAccessBit::Write |
BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer |
BufferMappingAccessBit::FlushExplicit | BufferMappingAccessBit::Unsynchronized |
BufferMappingAccessBit::Persistent | BufferMappingAccessBit::Coherent;
if ((accessBits & validBits) != accessBits) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/BufferImpl", "ValidateBufferMappingAccess",
"Access bits cannot contain invalid flags."));
return false;
}
return true;
}
} // namespace BufferImpl
} // namespace MobileGL::MG_Impl::GLImpl
+7 -9
View File
@@ -10,12 +10,10 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/BufferState/BufferObject.h> #include <MG_State/GLState/BufferState/BufferObject.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::BufferImpl {
namespace BufferImpl { Bool ValidateBufferTarget(BufferTarget target);
Bool ValidateBufferTarget(BufferTarget target); Bool ValidateBufferName(Uint index, Bool allowZero = false);
Bool ValidateBufferName(Uint index, Bool allowZero = false); Bool ValidateBufferUsage(BufferUsage usage);
Bool ValidateBufferUsage(BufferUsage usage); Bool ValidateBufferMappingAccess(Flags<BufferMappingAccessBit> accessBits);
Bool ValidateBufferMappingAccess(Flags<BufferMappingAccessBit> accessBits); Bool ValidateBufferBindingPointTarget(BufferTarget target);
Bool ValidateBufferBindingPointTarget(BufferTarget target); } // namespace MobileGL::MG_Impl::GLImpl::BufferImpl
} // namespace BufferImpl
} // namespace MobileGL::MG_Impl::GLImpl
+28 -31
View File
@@ -9,34 +9,31 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride);
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride);
GLsizei stride); void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride); const void* indices, GLint basevertex);
void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices);
const void* indices, GLint basevertex); void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices); GLsizei instancecount, GLint basevertex, GLuint baseinstance);
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex, GLuint baseinstance); GLsizei instancecount, GLint basevertex);
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex); GLsizei instancecount, GLuint baseinstance);
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount);
GLsizei instancecount, GLuint baseinstance); void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect);
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount); void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect); GLuint baseinstance);
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
GLuint baseinstance); void DrawArraysIndirect(GLenum mode, const void* indirect);
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex);
void DrawArraysIndirect(GLenum mode, const void* indirect); void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex); void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
void DrawArrays(GLenum mode, GLint first, GLsizei count); GLsizei drawcount);
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices,
GLsizei drawcount); GLsizei drawcount, const GLint* basevertex);
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, void Clear(GLbitfield mask);
GLsizei drawcount, const GLint* basevertex); void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
void Clear(GLbitfield mask); } // namespace MobileGL::MG_Impl::GLImpl
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
@@ -38,11 +38,11 @@ namespace MobileGL::MG_Impl::GLImpl {
RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(rbTarget); auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(rbTarget);
auto renderbufferObject = bindingSlot.GetBoundObject(); auto& renderbufferObject = bindingSlot.GetBoundObject();
if (!renderbufferObject) { if (!renderbufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorage_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorage_State",
"Renderbuffer target is bound to no renderbuffer object.")); "Renderbuffer target is bound to no renderbuffer object."));
return; return;
} }
@@ -50,7 +50,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!TextureImpl::ValidateTextureInternalFormat(format)) return; if (!TextureImpl::ValidateTextureInternalFormat(format)) return;
if (width < 0 || height < 0) { if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorage_State", ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorage_State",
"Width and height must be non-negative.")); "Width and height must be non-negative."));
return; return;
} }
@@ -74,10 +74,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenRenderbuffers_State", "n must be non-negative")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GenRenderbuffers_State", "n must be non-negative"));
return; return;
} }
auto renderbufferNames = MG_State::pGLContext->GenRenderbufferNames(n); static thread_local Vector<GLuint> renderbufferNames;
MG_State::pGLContext->GenRenderbufferNames(n, renderbufferNames);
Memcpy(renderbuffers, renderbufferNames.data(), sizeof(GLuint) * static_cast<SizeT>(n)); Memcpy(renderbuffers, renderbufferNames.data(), sizeof(GLuint) * static_cast<SizeT>(n));
} }
@@ -85,10 +86,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenFramebuffers_State", "n must be non-negative")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GenFramebuffers_State", "n must be non-negative"));
return; return;
} }
auto framebuffersNames = MG_State::pGLContext->GenFramebufferNames(n); static thread_local Vector<GLuint> framebuffersNames;
MG_State::pGLContext->GenFramebufferNames(n, framebuffersNames);
Memcpy(framebuffers, framebuffersNames.data(), sizeof(GLuint) * static_cast<SizeT>(n)); Memcpy(framebuffers, framebuffersNames.data(), sizeof(GLuint) * static_cast<SizeT>(n));
} }
@@ -119,11 +121,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!TextureImpl::ValidateTextureName(texture, true)) return; if (!TextureImpl::ValidateTextureName(texture, true)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) { if (!framebufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferTexture2D_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferTexture2D_State",
"Framebuffer target is bound to no framebuffer object.")); "Framebuffer target is bound to no framebuffer object."));
return; return;
} }
@@ -133,11 +135,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
auto textureObject = MG_State::pGLContext->GetTextureObject(texture); auto& textureObject = MG_State::pGLContext->GetTextureObject(texture);
if (!textureObject) { if (!textureObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferTexture2D_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferTexture2D_State",
std::format("Texture object {} is not valid.", texture))); std::format("Texture object {} is not valid.", texture)));
return; return;
} }
@@ -166,11 +168,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return; if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) { if (!framebufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferRenderbuffer_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferRenderbuffer_State",
"Framebuffer target is bound to no framebuffer object.")); "Framebuffer target is bound to no framebuffer object."));
return; return;
} }
@@ -180,11 +182,11 @@ namespace MobileGL::MG_Impl::GLImpl {
return; return;
} }
auto renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
if (!renderbufferObject) { if (!renderbufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferRenderbuffer_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "FramebufferRenderbuffer_State",
std::format("Renderbuffer object {} is not valid.", renderbuffer))); std::format("Renderbuffer object {} is not valid.", renderbuffer)));
return; return;
} }
@@ -196,18 +198,18 @@ namespace MobileGL::MG_Impl::GLImpl {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`n` is less than 0.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`n` is less than 0."));
return; return;
} else if (n > MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { } else if (n > MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`n` is greater than `GL_MAX_DRAW_BUFFERS`.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`n` is greater than `GL_MAX_DRAW_BUFFERS`."));
return; return;
} }
// Get bound framebuffer // Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw);
auto fbo = bindingSlot.GetBoundObject(); auto& fbo = bindingSlot.GetBoundObject();
bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO); bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1}; static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1};
@@ -220,7 +222,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (attType == FramebufferAttachmentType::Unknown) { if (attType == FramebufferAttachmentType::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("bufs[{}] = {} is not an accepted value.", i, std::format("bufs[{}] = {} is not an accepted value.", i,
MG_Util::ConvertGLEnumToString(bufs[i])))); MG_Util::ConvertGLEnumToString(bufs[i]))));
return; return;
@@ -230,7 +232,7 @@ namespace MobileGL::MG_Impl::GLImpl {
attType <= FramebufferAttachmentType::Color31) { attType <= FramebufferAttachmentType::Color31) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "MG_Impl/GLImpl", __func__,
std::format( std::format(
"FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i, "FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i,
@@ -242,7 +244,7 @@ namespace MobileGL::MG_Impl::GLImpl {
attType <= FramebufferAttachmentType::BackRight) { attType <= FramebufferAttachmentType::BackRight) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "MG_Impl/GLImpl", __func__,
std::format("FBO is not default FBO, but bufs[{}] = {} is anything other than `GL_NONE` or " std::format("FBO is not default FBO, but bufs[{}] = {} is anything other than `GL_NONE` or "
"one of the `GL_COLOR_ATTACHMENTn` tokens.", "one of the `GL_COLOR_ATTACHMENTn` tokens.",
@@ -253,7 +255,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (attType != FramebufferAttachmentType::None && existenceMap[(SizeT)attType] >= 0) { if (attType != FramebufferAttachmentType::None && existenceMap[(SizeT)attType] >= 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("a symbolic constant other than `GL_NONE` appears " std::format("a symbolic constant other than `GL_NONE` appears "
"more than once in bufs. bufs[{}] == bufs[{}] == {}.", "more than once in bufs. bufs[{}] == bufs[{}] == {}.",
i, existenceMap[(SizeT)attType], i, existenceMap[(SizeT)attType],
@@ -267,7 +269,7 @@ namespace MobileGL::MG_Impl::GLImpl {
(SizeT)FramebufferAttachmentType::Color0 + MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { (SizeT)FramebufferAttachmentType::Color0 + MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("bufs[{}] == {} indicates a color buffer that does " std::format("bufs[{}] == {} indicates a color buffer that does "
"not exist in the current GL context.", "not exist in the current GL context.",
i, MG_Util::ConvertGLEnumToString(bufs[i])))); i, MG_Util::ConvertGLEnumToString(bufs[i]))));
@@ -297,7 +299,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (attType == FramebufferAttachmentType::Unknown) { if (attType == FramebufferAttachmentType::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "MG_Impl/GLImpl", __func__,
std::format("`mode` = {} is not an accepted value.", MG_Util::ConvertGLEnumToString(mode)))); std::format("`mode` = {} is not an accepted value.", MG_Util::ConvertGLEnumToString(mode))));
return; return;
@@ -305,7 +307,7 @@ namespace MobileGL::MG_Impl::GLImpl {
// Get bound framebuffer // Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto fbo = bindingSlot.GetBoundObject(); auto& fbo = bindingSlot.GetBoundObject();
fbo->SetReadBuffer(attType); fbo->SetReadBuffer(attType);
} }
@@ -313,13 +315,13 @@ namespace MobileGL::MG_Impl::GLImpl {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteRenderbuffers_State", "n must be non-negative.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteRenderbuffers_State", "n must be non-negative."));
return; return;
} }
if (!renderbuffers) { if (!renderbuffers) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteRenderbuffers_State", ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteRenderbuffers_State",
"Renderbuffer names array cannot be null.")); "Renderbuffer names array cannot be null."));
return; return;
} }
@@ -336,13 +338,13 @@ namespace MobileGL::MG_Impl::GLImpl {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteFramebuffers_State", "n must be non-negative.")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteFramebuffers_State", "n must be non-negative."));
return; return;
} }
if (!framebuffers) { if (!framebuffers) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue, MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteFramebuffers_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteFramebuffers_State",
"Framebuffer names array cannot be null.")); "Framebuffer names array cannot be null."));
return; return;
} }
@@ -360,11 +362,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return GL_FRAMEBUFFER_UNDEFINED; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return GL_FRAMEBUFFER_UNDEFINED;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) { if (!framebufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "CheckFramebufferStatus_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CheckFramebufferStatus_State",
"Framebuffer target is bound to no framebuffer object.")); "Framebuffer target is bound to no framebuffer object."));
return GL_FRAMEBUFFER_UNDEFINED; return GL_FRAMEBUFFER_UNDEFINED;
} }
@@ -382,11 +384,11 @@ namespace MobileGL::MG_Impl::GLImpl {
RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return;
auto renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); Bool doesRenderbufferCreated = MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
if (!renderbufferObject) { if (!doesRenderbufferCreated) {
MG_State::pGLContext->CreateRenderbufferObject(renderbuffer); MG_State::pGLContext->CreateRenderbufferObject(renderbuffer);
renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
} }
auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget); auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
bindingSlot.Bind(renderbufferObject); bindingSlot.Bind(renderbufferObject);
@@ -403,11 +405,11 @@ namespace MobileGL::MG_Impl::GLImpl {
FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target); FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target);
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
auto framebufferObject = MG_State::pGLContext->GetFramebufferObject(framebuffer); Bool doesFramebufferCreated = MG_State::pGLContext->ValidateFramebufferObject(framebuffer);
if (!framebufferObject) { if (!doesFramebufferCreated) {
MG_State::pGLContext->CreateFramebufferObject(framebuffer); MG_State::pGLContext->CreateFramebufferObject(framebuffer);
framebufferObject = MG_State::pGLContext->GetFramebufferObject(framebuffer);
} }
auto& framebufferObject = MG_State::pGLContext->GetFramebufferObject(framebuffer);
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
bindingSlot.Bind(framebufferObject); bindingSlot.Bind(framebufferObject);
@@ -419,11 +421,11 @@ namespace MobileGL::MG_Impl::GLImpl {
RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return; if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget); auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
auto renderbufferObject = bindingSlot.GetBoundObject(); auto& renderbufferObject = bindingSlot.GetBoundObject();
if (!renderbufferObject) { if (!renderbufferObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetRenderbufferParameteriv_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetRenderbufferParameteriv_State",
"Renderbuffer target is bound to no renderbuffer object.")); "Renderbuffer target is bound to no renderbuffer object."));
return; return;
} }
@@ -462,7 +464,7 @@ namespace MobileGL::MG_Impl::GLImpl {
default: default:
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "GetRenderbufferParameteriv_State", "MG_Impl/GLImpl", "GetRenderbufferParameteriv_State",
std::format("pname {} is not an accepted value.", MG_Util::ConvertGLEnumToString(pname)))); std::format("pname {} is not an accepted value.", MG_Util::ConvertGLEnumToString(pname))));
return; return;
@@ -492,7 +494,7 @@ namespace MobileGL::MG_Impl::GLImpl {
// Check width/height // Check width/height
if (width < 0 || height < 0) { if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue, MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Width and height must be non-negative")); "Width and height must be non-negative"));
return; return;
} }
@@ -501,7 +503,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) { if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
return; return;
} }
@@ -509,17 +511,17 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) { if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
return; return;
} }
// Get bound framebuffer // Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read); auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto framebufferObject = bindingSlot.GetBoundObject(); auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) { if (!framebufferObject) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No framebuffer bound to read target")); "No framebuffer bound to read target"));
return; return;
} }
@@ -528,7 +530,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!framebufferObject->CheckCompleteness()) { if (!framebufferObject->CheckCompleteness()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation, ErrorCode::InvalidFramebufferOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
return; return;
} }
@@ -537,7 +539,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) { if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No stencil buffer for stencil index format")); "No stencil buffer for stencil index format"));
return; return;
} }
@@ -545,7 +547,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) { if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth buffer for depth component format")); "No depth buffer for depth component format"));
return; return;
} }
@@ -554,7 +556,7 @@ namespace MobileGL::MG_Impl::GLImpl {
!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) { !framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth/stencil buffer for depth-stencil format")); "No depth/stencil buffer for depth-stencil format"));
return; return;
} }
@@ -563,7 +565,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (texturePixelDataType != TexturePixelDataType::UnsignedInt248 && if (texturePixelDataType != TexturePixelDataType::UnsignedInt248 &&
texturePixelDataType != TexturePixelDataType::Float32UnsignedInt248Rev) { texturePixelDataType != TexturePixelDataType::Float32UnsignedInt248Rev) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Invalid type for depth-stencil format")); "Invalid type for depth-stencil format"));
return; return;
} }
@@ -577,7 +579,7 @@ namespace MobileGL::MG_Impl::GLImpl {
// Check if PBO is mapped // Check if PBO is mapped
if (pixelPackBufferObject->IsMapped()) { if (pixelPackBufferObject->IsMapped()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel pack buffer is currently mapped")); "Pixel pack buffer is currently mapped"));
return; return;
} }
@@ -587,7 +589,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) { if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel data not aligned for pixel pack buffer")); "Pixel data not aligned for pixel pack buffer"));
return; return;
} }
@@ -595,11 +597,11 @@ namespace MobileGL::MG_Impl::GLImpl {
// Check multisampling // Check multisampling
if (framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).IsRenderbuffer()) { if (framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).IsRenderbuffer()) {
auto rbo = framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).GetRenderbuffer(); auto& rbo = framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).GetRenderbuffer();
if (rbo && rbo->GetSamples() > 1) { if (rbo && rbo->GetSamples() > 1) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"ReadPixels not supported for multisampled framebuffers")); "ReadPixels not supported for multisampled framebuffers"));
return; return;
} }
@@ -732,6 +734,6 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
namespace FramebufferImpl { namespace FramebufferImpl {
DefaultFramebufferInfo* pDefaultFramebufferInfo; UniquePtr<DefaultFramebufferInfo> pDefaultFramebufferInfo;
} // namespace FramebufferImpl } // namespace FramebufferImpl
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
@@ -11,51 +11,49 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value);
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value); void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
GLsizei height); void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); GLboolean IsRenderbuffer(GLuint renderbuffer);
GLboolean IsRenderbuffer(GLuint renderbuffer); void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); void GenRenderbuffers(GLsizei n, GLuint* renderbuffers);
void GenRenderbuffers(GLsizei n, GLuint* renderbuffers); void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); void BindRenderbuffer(GLenum target, GLuint renderbuffer);
void BindRenderbuffer(GLenum target, GLuint renderbuffer); void SampleMaski(GLuint maskNumber, GLbitfield mask);
void SampleMaski(GLuint maskNumber, GLbitfield mask); GLboolean IsFramebuffer(GLuint framebuffer);
GLboolean IsFramebuffer(GLuint framebuffer); void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); void GenFramebuffers(GLsizei n, GLuint* framebuffers);
void GenFramebuffers(GLsizei n, GLuint* framebuffers); void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); void FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
void FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
GLint zoffset); void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
void FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level);
void FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); void DrawBuffer(GLenum buf);
void DrawBuffer(GLenum buf); void DrawBuffers(GLsizei n, const GLenum* bufs);
void DrawBuffers(GLsizei n, const GLenum* bufs); void ReadBuffer(GLenum src);
void ReadBuffer(GLenum src); void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers); GLenum CheckFramebufferStatus(GLenum target);
GLenum CheckFramebufferStatus(GLenum target); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
GLint dstY1, GLbitfield mask, GLenum filter); void BindFramebuffer(GLenum target, GLuint framebuffer);
void BindFramebuffer(GLenum target, GLuint framebuffer);
namespace FramebufferImpl { namespace FramebufferImpl {
struct DefaultFramebufferInfo { struct DefaultFramebufferInfo {
SharedPtr<MG_State::GLState::FramebufferObject> defaultFBO; SharedPtr<MG_State::GLState::FramebufferObject> defaultFBO;
SharedPtr<MG_State::GLState::ITextureObject> colorAttachment; SharedPtr<MG_State::GLState::ITextureObject> colorAttachment;
SharedPtr<MG_State::GLState::ITextureObject> depthAttachment; SharedPtr<MG_State::GLState::ITextureObject> depthAttachment;
SharedPtr<MG_State::GLState::ITextureObject> stencilAttachment; SharedPtr<MG_State::GLState::ITextureObject> stencilAttachment;
}; };
extern DefaultFramebufferInfo* pDefaultFramebufferInfo; extern UniquePtr<DefaultFramebufferInfo> pDefaultFramebufferInfo;
} // namespace FramebufferImpl } // namespace FramebufferImpl
} // namespace MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MobileGL
@@ -13,85 +13,82 @@
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h> #include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
#include <MG_Util/Converters/MGToStr/FramebufferEnumConverter.h> #include <MG_Util/Converters/MGToStr/FramebufferEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl {
namespace FramebufferImpl { Bool ValidateFramebufferTarget(FramebufferTarget target) {
Bool ValidateFramebufferTarget(FramebufferTarget target) { if (target == FramebufferTarget::Unknown) {
if (target == FramebufferTarget::Unknown) { using namespace MG_Util;
using namespace MG_Util; String bufferTargetStr = ConvertFramebufferTargetToString(target);
String bufferTargetStr = ConvertFramebufferTargetToString(target); String glTargetStr = ConvertGLEnumToString(ConvertFramebufferTargetToGLEnum(target));
String glTargetStr = ConvertGLEnumToString(ConvertFramebufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferTarget",
std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false;
}
return true;
}
Bool ValidateFramebufferName(Uint index, Bool allowZero) {
if (index == 0 && !allowZero) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferName",
"Framebuffer name 0 is not valid in this situation."));
return false;
}
Bool isValid = MG_State::pGLContext->ValidateFramebufferName(index);
if (isValid) return true;
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>(
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferName", "MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferTarget",
std::format("Framebuffer name {} is not valid.", index))); std::format("Target {} ({}) is not valid.", bufferTargetStr, glTargetStr)));
return false; return false;
} }
return true;
}
Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment) { Bool ValidateFramebufferName(Uint index, Bool allowZero) {
if (attachment == FramebufferAttachmentType::Unknown) { if (index == 0 && !allowZero) {
using namespace MG_Util;
String attachmentStr = ConvertFramebufferAttachmentTypeToString(attachment);
String glAttachmentStr = ConvertGLEnumToString(ConvertFramebufferAttachmentTypeToGLEnum(attachment));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferAttachmentType",
std::format("Attachment type {} ({}) is not valid.", attachmentStr, glAttachmentStr)));
return false;
}
return true;
}
Bool ValidateRenderbufferTarget(RenderbufferTarget target) {
if (target == RenderbufferTarget::Unknown) {
using namespace MG_Util;
String renderbufferTargetStr = ConvertRenderbufferTargetToString(target);
String glTargetStr = ConvertGLEnumToString(ConvertRenderbufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferTarget",
std::format("Target {} ({}) is not valid.", renderbufferTargetStr, glTargetStr)));
return false;
}
return true;
}
Bool ValidateRenderbufferName(Uint index, Bool allowZero) {
if (index == 0 && !allowZero) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName",
"Renderbuffer name 0 is not valid in this situation."));
return false;
}
Bool isValid = MG_State::pGLContext->ValidateRenderbufferName(index);
if (isValid) return true;
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferName",
std::format("Renderbuffer name {} is not valid.", index))); "Framebuffer name 0 is not valid in this situation."));
return false; return false;
} }
} // namespace FramebufferImpl Bool isValid = MG_State::pGLContext->ValidateFramebufferName(index);
} // namespace MobileGL::MG_Impl::GLImpl if (isValid) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferName",
std::format("Framebuffer name {} is not valid.", index)));
return false;
}
Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment) {
if (attachment == FramebufferAttachmentType::Unknown) {
using namespace MG_Util;
String attachmentStr = ConvertFramebufferAttachmentTypeToString(attachment);
String glAttachmentStr = ConvertGLEnumToString(ConvertFramebufferAttachmentTypeToGLEnum(attachment));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl/FramebufferImpl", "ValidateFramebufferAttachmentType",
std::format("Attachment type {} ({}) is not valid.", attachmentStr, glAttachmentStr)));
return false;
}
return true;
}
Bool ValidateRenderbufferTarget(RenderbufferTarget target) {
if (target == RenderbufferTarget::Unknown) {
using namespace MG_Util;
String renderbufferTargetStr = ConvertRenderbufferTargetToString(target);
String glTargetStr = ConvertGLEnumToString(ConvertRenderbufferTargetToGLEnum(target));
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferTarget",
std::format("Target {} ({}) is not valid.", renderbufferTargetStr, glTargetStr)));
return false;
}
return true;
}
Bool ValidateRenderbufferName(Uint index, Bool allowZero) {
if (index == 0 && !allowZero) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName",
"Renderbuffer name 0 is not valid in this situation."));
return false;
}
Bool isValid = MG_State::pGLContext->ValidateRenderbufferName(index);
if (isValid) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName",
std::format("Renderbuffer name {} is not valid.", index)));
return false;
}
} // namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl
@@ -10,12 +10,10 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/FramebufferState/FramebufferObject.h> #include <MG_State/GLState/FramebufferState/FramebufferObject.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl {
namespace FramebufferImpl { Bool ValidateFramebufferTarget(FramebufferTarget target);
Bool ValidateFramebufferTarget(FramebufferTarget target); Bool ValidateFramebufferName(Uint index, Bool allowZero = true);
Bool ValidateFramebufferName(Uint index, Bool allowZero = true); Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment);
Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment); Bool ValidateRenderbufferTarget(RenderbufferTarget target);
Bool ValidateRenderbufferTarget(RenderbufferTarget target); Bool ValidateRenderbufferName(Uint index, Bool allowZero = true);
Bool ValidateRenderbufferName(Uint index, Bool allowZero = true); } // namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl
} // namespace FramebufferImpl
} // namespace MobileGL::MG_Impl::GLImpl
+15 -14
View File
@@ -7,8 +7,6 @@
// End of Source File Header // End of Source File Header
#include "GL_Getter.h" #include "GL_Getter.h"
#include "GL/gl.h"
#include "MG_Util/Debug/Log.h"
#include <Config.h> #include <Config.h>
#include <MGGitHash.h> #include <MGGitHash.h>
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
@@ -127,7 +125,7 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!params) { if (!params) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetIntegerv", "params pointer cannot be null")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetIntegerv", "params pointer cannot be null"));
return; return;
} }
@@ -146,9 +144,9 @@ namespace MobileGL::MG_Impl::GLImpl {
*params = 0; // TODO *params = 0; // TODO
break; break;
case GL_ARRAY_BUFFER_BINDING: { case GL_ARRAY_BUFFER_BINDING: {
auto obj = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex).GetBoundObject(); auto& obj = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex).GetBoundObject();
if (obj) if (obj)
*params = obj->GetExternalIndex(); *params = (GLint)obj->GetExternalIndex();
else else
*params = 0; *params = 0;
break; break;
@@ -256,14 +254,14 @@ namespace MobileGL::MG_Impl::GLImpl {
break; break;
case GL_CURRENT_PROGRAM: { case GL_CURRENT_PROGRAM: {
const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram(); const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
*params = currentProgram ? currentProgram->GetExternalIndex() : 0; *params = currentProgram ? (GLint)currentProgram->GetExternalIndex() : 0;
break; break;
} }
case GL_DEPTH_CLEAR_VALUE: case GL_DEPTH_CLEAR_VALUE:
*params = MG_State::pGLContext->GetClearDepth(); *params = (GLint)MG_State::pGLContext->GetClearDepth();
break; break;
case GL_DEPTH_FUNC: case GL_DEPTH_FUNC:
*params = MG_Util::ConvertDepthTestFuncToGLEnum(MG_State::pGLContext->GetDepthFunc()); *params = (GLint)MG_Util::ConvertDepthTestFuncToGLEnum(MG_State::pGLContext->GetDepthFunc());
break; break;
case GL_DEPTH_RANGE: case GL_DEPTH_RANGE:
*params = 0; // TODO *params = 0; // TODO
@@ -288,12 +286,12 @@ namespace MobileGL::MG_Impl::GLImpl {
break; break;
case GL_DRAW_FRAMEBUFFER_BINDING: { case GL_DRAW_FRAMEBUFFER_BINDING: {
const auto& FBO = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); const auto& FBO = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
*params = FBO ? FBO->GetExternalIndex() : 0; *params = FBO ? (GLint)FBO->GetExternalIndex() : 0;
break; break;
} }
case GL_READ_FRAMEBUFFER_BINDING: { case GL_READ_FRAMEBUFFER_BINDING: {
const auto& FBO = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); const auto& FBO = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
*params = FBO ? FBO->GetExternalIndex() : 0; *params = FBO ? (GLint)FBO->GetExternalIndex() : 0;
break; break;
} }
case GL_ELEMENT_ARRAY_BUFFER_BINDING: { case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
@@ -302,7 +300,7 @@ namespace MobileGL::MG_Impl::GLImpl {
break; break;
} }
const auto& bufferObject = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Index).GetBoundObject(); const auto& bufferObject = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Index).GetBoundObject();
*params = bufferObject ? bufferObject->GetExternalIndex() : 0; *params = bufferObject ? (GLint)bufferObject->GetExternalIndex() : 0;
break; break;
} }
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
@@ -886,7 +884,7 @@ namespace MobileGL::MG_Impl::GLImpl {
default: default:
MGLOG_E("glGetIntegerv: Invalid enum %s (0x%X)", MG_Util::ConvertGLEnumToString(pname).c_str(), pname); MGLOG_E("glGetIntegerv: Invalid enum %s (0x%X)", MG_Util::ConvertGLEnumToString(pname).c_str(), pname);
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum, MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetIntegerv", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetIntegerv",
std::format("Invalid enum: 0x{:X}", pname))); std::format("Invalid enum: 0x{:X}", pname)));
break; break;
@@ -894,7 +892,10 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
GLenum GetError() { GLenum GetError() {
ErrorCode errorCode = MG_State::pGLContext->PopGLError().value_or(Error{ErrorCode::NoError, nullptr}).code; auto error = MG_State::pGLContext->PopGLError();
return MG_Util::ConvertErrorCodeToGLEnum(errorCode); if (!error || !error->get()) {
return GL_NO_ERROR;
}
return MG_Util::ConvertErrorCodeToGLEnum(error->get()->code);
} }
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
File diff suppressed because it is too large Load Diff
+56 -58
View File
@@ -9,61 +9,59 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { void AttachShader(GLuint program, GLuint shader);
void AttachShader(GLuint program, GLuint shader); void BindAttribLocation(GLuint program, GLuint index, const GLchar* name);
void BindAttribLocation(GLuint program, GLuint index, const GLchar* name); void CompileShader(GLuint shader);
void CompileShader(GLuint shader); GLuint CreateProgram(void);
GLuint CreateProgram(void); GLuint CreateShader(GLenum type);
GLuint CreateShader(GLenum type); void DeleteProgram(GLuint program);
void DeleteProgram(GLuint program); void DeleteShader(GLuint shader);
void DeleteShader(GLuint shader); void DetachShader(GLuint program, GLuint shader);
void DetachShader(GLuint program, GLuint shader); void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type,
void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
GLchar* name); void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type,
void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
GLchar* name); void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); GLint GetAttribLocation(GLuint program, const GLchar* name);
GLint GetAttribLocation(GLuint program, const GLchar* name); void GetProgramiv(GLuint program, GLenum pname, GLint* params);
void GetProgramiv(GLuint program, GLenum pname, GLint* params); void GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
void GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); void GetShaderiv(GLuint shader, GLenum pname, GLint* params);
void GetShaderiv(GLuint shader, GLenum pname, GLint* params); void GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
void GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); void GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* source);
void GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* source); GLint GetUniformLocation(GLuint program, const GLchar* name);
GLint GetUniformLocation(GLuint program, const GLchar* name); void GetUniformfv(GLuint program, GLint location, GLfloat* params);
void GetUniformfv(GLuint program, GLint location, GLfloat* params); void GetUniformiv(GLuint program, GLint location, GLint* params);
void GetUniformiv(GLuint program, GLint location, GLint* params); GLboolean IsProgram(GLuint program);
GLboolean IsProgram(GLuint program); GLboolean IsShader(GLuint shader);
GLboolean IsShader(GLuint shader); void LinkProgram(GLuint program);
void LinkProgram(GLuint program); void ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
void ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); void UseProgram(GLuint program);
void UseProgram(GLuint program); void Uniform1f(GLint location, GLfloat v0);
void Uniform1f(GLint location, GLfloat v0); void Uniform2f(GLint location, GLfloat v0, GLfloat v1);
void Uniform2f(GLint location, GLfloat v0, GLfloat v1); void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); void Uniform1i(GLint location, GLint v0);
void Uniform1i(GLint location, GLint v0); void Uniform2i(GLint location, GLint v0, GLint v1);
void Uniform2i(GLint location, GLint v0, GLint v1); void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2); void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); void Uniform1fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform1fv(GLint location, GLsizei count, const GLfloat* value); void Uniform2fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform2fv(GLint location, GLsizei count, const GLfloat* value); void Uniform3fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform3fv(GLint location, GLsizei count, const GLfloat* value); void Uniform4fv(GLint location, GLsizei count, const GLfloat* value);
void Uniform4fv(GLint location, GLsizei count, const GLfloat* value); void Uniform1iv(GLint location, GLsizei count, const GLint* value);
void Uniform1iv(GLint location, GLsizei count, const GLint* value); void Uniform2iv(GLint location, GLsizei count, const GLint* value);
void Uniform2iv(GLint location, GLsizei count, const GLint* value); void Uniform3iv(GLint location, GLsizei count, const GLint* value);
void Uniform3iv(GLint location, GLsizei count, const GLint* value); void Uniform4iv(GLint location, GLsizei count, const GLint* value);
void Uniform4iv(GLint location, GLsizei count, const GLint* value); void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName);
GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length,
void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
GLchar* uniformBlockName); void BindFragDataLocation(GLuint program, GLuint colorNumber, const char* name);
void BindFragDataLocation(GLuint program, GLuint colorNumber, const char* name); GLint GetFragDataLocation(GLuint program, const char* name);
GLint GetFragDataLocation(GLuint program, const char* name); void ValidateProgram(GLuint program);
void ValidateProgram(GLuint program); } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
@@ -7,474 +7,467 @@
// End of Source File Header // End of Source File Header
#include "GL_RenderState.h" #include "GL_RenderState.h"
#include "MG_State/GLState/RenderState/RenderState.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/RenderStateEnumConverter.h> #include <MG_Util/Converters/GLToMG/RenderStateEnumConverter.h>
#include <MG_Util/Converters/MGToGL/RenderStateEnumConverter.h> #include <MG_Util/Converters/MGToGL/RenderStateEnumConverter.h>
#include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h> #include <MG_Util/Converters/MGToStr/RenderStateEnumConverter.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) {
void Viewport_State(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) {
if (width < 0 || height < 0) { MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Viewport_State",
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Viewport_State", "Width abd height must be non-negative."));
"Width abd height must be non-negative.")); return;
return; }
}
MG_State::pGLContext->SetViewport(IntVec4(x, y, width, height));
MG_State::pGLContext->SetViewport(IntVec4(x, y, width, height)); }
}
void StencilOpSeparate_State(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
void StencilOpSeparate_State(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) { // TODO: implement
// TODO: implement }
}
void StencilOp_State(GLenum fail, GLenum zfail, GLenum zpass) {
void StencilOp_State(GLenum fail, GLenum zfail, GLenum zpass) { // TODO: implement
// TODO: implement }
}
void StencilMaskSeparate_State(GLenum face, GLuint mask) {
void StencilMaskSeparate_State(GLenum face, GLuint mask) { // TODO: implement
// TODO: implement }
}
void StencilMask_State(GLuint mask) {
void StencilMask_State(GLuint mask) { // TODO: implement
// TODO: implement }
}
void StencilFuncSeparate_State(GLenum face, GLenum func, GLint ref, GLuint mask) {
void StencilFuncSeparate_State(GLenum face, GLenum func, GLint ref, GLuint mask) { // TODO: implement
// TODO: implement }
}
void StencilFunc_State(GLenum func, GLint ref, GLuint mask) {
void StencilFunc_State(GLenum func, GLint ref, GLuint mask) { // TODO: implement
// TODO: implement }
}
void Scissor_State(GLint x, GLint y, GLsizei width, GLsizei height) {
void Scissor_State(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) {
if (width < 0 || height < 0) { MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Scissor_State",
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Scissor_State", "Width abd height must be non-negative."));
"Width abd height must be non-negative.")); return;
return; }
}
MG_State::pGLContext->SetScissorBox(IntVec4(x, y, width, height));
MG_State::pGLContext->SetScissorBox(IntVec4(x, y, width, height)); }
}
void SampleCoverage_State(GLfloat value, GLboolean invert) {
void SampleCoverage_State(GLfloat value, GLboolean invert) { // TODO: implement
// TODO: implement }
}
void PolygonOffset_State(GLfloat factor, GLfloat units) {
void PolygonOffset_State(GLfloat factor, GLfloat units) { // TODO: implement
// TODO: implement }
}
void PolygonMode_State(GLenum face, GLenum mode) {
void PolygonMode_State(GLenum face, GLenum mode) { // TODO: implement
// TODO: implement }
}
void PointSize_State(GLfloat size) {
void PointSize_State(GLfloat size) { // TODO: implement
// TODO: implement }
}
void PointParameterf_State(GLenum pname, GLfloat param) {
void PointParameterf_State(GLenum pname, GLfloat param) { // TODO: implement
// TODO: implement }
}
void PointParameteri_State(GLenum pname, GLint param) {
void PointParameteri_State(GLenum pname, GLint param) { // TODO: implement
// TODO: implement }
}
void PixelStorei_State(GLenum pname, GLint param) {
void PixelStorei_State(GLenum pname, GLint param) { MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), param);
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), param); PixelStoreParam pixelStoreParam = MG_Util::ConvertGLEnumToPixelStoreParam(pname);
PixelStoreParam pixelStoreParam = MG_Util::ConvertGLEnumToPixelStoreParam(pname); if (pixelStoreParam == PixelStoreParam::Unknown) {
if (pixelStoreParam == PixelStoreParam::Unknown) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum,
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "PixelStorei_State",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "PixelStorei_State", "Pixel store param enum " +
"Pixel store param enum " + MG_Util::ConvertPixelStoreParamToString(pixelStoreParam) + "(" +
MG_Util::ConvertPixelStoreParamToString(pixelStoreParam) + "(" + MG_Util::ConvertGLEnumToString(pname) + ") is not supported."));
MG_Util::ConvertGLEnumToString(pname) + ") is not supported.")); return;
return; }
}
MG_State::pGLContext->SetPixelStoreParam(pixelStoreParam, param);
MG_State::pGLContext->SetPixelStoreParam(pixelStoreParam, param); }
}
void LogicOp_State(GLenum opcode) {
void LogicOp_State(GLenum opcode) { // TODO: implement
// TODO: implement }
}
void LineWidth_State(GLfloat width) {
void LineWidth_State(GLfloat width) { // TODO: implement
// TODO: implement }
}
GLboolean IsEnabledi_State(GLenum target, GLuint index) {
GLboolean IsEnabledi_State(GLenum target, GLuint index) { CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); if (capInput == CapabilityInput::Unknown) {
if (capInput == CapabilityInput::Unknown) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum,
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsEnabledi_State",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsEnabledi_State", "Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"Capability enum " + "(" + MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
MG_Util::ConvertCapabilityInputToString(capInput) + "(" + return GL_FALSE;
MG_Util::ConvertGLEnumToString(target) + ") is not supported.")); }
return GL_FALSE;
} return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE;
}
return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE;
} GLboolean IsEnabled_State(GLenum cap) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
GLboolean IsEnabled_State(GLenum cap) { if (capInput == CapabilityInput::Unknown) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap); MG_State::pGLContext->RecordError(
if (capInput == CapabilityInput::Unknown) { ErrorCode::InvalidEnum,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsEnabled_State",
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>( "Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"MG_Impl/GLImpl", "IsEnabled_State", "(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported."));
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) + return GL_FALSE;
"(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported.")); }
return GL_FALSE;
} return MG_State::pGLContext->IsCapabilityEnabled(capInput) ? GL_TRUE : GL_FALSE;
}
return MG_State::pGLContext->IsCapabilityEnabled(capInput) ? GL_TRUE : GL_FALSE;
} void Hint_State(GLenum target, GLenum mode) {
// TODO: implement
void Hint_State(GLenum target, GLenum mode) { }
// TODO: implement
} void FrontFace_State(GLenum mode) {
// TODO: implement
void FrontFace_State(GLenum mode) { }
// TODO: implement
} void Enable_State(GLenum cap) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
void Enable_State(GLenum cap) { if (capInput == CapabilityInput::Unknown) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap); MG_State::pGLContext->RecordError(
if (capInput == CapabilityInput::Unknown) { ErrorCode::InvalidEnum,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Enable_State",
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>( "Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"MG_Impl/GLImpl", "Enable_State", "(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported."));
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) + return;
"(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported.")); }
return;
} MG_State::pGLContext->SetCapability(capInput, true);
}
MG_State::pGLContext->SetCapability(capInput, true);
} void Disable_State(GLenum cap) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
void Disable_State(GLenum cap) { if (capInput == CapabilityInput::Unknown) {
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap); MG_State::pGLContext->RecordError(
if (capInput == CapabilityInput::Unknown) { ErrorCode::InvalidEnum,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Disable_State",
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>( "Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"MG_Impl/GLImpl", "Disable_State", "(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported."));
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) + return;
"(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported.")); }
return;
} MG_State::pGLContext->SetCapability(capInput, false);
}
MG_State::pGLContext->SetCapability(capInput, false);
} void DepthRange_State(GLclampd near_val, GLclampd far_val) {
// TODO: implement
void DepthRange_State(GLclampd near_val, GLclampd far_val) { }
// TODO: implement
} void DepthMask_State(GLboolean flag) {
MG_State::pGLContext->SetDepthMask(flag == GL_TRUE);
void DepthMask_State(GLboolean flag) { }
MG_State::pGLContext->SetDepthMask(flag == GL_TRUE);
} void DepthFunc_State(GLenum func) {
DepthTestFunc depthFunc = MG_Util::ConvertGLEnumToDepthTestFunc(func);
void DepthFunc_State(GLenum func) { if (depthFunc == DepthTestFunc::Unknown) {
DepthTestFunc depthFunc = MG_Util::ConvertGLEnumToDepthTestFunc(func); MG_State::pGLContext->RecordError(
if (depthFunc == DepthTestFunc::Unknown) { ErrorCode::InvalidEnum,
MG_State::pGLContext->RecordError( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DepthFunc_State",
ErrorCode::InvalidEnum, "Depth function enum " + MG_Util::ConvertDepthTestFuncToString(depthFunc) +
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DepthFunc_State", "(" + MG_Util::ConvertGLEnumToString(func) + ") is not supported."));
"Depth function enum " + return;
MG_Util::ConvertDepthTestFuncToString(depthFunc) + "(" + }
MG_Util::ConvertGLEnumToString(func) + ") is not supported."));
return; MG_State::pGLContext->SetDepthFunc(depthFunc);
} }
MG_State::pGLContext->SetDepthFunc(depthFunc); void CullFace_State(GLenum mode) {
} CullFaceMode cullFaceMode = MG_Util::ConvertGLEnumToCullFaceMode(mode);
if (cullFaceMode == CullFaceMode::Unknown) {
void CullFace_State(GLenum mode) { MG_State::pGLContext->RecordError(
CullFaceMode cullFaceMode = MG_Util::ConvertGLEnumToCullFaceMode(mode); ErrorCode::InvalidEnum,
if (cullFaceMode == CullFaceMode::Unknown) { MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "CullFace_State",
MG_State::pGLContext->RecordError( "Cull face mode enum " +
ErrorCode::InvalidEnum, MG_Util::ConvertCullFaceModeToString(cullFaceMode) + "(" +
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "CullFace_State", MG_Util::ConvertGLEnumToString(mode) + ") is not supported."));
"Cull face mode enum " + return;
MG_Util::ConvertCullFaceModeToString(cullFaceMode) + "(" + }
MG_Util::ConvertGLEnumToString(mode) + ") is not supported."));
return; MG_State::pGLContext->SetCullFaceMode(cullFaceMode);
} }
MG_State::pGLContext->SetCullFaceMode(cullFaceMode); void ColorMask_State(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
} MG_State::pGLContext->SetColorMask(
BoolVec4(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE));
void ColorMask_State(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { }
MG_State::pGLContext->SetColorMask(
BoolVec4(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE)); void ClampColor_State(GLenum target, GLenum clamp) {
} // TODO: implement
}
void ClampColor_State(GLenum target, GLenum clamp) {
// TODO: implement void BlendFuncSeparate_State(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
} BlendFactor srcRGB = MG_Util::ConvertGLEnumToBlendFactor(sfactorRGB);
BlendFactor dstRGB = MG_Util::ConvertGLEnumToBlendFactor(dfactorRGB);
void BlendFuncSeparate_State(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) { BlendFactor srcAlpha = MG_Util::ConvertGLEnumToBlendFactor(sfactorAlpha);
BlendFactor srcRGB = MG_Util::ConvertGLEnumToBlendFactor(sfactorRGB); BlendFactor dstAlpha = MG_Util::ConvertGLEnumToBlendFactor(dfactorAlpha);
BlendFactor dstRGB = MG_Util::ConvertGLEnumToBlendFactor(dfactorRGB);
BlendFactor srcAlpha = MG_Util::ConvertGLEnumToBlendFactor(sfactorAlpha); if (srcRGB == BlendFactor::Unknown || dstRGB == BlendFactor::Unknown || srcAlpha == BlendFactor::Unknown ||
BlendFactor dstAlpha = MG_Util::ConvertGLEnumToBlendFactor(dfactorAlpha); dstAlpha == BlendFactor::Unknown) {
MG_State::pGLContext->RecordError(
if (srcRGB == BlendFactor::Unknown || dstRGB == BlendFactor::Unknown || srcAlpha == BlendFactor::Unknown || ErrorCode::InvalidEnum,
dstAlpha == BlendFactor::Unknown) { MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "BlendFuncSeparate_State",
MG_State::pGLContext->RecordError( "One of the blend factor enums is not supported: srcRGB " +
ErrorCode::InvalidEnum, MG_Util::ConvertBlendFactorToString(srcRGB) + "(" +
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "BlendFuncSeparate_State", MG_Util::ConvertGLEnumToString(sfactorRGB) + "), dstRGB " +
"One of the blend factor enums is not supported: srcRGB " + MG_Util::ConvertBlendFactorToString(dstRGB) + "(" +
MG_Util::ConvertBlendFactorToString(srcRGB) + "(" + MG_Util::ConvertGLEnumToString(dfactorRGB) + "), srcAlpha " +
MG_Util::ConvertGLEnumToString(sfactorRGB) + "), dstRGB " + MG_Util::ConvertBlendFactorToString(srcAlpha) + "(" +
MG_Util::ConvertBlendFactorToString(dstRGB) + "(" + MG_Util::ConvertGLEnumToString(sfactorAlpha) + "), dstAlpha " +
MG_Util::ConvertGLEnumToString(dfactorRGB) + "), srcAlpha " + MG_Util::ConvertBlendFactorToString(dstAlpha) + "(" +
MG_Util::ConvertBlendFactorToString(srcAlpha) + "(" + MG_Util::ConvertGLEnumToString(dfactorAlpha) + ")."));
MG_Util::ConvertGLEnumToString(sfactorAlpha) + "), dstAlpha " + return;
MG_Util::ConvertBlendFactorToString(dstAlpha) + "(" + }
MG_Util::ConvertGLEnumToString(dfactorAlpha) + ")."));
return; MG_State::pGLContext->SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
} }
MG_State::pGLContext->SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); void BlendFunc_State(GLenum sfactor, GLenum dfactor) {
} BlendFuncSeparate_State(sfactor, dfactor, sfactor, dfactor);
}
void BlendFunc_State(GLenum sfactor, GLenum dfactor) {
BlendFuncSeparate_State(sfactor, dfactor, sfactor, dfactor); void BlendEquation_State(GLenum mode) {
} // TODO: implement
}
void BlendEquation_State(GLenum mode) {
// TODO: implement void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
} // TODO: implement
}
void BlendColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
// TODO: implement void ClearStencil_State(GLint s) {
} MG_State::pGLContext->SetClearStencil(static_cast<Int>(s));
}
void ClearStencil_State(GLint s) {
MG_State::pGLContext->SetClearStencil(static_cast<Int>(s)); void ClearDepth_State(GLclampd depth) {
} MG_State::pGLContext->SetClearDepth(static_cast<Float>(depth));
}
void ClearDepth_State(GLclampd depth) {
MG_State::pGLContext->SetClearDepth(static_cast<Float>(depth)); void ClearColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
} MG_State::pGLContext->SetClearColor(FloatVec4(red, green, blue, alpha));
}
void BlendFuncSeparatei_State(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
if (buf >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "BlendFuncSeparatei_State",
"Buffer index " + std::to_string(buf) + " is out of range. Max supported is " +
std::to_string(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS - 1) + "."));
return;
}
BlendFactor srcRGBM = MG_Util::ConvertGLEnumToBlendFactor(srcRGB);
BlendFactor dstRGBM = MG_Util::ConvertGLEnumToBlendFactor(dstRGB);
BlendFactor srcAlphaM = MG_Util::ConvertGLEnumToBlendFactor(srcAlpha);
BlendFactor dstAlphaM = MG_Util::ConvertGLEnumToBlendFactor(dstAlpha);
MG_State::pGLContext->SetBlendFuncIndexed(buf, srcRGBM, dstRGBM, srcAlphaM, dstAlphaM);
}
void Disablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Disablei_State",
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"(" + MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, false);
}
void Enablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "Enablei_State",
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"(" + MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, true);
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void Disablei(GLenum target, GLuint index) {
Disablei_State(target, index);
}
void Enablei(GLenum target, GLuint index) {
Enablei_State(target, index);
}
void BlendFunc(GLenum sfactor, GLenum dfactor) {
BlendFunc_State(sfactor, dfactor);
}
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
Viewport_State(x, y, width, height);
}
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
StencilOpSeparate_State(face, sfail, dpfail, dppass);
}
void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
StencilOp_State(fail, zfail, zpass);
}
void StencilMaskSeparate(GLenum face, GLuint mask) {
StencilMaskSeparate_State(face, mask);
}
void StencilMask(GLuint mask) {
StencilMask_State(mask);
}
void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
StencilFuncSeparate_State(face, func, ref, mask);
}
void StencilFunc(GLenum func, GLint ref, GLuint mask) {
StencilFunc_State(func, ref, mask);
}
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
Scissor_State(x, y, width, height);
}
void SampleCoverage(GLfloat value, GLboolean invert) {
SampleCoverage_State(value, invert);
}
void PolygonOffset(GLfloat factor, GLfloat units) {
PolygonOffset_State(factor, units);
}
void PolygonMode(GLenum face, GLenum mode) {
PolygonMode_State(face, mode);
}
void PointSize(GLfloat size) {
PointSize_State(size);
}
void PointParameterf(GLenum pname, GLfloat param) {
PointParameterf_State(pname, param);
}
void PointParameteri(GLenum pname, GLint param) {
PointParameteri_State(pname, param);
}
void PixelStorei(GLenum pname, GLint param) {
PixelStorei_State(pname, param);
}
void LogicOp(GLenum opcode) {
LogicOp_State(opcode);
}
void ClearColor_State(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { void LineWidth(GLfloat width) {
MG_State::pGLContext->SetClearColor(FloatVec4(red, green, blue, alpha)); LineWidth_State(width);
} }
void BlendFuncSeparatei_State(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { GLboolean IsEnabledi(GLenum target, GLuint index) {
if (buf >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { return IsEnabledi_State(target, index);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>( GLboolean IsEnabled(GLenum cap) {
"MG_Impl/GLImpl", "BlendFuncSeparatei_State", return IsEnabled_State(cap);
"Buffer index " + std::to_string(buf) + " is out of range. Max supported is " + }
std::to_string(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS - 1) + "."));
return;
}
BlendFactor srcRGBM = MG_Util::ConvertGLEnumToBlendFactor(srcRGB);
BlendFactor dstRGBM = MG_Util::ConvertGLEnumToBlendFactor(dstRGB);
BlendFactor srcAlphaM = MG_Util::ConvertGLEnumToBlendFactor(srcAlpha);
BlendFactor dstAlphaM = MG_Util::ConvertGLEnumToBlendFactor(dstAlpha);
MG_State::pGLContext->SetBlendFuncIndexed(buf, srcRGBM, dstRGBM, srcAlphaM, dstAlphaM);
}
void Disablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Disablei_State",
"Capability enum " +
MG_Util::ConvertCapabilityInputToString(capInput) + "(" +
MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, false);
}
void Enablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Enablei_State",
"Capability enum " +
MG_Util::ConvertCapabilityInputToString(capInput) + "(" +
MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, true);
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void Disablei(GLenum target, GLuint index) {
Disablei_State(target, index);
}
void Enablei(GLenum target, GLuint index) {
Enablei_State(target, index);
}
void BlendFunc(GLenum sfactor, GLenum dfactor) {
BlendFunc_State(sfactor, dfactor);
}
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
Viewport_State(x, y, width, height);
}
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
StencilOpSeparate_State(face, sfail, dpfail, dppass);
}
void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
StencilOp_State(fail, zfail, zpass);
}
void StencilMaskSeparate(GLenum face, GLuint mask) {
StencilMaskSeparate_State(face, mask);
}
void StencilMask(GLuint mask) {
StencilMask_State(mask);
}
void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
StencilFuncSeparate_State(face, func, ref, mask);
}
void StencilFunc(GLenum func, GLint ref, GLuint mask) {
StencilFunc_State(func, ref, mask);
}
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
Scissor_State(x, y, width, height);
}
void SampleCoverage(GLfloat value, GLboolean invert) {
SampleCoverage_State(value, invert);
}
void PolygonOffset(GLfloat factor, GLfloat units) {
PolygonOffset_State(factor, units);
}
void PolygonMode(GLenum face, GLenum mode) { void Hint(GLenum target, GLenum mode) {
PolygonMode_State(face, mode); Hint_State(target, mode);
} }
void PointSize(GLfloat size) { void FrontFace(GLenum mode) {
PointSize_State(size); FrontFace_State(mode);
} }
void Enable(GLenum cap) {
Enable_State(cap);
}
void PointParameterf(GLenum pname, GLfloat param) { void Disable(GLenum cap) {
PointParameterf_State(pname, param); Disable_State(cap);
} }
void PointParameteri(GLenum pname, GLint param) { void DepthRange(GLclampd near_val, GLclampd far_val) {
PointParameteri_State(pname, param); DepthRange_State(near_val, far_val);
} }
void PixelStorei(GLenum pname, GLint param) { void DepthMask(GLboolean flag) {
PixelStorei_State(pname, param); DepthMask_State(flag);
} }
void LogicOp(GLenum opcode) {
LogicOp_State(opcode);
}
void LineWidth(GLfloat width) {
LineWidth_State(width);
}
GLboolean IsEnabledi(GLenum target, GLuint index) { void DepthFunc(GLenum func) {
return IsEnabledi_State(target, index); DepthFunc_State(func);
} }
GLboolean IsEnabled(GLenum cap) { void CullFace(GLenum mode) {
return IsEnabled_State(cap); CullFace_State(mode);
} }
void Hint(GLenum target, GLenum mode) { void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
Hint_State(target, mode); ColorMask_State(red, green, blue, alpha);
} }
void FrontFace(GLenum mode) { void ClampColor(GLenum target, GLenum clamp) {
FrontFace_State(mode); ClampColor_State(target, clamp);
} }
void Enable(GLenum cap) { void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
Enable_State(cap); BlendFuncSeparate_State(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
} }
void Disable(GLenum cap) { void BlendEquation(GLenum mode) {
Disable_State(cap); BlendEquation_State(mode);
} }
void DepthRange(GLclampd near_val, GLclampd far_val) { void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
DepthRange_State(near_val, far_val); BlendColor_State(red, green, blue, alpha);
} }
void DepthMask(GLboolean flag) { void ClearStencil(GLint s) {
DepthMask_State(flag); ClearStencil_State(s);
} }
void DepthFunc(GLenum func) { void ClearDepth(GLclampd depth) {
DepthFunc_State(func); ClearDepth_State(depth);
} }
void CullFace(GLenum mode) { void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
CullFace_State(mode); ClearColor_State(red, green, blue, alpha);
} }
} // namespace MobileGL::MG_Impl::GLImpl
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
ColorMask_State(red, green, blue, alpha);
}
void ClampColor(GLenum target, GLenum clamp) {
ClampColor_State(target, clamp);
}
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
BlendFuncSeparate_State(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
}
void BlendEquation(GLenum mode) {
BlendEquation_State(mode);
}
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
BlendColor_State(red, green, blue, alpha);
}
void ClearStencil(GLint s) {
ClearStencil_State(s);
}
void ClearDepth(GLclampd depth) {
ClearDepth_State(depth);
}
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
ClearColor_State(red, green, blue, alpha);
}
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
@@ -9,47 +9,45 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); void Disablei(GLenum target, GLuint index);
void Disablei(GLenum target, GLuint index); void Enablei(GLenum target, GLuint index);
void Enablei(GLenum target, GLuint index); void BlendFunc(GLenum sfactor, GLenum dfactor);
void BlendFunc(GLenum sfactor, GLenum dfactor); void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); void StencilOp(GLenum fail, GLenum zfail, GLenum zpass);
void StencilOp(GLenum fail, GLenum zfail, GLenum zpass); void StencilMaskSeparate(GLenum face, GLuint mask);
void StencilMaskSeparate(GLenum face, GLuint mask); void StencilMask(GLuint mask);
void StencilMask(GLuint mask); void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); void StencilFunc(GLenum func, GLint ref, GLuint mask);
void StencilFunc(GLenum func, GLint ref, GLuint mask); void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height); void SampleCoverage(GLfloat value, GLboolean invert);
void SampleCoverage(GLfloat value, GLboolean invert); void PolygonOffset(GLfloat factor, GLfloat units);
void PolygonOffset(GLfloat factor, GLfloat units); void PolygonMode(GLenum face, GLenum mode);
void PolygonMode(GLenum face, GLenum mode); void PointSize(GLfloat size);
void PointSize(GLfloat size); void PointParameterf(GLenum pname, GLfloat param);
void PointParameterf(GLenum pname, GLfloat param); void PointParameteri(GLenum pname, GLint param);
void PointParameteri(GLenum pname, GLint param); void PixelStorei(GLenum pname, GLint param);
void PixelStorei(GLenum pname, GLint param); void LogicOp(GLenum opcode);
void LogicOp(GLenum opcode); void LineWidth(GLfloat width);
void LineWidth(GLfloat width); GLboolean IsEnabledi(GLenum target, GLuint index);
GLboolean IsEnabledi(GLenum target, GLuint index); GLboolean IsEnabled(GLenum cap);
GLboolean IsEnabled(GLenum cap); void Hint(GLenum target, GLenum mode);
void Hint(GLenum target, GLenum mode); void FrontFace(GLenum mode);
void FrontFace(GLenum mode); void Enable(GLenum cap);
void Enable(GLenum cap); void Disable(GLenum cap);
void Disable(GLenum cap); void DepthRange(GLclampd near_val, GLclampd far_val);
void DepthRange(GLclampd near_val, GLclampd far_val); void DepthMask(GLboolean flag);
void DepthMask(GLboolean flag); void DepthFunc(GLenum func);
void DepthFunc(GLenum func); void CullFace(GLenum mode);
void CullFace(GLenum mode); void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void ClampColor(GLenum target, GLenum clamp);
void ClampColor(GLenum target, GLenum clamp); void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); void BlendEquation(GLenum mode);
void BlendEquation(GLenum mode); void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void ClearStencil(GLint s);
void ClearStencil(GLint s); void ClearDepth(GLclampd depth);
void ClearDepth(GLclampd depth); void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
+233 -229
View File
@@ -12,254 +12,258 @@
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat, bool isInteger) {
void SetSamplerParam_State(GLuint sampler, GLenum pname, const void* param, bool isFloat, bool isInteger) { if (!SamplerImpl::ValidateSamplerName(sampler)) return;
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
if (!doesSamplerObjectCreated) {
// Create one for compatibility
MG_State::pGLContext->CreateSamplerObject(sampler);
}
auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
using namespace MG_Util;
switch (pname) {
case GL_TEXTURE_WRAP_S:
samplerObj->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param));
break;
case GL_TEXTURE_WRAP_T:
samplerObj->SetWrapT(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param));
break;
case GL_TEXTURE_WRAP_R:
samplerObj->SetWrapR(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param));
break;
case GL_TEXTURE_MIN_FILTER:
samplerObj->SetMinFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(*(const GLint*)param));
samplerObj->SetMipmapMode(MG_Util::ConvertGLEnumToSamplerMipmapMode(*(const GLint*)param));
break;
case GL_TEXTURE_MAG_FILTER:
samplerObj->SetMagFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(*(const GLint*)param));
break;
case GL_TEXTURE_MIN_LOD:
samplerObj->SetLodRange(*(const GLfloat*)param, samplerObj->GetMaxLod());
break;
case GL_TEXTURE_MAX_LOD:
samplerObj->SetLodRange(samplerObj->GetMinLod(), *(const GLfloat*)param);
break;
case GL_TEXTURE_LOD_BIAS:
samplerObj->SetLodBias(*(const GLfloat*)param);
break;
case GL_TEXTURE_COMPARE_MODE:
samplerObj->SetCompareMode(MG_Util::ConvertGLEnumToSamplerCompareMode(*(const GLint*)param));
break;
case GL_TEXTURE_COMPARE_FUNC:
samplerObj->SetSamplerCompareFunc(MG_Util::ConvertGLEnumToSamplerCompareFunc(*(const GLint*)param));
break;
default:
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "SetSamplerParam_State",
"Invalid pname for sampler parameter"));
}
}
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) {
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
if (!doesSamplerObjectCreated) {
// Create one for compatibility
MG_State::pGLContext->CreateSamplerObject(sampler);
}
auto& samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
using namespace MG_Util;
switch (pname) {
case GL_TEXTURE_WRAP_S:
*(GLuint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapS());
break;
case GL_TEXTURE_WRAP_T:
*(GLuint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapT());
break;
case GL_TEXTURE_WRAP_R:
*(GLuint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapR());
break;
case GL_TEXTURE_MIN_FILTER:
*(GLuint*)params =
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObj->GetMinFilter(), samplerObj->GetMipmapMode());
break;
case GL_TEXTURE_MAG_FILTER:
*(GLuint*)params =
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObj->GetMagFilter(), SamplerMipmapMode::None);
break;
case GL_TEXTURE_MIN_LOD:
*(GLfloat*)params = samplerObj->GetMinLod();
break;
case GL_TEXTURE_MAX_LOD:
*(GLfloat*)params = samplerObj->GetMaxLod();
break;
case GL_TEXTURE_LOD_BIAS:
*(GLfloat*)params = samplerObj->GetLodBias();
break;
case GL_TEXTURE_COMPARE_MODE:
*(GLuint*)params = MG_Util::ConvertSamplerCompareModeToGLEnum(samplerObj->GetCompareMode());
break;
case GL_TEXTURE_COMPARE_FUNC:
*(GLuint*)params = MG_Util::ConvertSamplerCompareFuncToGLEnum(samplerObj->GetSamplerCompareFunc());
break;
default:
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GetSamplerParam_State",
"Invalid pname for sampler parameter"));
}
}
GLboolean IsSampler_State(GLuint sampler) {
return MG_State::pGLContext->ValidateSamplerObject(sampler) ? GL_TRUE : GL_FALSE;
}
// migrate below functions without "_State" into this section
void GenSamplers_State(GLsizei count, GLuint* samplers) {
if (count < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GenSamplers", "count must be non-negative"));
return;
}
static thread_local Vector<GLuint> names;
MG_State::pGLContext->GenSamplerNames(count, names);
Memcpy(samplers, names.data(), count * sizeof(GLuint));
}
void DeleteSamplers_State(GLsizei count, const GLuint* samplers) {
if (count < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteSamplers", "count must be non-negative"));
return;
}
for (GLsizei i = 0; i < count; ++i) {
if (samplers[i] != 0) {
MG_State::pGLContext->MarkSamplerObjectForDeletion(samplers[i]);
}
}
}
void CreateSamplers_State(GLsizei n, GLuint* samplers) {
if (n < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GenSamplers", "count must be non-negative"));
return;
}
static thread_local Vector<GLuint> names;
MG_State::pGLContext->GenSamplerNames(n, names);
Memcpy(samplers, names.data(), n * sizeof(GLuint));
for (GLsizei i = 0; i < n; ++i) {
samplers[i] = names[i];
MG_State::pGLContext->CreateSamplerObject(names[i]);
}
}
void BindSampler_State(GLuint unit, GLuint sampler) {
if (unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "BindSampler", "texture unit out of range"));
return;
}
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject((Int)unit);
if (sampler == 0) {
textureUnit.SetSamplerObject(nullptr);
} else {
if (!SamplerImpl::ValidateSamplerName(sampler)) return; if (!SamplerImpl::ValidateSamplerName(sampler)) return;
Bool doesSamplerObjectCreated = MG_State::pGLContext->ValidateSamplerObject(sampler);
auto samplerObj = MG_State::pGLContext->GetSamplerObject(sampler); if (!doesSamplerObjectCreated) {
if (!samplerObj) { MG_State::pGLContext->CreateSamplerObject(sampler);
samplerObj = MG_State::pGLContext->CreateSamplerObject(sampler); // for compatibility
} }
if (!SamplerImpl::ValidateSamplerObject(sampler)) return; auto& samplerObject = MG_State::pGLContext->GetSamplerObject(sampler);
using namespace MG_Util; textureUnit.SetSamplerObject(MG_State::pGLContext->GetSamplerObject(sampler));
switch (pname) { }
case GL_TEXTURE_WRAP_S: }
samplerObj->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param));
break; void BindSamplers_State(GLuint first, GLsizei count, const GLuint* samplers) {
case GL_TEXTURE_WRAP_T: if (count < 0) {
samplerObj->SetWrapT(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param)); MG_State::pGLContext->RecordError(
break; ErrorCode::InvalidValue,
case GL_TEXTURE_WRAP_R: MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "BindSamplers", "count must be non-negative"));
samplerObj->SetWrapR(MG_Util::ConvertGLEnumToSamplerWrapMode(*(const GLint*)param)); return;
break;
case GL_TEXTURE_MIN_FILTER:
samplerObj->SetMinFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(*(const GLint*)param));
samplerObj->SetMipmapMode(MG_Util::ConvertGLEnumToSamplerMipmapMode(*(const GLint*)param));
break;
case GL_TEXTURE_MAG_FILTER:
samplerObj->SetMagFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(*(const GLint*)param));
break;
case GL_TEXTURE_MIN_LOD:
samplerObj->SetLodRange(*(const GLfloat*)param, samplerObj->GetMaxLod());
break;
case GL_TEXTURE_MAX_LOD:
samplerObj->SetLodRange(samplerObj->GetMinLod(), *(const GLfloat*)param);
break;
case GL_TEXTURE_LOD_BIAS:
samplerObj->SetLodBias(*(const GLfloat*)param);
break;
case GL_TEXTURE_COMPARE_MODE:
samplerObj->SetCompareMode(MG_Util::ConvertGLEnumToSamplerCompareMode(*(const GLint*)param));
break;
case GL_TEXTURE_COMPARE_FUNC:
samplerObj->SetSamplerCompareFunc(MG_Util::ConvertGLEnumToSamplerCompareFunc(*(const GLint*)param));
break;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "SetSamplerParam_State",
"Invalid pname for sampler parameter"));
}
} }
void GetSamplerParam_State(GLuint sampler, GLenum pname, void* params, bool isFloat, bool isInteger) { for (GLsizei i = 0; i < count; ++i) {
if (!SamplerImpl::ValidateSamplerName(sampler)) return; BindSampler_State(first + i, samplers ? samplers[i] : 0);
auto samplerObj = MG_State::pGLContext->GetSamplerObject(sampler);
if (!samplerObj) {
samplerObj = MG_State::pGLContext->CreateSamplerObject(sampler); // for compatibility
}
if (!SamplerImpl::ValidateSamplerObject(sampler)) return;
using namespace MG_Util;
switch (pname) {
case GL_TEXTURE_WRAP_S:
*(GLint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapS());
break;
case GL_TEXTURE_WRAP_T:
*(GLint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapT());
break;
case GL_TEXTURE_WRAP_R:
*(GLint*)params = MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObj->GetWrapR());
break;
case GL_TEXTURE_MIN_FILTER:
*(GLint*)params =
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObj->GetMinFilter(), samplerObj->GetMipmapMode());
break;
case GL_TEXTURE_MAG_FILTER:
*(GLint*)params =
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObj->GetMagFilter(), SamplerMipmapMode::None);
break;
case GL_TEXTURE_MIN_LOD:
*(GLfloat*)params = samplerObj->GetMinLod();
break;
case GL_TEXTURE_MAX_LOD:
*(GLfloat*)params = samplerObj->GetMaxLod();
break;
case GL_TEXTURE_LOD_BIAS:
*(GLfloat*)params = samplerObj->GetLodBias();
break;
case GL_TEXTURE_COMPARE_MODE:
*(GLint*)params = MG_Util::ConvertSamplerCompareModeToGLEnum(samplerObj->GetCompareMode());
break;
case GL_TEXTURE_COMPARE_FUNC:
*(GLint*)params = MG_Util::ConvertSamplerCompareFuncToGLEnum(samplerObj->GetSamplerCompareFunc());
break;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetSamplerParam_State",
"Invalid pname for sampler parameter"));
}
} }
}
GLboolean IsSampler_State(GLuint sampler) { /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
return MG_State::pGLContext->ValidateSamplerObject(sampler) ? GL_TRUE : GL_FALSE; void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) {
} GetSamplerParam_State(sampler, pname, params, false, false);
}
// migrate below functions without "_State" into this section void SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint* param) {
void GenSamplers_State(GLsizei count, GLuint* samplers) { SetSamplerParam_State(sampler, pname, param, false, true);
if (count < 0) { }
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenSamplers", "count must be non-negative"));
return;
}
auto names = MG_State::pGLContext->GenSamplerNames(count); void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint* param) {
for (GLsizei i = 0; i < count; ++i) { SetSamplerParam_State(sampler, pname, param, false, true);
samplers[i] = names[i]; }
}
}
void DeleteSamplers_State(GLsizei count, const GLuint* samplers) { void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) {
if (count < 0) { SetSamplerParam_State(sampler, pname, param, false, false);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteSamplers", "count must be non-negative"));
return;
}
for (GLsizei i = 0; i < count; ++i) { void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) {
if (samplers[i] != 0) { SetSamplerParam_State(sampler, pname, param, true, false);
MG_State::pGLContext->MarkSamplerObjectForDeletion(samplers[i]); }
}
}
}
void CreateSamplers_State(GLsizei n, GLuint* samplers) { void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) {
if (n < 0) { SamplerParameteriv(sampler, pname, &param);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenSamplers", "count must be non-negative"));
return;
}
auto names = MG_State::pGLContext->GenSamplerNames(n); void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) {
for (GLsizei i = 0; i < n; ++i) { SamplerParameterfv(sampler, pname, &param);
samplers[i] = names[i]; }
MG_State::pGLContext->CreateSamplerObject(names[i]);
}
}
void BindSampler_State(GLuint unit, GLuint sampler) { GLboolean IsSampler(GLuint sampler) {
if (unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) { return IsSampler_State(sampler);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "BindSampler", "texture unit out of range"));
return;
}
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit); void GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params) {
if (sampler == 0) { GetSamplerParam_State(sampler, pname, params, false, true);
textureUnit.SetSamplerObject(nullptr); }
} else {
if (!SamplerImpl::ValidateSamplerName(sampler)) return;
auto samplerObject = MG_State::pGLContext->GetSamplerObject(sampler);
if (!samplerObject) {
samplerObject = MG_State::pGLContext->CreateSamplerObject(sampler);
}
textureUnit.SetSamplerObject(MG_State::pGLContext->GetSamplerObject(sampler)); void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params) {
} GetSamplerParam_State(sampler, pname, params, false, true);
} }
void BindSamplers_State(GLuint first, GLsizei count, const GLuint* samplers) { void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) {
if (count < 0) { GetSamplerParam_State(sampler, pname, params, true, false);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "BindSamplers", "count must be non-negative"));
return;
}
for (GLsizei i = 0; i < count; ++i) { void GenSamplers(GLsizei count, GLuint* samplers) {
BindSampler_State(first + i, samplers ? samplers[i] : 0); GenSamplers_State(count, samplers);
} }
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ void DeleteSamplers(GLsizei count, const GLuint* samplers) {
void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { DeleteSamplers_State(count, samplers);
GetSamplerParam_State(sampler, pname, params, false, false); }
}
void SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint* param) { void CreateSamplers(GLsizei n, GLuint* samplers) {
SetSamplerParam_State(sampler, pname, param, false, true); CreateSamplers_State(n, samplers);
} }
void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint* param) { void BindSamplers(GLuint first, GLsizei count, const GLuint* samplers) {
SetSamplerParam_State(sampler, pname, param, false, true); BindSamplers_State(first, count, samplers);
} }
void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { void BindSampler(GLuint unit, GLuint sampler) {
SetSamplerParam_State(sampler, pname, param, false, false); BindSampler_State(unit, sampler);
} }
} // namespace MobileGL::MG_Impl::GLImpl
void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) {
SetSamplerParam_State(sampler, pname, param, true, false);
}
void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) {
SamplerParameteriv(sampler, pname, &param);
}
void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) {
SamplerParameterfv(sampler, pname, &param);
}
GLboolean IsSampler(GLuint sampler) {
return IsSampler_State(sampler);
}
void GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params) {
GetSamplerParam_State(sampler, pname, params, false, true);
}
void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params) {
GetSamplerParam_State(sampler, pname, params, false, true);
}
void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) {
GetSamplerParam_State(sampler, pname, params, true, false);
}
void GenSamplers(GLsizei count, GLuint* samplers) {
GenSamplers_State(count, samplers);
}
void DeleteSamplers(GLsizei count, const GLuint* samplers) {
DeleteSamplers_State(count, samplers);
}
void CreateSamplers(GLsizei n, GLuint* samplers) {
CreateSamplers_State(n, samplers);
}
void BindSamplers(GLuint first, GLsizei count, const GLuint* samplers) {
BindSamplers_State(first, count, samplers);
}
void BindSampler(GLuint unit, GLuint sampler) {
BindSampler_State(unit, sampler);
}
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
+19 -21
View File
@@ -9,24 +9,22 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params);
void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params); void SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint* param);
void SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint* param); void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint* param);
void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint* param); void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param);
void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param); void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param);
void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param); void SamplerParameteri(GLuint sampler, GLenum pname, GLint param);
void SamplerParameteri(GLuint sampler, GLenum pname, GLint param); void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param); GLboolean IsSampler(GLuint sampler);
GLboolean IsSampler(GLuint sampler); void GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params);
void GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params); void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params);
void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params); void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params);
void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params); void GenSamplers(GLsizei count, GLuint* samplers);
void GenSamplers(GLsizei count, GLuint* samplers); void DeleteSamplers(GLsizei count, const GLuint* samplers);
void DeleteSamplers(GLsizei count, const GLuint* samplers); void CreateSamplers(GLsizei n, GLuint* samplers);
void CreateSamplers(GLsizei n, GLuint* samplers); void BindSamplers(GLuint first, GLsizei count, const GLuint* samplers);
void BindSamplers(GLuint first, GLsizei count, const GLuint* samplers); void BindSampler(GLuint unit, GLuint sampler);
void BindSampler(GLuint unit, GLuint sampler); } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
+113 -117
View File
@@ -11,126 +11,122 @@
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::SamplerImpl {
namespace SamplerImpl { Bool ValidateSamplerName(GLuint sampler) {
Bool ValidateSamplerName(GLuint sampler) { if (!MG_State::pGLContext->ValidateSamplerName(sampler)) {
if (!MG_State::pGLContext->ValidateSamplerName(sampler)) { MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerName",
std::format("Invalid sampler name {}", sampler)));
return false;
}
return true;
}
Bool ValidateSamplerObject(GLuint sampler) {
if (!MG_State::pGLContext->ValidateSamplerObject(sampler)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerObject",
std::format("Sampler object {} does not exist", sampler)));
return false;
}
return true;
}
Bool ValidateSamplerParam(GLenum pname, GLenum param) {
using namespace MG_Util;
switch (pname) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
if (MG_Util::ConvertGLEnumToSamplerWrapMode(param) == SamplerWrapMode::Unknown) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid wrap mode parameter"));
return false;
}
break;
case GL_TEXTURE_MIN_FILTER:
if (MG_Util::ConvertGLEnumToSamplerFilterMode(param) == SamplerFilterMode::Unknown) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid min filter parameter"));
return false;
}
break;
case GL_TEXTURE_MAG_FILTER:
if (param != GL_NEAREST && param != GL_LINEAR) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid mag filter parameter"));
return false;
}
break;
case GL_TEXTURE_COMPARE_MODE:
if (param != GL_NONE && param != GL_COMPARE_REF_TO_TEXTURE) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid compare mode parameter"));
return false;
}
break;
case GL_TEXTURE_COMPARE_FUNC:
if (param < GL_LEQUAL || param > GL_ALWAYS) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid compare function parameter"));
return false;
}
break;
default:
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid pname for sampler parameter"));
return false;
}
return true;
}
Bool ValidateSamplerFloatParam(GLenum pname, GLfloat param) {
switch (pname) {
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
case GL_TEXTURE_LOD_BIAS:
return true;
case GL_TEXTURE_BORDER_COLOR:
if (param < 0.0f || param > 1.0f) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerFloatParam",
"Border color component out of [0,1] range"));
return false;
}
return true;
default:
return ValidateSamplerParam(pname, static_cast<GLenum>(param));
}
}
Bool ValidateSamplerIntParam(GLenum pname, GLint param) {
switch (pname) {
case GL_TEXTURE_BORDER_COLOR:
if (param < 0 || param > 255) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerName", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerIntParam",
std::format("Invalid sampler name {}", sampler))); "Border color component out of [0,255] range"));
return false; return false;
} }
return true; return true;
default:
return ValidateSamplerParam(pname, static_cast<GLenum>(param));
} }
}
Bool ValidateSamplerObject(GLuint sampler) { } // namespace MobileGL::MG_Impl::GLImpl::SamplerImpl
if (!MG_State::pGLContext->ValidateSamplerObject(sampler)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerObject",
std::format("Sampler object {} does not exist", sampler)));
return false;
}
return true;
}
Bool ValidateSamplerParam(GLenum pname, GLenum param) {
using namespace MG_Util;
switch (pname) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
if (MG_Util::ConvertGLEnumToSamplerWrapMode(param) == SamplerWrapMode::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid wrap mode parameter"));
return false;
}
break;
case GL_TEXTURE_MIN_FILTER:
if (MG_Util::ConvertGLEnumToSamplerFilterMode(param) == SamplerFilterMode::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid min filter parameter"));
return false;
}
break;
case GL_TEXTURE_MAG_FILTER:
if (param != GL_NEAREST && param != GL_LINEAR) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid mag filter parameter"));
return false;
}
break;
case GL_TEXTURE_COMPARE_MODE:
if (param != GL_NONE && param != GL_COMPARE_REF_TO_TEXTURE) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid compare mode parameter"));
return false;
}
break;
case GL_TEXTURE_COMPARE_FUNC:
if (param < GL_LEQUAL || param > GL_ALWAYS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid compare function parameter"));
return false;
}
break;
default:
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerParam",
"Invalid pname for sampler parameter"));
return false;
}
return true;
}
Bool ValidateSamplerFloatParam(GLenum pname, GLfloat param) {
switch (pname) {
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
case GL_TEXTURE_LOD_BIAS:
return true;
case GL_TEXTURE_BORDER_COLOR:
if (param < 0.0f || param > 1.0f) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerFloatParam",
"Border color component out of [0,1] range"));
return false;
}
return true;
default:
return ValidateSamplerParam(pname, static_cast<GLenum>(param));
}
}
Bool ValidateSamplerIntParam(GLenum pname, GLint param) {
switch (pname) {
case GL_TEXTURE_BORDER_COLOR:
if (param < 0 || param > 255) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateSamplerIntParam",
"Border color component out of [0,255] range"));
return false;
}
return true;
default:
return ValidateSamplerParam(pname, static_cast<GLenum>(param));
}
}
} // namespace SamplerImpl
} // namespace MobileGL::MG_Impl::GLImpl
+7 -9
View File
@@ -10,12 +10,10 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h> #include <MG_State/GLState/SamplerState/SamplerObject.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::SamplerImpl {
namespace SamplerImpl { Bool ValidateSamplerName(GLuint sampler);
Bool ValidateSamplerName(GLuint sampler); Bool ValidateSamplerObject(GLuint sampler);
Bool ValidateSamplerObject(GLuint sampler); Bool ValidateSamplerParam(GLenum pname, GLenum param);
Bool ValidateSamplerParam(GLenum pname, GLenum param); Bool ValidateSamplerFloatParam(GLenum pname, GLfloat param);
Bool ValidateSamplerFloatParam(GLenum pname, GLfloat param); Bool ValidateSamplerIntParam(GLenum pname, GLint param);
Bool ValidateSamplerIntParam(GLenum pname, GLint param); } // namespace MobileGL::MG_Impl::GLImpl::SamplerImpl
} // namespace SamplerImpl
} // namespace MobileGL::MG_Impl::GLImpl
+23 -25
View File
@@ -10,36 +10,34 @@
#include "MG_State/GLState/Core.h" #include "MG_State/GLState/Core.h"
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { GLsync FenceSync_Backend(GLenum condition, GLbitfield flags) {
GLsync FenceSync_Backend(GLenum condition, GLbitfield flags) { return 0;
return 0; }
}
GLenum ClientWaitSync_Backend(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync_Backend(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; return 0;
} }
void DeleteSync_Backend(GLsync sync) {} void DeleteSync_Backend(GLsync sync) {}
GLsync FenceSync_State(GLenum condition, GLbitfield flags) { GLsync FenceSync_State(GLenum condition, GLbitfield flags) {
return 0; return 0;
} }
GLenum ClientWaitSync_State(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync_State(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; return 0;
} }
void DeleteSync_State(GLsync sync) {} void DeleteSync_State(GLsync sync) {}
GLsync FenceSync(GLenum condition, GLbitfield flags) { GLsync FenceSync(GLenum condition, GLbitfield flags) {
return 0; return 0;
} }
GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
return 0; return 0;
} }
void DeleteSync(GLsync sync) {} void DeleteSync(GLsync sync) {}
} // namespace MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MobileGL
+5 -7
View File
@@ -9,10 +9,8 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { GLsync FenceSync(GLenum condition, GLbitfield flags);
GLsync FenceSync(GLenum condition, GLbitfield flags); GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); void DeleteSync(GLsync sync);
void DeleteSync(GLsync sync); } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
File diff suppressed because it is too large Load Diff
@@ -7,48 +7,47 @@
// End of Source File Header // End of Source File Header
#include "ProxyTexture.h" #include "ProxyTexture.h"
#include "MG_State/GLState/TextureState/TextureObject2D.h" #include <MG_State/GLState/TextureState/TextureObject2D.h>
#include "MG_Util/Types.h"
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
namespace TextureImpl { UniquePtr<ProxyTextureManager> pProxyTextureManager;
ProxyTextureManager* pProxyTextureManager;
Bool IsProxyTextureTarget(TextureUploadTarget target) { Bool IsProxyTextureTarget(TextureUploadTarget target) {
switch (target) { switch (target) {
case TextureUploadTarget::ProxyCubeMap: case TextureUploadTarget::ProxyCubeMap:
case TextureUploadTarget::ProxyTexture1DArray: case TextureUploadTarget::ProxyTexture1DArray:
case TextureUploadTarget::ProxyTexture2DArray: case TextureUploadTarget::ProxyTexture2DArray:
case TextureUploadTarget::ProxyTexture1D: case TextureUploadTarget::ProxyTexture1D:
case TextureUploadTarget::ProxyTexture2D: case TextureUploadTarget::ProxyTexture2D:
case TextureUploadTarget::ProxyTexture3D: case TextureUploadTarget::ProxyTexture3D:
case TextureUploadTarget::ProxyTexture2DMultisample: case TextureUploadTarget::ProxyTexture2DMultisample:
case TextureUploadTarget::ProxyTexture2DMultisampleArray: case TextureUploadTarget::ProxyTexture2DMultisampleArray:
case TextureUploadTarget::ProxyTextureRectangle: case TextureUploadTarget::ProxyTextureRectangle:
case TextureUploadTarget::ProxyCubeMapArray: case TextureUploadTarget::ProxyCubeMapArray:
return true; return true;
default: default:
return false; return false;
}
} }
}
SharedPtr<MG_State::GLState::ITextureObject> ProxyTextureManager::CreateOrReplaceProxyTextureObject( const SharedPtr<MG_State::GLState::ITextureObject>& ProxyTextureManager::CreateOrReplaceProxyTextureObject(
TextureUploadTarget target) { TextureUploadTarget target) {
auto it = m_proxyTexturesMap.find(target); auto it = m_proxyTexturesMap.find(target);
if (it != m_proxyTexturesMap.end()) { if (it != m_proxyTexturesMap.end()) {
m_proxyTexturesMap.erase(it); m_proxyTexturesMap.erase(it);
}
m_proxyTexturesMap[target] = MakeShared<MG_State::GLState::TextureObject2D>(0);
return m_proxyTexturesMap[target];
} }
auto& obj = m_proxyTexturesMap[target];
obj = MakeShared<MG_State::GLState::TextureObject2D>(0);
return obj;
}
SharedPtr<MG_State::GLState::ITextureObject> ProxyTextureManager::GetProxyTextureObject( const SharedPtr<MG_State::GLState::ITextureObject>& ProxyTextureManager::GetProxyTextureObject(
TextureUploadTarget target) { TextureUploadTarget target) {
auto it = m_proxyTexturesMap.find(target); auto it = m_proxyTexturesMap.find(target);
if (it != m_proxyTexturesMap.end()) { if (it != m_proxyTexturesMap.end()) {
return it->second; return it->second;
}
return nullptr;
} }
} // namespace TextureImpl static SharedPtr<MG_State::GLState::ITextureObject> nullTextureObject = nullptr;
} // namespace MobileGL::MG_Impl::GLImpl return nullTextureObject;
}
} // namespace MobileGL::MG_Impl::GLImpl::TextureImpl
+12 -13
View File
@@ -10,19 +10,18 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
namespace TextureImpl { Bool IsProxyTextureTarget(TextureUploadTarget target);
Bool IsProxyTextureTarget(TextureUploadTarget target);
class ProxyTextureManager { class ProxyTextureManager {
public: public:
SharedPtr<MG_State::GLState::ITextureObject> CreateOrReplaceProxyTextureObject(TextureUploadTarget target); const SharedPtr<MG_State::GLState::ITextureObject>& CreateOrReplaceProxyTextureObject(
SharedPtr<MG_State::GLState::ITextureObject> GetProxyTextureObject(TextureUploadTarget target); TextureUploadTarget target);
const SharedPtr<MG_State::GLState::ITextureObject>& GetProxyTextureObject(TextureUploadTarget target);
private: private:
UnorderedMap<TextureUploadTarget, SharedPtr<MG_State::GLState::ITextureObject>> m_proxyTexturesMap; UnorderedMap<TextureUploadTarget, SharedPtr<MG_State::GLState::ITextureObject>> m_proxyTexturesMap;
}; };
extern ProxyTextureManager* pProxyTextureManager; extern UniquePtr<ProxyTextureManager> pProxyTextureManager;
} // namespace TextureImpl } // namespace MobileGL::MG_Impl::GLImpl::TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl
+240 -254
View File
@@ -15,309 +15,295 @@
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h> #include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h> #include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
namespace TextureImpl { Bool ValidateTextureTarget(TextureTarget target) {
Bool ValidateTextureTarget(TextureTarget target) { if (target == TextureTarget::Unknown) {
if (target == TextureTarget::Unknown) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum,
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureTarget", "Invalid texture target"));
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureTarget", "Invalid texture target")); return false;
return false; }
} return true;
return true; }
Bool ValidateTextureUploadTarget(TextureUploadTarget textureUploadTarget) {
if (textureUploadTarget == TextureUploadTarget::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureUploadTarget",
"Invalid texture upload target"));
return false;
}
return true;
}
Bool ValidateTextureName(Uint texture, Bool allowZero) {
if (texture == 0) {
if (allowZero) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureName", "Texture name cannot be zero"));
return false;
} }
Bool ValidateTextureUploadTarget(TextureUploadTarget textureUploadTarget) { if (!MG_State::pGLContext->ValidateTextureName(texture)) {
if (textureUploadTarget == TextureUploadTarget::Unknown) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureName", "Invalid texture name"));
"ValidateTextureUploadTarget", return false;
"Invalid texture upload target")); }
return false; return true;
} }
return true;
Bool ValidateTextureInputFormat(TextureInputFormat format) {
if (format == TextureInputFormat::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInputFormat",
"Invalid texture input format"));
return false;
}
return true;
}
Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType) {
if (texturePixelDataType == TexturePixelDataType::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTexturePixelDataType",
"Invalid texture pixel data type"));
return false;
}
return true;
}
Bool ValidateTextureLevelNumber(GLint level) {
if (level < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureLevelNumber",
"Texture level must be non-negative"));
return false;
} }
Bool ValidateTextureName(Uint texture, Bool allowZero) { // TODO: GL_INVALID_VALUE may be generated if level is greater than log2(max), where max is the returned
if (texture == 0) { // value of GL_MAX_TEXTURE_SIZE.
if (allowZero) return true;
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue, return true;
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureName", }
"Texture name cannot be zero"));
return false;
}
if (!MG_State::pGLContext->ValidateTextureName(texture)) { Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height) {
if (target == TextureUploadTarget::CubeMapPositiveX || target == TextureUploadTarget::CubeMapNegativeX ||
target == TextureUploadTarget::CubeMapPositiveY || target == TextureUploadTarget::CubeMapNegativeY ||
target == TextureUploadTarget::CubeMapPositiveZ || target == TextureUploadTarget::CubeMapNegativeZ) {
if (width != height) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureName", "Invalid texture name")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Width and height must be equal for cube map textures"));
return false; return false;
} }
return true;
} }
Bool ValidateTextureInputFormat(TextureInputFormat format) { if (!(target == TextureUploadTarget::Texture1DArray || target == TextureUploadTarget::ProxyTexture1DArray)) {
if (format == TextureInputFormat::Unknown) { if (height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInputFormat",
"Invalid texture input format"));
return false;
}
return true;
}
Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType) {
if (texturePixelDataType == TexturePixelDataType::Unknown) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTexturePixelDataType",
"Invalid texture pixel data type"));
return false;
}
return true;
}
Bool ValidateTextureLevelNumber(GLint level) {
if (level < 0) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureLevelNumber",
"Texture level must be non-negative"));
return false;
}
// TODO: GL_INVALID_VALUE may be generated if level is greater than log2(max), where max is the returned
// value of GL_MAX_TEXTURE_SIZE.
return true;
}
Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height) {
if (target == TextureUploadTarget::CubeMapPositiveX || target == TextureUploadTarget::CubeMapNegativeX ||
target == TextureUploadTarget::CubeMapPositiveY || target == TextureUploadTarget::CubeMapNegativeY ||
target == TextureUploadTarget::CubeMapPositiveZ || target == TextureUploadTarget::CubeMapNegativeZ) {
if (width != height) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Width and height must be equal for cube map textures"));
return false;
}
}
if (!(target == TextureUploadTarget::Texture1DArray ||
target == TextureUploadTarget::ProxyTexture1DArray)) {
if (height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Height must be greater than or equal to zero"));
return false;
}
// TODO: GL_INVALID_VALUE is generated if target is not GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY
// and height is greater than GL_MAX_TEXTURE_SIZE.
}
if (target == TextureUploadTarget::Texture1DArray || target == TextureUploadTarget::ProxyTexture1DArray) {
if (height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Height must be greater than or equal to zero"));
return false;
}
// TODO: GL_INVALID_VALUE is generated if target is GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY and
// height is greater than GL_MAX_ARRAY_TEXTURE_LAYERS.
}
return true;
}
Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth) {
if (width < 0 || height < 0 || depth < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeRange", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Width and height must be greater than zero")); "Height must be greater than or equal to zero"));
return false; return false;
} }
// TODO: GL_INVALID_VALUE is generated if target is not GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY
// TODO: GL_INVALID_VALUE is generated if width is greater than GL_MAX_TEXTURE_SIZE. // and height is greater than GL_MAX_TEXTURE_SIZE.
return true;
} }
Bool ValidateTextureInternalFormat(TextureInternalFormat format) { if (target == TextureUploadTarget::Texture1DArray || target == TextureUploadTarget::ProxyTexture1DArray) {
if (format == TextureInternalFormat::Unknown) { if (height < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormat", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeWithTarget",
"Invalid texture sized internal format")); "Height must be greater than or equal to zero"));
return false; return false;
} }
return true; // TODO: GL_INVALID_VALUE is generated if target is GL_TEXTURE_1D_ARRAY or GL_PROXY_TEXTURE_1D_ARRAY and
// height is greater than GL_MAX_ARRAY_TEXTURE_LAYERS.
} }
Bool ValidateTextureBorderNumber(Int border) { return true;
if (border != 0) { }
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth) {
"ValidateTextureBorderNumber", if (width < 0 || height < 0 || depth < 0) {
"Border must be zero")); MG_State::pGLContext->RecordError(
return false; ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSizeRange",
} "Width and height must be greater than zero"));
return true; return false;
} }
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, // TODO: GL_INVALID_VALUE is generated if width is greater than GL_MAX_TEXTURE_SIZE.
TextureInternalFormat internalFormat,
TexturePixelDataType type) {
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
type == TexturePixelDataType::UnsignedInt101111Rev) {
if (format != TextureInputFormat::RGB) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for the given type"));
return false;
}
}
if (type == TexturePixelDataType::UnsignedShort4444 || type == TexturePixelDataType::UnsignedShort4444Rev || return true;
type == TexturePixelDataType::UnsignedShort5551 || type == TexturePixelDataType::UnsignedShort1555Rev || }
type == TexturePixelDataType::UnsignedInt8888 || type == TexturePixelDataType::UnsignedInt8888Rev ||
type == TexturePixelDataType::UnsignedInt1010102 ||
type == TexturePixelDataType::UnsignedInt2101010Rev ||
type == TexturePixelDataType::UnsignedInt5999Rev) {
if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for the given type"));
return false;
}
}
if (internalFormat == TextureInternalFormat::DepthComponent || Bool ValidateTextureInternalFormat(TextureInternalFormat format) {
internalFormat == TextureInternalFormat::DepthComponent16 || if (format == TextureInternalFormat::Unknown) {
internalFormat == TextureInternalFormat::DepthComponent24 || MG_State::pGLContext->RecordError(
internalFormat == TextureInternalFormat::DepthComponent32F) { ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormat",
if (format != TextureInputFormat::DepthComponent) { "Invalid texture sized internal format"));
MG_State::pGLContext->RecordError( return false;
ErrorCode::InvalidOperation, }
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", return true;
"ValidateTextureInternalFormatCompatibleWithInput", }
"Invalid format for depth component internal format"));
return false;
}
}
if (format == TextureInputFormat::DepthComponent && Bool ValidateTextureBorderNumber(Int border) {
(internalFormat != TextureInternalFormat::DepthComponent && if (border != 0) {
internalFormat != TextureInternalFormat::DepthComponent16 && MG_State::pGLContext->RecordError(
internalFormat != TextureInternalFormat::DepthComponent24 && ErrorCode::InvalidValue,
internalFormat != TextureInternalFormat::DepthComponent32F && MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureBorderNumber", "Border must be zero"));
internalFormat != TextureInternalFormat::DepthComponent32 // workaround for Minecraft 1.21.5+ return false;
)) { }
return true;
}
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
TextureInternalFormat internalFormat,
TexturePixelDataType type) {
if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev ||
type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev ||
type == TexturePixelDataType::UnsignedInt101111Rev) {
if (format != TextureInputFormat::RGB) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
"Invalid internal format for depth component format")); "Invalid format for the given type"));
return false; return false;
} }
return true;
} }
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level) { if (type == TexturePixelDataType::UnsignedShort4444 || type == TexturePixelDataType::UnsignedShort4444Rev ||
if (target == TextureUploadTarget::TextureRectangle || type == TexturePixelDataType::UnsignedShort5551 || type == TexturePixelDataType::UnsignedShort1555Rev ||
target == TextureUploadTarget::ProxyTextureRectangle) { type == TexturePixelDataType::UnsignedInt8888 || type == TexturePixelDataType::UnsignedInt8888Rev ||
if (level != 0) { type == TexturePixelDataType::UnsignedInt1010102 || type == TexturePixelDataType::UnsignedInt2101010Rev ||
MG_State::pGLContext->RecordError( type == TexturePixelDataType::UnsignedInt5999Rev) {
ErrorCode::InvalidValue, if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) {
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureLevelWithUploadTarget",
"Level must be zero for rectangle textures"));
return false;
}
}
return true;
}
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject) {
if (!textureObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureObject", "Texture object is null")); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
"Invalid format for the given type"));
return false; return false;
} }
return true;
} }
Bool ValidateTextureTargetUniformity(SharedPtr<MG_State::GLState::ITextureObject> textureObject, if (internalFormat == TextureInternalFormat::DepthComponent ||
TextureTarget target) { internalFormat == TextureInternalFormat::DepthComponent16 ||
if (!textureObject) return true; // should be created later internalFormat == TextureInternalFormat::DepthComponent24 ||
TextureTarget prevTarget = textureObject->GetTarget(); internalFormat == TextureInternalFormat::DepthComponent32F) {
if (prevTarget != target) { if (format != TextureInputFormat::DepthComponent) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureTargetUniformity", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
"Texture target does not match the previously created texture")); "Invalid format for depth component internal format"));
return false; return false;
} }
return true;
} }
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset, if (format == TextureInputFormat::DepthComponent &&
Int width, Int yoffset, Int height, Int zoffset, Int depth) { (internalFormat != TextureInternalFormat::DepthComponent &&
auto baseSize = textureObject->GetBaseSize(); internalFormat != TextureInternalFormat::DepthComponent16 &&
if (xoffset < 0 || (xoffset + width) > baseSize.x()) { internalFormat != TextureInternalFormat::DepthComponent24 &&
MG_State::pGLContext->RecordError( internalFormat != TextureInternalFormat::DepthComponent32F &&
ErrorCode::InvalidValue, internalFormat != TextureInternalFormat::DepthComponent32 // workaround for Minecraft 1.21.5+
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets", )) {
"xoffset must be non-negative and (xoffset + width) must not exceed " MG_State::pGLContext->RecordError(
"the texture width.")); ErrorCode::InvalidOperation,
return false; MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput",
} "Invalid internal format for depth component format"));
if (baseSize.y() == 0) return true; return false;
if (yoffset < 0 || (yoffset + height) > baseSize.y()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets",
"yoffset must be non-negative and (yoffset + height) must not exceed "
"the texture height."));
return false;
}
if (baseSize.z() == 0) return true;
if (zoffset < 0 || (zoffset + depth) > baseSize.z()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets",
"zoffset must be non-negative and (zoffset + depth) must not exceed "
"the texture depth."));
return false;
}
return true;
} }
return true;
}
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2) { Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level) {
auto unsizedFormat1 = MG_Util::ConvertInternalFormatToUnsized(format1); if (target == TextureUploadTarget::TextureRectangle || target == TextureUploadTarget::ProxyTextureRectangle) {
auto unsizedFormat2 = MG_Util::ConvertInternalFormatToUnsized(format2); if (level != 0) {
if (unsizedFormat1 != unsizedFormat2) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>( MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureLevelWithUploadTarget",
std::format("MG_Impl/GLImpl", "ValidateBaseInternalFormatMatch", "Level must be zero for rectangle textures"));
"The base internal format of the two formats do not match ({} vs. {})",
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat1).c_str(),
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat2).c_str())));
return false; return false;
} }
return true; }
} // namespace TextureImpl return true;
}
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject) {
if (!textureObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureObject", "Texture object is null"));
return false;
}
return true;
}
Bool ValidateTextureTargetUniformity(SharedPtr<MG_State::GLState::ITextureObject> textureObject,
TextureTarget target) {
if (!textureObject) return true; // should be created later
TextureTarget prevTarget = textureObject->GetTarget();
if (prevTarget != target) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureTargetUniformity",
"Texture target does not match the previously created texture"));
return false;
}
return true;
}
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset,
Int width, Int yoffset, Int height, Int zoffset, Int depth) {
auto baseSize = textureObject->GetBaseSize();
if (xoffset < 0 || (xoffset + width) > baseSize.x()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets",
"xoffset must be non-negative and (xoffset + width) must not exceed "
"the texture width."));
return false;
}
if (baseSize.y() == 0) return true;
if (yoffset < 0 || (yoffset + height) > baseSize.y()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets",
"yoffset must be non-negative and (yoffset + height) must not exceed "
"the texture height."));
return false;
}
if (baseSize.z() == 0) return true;
if (zoffset < 0 || (zoffset + depth) > baseSize.z()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateTextureSubImageOffsets",
"zoffset must be non-negative and (zoffset + depth) must not exceed "
"the texture depth."));
return false;
}
return true;
}
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2) {
auto unsizedFormat1 = MG_Util::ConvertInternalFormatToUnsized(format1);
auto unsizedFormat2 = MG_Util::ConvertInternalFormatToUnsized(format2);
if (unsizedFormat1 != unsizedFormat2) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
std::format("MG_Impl/GLImpl", "ValidateBaseInternalFormatMatch",
"The base internal format of the two formats do not match ({} vs. {})",
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat1).c_str(),
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat2).c_str())));
return false;
}
return true;
} // namespace TextureImpl } // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl::TextureImpl
+22 -24
View File
@@ -12,27 +12,25 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h> #include <MG_State/GLState/TextureState/TextureObject.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::TextureImpl {
namespace TextureImpl { Bool ValidateTextureTarget(TextureTarget target);
Bool ValidateTextureTarget(TextureTarget target); Bool ValidateTextureUploadTarget(TextureUploadTarget textureUploadTarget);
Bool ValidateTextureUploadTarget(TextureUploadTarget textureUploadTarget); Bool ValidateTextureName(Uint texture, Bool allowZero = false);
Bool ValidateTextureName(Uint texture, Bool allowZero = false); Bool ValidateTextureInputFormat(TextureInputFormat format);
Bool ValidateTextureInputFormat(TextureInputFormat format); Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType);
Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType); Bool ValidateTextureLevelNumber(Int level);
Bool ValidateTextureLevelNumber(Int level); Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height);
Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height); Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth);
Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth); Bool ValidateTextureInternalFormat(TextureInternalFormat format);
Bool ValidateTextureInternalFormat(TextureInternalFormat format); Bool ValidateTextureBorderNumber(Int border);
Bool ValidateTextureBorderNumber(Int border); Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat,
TextureInternalFormat internalFormat, TexturePixelDataType type);
TexturePixelDataType type); Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level);
Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level); Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject);
Bool ValidateTextureObject(SharedPtr<MG_State::GLState::ITextureObject> textureObject); Bool ValidateTextureTargetUniformity(SharedPtr<MG_State::GLState::ITextureObject> textureObject,
Bool ValidateTextureTargetUniformity(SharedPtr<MG_State::GLState::ITextureObject> textureObject, TextureTarget target);
TextureTarget target); Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset,
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset, Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0);
Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0); Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2);
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2); } // namespace MobileGL::MG_Impl::GLImpl::TextureImpl
} // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl
@@ -12,222 +12,216 @@
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToMG/DataTypeConverter.h> #include <MG_Util/Converters/GLToMG/DataTypeConverter.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { void DisableVertexAttribArray_State(GLuint index) {
void DisableVertexAttribArray_State(GLuint index) { if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray(); auto& vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) { if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl",
"EnableVertexAttribArray_State", "EnableVertexAttribArray_State",
"No vertex array object is bound.")); "No vertex array object is bound."));
return; return;
}
vao->DisableAttribute(index);
} }
void EnableVertexAttribArray_State(GLuint index) { vao->DisableAttribute(index);
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; }
auto vao = MG_State::pGLContext->GetBoundVertexArray(); void EnableVertexAttribArray_State(GLuint index) {
if (!vao) { if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"EnableVertexAttribArray_State",
"No vertex array object is bound."));
return;
}
vao->EnableAttribute(index); auto& vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl",
"EnableVertexAttribArray_State",
"No vertex array object is bound."));
return;
} }
// TODO: implement GL_BGRA support vao->EnableAttribute(index);
void VertexAttribIPointer_State(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) { }
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
DataType dataType = MG_Util::ConvertGLEnumToDataType(type); // TODO: implement GL_BGRA support
if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return; void VertexAttribIPointer_State(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
auto vao = MG_State::pGLContext->GetBoundVertexArray(); DataType dataType = MG_Util::ConvertGLEnumToDataType(type);
if (!vao) { if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return;
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribPointer_State",
"No vertex array object is bound."));
return;
}
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex); auto& vao = MG_State::pGLContext->GetBoundVertexArray();
auto vbo = vboSlot.GetBoundObject(); if (!vao) {
if (!vbo) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
ErrorCode::InvalidOperation, "No vertex array object is bound."));
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State", return;
"No buffer is bound to GL_ARRAY_BUFFER."));
return;
}
SizeT offset = reinterpret_cast<SizeT>(pointer);
vao->SetAttributeFormat(index, size, dataType, false, stride, offset, true);
vao->BindAttributeBuffer(index, vbo);
} }
// TODO: implement GL_BGRA support auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
void VertexAttribPointer_State(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, auto& vbo = vboSlot.GetBoundObject();
const void* pointer) { if (!vbo) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
DataType dataType = MG_Util::ConvertGLEnumToDataType(type); "No buffer is bound to GL_ARRAY_BUFFER."));
if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return; return;
auto vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribPointer_State",
"No vertex array object is bound."));
return;
}
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
auto vbo = vboSlot.GetBoundObject();
if (!vbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
"No buffer is bound to GL_ARRAY_BUFFER."));
return;
}
SizeT offset = reinterpret_cast<SizeT>(pointer);
vao->SetAttributeFormat(index, size, dataType, normalized, stride, offset, false);
vao->BindAttributeBuffer(index, vbo);
} }
void BindVertexArray_State(GLuint array) { auto offset = reinterpret_cast<SizeT>(pointer);
if (array == 0) {
vao->SetAttributeFormat(index, size, dataType, false, stride, offset, true);
vao->BindAttributeBuffer(index, vbo);
}
// TODO: implement GL_BGRA support
void VertexAttribPointer_State(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
const void* pointer) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
DataType dataType = MG_Util::ConvertGLEnumToDataType(type);
if (!VertexArrayImpl::ValidateVertexAttribPointerParams(index, size, dataType, stride)) return;
auto& vao = MG_State::pGLContext->GetBoundVertexArray();
if (!vao) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
"No vertex array object is bound."));
return;
}
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
auto& vbo = vboSlot.GetBoundObject();
if (!vbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
"No buffer is bound to GL_ARRAY_BUFFER."));
return;
}
SizeT offset = reinterpret_cast<SizeT>(pointer);
vao->SetAttributeFormat(index, size, dataType, normalized, stride, offset, false);
vao->BindAttributeBuffer(index, vbo);
}
void BindVertexArray_State(GLuint array) {
if (array == 0) {
MG_State::pGLContext->BindVertexArray(0);
return;
}
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return;
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
MG_State::pGLContext->CreateVertexArrayObject(array);
}
MG_State::pGLContext->BindVertexArray(array);
}
void DeleteVertexArrays_State(GLsizei n, const GLuint* arrays) {
if (n < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteVertexArrays_State", "n must be non-negative."));
return;
}
for (GLsizei i = 0; i < n; ++i) {
GLuint vao = arrays[i];
if (vao == 0) continue;
if (!VertexArrayImpl::ValidateVertexArrayName(vao)) continue;
if (MG_State::pGLContext->GetBoundVertexArray() &&
MG_State::pGLContext->GetBoundVertexArray() == MG_State::pGLContext->GetVertexArrayObject(vao)) {
MG_State::pGLContext->BindVertexArray(0); MG_State::pGLContext->BindVertexArray(0);
return;
} }
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return; MG_State::pGLContext->MarkVertexArrayForDeletion(vao);
}
}
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) { void GenVertexArrays_State(GLsizei n, GLuint* arrays) {
MG_State::pGLContext->CreateVertexArrayObject(array); if (n < 0) {
} MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MG_State::pGLContext->BindVertexArray(array); MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "GenVertexArrays_State", "n must be non-negative."));
return;
} }
void DeleteVertexArrays_State(GLsizei n, const GLuint* arrays) { static thread_local Vector<Uint> vaos;
if (n < 0) { MG_State::pGLContext->GenVertexArrayNames(n, vaos);
MG_State::pGLContext->RecordError( Memcpy(arrays, vaos.data(), n * sizeof(GLuint));
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteVertexArrays_State", }
"n must be non-negative."));
return;
}
for (GLsizei i = 0; i < n; ++i) { GLboolean IsVertexArray_State(GLuint array) {
GLuint vao = arrays[i]; if (array == 0) {
if (vao == 0) continue; MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
"Vertex array name 0 is not supported."));
return GL_FALSE;
}
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return GL_FALSE;
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
std::format("Vertex array object {} does not exist.", array)));
return GL_FALSE;
}
return GL_TRUE;
}
if (!VertexArrayImpl::ValidateVertexArrayName(vao)) continue; void VertexAttribDivisor_State(GLuint index, GLuint divisor) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
if (MG_State::pGLContext->GetBoundVertexArray() && auto& vao = MG_State::pGLContext->GetBoundVertexArray();
MG_State::pGLContext->GetBoundVertexArray() == MG_State::pGLContext->GetVertexArrayObject(vao)) { if (!vao) {
MG_State::pGLContext->BindVertexArray(0); MG_State::pGLContext->RecordError(
} ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribDivisor_State",
"No vertex array object is bound."));
MG_State::pGLContext->MarkVertexArrayForDeletion(vao); return;
}
} }
void GenVertexArrays_State(GLsizei n, GLuint* arrays) { vao->SetAttributeDivisor(index, divisor);
if (n < 0) { }
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenVertexArrays_State", "n must be non-negative."));
return;
}
auto vaoNames = MG_State::pGLContext->GenVertexArrayNames(n); /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
Copy(vaoNames.data(), arrays, vaoNames.size()); void VertexAttribDivisor(GLuint index, GLuint divisor) {
} VertexAttribDivisor_State(index, divisor);
}
GLboolean IsVertexArray_State(GLuint array) { GLboolean IsVertexArray(GLuint array) {
if (array == 0) { return IsVertexArray_State(array);
MG_State::pGLContext->RecordError( }
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
"Vertex array name 0 is not supported."));
return GL_FALSE;
}
if (!VertexArrayImpl::ValidateVertexArrayName(array)) return GL_FALSE;
if (!MG_State::pGLContext->ValidateVertexArrayObject(array)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsVertexArray_State",
std::format("Vertex array object {} does not exist.", array)));
return GL_FALSE;
}
return GL_TRUE;
}
void VertexAttribDivisor_State(GLuint index, GLuint divisor) { void DisableVertexAttribArray(GLuint index) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; DisableVertexAttribArray_State(index);
}
auto vao = MG_State::pGLContext->GetBoundVertexArray(); void EnableVertexAttribArray(GLuint index) {
if (!vao) { EnableVertexAttribArray_State(index);
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, }
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl",
"VertexAttribDivisor_State",
"No vertex array object is bound."));
return;
}
vao->SetAttributeDivisor(index, divisor); void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) {
} VertexAttribIPointer_State(index, size, type, stride, pointer);
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
void VertexAttribDivisor(GLuint index, GLuint divisor) { const void* pointer) {
VertexAttribDivisor_State(index, divisor); VertexAttribPointer_State(index, size, type, normalized, stride, pointer);
} }
GLboolean IsVertexArray(GLuint array) { void BindVertexArray(GLuint array) {
return IsVertexArray_State(array); BindVertexArray_State(array);
} }
void DisableVertexAttribArray(GLuint index) { void DeleteVertexArrays(GLsizei n, const GLuint* arrays) {
DisableVertexAttribArray_State(index); DeleteVertexArrays_State(n, arrays);
} }
void EnableVertexAttribArray(GLuint index) { void GenVertexArrays(GLsizei n, GLuint* arrays) {
EnableVertexAttribArray_State(index); GenVertexArrays_State(n, arrays);
} }
} // namespace MobileGL::MG_Impl::GLImpl
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) {
VertexAttribIPointer_State(index, size, type, stride, pointer);
}
void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
const void* pointer) {
VertexAttribPointer_State(index, size, type, normalized, stride, pointer);
}
void BindVertexArray(GLuint array) {
BindVertexArray_State(array);
}
void DeleteVertexArrays(GLsizei n, const GLuint* arrays) {
DeleteVertexArrays_State(n, arrays);
}
void GenVertexArrays(GLsizei n, GLuint* arrays) {
GenVertexArrays_State(n, arrays);
}
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
@@ -9,18 +9,16 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl::GLImpl {
namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ void VertexAttribDivisor(GLuint index, GLuint divisor);
void VertexAttribDivisor(GLuint index, GLuint divisor); GLboolean IsVertexArray(GLuint array);
GLboolean IsVertexArray(GLuint array); void DisableVertexAttribArray(GLuint index);
void DisableVertexAttribArray(GLuint index); void EnableVertexAttribArray(GLuint index);
void EnableVertexAttribArray(GLuint index); void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
const void* pointer); void BindVertexArray(GLuint array);
void BindVertexArray(GLuint array); void DeleteVertexArrays(GLsizei n, const GLuint* arrays);
void DeleteVertexArrays(GLsizei n, const GLuint* arrays); void GenVertexArrays(GLsizei n, GLuint* arrays);
void GenVertexArrays(GLsizei n, GLuint* arrays); } // namespace MobileGL::MG_Impl::GLImpl
} // namespace MG_Impl::GLImpl
} // namespace MobileGL
@@ -12,74 +12,71 @@
#include <MG_Util/Converters/MGToGL/DataTypeConverter.h> #include <MG_Util/Converters/MGToGL/DataTypeConverter.h>
#include <MG_Util/Converters/MGToStr/DataTypeConverter.h> #include <MG_Util/Converters/MGToStr/DataTypeConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl {
namespace VertexArrayImpl { Bool ValidateVertexArrayName(Uint index) {
Bool isValid = MG_State::pGLContext->ValidateVertexArrayName(index);
if (!isValid) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayName",
std::format("Vertex array name {} is not valid.", index)));
return false;
}
return true;
}
Bool ValidateVertexArrayName(Uint index) { Bool ValidateVertexArrayObject(Uint index) {
Bool isValid = MG_State::pGLContext->ValidateVertexArrayName(index); if (!MG_State::pGLContext->ValidateVertexArrayObject(index)) {
if (!isValid) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation,
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayObject",
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayName", std::format("Vertex array object {} does not exist.", index)));
std::format("Vertex array name {} is not valid.", index))); return false;
return false; }
} return true;
return true; }
Bool ValidateVertexAttributeIndex(Uint index) {
if (index >= MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "ValidateVertexAttributeIndex",
std::format("Attribute index {} exceeds maximum of {}.", index,
MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS - 1)));
return false;
}
return true;
}
Bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride) {
if (size < 1 || size > 4) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Invalid size {} for attribute {}. Must be 1-4.", size, index)));
return false;
} }
Bool ValidateVertexArrayObject(Uint index) { if (type == DataType::Unknown) {
if (!MG_State::pGLContext->ValidateVertexArrayObject(index)) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum,
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>(
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexArrayObject", "MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Vertex array object {} does not exist.", index))); std::format("Invalid type {} for attribute {}.", MG_Util::ConvertDataTypeToString(type), index)));
return false; return false;
}
return true;
} }
Bool ValidateVertexAttributeIndex(Uint index) { if (stride < 0) {
if (index >= MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS) { MG_State::pGLContext->RecordError(
MG_State::pGLContext->RecordError( ErrorCode::InvalidValue,
ErrorCode::InvalidValue, MakeUnique<GenericErrorInfo>(
MakeShared<GenericErrorInfo>( "MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
"MG_Impl/GLImpl", "ValidateVertexAttributeIndex", std::format("Negative stride {} is not allowed for attribute {}.", stride, index)));
std::format("Attribute index {} exceeds maximum of {}.", index, return false;
MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS - 1)));
return false;
}
return true;
} }
Bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride) { return true;
if (size < 1 || size > 4) { }
MG_State::pGLContext->RecordError( } // namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Invalid size {} for attribute {}. Must be 1-4.", size, index)));
return false;
}
if (type == DataType::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Invalid type {} for attribute {}.",
MG_Util::ConvertDataTypeToString(type).c_str(), index)));
return false;
}
if (stride < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "ValidateVertexAttribPointerParams",
std::format("Negative stride {} is not allowed for attribute {}.", stride, index)));
return false;
}
return true;
}
} // namespace VertexArrayImpl
} // namespace MobileGL::MG_Impl::GLImpl
@@ -10,11 +10,9 @@
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/VertexArrayState/VertexArrayObject.h> #include <MG_State/GLState/VertexArrayState/VertexArrayObject.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl {
namespace VertexArrayImpl { Bool ValidateVertexArrayName(Uint index);
Bool ValidateVertexArrayName(Uint index); Bool ValidateVertexArrayObject(Uint index);
Bool ValidateVertexArrayObject(Uint index); Bool ValidateVertexAttributeIndex(Uint index);
Bool ValidateVertexAttributeIndex(Uint index); Bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride);
Bool ValidateVertexAttribPointerParams(Uint index, SizeT size, DataType type, Int stride); } // namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl
} // namespace VertexArrayImpl
} // namespace MobileGL::MG_Impl::GLImpl
+4 -6
View File
@@ -10,9 +10,7 @@
#include <Includes.h> #include <Includes.h>
#include "MG_Impl/GetProcAddress.h" #include "MG_Impl/GetProcAddress.h"
namespace MG_Impl { namespace MG_Impl::GLXImpl {
namespace GLXImpl { void* GetProcAddress(const char* name);
void* GetProcAddress(const char* name); void* GetProcAddressARB(const char* name);
void* GetProcAddressARB(const char* name); } // namespace MG_Impl::GLXImpl
} // namespace GLXImpl
} // namespace MG_Impl
File diff suppressed because it is too large Load Diff
+3 -5
View File
@@ -9,8 +9,6 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL::MG_Impl {
namespace MG_Impl { void* GetProcAddress(const char* name);
void* GetProcAddress(const char* name); } // namespace MobileGL::MG_Impl
} // namespace MG_Impl
} // namespace MobileGL
+6 -4
View File
@@ -18,25 +18,27 @@
namespace MobileGL::MG_Impl { namespace MobileGL::MG_Impl {
void Init() { void Init() {
MGLOG_D("Initializing MobileGL Implementation..."); MGLOG_D("Initializing MobileGL Implementation...");
GLImpl::TextureImpl::pProxyTextureManager = new GLImpl::TextureImpl::ProxyTextureManager(); GLImpl::TextureImpl::pProxyTextureManager = MakeUnique<GLImpl::TextureImpl::ProxyTextureManager>();
// TODO: get real info in EGL // TODO: get real info in EGL
auto fbo0 = MG_State::pGLContext->CreateFramebufferObject(0); auto& fbo0 = MG_State::pGLContext->CreateFramebufferObject(0);
auto colorTex = MakeShared<MG_State::GLState::TextureObject2D>(0); auto colorTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
colorTex->SetInternalFormat(TextureInternalFormat::RGBA8); colorTex->SetInternalFormat(TextureInternalFormat::RGBA8);
colorTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0}); colorTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0});
// colorTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
auto depthTex = MakeShared<MG_State::GLState::TextureObject2D>(0); auto depthTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
depthTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8); depthTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0}); depthTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0});
// depthTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
auto stencilTex = MakeShared<MG_State::GLState::TextureObject2D>(0); auto stencilTex = MakeShared<MG_State::GLState::TextureObject2D>(0);
stencilTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8); stencilTex->SetInternalFormat(TextureInternalFormat::Depth32FStencil8);
stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0}); stencilTex->AllocateStorage(TextureUploadTarget::Texture2D, 0, {{512, 512, 1}, 0});
// stencilTex->SetMipmapLevel({{512, 512, 1}, 0, false, 0, {nullptr, 0}});
fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex); fbo0->AttachTexture(FramebufferAttachmentType::Color0, colorTex);
fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex); fbo0->AttachTexture(FramebufferAttachmentType::Depth, depthTex);
fbo0->AttachTexture(FramebufferAttachmentType::Stencil, stencilTex); fbo0->AttachTexture(FramebufferAttachmentType::Stencil, stencilTex);
GLImpl::FramebufferImpl::pDefaultFramebufferInfo = GLImpl::FramebufferImpl::pDefaultFramebufferInfo =
new GLImpl::FramebufferImpl::DefaultFramebufferInfo(fbo0, colorTex, depthTex, stencilTex); MakeUnique<GLImpl::FramebufferImpl::DefaultFramebufferInfo>(fbo0, colorTex, depthTex, stencilTex);
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).Bind(fbo0); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).Bind(fbo0);
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).Bind(fbo0); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).Bind(fbo0);
} }
File diff suppressed because it is too large Load Diff
+258
View File
@@ -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 UniquePtr<EGLState::EGLContext> pEGLContext;
} // namespace MG_State
} // namespace MobileGL
@@ -7,210 +7,203 @@
// End of Source File Header // End of Source File Header
#include "BufferObject.h" #include "BufferObject.h"
#include "MG_Util/Types.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { BufferObject::BufferObject(Uint externalIndex)
namespace GLState { : m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
BufferObject::BufferObject(Uint externalIndex) m_mappingAccess(BufferMappingAccessBit::Null),
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false), m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}),
m_mappingAccess(BufferMappingAccessBit::Null), m_dataPtr(MakeShared<Data>()), m_ownsStagingData{} {
m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}), m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT);
m_dataPtr(MakeShared<Data>()) { }
m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT);
}
void BufferObject::Resize(SizeT size) { void BufferObject::Resize(SizeT size) {
m_size = size; m_size = size;
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
m_dataPtr->resize(size); m_dataPtr->resize(size);
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
}
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
MOBILEGL_ASSERT(atOffset + data.size <= m_size,
"UploadData out of bounds: atOffset (%zu) + data.size (%zu) > m_size (%zu)", atOffset,
data.size, m_size);
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
// This function may be called by `glBufferData`, but we still set the forbid bits above,
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
// The bits can fit the `glBufferSubData` semantics
// (though `glBufferSubData` calls `UploadSubData` instead).
}
void BufferObject::SetUsage(BufferUsage usage) {
m_usage = usage;
}
void BufferObject::ReleaseMemory() {
if (!m_isMapped) return;
if (m_mappingAccess & BufferMappingAccessBit::Write) { // if we wrote to the buffer
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
m_mappedRange.end - m_mappedRange.start);
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
m_change.Bits |= BufferChangeBits::DirtyBit; m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
} }
void BufferObject::UploadData(DataPtr data, SizeT atOffset) { m_stagingData.clear();
MOBILEGL_ASSERT(atOffset + data.size <= m_size, }
"UploadData out of bounds: atOffset (%zu) + data.size (%zu) > m_size (%zu)", atOffset,
data.size, m_size);
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
// This function may be called by `glBufferData`, but we still set the forbid bits above,
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
// The bits can fit the `glBufferSubData` semantics
// (though `glBufferSubData` calls `UploadSubData` instead).
}
void BufferObject::SetUsage(BufferUsage usage) { m_isMapped = false;
m_usage = usage; m_mappingAccess = BufferMappingAccessBit::Null;
} m_mappedRange = {0, 0};
m_ownsStagingData = false;
}
void BufferObject::ReleaseMemory() { void BufferObject::FlushMemoryRange(SizeT offset, SizeT length) {
if (!m_isMapped) return; MOBILEGL_ASSERT(m_isMapped, "Buffer must be mapped to flush memory range.");
MOBILEGL_ASSERT((m_mappingAccess & BufferMappingAccessBit::FlushExplicit),
"Buffer must be mapped with FlushExplicit access to flush memory range.");
MOBILEGL_ASSERT((m_mappingAccess & BufferMappingAccessBit::Write),
"Buffer must be mapped with Write access to flush memory range.");
if (m_mappingAccess & BufferMappingAccessBit::Write) { // if we wrote to the buffer SizeT start = m_mappedRange.start + offset;
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly SizeT end = start + length;
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(), MOBILEGL_ASSERT(end <= m_mappedRange.end, "Flush range out of bounds: mappedRange.end (%zu) < end (%zu)",
m_mappedRange.end - m_mappedRange.start); m_mappedRange.end, end);
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
m_stagingData.clear(); Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
m_change.DirtyRanges.Add({start, end});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload sub data while buffer is mapped.");
MOBILEGL_ASSERT(atOffset + data.size <= m_size,
"UploadSubData out of bounds: atOffset (%zu) + data.size (%zu) > m_size (%zu)", atOffset,
data.size, m_size);
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
m_change.Bits |= BufferChangeBits::DirtyBit;
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
}
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset, SizeT size) {
MOBILEGL_ASSERT(!m_isMapped, "Cannot copy data while buffer is mapped.");
MOBILEGL_ASSERT(!src->IsMapped(), "Cannot copy data from a buffer that is mapped.");
MOBILEGL_ASSERT(srcOffset + size <= src->GetSize(),
"Source buffer copy out of bounds: srcOffset (%zu) + size (%zu) > src->GetSize() (%zu)",
srcOffset, size, src->GetSize());
MOBILEGL_ASSERT(dstOffset + size <= m_size,
"Destination buffer copy out of bounds: dstOffset (%zu) + size (%zu) > m_size (%zu)", dstOffset,
size, m_size);
const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
m_change.DirtyRanges.Add({dstOffset, dstOffset + size});
m_change.Bits |= BufferChangeBits::DirtyBit;
}
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
if (markMapped) {
m_isMapped = true;
auto a = BufferMappingAccessBit::Coherent | BufferMappingAccessBit::Read;
m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) |
(write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null);
m_mappedRange = {0, m_size};
if (m_mappingAccess & BufferMappingAccessBit::Write) {
m_stagingData.resize(m_size);
m_ownsStagingData = true;
if (!(m_mappingAccess &
(BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer))) {
Memcpy(m_stagingData.data(), m_dataPtr->data(), m_size);
} }
m_isMapped = false; return m_stagingData.data();
m_mappingAccess = BufferMappingAccessBit::Null; }
m_mappedRange = {0, 0}; }
m_ownsStagingData = false;
return m_dataPtr->data();
}
void* BufferObject::AcquireMemoryRange(Range1D range, Flags<BufferMappingAccessBit> access) {
MOBILEGL_ASSERT(range.end <= m_size && range.start <= range.end,
"AcquireMemoryRange out of bounds: range (%zu, %zu) exceeds m_size (%zu)", range.start,
range.end, m_size);
m_isMapped = true;
m_mappingAccess = access;
m_mappedRange = range;
if (access & BufferMappingAccessBit::Write) {
m_stagingData.resize(range.end - range.start);
m_ownsStagingData = true;
if (!(access & (BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer))) {
Memcpy(m_stagingData.data(), m_dataPtr->data() + range.start, m_stagingData.size());
} }
void BufferObject::FlushMemoryRange(SizeT offset, SizeT length) { return m_stagingData.data();
MOBILEGL_ASSERT(m_isMapped, "Buffer must be mapped to flush memory range."); } else {
MOBILEGL_ASSERT((m_mappingAccess & BufferMappingAccessBit::FlushExplicit), m_ownsStagingData = false;
"Buffer must be mapped with FlushExplicit access to flush memory range."); return m_dataPtr->data() + range.start;
MOBILEGL_ASSERT((m_mappingAccess & BufferMappingAccessBit::Write), }
"Buffer must be mapped with Write access to flush memory range.");
SizeT start = m_mappedRange.start + offset; m_change.Bits |=
SizeT end = start + length; !(access & BufferMappingAccessBit::InvalidateBuffer || access & BufferMappingAccessBit::InvalidateRange)
MOBILEGL_ASSERT(end <= m_mappedRange.end, ? BufferChangeBits::ForbidInvalidationBit
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end); : BufferChangeBits::None;
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
? BufferChangeBits::ForbidUnsynchronizationBit
: BufferChangeBits::None;
}
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length); const SharedPtr<Data>& BufferObject::GetDataReadOnly() const {
m_change.DirtyRanges.Add({start, end}); return m_dataPtr;
m_change.Bits |= BufferChangeBits::DirtyBit; }
}
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) { void BufferObject::ClearDirty() {
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload sub data while buffer is mapped."); m_change.DirtyRanges.clear();
MOBILEGL_ASSERT(atOffset + data.size <= m_size, m_change.Bits = BufferChangeBits::None;
"UploadSubData out of bounds: atOffset (%zu) + data.size (%zu) > m_size (%zu)", }
atOffset, data.size, m_size);
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size); SizeT BufferObject::GetSize() const {
m_change.DirtyRanges.Add({atOffset, atOffset + data.size}); return m_size;
m_change.Bits |= BufferChangeBits::DirtyBit; }
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
}
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset, BufferUsage BufferObject::GetUsage() const {
SizeT size) { return m_usage;
MOBILEGL_ASSERT(!m_isMapped, "Cannot copy data while buffer is mapped."); }
MOBILEGL_ASSERT(!src->IsMapped(), "Cannot copy data from a buffer that is mapped.");
MOBILEGL_ASSERT(srcOffset + size <= src->GetSize(),
"Source buffer copy out of bounds: srcOffset (%zu) + size (%zu) > src->GetSize() (%zu)",
srcOffset, size, src->GetSize());
MOBILEGL_ASSERT(dstOffset + size <= m_size,
"Destination buffer copy out of bounds: dstOffset (%zu) + size (%zu) > m_size (%zu)",
dstOffset, size, m_size);
const Uint8* srcData = src->m_dataPtr->data() + srcOffset; const VecRange1D& BufferObject::GetDirtyRanges() const {
Memcpy(m_dataPtr->data() + dstOffset, srcData, size); return m_change.DirtyRanges;
m_change.DirtyRanges.Add({dstOffset, dstOffset + size}); }
m_change.Bits |= BufferChangeBits::DirtyBit;
}
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) { Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
if (markMapped) { return m_change.Bits;
m_isMapped = true; }
auto a = BufferMappingAccessBit::Coherent | BufferMappingAccessBit::Read;
m_mappingAccess = (read ? BufferMappingAccessBit::Read : BufferMappingAccessBit::Null) |
(write ? BufferMappingAccessBit::Write : BufferMappingAccessBit::Null);
m_mappedRange = {0, m_size};
if (m_mappingAccess & BufferMappingAccessBit::Write) { Bool BufferObject::IsMapped() const {
m_stagingData.resize(m_size); return m_isMapped;
m_ownsStagingData = true; }
if (!(m_mappingAccess & Range1D BufferObject::GetMappedRange() const {
(BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer))) { return m_isMapped ? m_mappedRange : Range1D{0, 0};
Memcpy(m_stagingData.data(), m_dataPtr->data(), m_size); }
}
return m_stagingData.data(); Flags<BufferMappingAccessBit> BufferObject::GetMappingAccess() const {
} return m_isMapped ? m_mappingAccess : BufferMappingAccessBit::Null;
} }
return m_dataPtr->data(); Uint BufferObject::GetExternalIndex() const {
} return m_externalIndex;
}
void* BufferObject::AcquireMemoryRange(Range1D range, Flags<BufferMappingAccessBit> access) { } // namespace MobileGL::MG_State::GLState
MOBILEGL_ASSERT(range.end <= m_size && range.start <= range.end,
"AcquireMemoryRange out of bounds: range (%zu, %zu) exceeds m_size (%zu)", range.start,
range.end, m_size);
m_isMapped = true;
m_mappingAccess = access;
m_mappedRange = range;
if (access & BufferMappingAccessBit::Write) {
m_stagingData.resize(range.end - range.start);
m_ownsStagingData = true;
if (!(access &
(BufferMappingAccessBit::InvalidateRange | BufferMappingAccessBit::InvalidateBuffer))) {
Memcpy(m_stagingData.data(), m_dataPtr->data() + range.start, m_stagingData.size());
}
return m_stagingData.data();
} else {
m_ownsStagingData = false;
return m_dataPtr->data() + range.start;
}
m_change.Bits |= !(access & BufferMappingAccessBit::InvalidateBuffer ||
access & BufferMappingAccessBit::InvalidateRange)
? BufferChangeBits::ForbidInvalidationBit
: BufferChangeBits::None;
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
? BufferChangeBits::ForbidUnsynchronizationBit
: BufferChangeBits::None;
}
const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
return m_dataPtr;
}
void BufferObject::ClearDirty() {
m_change.DirtyRanges.clear();
m_change.Bits = BufferChangeBits::None;
}
SizeT BufferObject::GetSize() const {
return m_size;
}
BufferUsage BufferObject::GetUsage() const {
return m_usage;
}
const VecRange1D& BufferObject::GetDirtyRanges() const {
return m_change.DirtyRanges;
}
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
return m_change.Bits;
}
Bool BufferObject::IsMapped() const {
return m_isMapped;
}
Range1D BufferObject::GetMappedRange() const {
return m_isMapped ? m_mappedRange : Range1D{0, 0};
}
Flags<BufferMappingAccessBit> BufferObject::GetMappingAccess() const {
return m_isMapped ? m_mappingAccess : BufferMappingAccessBit::Null;
}
Uint BufferObject::GetExternalIndex() const {
return m_externalIndex;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -7,7 +7,6 @@
// End of Source File Header // End of Source File Header
#pragma once #pragma once
#include "MG_Util/Types.h"
#include <Includes.h> #include <Includes.h>
#include <MG_Util/Math/VectorTypes.h> #include <MG_Util/Math/VectorTypes.h>
@@ -73,47 +72,45 @@ namespace MobileGL {
VecRange1D DirtyRanges; VecRange1D DirtyRanges;
}; };
namespace MG_State { namespace MG_State::GLState {
namespace GLState { class BufferObject {
class BufferObject { public:
public: using TargetEnum = BufferTarget;
using TargetEnum = BufferTarget;
BufferObject(Uint externalIndex); BufferObject(Uint externalIndex);
void Resize(SizeT size); void Resize(SizeT size);
void UploadData(DataPtr data, SizeT atOffset); void UploadData(DataPtr data, SizeT atOffset);
void SetUsage(BufferUsage usage); void SetUsage(BufferUsage usage);
void* AcquireMemory(Bool markMapped, Bool read, Bool write); void* AcquireMemory(Bool markMapped, Bool read, Bool write);
void* AcquireMemoryRange(Range1D range, Flags<BufferMappingAccessBit> access); void* AcquireMemoryRange(Range1D range, Flags<BufferMappingAccessBit> access);
void ReleaseMemory(); void ReleaseMemory();
void FlushMemoryRange(SizeT offset, SizeT length); void FlushMemoryRange(SizeT offset, SizeT length);
void UploadSubData(DataPtr data, SizeT atOffset); void UploadSubData(DataPtr data, SizeT atOffset);
void CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset, SizeT size); void CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset, SizeT size);
void ClearDirty(); void ClearDirty();
Bool IsMapped() const; Bool IsMapped() const;
SizeT GetSize() const; SizeT GetSize() const;
BufferUsage GetUsage() const; BufferUsage GetUsage() const;
Range1D GetMappedRange() const; Range1D GetMappedRange() const;
const SharedPtr<Data> GetDataReadOnly() const; const SharedPtr<Data>& GetDataReadOnly() const;
Flags<BufferMappingAccessBit> GetMappingAccess() const; Flags<BufferMappingAccessBit> GetMappingAccess() const;
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
const VecRange1D& GetDirtyRanges() const; const VecRange1D& GetDirtyRanges() const;
Flags<BufferChangeBits> GetChangeBits() const; Flags<BufferChangeBits> GetChangeBits() const;
private: private:
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
SizeT m_size = 0; SizeT m_size = 0;
BufferUsage m_usage = BufferUsage::StaticDraw; BufferUsage m_usage = BufferUsage::StaticDraw;
SharedPtr<Data> m_dataPtr; SharedPtr<Data> m_dataPtr;
Bool m_isMapped; Bool m_isMapped;
Flags<BufferMappingAccessBit> m_mappingAccess; Flags<BufferMappingAccessBit> m_mappingAccess;
BufferChange m_change; BufferChange m_change;
Range1D m_mappedRange; Range1D m_mappedRange;
Vector<Uint8> m_stagingData; Vector<Uint8> m_stagingData;
Bool m_ownsStagingData; Bool m_ownsStagingData;
}; };
} // namespace GLState } // namespace MG_State::GLState
} // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -8,78 +8,75 @@
#include "BufferState.h" #include "BufferState.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { BufferState::BufferState() : m_indexGenerator(1024, 1) {
namespace GLState { for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
BufferState::BufferState() : m_indexGenerator(1024, 1) { m_bindingSlots[i] = BindingSlot<BufferObject>(GlobalBufferTargets[i]);
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { }
m_bindingSlots[i] = BindingSlot<BufferObject>(GlobalBufferTargets[i]); }
}
}
SharedPtr<BufferObject> BufferState::GetBufferObject(Uint index) { const SharedPtr<BufferObject>& BufferState::GetBufferObject(Uint index) {
auto it = m_bufferObjects.find(index); auto it = m_bufferObjects.find(index);
if (it != m_bufferObjects.end()) { if (it != m_bufferObjects.end()) {
return it->second; return it->second;
} }
return nullptr; static SharedPtr<BufferObject> nullBufferObject = nullptr;
} return nullBufferObject;
}
Vector<Uint> BufferState::GenerateNames(Uint number) { void BufferState::GenerateNames(Uint number, Vector<Uint>& buffers) {
Vector<Uint> buffers(number); buffers.resize(number);
m_indexGenerator.Generate(number, buffers.data()); m_indexGenerator.Generate(number, buffers.data());
return buffers; }
}
SharedPtr<BufferObject> BufferState::CreateBufferObject(Uint index) { const SharedPtr<BufferObject>& BufferState::CreateBufferObject(Uint index) {
auto bufferObject = MakeShared<BufferObject>(index); auto& bufferObj = m_bufferObjects[index];
m_bufferObjects[index] = bufferObject; if (!bufferObj) {
return bufferObject; bufferObj = MakeShared<BufferObject>(index);
} }
return bufferObj;
}
BindingSlot<BufferObject>& BufferState::GetBindingSlot(BufferTarget target) { BindingSlot<BufferObject>& BufferState::GetBindingSlot(BufferTarget target) {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { for (auto& bindingSlot : m_bindingSlots) {
if (m_bindingSlots[i].GetTarget() == target) { if (bindingSlot.GetTarget() == target) {
return m_bindingSlots[i]; return bindingSlot;
}
}
MOBILEGL_ASSERT(false, "Invalid BufferTarget enum value: %d", static_cast<int>(target));
return m_bindingSlots[0];
}
void BufferState::MarkBufferObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) {
auto it = m_bufferObjects.find(index);
if (it != m_bufferObjects.end()) {
for (auto& bindingSlot : m_bindingSlots) {
if (bindingSlot.GetBoundObject() == it->second) {
bindingSlot.Bind(nullptr);
} }
} }
MOBILEGL_ASSERT(false, "Invalid BufferTarget enum value: %d", static_cast<int>(target)); m_bufferObjects.erase(it);
return m_bindingSlots[0];
} }
m_indexGenerator.Delete(index);
}
}
void BufferState::MarkBufferObjectForDeletion(Uint index) { Bool BufferState::ValidateName(Uint index) const {
if (m_indexGenerator.IsValid(index)) { return m_indexGenerator.IsValid(index);
auto it = m_bufferObjects.find(index); }
if (it != m_bufferObjects.end()) {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
if (m_bindingSlots[i].GetBoundObject() == it->second) {
m_bindingSlots[i].Bind(nullptr);
}
}
m_bufferObjects.erase(it);
}
m_indexGenerator.Delete(index);
}
}
Bool BufferState::ValidateName(Uint index) const { Bool BufferState::ValidateBufferObject(Uint index) const {
return m_indexGenerator.IsValid(index); return m_bufferObjects.find(index) != m_bufferObjects.end();
} }
Bool BufferState::ValidateBufferObject(Uint index) const { BindingSlotRange1D<BufferObject>& BufferState::GetBindingPoint(BufferTarget target, Uint index) {
return m_bufferObjects.find(index) != m_bufferObjects.end(); for (SizeT i = 0; i < BufferBindPointTargets.size(); ++i) {
if (BufferBindPointTargets[i] == target) {
return m_bufferBindPointTargets[i][index];
} }
}
BindingSlotRange1D<BufferObject>& BufferState::GetBindingPoint(BufferTarget target, Uint index) { MOBILEGL_ASSERT(false, "Invalid BufferTarget enum value for binding point: %d", static_cast<int>(target));
for (SizeT i = 0; i < BufferBindPointTargets.size(); ++i) { return m_bufferBindPointTargets[0][index];
if (BufferBindPointTargets[i] == target) { }
return m_bufferBindPointTargets[i][index]; } // namespace MobileGL::MG_State::GLState
}
}
MOBILEGL_ASSERT(false, "Invalid BufferTarget enum value for binding point: %d",
static_cast<int>(target));
return m_bufferBindPointTargets[0][index];
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -11,46 +11,40 @@
#include <MG_Util/Miscellany/IndexGenerator.h> #include <MG_Util/Miscellany/IndexGenerator.h>
#include "BufferObject.h" #include "BufferObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { constexpr const auto GlobalBufferTargets =
namespace GLState { ToArray(BufferTarget::Vertex, BufferTarget::Uniform, BufferTarget::CopyRead, BufferTarget::CopyWrite,
constexpr const auto GlobalBufferTargets = BufferTarget::PixelPack, BufferTarget::PixelUnpack, BufferTarget::Query, BufferTarget::Texture,
ToArray(BufferTarget::Vertex, BufferTarget::Uniform, BufferTarget::CopyRead, BufferTarget::CopyWrite, BufferTarget::TransformFeedback, BufferTarget::AtomicCounter, BufferTarget::DispatchIndirect,
BufferTarget::PixelPack, BufferTarget::PixelUnpack, BufferTarget::Query, BufferTarget::Texture, BufferTarget::DrawIndirect, BufferTarget::ShaderStorage);
BufferTarget::TransformFeedback, BufferTarget::AtomicCounter, BufferTarget::DispatchIndirect, constexpr const auto BufferBindPointTargets = ToArray(BufferTarget::Uniform, BufferTarget::TransformFeedback,
BufferTarget::DrawIndirect, BufferTarget::ShaderStorage); BufferTarget::AtomicCounter, BufferTarget::ShaderStorage);
constexpr const auto BufferBindPointTargets =
ToArray(BufferTarget::Uniform, BufferTarget::TransformFeedback, BufferTarget::AtomicCounter,
BufferTarget::ShaderStorage);
class BufferState { class BufferState {
public: public:
BufferState(); BufferState();
SharedPtr<BufferObject> GetBufferObject(Uint index); const SharedPtr<BufferObject>& GetBufferObject(Uint index);
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& buffers);
SharedPtr<BufferObject> CreateBufferObject(Uint index); const SharedPtr<BufferObject>& CreateBufferObject(Uint index);
BindingSlot<BufferObject>& GetBindingSlot(BufferTarget target); BindingSlot<BufferObject>& GetBindingSlot(BufferTarget target);
// For glBindBufferBase / glBindBufferRange // For glBindBufferBase / glBindBufferRange
BindingSlotRange1D<BufferObject>& GetBindingPoint(BufferTarget target, Uint index); BindingSlotRange1D<BufferObject>& GetBindingPoint(BufferTarget target, Uint index);
constexpr SizeT GetBindingPointCount(const BufferTarget target) const { constexpr SizeT GetBindingPointCount(const BufferTarget target) const {
auto it = std::find(BufferBindPointTargets.begin(), BufferBindPointTargets.end(), target); auto it = std::find(BufferBindPointTargets.begin(), BufferBindPointTargets.end(), target);
auto index = std::distance(BufferBindPointTargets.begin(), it); auto index = std::distance(BufferBindPointTargets.begin(), it);
return m_bufferBindPointTargets[index].size(); return m_bufferBindPointTargets[index].size();
} }
void MarkBufferObjectForDeletion(Uint index); void MarkBufferObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateBufferObject(Uint index) const; Bool ValidateBufferObject(Uint index) const;
private: private:
UnorderedMap<Uint, SharedPtr<BufferObject>> m_bufferObjects; UnorderedMap<Uint, SharedPtr<BufferObject>> m_bufferObjects;
IndexGenerator<Uint> m_indexGenerator; IndexGenerator<Uint> m_indexGenerator;
Array<BindingSlot<BufferObject>, GlobalBufferTargets.size()> m_bindingSlots; Array<BindingSlot<BufferObject>, GlobalBufferTargets.size()> m_bindingSlots;
// TODO: query the count somewhere globally? // TODO: query the count somewhere globally?
// For glBindBufferBase / glBindBufferRange // For glBindBufferBase / glBindBufferRange
Array<Array<BindingSlotRange1D<BufferObject>, 16>, BufferBindPointTargets.size()> Array<Array<BindingSlotRange1D<BufferObject>, 16>, BufferBindPointTargets.size()> m_bufferBindPointTargets;
m_bufferBindPointTargets; };
}; } // namespace MobileGL::MG_State::GLState
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
+336 -334
View File
@@ -8,436 +8,438 @@
#include "Core.h" #include "Core.h"
#include "MG_State/GLState/RenderbufferState/RenderbufferObject.h" #include "MG_State/GLState/RenderbufferState/RenderbufferObject.h"
#include "MG_State/EGLState/Core.h"
namespace MobileGL { namespace MobileGL::MG_State {
namespace MG_State { void Init() {
void Init() { MGLOG_D("Initializing MobileGL State...");
MGLOG_D("Initializing MobileGL State..."); pGLContext = MakeUnique<GLState::GLContext>();
pGLContext = new MG_State::GLState::GLContext(); pEGLContext = MakeUnique<EGLState::EGLContext>();
}
namespace GLState {
// Error
void GLContext::RecordError(ErrorCode code, UniquePtr<ErrorInfo> info) {
m_errorState.RecordError(code, Move(info));
} }
namespace GLState { Bool GLContext::HasGLError() const {
// Error return m_errorState.HasGLError();
void GLContext::RecordError(ErrorCode code, SharedPtr<ErrorInfo> info) { }
m_errorState.RecordError(code, info);
Optional<const Error*> GLContext::PeekGLError() const {
return m_errorState.PeekGLError();
}
Optional<UniquePtr<Error>> GLContext::PopGLError() {
return Move(m_errorState.PopGLError());
}
Bool GLContext::HasNonGLError() const {
return m_errorState.HasNonGLError();
}
Optional<const Error*> GLContext::PeekNonGLError() const {
return m_errorState.PeekNonGLError();
}
Optional<UniquePtr<Error>> GLContext::PopNonGLError() {
return Move(m_errorState.PopNonGLError());
}
void GLContext::ClearErrors() {
m_errorState.Clear();
}
// Buffer
void GLContext::GenBufferNames(Uint number, Vector<Uint>& buffers) {
m_bufferState.GenerateNames(number, buffers);
}
const SharedPtr<BufferObject>& GLContext::GetBufferObject(Uint index) {
return m_bufferState.GetBufferObject(index);
}
BindingSlot<BufferObject>& GLContext::GetBufferBindingSlot(BufferTarget target) {
if (target == BufferTarget::Index) {
const auto& vao = m_vertexArrayState.GetBoundVertexArray();
MOBILEGL_ASSERT(vao != nullptr, "No VAO is currently bound when accessing index buffer binding slot.");
return vao->GetIndexBufferBindingSlot();
} }
Bool GLContext::HasGLError() const { return m_bufferState.GetBindingSlot(target);
return m_errorState.HasGLError(); }
}
Optional<const Error> GLContext::PeekGLError() const { BindingSlotRange1D<BufferObject>& GLContext::GetBufferBindingPoint(BufferTarget target, Uint index) {
return m_errorState.PeekGLError(); return m_bufferState.GetBindingPoint(target, index);
} }
Optional<Error> GLContext::PopGLError() { const SharedPtr<BufferObject>& GLContext::CreateBufferObject(Uint index) {
return m_errorState.PopGLError(); return m_bufferState.CreateBufferObject(index);
} }
Bool GLContext::HasNonGLError() const { void GLContext::MarkBufferObjectForDeletion(Uint index) {
return m_errorState.HasNonGLError(); if (ValidateBufferObject(index)) {
} auto bufferObject = m_bufferState.GetBufferObject(index);
auto& vaos = m_vertexArrayState.GetAllVertexArrays();
for (auto& vao : vaos) {
if (vao == nullptr) continue;
Optional<const Error> GLContext::PeekNonGLError() const { if (vao->GetIndexBufferBindingSlot().GetBoundObject() == bufferObject) {
return m_errorState.PeekNonGLError(); vao->GetIndexBufferBindingSlot().Bind(nullptr);
} }
for (SizeT j = 0; j < VertexArrayObject::MAX_VERTEX_ATTRIBS; ++j) {
Optional<Error> GLContext::PopNonGLError() { if (vao->GetAttribute(j).Buffer == bufferObject) {
return m_errorState.PopNonGLError(); vao->BindAttributeBuffer(j, nullptr);
}
void GLContext::ClearErrors() {
m_errorState.Clear();
}
// Buffer
Vector<Uint> GLContext::GenBufferNames(Uint number) {
return m_bufferState.GenerateNames(number);
}
SharedPtr<BufferObject> GLContext::GetBufferObject(Uint index) {
return m_bufferState.GetBufferObject(index);
}
BindingSlot<BufferObject>& GLContext::GetBufferBindingSlot(BufferTarget target) {
if (target == BufferTarget::Index) {
const auto& vao = m_vertexArrayState.GetBoundVertexArray();
MOBILEGL_ASSERT(vao != nullptr,
"No VAO is currently bound when accessing index buffer binding slot.");
return vao->GetIndexBufferBindingSlot();
}
return m_bufferState.GetBindingSlot(target);
}
BindingSlotRange1D<BufferObject>& GLContext::GetBufferBindingPoint(BufferTarget target, Uint index) {
return m_bufferState.GetBindingPoint(target, index);
}
SharedPtr<BufferObject> GLContext::CreateBufferObject(Uint index) {
return m_bufferState.CreateBufferObject(index);
}
void GLContext::MarkBufferObjectForDeletion(Uint index) {
if (ValidateBufferObject(index)) {
auto bufferObject = m_bufferState.GetBufferObject(index);
auto& vaos = m_vertexArrayState.GetAllVertexArrays();
for (SizeT i = 0; i < vaos.size(); ++i) {
auto vao = vaos[i];
if (vao == nullptr) continue;
if (vao->GetIndexBufferBindingSlot().GetBoundObject() == bufferObject) {
vao->GetIndexBufferBindingSlot().Bind(nullptr);
}
for (SizeT j = 0; j < VertexArrayObject::MAX_VERTEX_ATTRIBS; ++j) {
if (vao->GetAttribute(j).Buffer == bufferObject) {
vao->BindAttributeBuffer(j, nullptr);
}
} }
} }
} }
m_bufferState.MarkBufferObjectForDeletion(index);
} }
Bool GLContext::ValidateBufferName(Uint index) const { m_bufferState.MarkBufferObjectForDeletion(index);
return m_bufferState.ValidateName(index); }
}
Bool GLContext::ValidateBufferObject(Uint index) const { Bool GLContext::ValidateBufferName(Uint index) const {
return m_bufferState.ValidateBufferObject(index); return m_bufferState.ValidateName(index);
} }
// VertexArray Bool GLContext::ValidateBufferObject(Uint index) const {
Vector<Uint> GLContext::GenVertexArrayNames(Uint number) { return m_bufferState.ValidateBufferObject(index);
return m_vertexArrayState.GenerateNames(number); }
}
SharedPtr<VertexArrayObject> GLContext::GetVertexArrayObject(Uint index) { // VertexArray
return m_vertexArrayState.GetVertexArrayObject(index); void GLContext::GenVertexArrayNames(Uint number, Vector<Uint>& vertexArrays) {
} m_vertexArrayState.GenerateNames(number, vertexArrays);
}
void GLContext::BindVertexArray(Uint index) { const SharedPtr<VertexArrayObject>& GLContext::GetVertexArrayObject(Uint index) {
m_vertexArrayState.Bind(index); return m_vertexArrayState.GetVertexArrayObject(index);
} }
SharedPtr<VertexArrayObject> GLContext::CreateVertexArrayObject(Uint index) { void GLContext::BindVertexArray(Uint index) {
return m_vertexArrayState.CreateVertexArrayObject(index); m_vertexArrayState.Bind(index);
} }
void GLContext::MarkVertexArrayForDeletion(Uint index) { const SharedPtr<VertexArrayObject>& GLContext::CreateVertexArrayObject(Uint index) {
m_vertexArrayState.MarkVertexArrayForDeletion(index); return m_vertexArrayState.CreateVertexArrayObject(index);
} }
Bool GLContext::ValidateVertexArrayName(Uint index) const { void GLContext::MarkVertexArrayForDeletion(Uint index) {
return m_vertexArrayState.ValidateName(index); m_vertexArrayState.MarkVertexArrayForDeletion(index);
} }
Bool GLContext::ValidateVertexArrayObject(Uint index) const { Bool GLContext::ValidateVertexArrayName(Uint index) const {
return m_vertexArrayState.ValidateVertexArrayObject(index); return m_vertexArrayState.ValidateName(index);
} }
SharedPtr<VertexArrayObject> GLContext::GetBoundVertexArray() { Bool GLContext::ValidateVertexArrayObject(Uint index) const {
return m_vertexArrayState.GetBoundVertexArray(); return m_vertexArrayState.ValidateVertexArrayObject(index);
} }
// Texture const SharedPtr<VertexArrayObject>& GLContext::GetBoundVertexArray() {
Vector<Uint> GLContext::GenTextureNames(Uint number) { return m_vertexArrayState.GetBoundVertexArray();
return m_textureState.GenerateNames(number); }
}
SharedPtr<ITextureObject> GLContext::GetTextureObject(Uint index) { // Texture
return m_textureState.GetTextureObject(index); void GLContext::GenTextureNames(Uint number, Vector<Uint>& textures) {
} m_textureState.GenerateNames(number, textures);
}
SharedPtr<ITextureObject> GLContext::CreateTextureObject(Uint index, TextureTarget target) { const SharedPtr<ITextureObject>& GLContext::GetTextureObject(Uint index) {
return m_textureState.CreateTextureObject(index, target); return m_textureState.GetTextureObject(index);
} }
void GLContext::MarkTextureObjectForDeletion(Uint index) { const SharedPtr<ITextureObject>& GLContext::CreateTextureObject(Uint index, TextureTarget target) {
m_textureState.MarkTextureObjectForDeletion(index); return m_textureState.CreateTextureObject(index, target);
} }
TextureUnit& GLContext::GetTextureUnitObject(Int unit) { void GLContext::MarkTextureObjectForDeletion(Uint index) {
return m_textureState.GetUnitObject(unit); m_textureState.MarkTextureObjectForDeletion(index);
} }
Bool GLContext::ValidateTextureName(Uint index) const { TextureUnit& GLContext::GetTextureUnitObject(Int unit) {
return m_textureState.ValidateName(index); return m_textureState.GetUnitObject(unit);
} }
Bool GLContext::ValidateTextureObject(Uint index) const { Bool GLContext::ValidateTextureName(Uint index) const {
return m_textureState.ValidateTextureObject(index); return m_textureState.ValidateName(index);
} }
Int GLContext::GetActiveTextureUnit() const { Bool GLContext::ValidateTextureObject(Uint index) const {
return m_textureState.GetActiveTextureUnit(); return m_textureState.ValidateTextureObject(index);
} }
void GLContext::SetActiveTextureUnit(Int unit) { Int GLContext::GetActiveTextureUnit() const {
m_textureState.SetActiveTextureUnit(unit); return m_textureState.GetActiveTextureUnit();
} }
// Program void GLContext::SetActiveTextureUnit(Int unit) {
Uint GLContext::CreateProgram() { m_textureState.SetActiveTextureUnit(unit);
return m_programState.CreateProgram(); }
}
Uint GLContext::CreateShader(const ShaderStage stage) { // Program
return m_programState.CreateShader(stage); Uint GLContext::CreateProgram() {
} return m_programState.CreateProgram();
}
void GLContext::MarkProgramForDeletion(const Uint index) { Uint GLContext::CreateShader(const ShaderStage stage) {
return m_programState.MarkProgramObjectForDeletion(index); return m_programState.CreateShader(stage);
} }
void GLContext::MarkShaderForDeletion(const Uint index) { void GLContext::MarkProgramForDeletion(const Uint index) {
return m_programState.MarkShaderObjectForDeletion(index); return m_programState.MarkProgramObjectForDeletion(index);
} }
Bool GLContext::ValidateProgramName(const Uint index) const { void GLContext::MarkShaderForDeletion(const Uint index) {
return m_programState.ValidateProgramObject(index); return m_programState.MarkShaderObjectForDeletion(index);
} }
Bool GLContext::ValidateShaderName(const Uint index) const { Bool GLContext::ValidateProgramName(const Uint index) const {
return m_programState.ValidateShaderObject(index); return m_programState.ValidateProgramObject(index);
} }
SharedPtr<ProgramObject> GLContext::GetProgramObject(const Uint index) { Bool GLContext::ValidateShaderName(const Uint index) const {
return m_programState.GetProgramObject(index); return m_programState.ValidateShaderObject(index);
} }
SharedPtr<ShaderObject> GLContext::GetShaderObject(const Uint index) { const SharedPtr<ProgramObject>& GLContext::GetProgramObject(const Uint index) {
return m_programState.GetShaderObject(index); return m_programState.GetProgramObject(index);
} }
void GLContext::UseProgram(Uint program) { const SharedPtr<ShaderObject>& GLContext::GetShaderObject(const Uint index) {
return m_programState.UseProgram(program); return m_programState.GetShaderObject(index);
} }
SharedPtr<ProgramObject> GLContext::GetCurrentProgram() { void GLContext::UseProgram(Uint program) {
return m_programState.GetCurrentProgram(); return m_programState.UseProgram(program);
} }
// RenderState const SharedPtr<ProgramObject>& GLContext::GetCurrentProgram() {
Uint GLContext::GetRenderStateParametersVersion() const { return m_programState.GetCurrentProgram();
return m_renderState.GetVersion(); }
}
const RenderStateParameters& GLContext::GetRenderStateParameters() const { // RenderState
return m_renderState.GetAllParameters(); Uint GLContext::GetRenderStateParametersVersion() const {
} return m_renderState.GetVersion();
}
void GLContext::SetViewport(IntVec4 viewport) { const RenderStateParameters& GLContext::GetRenderStateParameters() const {
m_renderState.SetViewport(viewport); return m_renderState.GetAllParameters();
} }
const IntVec4& GLContext::GetViewport() const { void GLContext::SetViewport(IntVec4 viewport) {
return m_renderState.GetViewport(); m_renderState.SetViewport(viewport);
} }
void GLContext::SetCapability(CapabilityInput cap, Bool enabled) { const IntVec4& GLContext::GetViewport() const {
m_renderState.SetCapability(cap, enabled); return m_renderState.GetViewport();
} }
Bool GLContext::IsCapabilityEnabled(CapabilityInput cap) const { void GLContext::SetCapability(CapabilityInput cap, Bool enabled) {
return m_renderState.IsCapabilityEnabled(cap); m_renderState.SetCapability(cap, enabled);
} }
void GLContext::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) { Bool GLContext::IsCapabilityEnabled(CapabilityInput cap) const {
m_renderState.SetCapabilityIndexed(cap, index, enabled); return m_renderState.IsCapabilityEnabled(cap);
} }
Bool GLContext::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const { void GLContext::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) {
return m_renderState.IsCapabilityEnabledIndexed(cap, index); m_renderState.SetCapabilityIndexed(cap, index, enabled);
} }
void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, Bool GLContext::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const {
BlendFactor dstAlpha) { return m_renderState.IsCapabilityEnabledIndexed(cap, index);
m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); }
}
void GLContext::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor& dstAlpha) const { BlendFactor dstAlpha) {
m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
} }
void GLContext::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, void GLContext::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor srcAlpha, BlendFactor dstAlpha) { BlendFactor& dstAlpha) const {
m_renderState.SetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha); m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
} }
void GLContext::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, void GLContext::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor& srcAlpha, BlendFactor& dstAlpha) const { BlendFactor dstAlpha) {
m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha); m_renderState.SetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
} }
void GLContext::SetDepthFunc(DepthTestFunc func) { void GLContext::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
m_renderState.SetDepthFunc(func); BlendFactor& dstAlpha) const {
} m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
DepthTestFunc GLContext::GetDepthFunc() const { void GLContext::SetDepthFunc(DepthTestFunc func) {
return m_renderState.GetDepthFunc(); m_renderState.SetDepthFunc(func);
} }
void GLContext::SetDepthMask(Bool flag) { DepthTestFunc GLContext::GetDepthFunc() const {
m_renderState.SetDepthMask(flag); return m_renderState.GetDepthFunc();
} }
Bool GLContext::GetDepthMask() const { void GLContext::SetDepthMask(Bool flag) {
return m_renderState.GetDepthMask(); m_renderState.SetDepthMask(flag);
} }
void GLContext::SetColorMask(BoolVec4 mask) { Bool GLContext::GetDepthMask() const {
m_renderState.SetColorMask(mask); return m_renderState.GetDepthMask();
} }
const BoolVec4 GLContext::GetColorMask() const { void GLContext::SetColorMask(BoolVec4 mask) {
return m_renderState.GetColorMask(); m_renderState.SetColorMask(mask);
} }
void GLContext::SetClearColor(FloatVec4 color) { BoolVec4 GLContext::GetColorMask() const {
m_renderState.SetClearColor(color); return m_renderState.GetColorMask();
} }
const FloatVec4& GLContext::GetClearColor() const { void GLContext::SetClearColor(FloatVec4 color) {
return m_renderState.GetClearColor(); m_renderState.SetClearColor(color);
} }
void GLContext::SetClearDepth(Float depth) { const FloatVec4& GLContext::GetClearColor() const {
m_renderState.SetClearDepth(depth); return m_renderState.GetClearColor();
} }
Float GLContext::GetClearDepth() const { void GLContext::SetClearDepth(Float depth) {
return m_renderState.GetClearDepth(); m_renderState.SetClearDepth(depth);
} }
void GLContext::SetClearStencil(Int stencil) { Float GLContext::GetClearDepth() const {
m_renderState.SetClearStencil(stencil); return m_renderState.GetClearDepth();
} }
void GLContext::SetClearStencil(Int stencil) {
m_renderState.SetClearStencil(stencil);
}
Uint32 GLContext::GetClearStencil() const { Uint32 GLContext::GetClearStencil() const {
return m_renderState.GetClearStencil(); return m_renderState.GetClearStencil();
} }
void GLContext::SetPixelStoreParam(PixelStoreParam param, Int value) { void GLContext::SetPixelStoreParam(PixelStoreParam param, Int value) {
m_renderState.SetPixelStoreParam(param, value); m_renderState.SetPixelStoreParam(param, value);
} }
Int GLContext::GetPixelStoreParam(PixelStoreParam param) const { Int GLContext::GetPixelStoreParam(PixelStoreParam param) const {
return m_renderState.GetPixelStoreParam(param); return m_renderState.GetPixelStoreParam(param);
} }
PixelStoreParameters GLContext::GetPixelStoreParameters(Bool isUnpack) const { PixelStoreParameters GLContext::GetPixelStoreParameters(Bool isUnpack) const {
return m_renderState.GetPixelStoreParameters(isUnpack); return m_renderState.GetPixelStoreParameters(isUnpack);
} }
void GLContext::SetCullFaceMode(CullFaceMode mode) { void GLContext::SetCullFaceMode(CullFaceMode mode) {
m_renderState.SetCullFaceMode(mode); m_renderState.SetCullFaceMode(mode);
} }
CullFaceMode GLContext::GetCullFaceMode() const { CullFaceMode GLContext::GetCullFaceMode() const {
return m_renderState.GetCullFaceMode(); return m_renderState.GetCullFaceMode();
} }
void GLContext::SetScissorBox(IntVec4 box) { void GLContext::SetScissorBox(IntVec4 box) {
m_renderState.SetScissorBox(box); m_renderState.SetScissorBox(box);
} }
const IntVec4& GLContext::GetScissorBox() const { const IntVec4& GLContext::GetScissorBox() const {
return m_renderState.GetScissorBox(); return m_renderState.GetScissorBox();
} }
// Framebuffer // Framebuffer
Vector<Uint> GLContext::GenFramebufferNames(Uint number) { void GLContext::GenFramebufferNames(Uint number, Vector<Uint>& framebuffers) {
return m_framebufferState.GenerateNames(number); m_framebufferState.GenerateNames(number, framebuffers);
} }
SharedPtr<FramebufferObject> GLContext::GetFramebufferObject(Uint index) { const SharedPtr<FramebufferObject>& GLContext::GetFramebufferObject(Uint index) {
return m_framebufferState.GetFramebufferObject(index); return m_framebufferState.GetFramebufferObject(index);
} }
BindingSlot<FramebufferObject>& GLContext::GetFramebufferBindingSlot(FramebufferTarget target) { BindingSlot<FramebufferObject>& GLContext::GetFramebufferBindingSlot(FramebufferTarget target) {
return m_framebufferState.GetBindingSlot(target); return m_framebufferState.GetBindingSlot(target);
} }
SharedPtr<FramebufferObject> GLContext::CreateFramebufferObject(Uint index) { const SharedPtr<FramebufferObject>& GLContext::CreateFramebufferObject(Uint index) {
return m_framebufferState.CreateFramebufferObject(index); return m_framebufferState.CreateFramebufferObject(index);
} }
void GLContext::MarkFramebufferObjectForDeletion(Uint index) { void GLContext::MarkFramebufferObjectForDeletion(Uint index) {
m_framebufferState.MarkFramebufferObjectForDeletion(index); m_framebufferState.MarkFramebufferObjectForDeletion(index);
} }
Bool GLContext::ValidateFramebufferName(Uint index) const { Bool GLContext::ValidateFramebufferName(Uint index) const {
return m_framebufferState.ValidateName(index); return m_framebufferState.ValidateName(index);
} }
Bool GLContext::ValidateFramebufferObject(Uint index) const { Bool GLContext::ValidateFramebufferObject(Uint index) const {
return m_framebufferState.ValidateFramebufferObject(index); return m_framebufferState.ValidateFramebufferObject(index);
} }
// Sampler // Sampler
Vector<Uint> GLContext::GenSamplerNames(Uint number) { void GLContext::GenSamplerNames(Uint number, Vector<Uint>& samplers) {
return m_samplerState.GenerateNames(number); m_samplerState.GenerateNames(number, samplers);
} }
SharedPtr<SamplerObject> GLContext::GetSamplerObject(Uint index) { const SharedPtr<SamplerObject>& GLContext::GetSamplerObject(Uint index) {
return m_samplerState.GetSamplerObject(index); return m_samplerState.GetSamplerObject(index);
} }
SharedPtr<SamplerObject> GLContext::CreateSamplerObject(Uint index) { const SharedPtr<SamplerObject>& GLContext::CreateSamplerObject(Uint index) {
return m_samplerState.CreateSamplerObject(index); return m_samplerState.CreateSamplerObject(index);
} }
void GLContext::MarkSamplerObjectForDeletion(Uint index) { void GLContext::MarkSamplerObjectForDeletion(Uint index) {
// Unbind the sampler from all texture units // Unbind the sampler from all texture units
if (ValidateSamplerObject(index)) { if (ValidateSamplerObject(index)) {
auto sampler = m_samplerState.GetSamplerObject(index); auto sampler = m_samplerState.GetSamplerObject(index);
for (Int unit = 0; unit < TextureState::MAX_TEXTURE_IMAGE_UNITS; ++unit) { for (Int unit = 0; unit < TextureState::MAX_TEXTURE_IMAGE_UNITS; ++unit) {
auto& textureUnit = m_textureState.GetUnitObject(unit); auto& textureUnit = m_textureState.GetUnitObject(unit);
if (textureUnit.GetSamplerObject() == sampler) { if (textureUnit.GetSamplerObject() == sampler) {
textureUnit.SetSamplerObject(nullptr); textureUnit.SetSamplerObject(nullptr);
}
} }
} }
m_samplerState.MarkSamplerObjectForDeletion(index);
} }
m_samplerState.MarkSamplerObjectForDeletion(index);
}
Bool GLContext::ValidateSamplerName(Uint index) const { Bool GLContext::ValidateSamplerName(Uint index) const {
return m_samplerState.ValidateName(index); return m_samplerState.ValidateName(index);
} }
Bool GLContext::ValidateSamplerObject(Uint index) const { Bool GLContext::ValidateSamplerObject(Uint index) const {
return m_samplerState.ValidateSamplerObject(index); return m_samplerState.ValidateSamplerObject(index);
} }
// Renderbuffer // Renderbuffer
Vector<Uint> GLContext::GenRenderbufferNames(Uint number) { void GLContext::GenRenderbufferNames(Uint number, Vector<Uint>& renderbuffers) {
return m_renderbufferState.GenerateNames(number); m_renderbufferState.GenerateNames(number, renderbuffers);
} }
SharedPtr<RenderbufferObject> GLContext::GetRenderbufferObject(Uint index) { const SharedPtr<RenderbufferObject>& GLContext::GetRenderbufferObject(Uint index) {
return m_renderbufferState.GetRenderbufferObject(index); return m_renderbufferState.GetRenderbufferObject(index);
} }
BindingSlot<RenderbufferObject>& GLContext::GetRenderbufferBindingSlot(RenderbufferTarget target) { BindingSlot<RenderbufferObject>& GLContext::GetRenderbufferBindingSlot(RenderbufferTarget target) {
return m_renderbufferState.GetBindingSlot(target); return m_renderbufferState.GetBindingSlot(target);
} }
SharedPtr<RenderbufferObject> GLContext::CreateRenderbufferObject(Uint index) { const SharedPtr<RenderbufferObject>& GLContext::CreateRenderbufferObject(Uint index) {
return m_renderbufferState.CreateRenderbufferObject(index); return m_renderbufferState.CreateRenderbufferObject(index);
} }
void GLContext::MarkRenderbufferObjectForDeletion(Uint index) { void GLContext::MarkRenderbufferObjectForDeletion(Uint index) {
m_renderbufferState.MarkRenderbufferObjectForDeletion(index); m_renderbufferState.MarkRenderbufferObjectForDeletion(index);
} }
Bool GLContext::ValidateRenderbufferName(Uint index) const { Bool GLContext::ValidateRenderbufferName(Uint index) const {
return m_renderbufferState.ValidateName(index); return m_renderbufferState.ValidateName(index);
} }
} // namespace GLState
GLState::GLContext* pGLContext; Bool GLContext::ValidateRenderbufferObject(Uint index) const {
} // namespace MG_State return m_renderbufferState.ValidateRenderbufferObject(index);
} // namespace MobileGL }
} // namespace GLState
UniquePtr<GLState::GLContext> pGLContext;
} // namespace MobileGL::MG_State
+29 -29
View File
@@ -30,42 +30,42 @@ namespace MobileGL {
GLContext() = default; GLContext() = default;
// Error // Error
void RecordError(ErrorCode code, SharedPtr<ErrorInfo> info = nullptr); void RecordError(ErrorCode code, UniquePtr<ErrorInfo> info);
Bool HasGLError() const; Bool HasGLError() const;
Optional<const Error> PeekGLError() const; Optional<const Error*> PeekNonGLError() const;
Optional<Error> PopGLError(); Optional<UniquePtr<Error>> PopNonGLError();
Bool HasNonGLError() const; Bool HasNonGLError() const;
Optional<const Error> PeekNonGLError() const; Optional<const Error*> PeekGLError() const;
Optional<Error> PopNonGLError(); Optional<UniquePtr<Error>> PopGLError();
void ClearErrors(); void ClearErrors();
// Buffer // Buffer
Vector<Uint> GenBufferNames(Uint number); void GenBufferNames(Uint number, Vector<Uint>& buffers);
SharedPtr<BufferObject> GetBufferObject(Uint index); const SharedPtr<BufferObject>& GetBufferObject(Uint index);
BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget target); BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget target);
BindingSlotRange1D<BufferObject>& GetBufferBindingPoint(BufferTarget target, Uint index); BindingSlotRange1D<BufferObject>& GetBufferBindingPoint(BufferTarget target, Uint index);
constexpr SizeT GetBufferBindingPointCount(BufferTarget target) const { constexpr SizeT GetBufferBindingPointCount(BufferTarget target) const {
return m_bufferState.GetBindingPointCount(target); return m_bufferState.GetBindingPointCount(target);
} }
SharedPtr<BufferObject> CreateBufferObject(Uint index); const SharedPtr<BufferObject>& CreateBufferObject(Uint index);
void MarkBufferObjectForDeletion(Uint index); void MarkBufferObjectForDeletion(Uint index);
Bool ValidateBufferName(Uint index) const; Bool ValidateBufferName(Uint index) const;
Bool ValidateBufferObject(Uint index) const; Bool ValidateBufferObject(Uint index) const;
// VertexArray // VertexArray
Vector<Uint> GenVertexArrayNames(Uint number); void GenVertexArrayNames(Uint number, Vector<Uint>& vertexArrays);
SharedPtr<VertexArrayObject> GetVertexArrayObject(Uint index); const SharedPtr<VertexArrayObject>& GetVertexArrayObject(Uint index);
void BindVertexArray(Uint index); void BindVertexArray(Uint index);
SharedPtr<VertexArrayObject> CreateVertexArrayObject(Uint index); const SharedPtr<VertexArrayObject>& CreateVertexArrayObject(Uint index);
void MarkVertexArrayForDeletion(Uint index); void MarkVertexArrayForDeletion(Uint index);
Bool ValidateVertexArrayName(Uint index) const; Bool ValidateVertexArrayName(Uint index) const;
Bool ValidateVertexArrayObject(Uint index) const; Bool ValidateVertexArrayObject(Uint index) const;
SharedPtr<VertexArrayObject> GetBoundVertexArray(); const SharedPtr<VertexArrayObject>& GetBoundVertexArray();
// Texture // Texture
Vector<Uint> GenTextureNames(Uint number); void GenTextureNames(Uint number, Vector<Uint>& textures);
SharedPtr<ITextureObject> GetTextureObject(Uint index); const SharedPtr<ITextureObject>& GetTextureObject(Uint index);
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target); const SharedPtr<ITextureObject>& CreateTextureObject(Uint index, TextureTarget target);
void MarkTextureObjectForDeletion(Uint index); void MarkTextureObjectForDeletion(Uint index);
TextureUnit& GetTextureUnitObject(Int unit); TextureUnit& GetTextureUnitObject(Int unit);
Bool ValidateTextureName(Uint index) const; Bool ValidateTextureName(Uint index) const;
@@ -80,10 +80,10 @@ namespace MobileGL {
void MarkShaderForDeletion(Uint index); void MarkShaderForDeletion(Uint index);
Bool ValidateProgramName(Uint index) const; Bool ValidateProgramName(Uint index) const;
Bool ValidateShaderName(Uint index) const; Bool ValidateShaderName(Uint index) const;
SharedPtr<ProgramObject> GetProgramObject(Uint index); const SharedPtr<ProgramObject>& GetProgramObject(Uint index);
SharedPtr<ShaderObject> GetShaderObject(Uint index); const SharedPtr<ShaderObject>& GetShaderObject(Uint index);
void UseProgram(Uint program); void UseProgram(Uint program);
SharedPtr<ProgramObject> GetCurrentProgram(); const SharedPtr<ProgramObject>& GetCurrentProgram();
// RenderState // RenderState
Uint GetRenderStateParametersVersion() const; Uint GetRenderStateParametersVersion() const;
@@ -106,7 +106,7 @@ namespace MobileGL {
void SetDepthMask(Bool flag); void SetDepthMask(Bool flag);
Bool GetDepthMask() const; Bool GetDepthMask() const;
void SetColorMask(BoolVec4 mask); void SetColorMask(BoolVec4 mask);
const BoolVec4 GetColorMask() const; BoolVec4 GetColorMask() const;
void SetClearColor(FloatVec4 color); void SetClearColor(FloatVec4 color);
const FloatVec4& GetClearColor() const; const FloatVec4& GetClearColor() const;
void SetClearDepth(Float depth); void SetClearDepth(Float depth);
@@ -122,27 +122,27 @@ namespace MobileGL {
const IntVec4& GetScissorBox() const; // x, y, width, height const IntVec4& GetScissorBox() const; // x, y, width, height
// Framebuffer // Framebuffer
Vector<Uint> GenFramebufferNames(Uint number); void GenFramebufferNames(Uint number, Vector<Uint>& framebuffers);
SharedPtr<FramebufferObject> GetFramebufferObject(Uint index); const SharedPtr<FramebufferObject>& GetFramebufferObject(Uint index);
BindingSlot<FramebufferObject>& GetFramebufferBindingSlot(FramebufferTarget target); BindingSlot<FramebufferObject>& GetFramebufferBindingSlot(FramebufferTarget target);
SharedPtr<FramebufferObject> CreateFramebufferObject(Uint index); const SharedPtr<FramebufferObject>& CreateFramebufferObject(Uint index);
void MarkFramebufferObjectForDeletion(Uint index); void MarkFramebufferObjectForDeletion(Uint index);
Bool ValidateFramebufferName(Uint index) const; Bool ValidateFramebufferName(Uint index) const;
Bool ValidateFramebufferObject(Uint index) const; Bool ValidateFramebufferObject(Uint index) const;
// Sampler // Sampler
Vector<Uint> GenSamplerNames(Uint number); void GenSamplerNames(Uint number, Vector<Uint>& samplers);
SharedPtr<SamplerObject> GetSamplerObject(Uint index); const SharedPtr<SamplerObject>& GetSamplerObject(Uint index);
SharedPtr<SamplerObject> CreateSamplerObject(Uint index); const SharedPtr<SamplerObject>& CreateSamplerObject(Uint index);
void MarkSamplerObjectForDeletion(Uint index); void MarkSamplerObjectForDeletion(Uint index);
Bool ValidateSamplerName(Uint index) const; Bool ValidateSamplerName(Uint index) const;
Bool ValidateSamplerObject(Uint index) const; Bool ValidateSamplerObject(Uint index) const;
// Renderbuffer // Renderbuffer
Vector<Uint> GenRenderbufferNames(Uint number); void GenRenderbufferNames(Uint number, Vector<Uint>& renderbuffers);
SharedPtr<RenderbufferObject> GetRenderbufferObject(Uint index); const SharedPtr<RenderbufferObject>& GetRenderbufferObject(Uint index);
BindingSlot<RenderbufferObject>& GetRenderbufferBindingSlot(RenderbufferTarget target); BindingSlot<RenderbufferObject>& GetRenderbufferBindingSlot(RenderbufferTarget target);
SharedPtr<RenderbufferObject> CreateRenderbufferObject(Uint index); const SharedPtr<RenderbufferObject>& CreateRenderbufferObject(Uint index);
void MarkRenderbufferObjectForDeletion(Uint index); void MarkRenderbufferObjectForDeletion(Uint index);
Bool ValidateRenderbufferName(Uint index) const; Bool ValidateRenderbufferName(Uint index) const;
Bool ValidateRenderbufferObject(Uint index) const; Bool ValidateRenderbufferObject(Uint index) const;
@@ -161,6 +161,6 @@ namespace MobileGL {
}; };
} // namespace GLState } // namespace GLState
extern GLState::GLContext* pGLContext; extern UniquePtr<GLState::GLContext> pGLContext;
} // namespace MG_State } // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
+43 -47
View File
@@ -10,57 +10,53 @@
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/MGToGL/ErrorCodeConverter.h> #include <MG_Util/Converters/MGToGL/ErrorCodeConverter.h>
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { void ErrorState::RecordError(ErrorCode code, UniquePtr<ErrorInfo> info) {
namespace GLState { if (code == ErrorCode::NoError) {
void ErrorState::RecordError(ErrorCode code, SharedPtr<ErrorInfo> info) { MGLOG_E("Recording Non-OpenGL error:\n%s", info->toString().c_str());
if (code == ErrorCode::NoError) { m_nonGLErrors.push_back(MakeUnique<Error>(code, Move(info)));
MGLOG_E("Recording Non-OpenGL error:\n%s", info->ToString().c_str()); } else {
m_nonGLErrors.push_back(Error{code, info}); MGLOG_E("Recording OpenGL error (%s):\n%s",
} else { MG_Util::ConvertGLEnumToString(MG_Util::ConvertErrorCodeToGLEnum(code)).c_str(),
MGLOG_E("Recording OpenGL error (%s):\n%s", info->toString().c_str());
MG_Util::ConvertGLEnumToString(MG_Util::ConvertErrorCodeToGLEnum(code)).c_str(), m_errors.push_back(MakeUnique<Error>(code, Move(info)));
info->ToString().c_str()); }
m_errors.push_back(Error{code, info}); }
}
}
Bool ErrorState::HasNonGLError() const { Bool ErrorState::HasNonGLError() const {
return !m_nonGLErrors.empty(); return !m_nonGLErrors.empty();
} }
Optional<const Error> ErrorState::PeekNonGLError() const { Optional<const Error*> ErrorState::PeekNonGLError() const {
if (m_nonGLErrors.empty()) return Optional<const Error>{}; if (m_nonGLErrors.empty()) return Nullopt;
return Optional<const Error>{m_nonGLErrors.front()}; return Optional<const Error*>{m_nonGLErrors.front().get()};
} }
Optional<Error> ErrorState::PopNonGLError() { Optional<UniquePtr<Error>> ErrorState::PopNonGLError() {
if (m_nonGLErrors.empty()) return Optional<const Error>{}; if (m_nonGLErrors.empty()) return Nullopt;
auto error = Move(m_nonGLErrors.front()); auto error = Move(m_nonGLErrors.front());
m_nonGLErrors.erase(m_nonGLErrors.begin()); m_nonGLErrors.erase(m_nonGLErrors.begin());
return Optional<const Error>{error}; return Move(error);
} }
Bool ErrorState::HasGLError() const { Bool ErrorState::HasGLError() const {
return !m_errors.empty(); return !m_errors.empty();
} }
Optional<const Error> ErrorState::PeekGLError() const { Optional<const Error*> ErrorState::PeekGLError() const {
if (m_errors.empty()) return Optional<const Error>{}; if (m_errors.empty()) return Optional<const Error*>{};
return Optional<const Error>{m_errors.front()}; return Optional<const Error*>{m_errors.front().get()};
} }
Optional<Error> ErrorState::PopGLError() { Optional<UniquePtr<Error>> ErrorState::PopGLError() {
if (m_errors.empty()) return Optional<const Error>{}; if (m_errors.empty()) return Nullopt;
auto error = Move(m_errors.front()); auto error = Move(m_errors.front());
m_errors.erase(m_errors.begin()); m_errors.erase(m_errors.begin());
return Optional<const Error>{error}; return Move(error);
} }
void ErrorState::Clear() { void ErrorState::Clear() {
m_errors.clear(); m_errors.clear();
m_nonGLErrors.clear(); m_nonGLErrors.clear();
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
+17 -19
View File
@@ -14,26 +14,24 @@
namespace MobileGL { namespace MobileGL {
struct Error { struct Error {
ErrorCode code; ErrorCode code;
SharedPtr<ErrorInfo> info; UniquePtr<ErrorInfo> info;
}; };
namespace MG_State { namespace MG_State::GLState {
namespace GLState { class ErrorState {
class ErrorState { public:
public: void RecordError(ErrorCode code, UniquePtr<ErrorInfo> info);
void RecordError(ErrorCode code, SharedPtr<ErrorInfo> info = nullptr); Bool HasNonGLError() const;
Bool HasNonGLError() const; Optional<const Error*> PeekNonGLError() const;
Optional<const Error> PeekNonGLError() const; Optional<UniquePtr<Error>> PopNonGLError();
Optional<Error> PopNonGLError(); Bool HasGLError() const;
Bool HasGLError() const; Optional<const Error*> PeekGLError() const;
Optional<const Error> PeekGLError() const; Optional<UniquePtr<Error>> PopGLError();
Optional<Error> PopGLError(); void Clear();
void Clear();
private: private:
Vector<Error> m_errors; Vector<UniquePtr<Error>> m_errors;
Vector<Error> m_nonGLErrors; Vector<UniquePtr<Error>> m_nonGLErrors;
}; };
} // namespace GLState } // namespace MG_State::GLState
} // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -13,7 +13,7 @@ namespace MobileGL {
class ErrorInfo { class ErrorInfo {
public: public:
virtual ~ErrorInfo() = default; virtual ~ErrorInfo() = default;
virtual String ToString() const = 0; virtual String toString() const = 0;
}; };
class GenericErrorInfo : public ErrorInfo { class GenericErrorInfo : public ErrorInfo {
@@ -24,7 +24,7 @@ namespace MobileGL {
explicit GenericErrorInfo(String m_prefix, String m_prefix_2, String message) explicit GenericErrorInfo(String m_prefix, String m_prefix_2, String message)
: m_message(Move(message)), m_prefix(Move(m_prefix)), m_prefix_2(Move(m_prefix_2)) {} : m_message(Move(message)), m_prefix(Move(m_prefix)), m_prefix_2(Move(m_prefix_2)) {}
String ToString() const override { String toString() const override {
StringStream ss; StringStream ss;
if (m_prefix.has_value()) { if (m_prefix.has_value()) {
ss << "[" << m_prefix.value() << "] "; ss << "[" << m_prefix.value() << "] ";
@@ -9,157 +9,153 @@
#include "FramebufferObject.h" #include "FramebufferObject.h"
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { // FramebufferAttachmentObject
namespace GLState { FramebufferAttachmentObject::FramebufferAttachmentObject(
// FramebufferAttachmentObject const SharedPtr<MG_State::GLState::ITextureObject>& texture, Int level)
FramebufferAttachmentObject::FramebufferAttachmentObject( : m_texture(texture), m_textureLevel(level) {}
SharedPtr<MG_State::GLState::ITextureObject> texture, Int level) FramebufferAttachmentObject::FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer)
: m_texture(texture), m_textureLevel(level) {} : m_renderbuffer(renderbuffer) {}
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer) FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid)
: m_renderbuffer(renderbuffer) {} : m_texture(nullptr), m_renderbuffer(nullptr) {
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid) m_isValid = IsValid;
: m_texture(nullptr), m_renderbuffer(nullptr) { }
m_isValid = IsValid;
}
Bool FramebufferAttachmentObject::IsTexture() const { Bool FramebufferAttachmentObject::IsTexture() const {
return m_texture != nullptr; return m_texture != nullptr;
} }
Bool FramebufferAttachmentObject::IsRenderbuffer() const { Bool FramebufferAttachmentObject::IsRenderbuffer() const {
return m_renderbuffer != nullptr; return m_renderbuffer != nullptr;
} }
Bool FramebufferAttachmentObject::IsEmpty() const { Bool FramebufferAttachmentObject::IsEmpty() const {
return m_texture == nullptr && m_renderbuffer == nullptr; return m_texture == nullptr && m_renderbuffer == nullptr;
} }
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachmentObject::GetTexture() const { const SharedPtr<MG_State::GLState::ITextureObject>& FramebufferAttachmentObject::GetTexture() const {
return m_texture; return m_texture;
} }
SharedPtr<RenderbufferObject> FramebufferAttachmentObject::GetRenderbuffer() const { const SharedPtr<RenderbufferObject>& FramebufferAttachmentObject::GetRenderbuffer() const {
return m_renderbuffer; return m_renderbuffer;
} }
Int FramebufferAttachmentObject::GetTextureLevel() const { Int FramebufferAttachmentObject::GetTextureLevel() const {
return m_textureLevel; return m_textureLevel;
} }
Bool FramebufferAttachmentObject::IsComplete() const { Bool FramebufferAttachmentObject::IsComplete() const {
if (IsTexture()) { if (IsTexture()) {
Bool complete = m_texture->IsComplete(); Bool complete = m_texture->IsComplete();
return complete; return complete;
} else if (IsRenderbuffer()) { } else if (IsRenderbuffer()) {
Bool complete = m_renderbuffer->IsAllocated(); Bool complete = m_renderbuffer->IsAllocated();
return complete; return complete;
} }
return false;
}
IntVec3 FramebufferAttachmentObject::GetSize() const {
if (IsTexture()) {
// TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
} else if (IsRenderbuffer()) {
return {m_renderbuffer->GetWidth(), m_renderbuffer->GetHeight(), 1};
}
return {0, 0, 0};
}
Bool FramebufferAttachmentObject::IsValid() const {
return m_isValid;
}
// FramebufferObject
FramebufferObject::FramebufferObject(Uint externalIndex)
: m_externalIndex(externalIndex), m_attachmentVersions{}, m_drawBuffers{} {
m_attachmentObjects.fill(FramebufferAttachmentObject(false));
m_drawBuffers.fill(FramebufferAttachmentType::None);
m_drawBuffers[0] = FramebufferAttachmentType::Color0;
m_attachmentVersions.fill(0);
}
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture,
int level) {
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(texture, level);
BumpAttachmentVersion(type);
}
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type,
const SharedPtr<RenderbufferObject>& renderbuffer) {
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer);
BumpAttachmentVersion(type);
}
void FramebufferObject::Detach(FramebufferAttachmentType type) {
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false);
BumpAttachmentVersion(type);
}
const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
return m_attachmentObjects[static_cast<SizeT>(type)];
}
const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects() const {
return m_attachmentObjects;
}
Bool FramebufferObject::CheckCompleteness() const {
if (m_attachmentObjects.empty()) {
return false;
}
Int width = -1, height = -1;
Int validAttachmentCount = 0;
for (const auto& attachmentObject : m_attachmentObjects) {
if (!attachmentObject.IsValid()) continue;
++validAttachmentCount;
const auto& attachment = attachmentObject;
auto attachmentSize = attachment.GetSize();
Int w = attachmentSize.x();
Int h = attachmentSize.y();
if (width == -1) {
width = w;
height = h;
} else if (width != w || height != h) {
return false; return false;
} }
IntVec3 FramebufferAttachmentObject::GetSize() const { if (!attachment.IsComplete()) {
if (IsTexture()) { return false;
// TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
} else if (IsRenderbuffer()) {
return IntVec3(m_renderbuffer->GetWidth(), m_renderbuffer->GetHeight(), 1);
}
return {0, 0, 0};
} }
}
Bool FramebufferAttachmentObject::IsValid() const { if (validAttachmentCount == 0) return false;
return m_isValid; return true;
} }
// FramebufferObject void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) { if (m_drawBuffers[index] == buffer) return;
m_attachmentObjects.fill(FramebufferAttachmentObject(false)); m_drawBuffers[index] = buffer;
m_drawBuffers.fill(FramebufferAttachmentType::None); BumpAttachmentVersion(buffer);
m_drawBuffers[0] = FramebufferAttachmentType::Color0; }
m_attachmentVersions.fill(0);
}
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
int level) { return m_drawBuffers;
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(std::move(texture), level); }
BumpAttachmentVersion(type);
}
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type, Uint FramebufferObject::GetExternalIndex() const {
std::shared_ptr<RenderbufferObject> renderbuffer) { return m_externalIndex;
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer); }
BumpAttachmentVersion(type);
}
void FramebufferObject::Detach(FramebufferAttachmentType type) { void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false); ++m_attachmentVersions[static_cast<SizeT>(type)];
BumpAttachmentVersion(type); ++m_objectVersion;
} }
} // namespace MobileGL::MG_State::GLState
const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
return m_attachmentObjects[static_cast<SizeT>(type)];
}
const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects()
const {
return m_attachmentObjects;
}
Bool FramebufferObject::CheckCompleteness() const {
if (m_attachmentObjects.empty()) {
return false;
}
Int width = -1, height = -1;
Int validAttachmentCount = 0;
for (SizeT i = 0; i < m_attachmentObjects.size(); ++i) {
if (!m_attachmentObjects[i].IsValid()) continue;
++validAttachmentCount;
const auto& attachment = m_attachmentObjects[i];
auto attachmentSize = attachment.GetSize();
Int w = attachmentSize.x();
Int h = attachmentSize.y();
if (width == -1) {
width = w;
height = h;
} else if (width != w || height != h) {
return false;
}
if (!attachment.IsComplete()) {
return false;
}
}
if (validAttachmentCount == 0) return false;
return true;
}
void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
if (m_drawBuffers[index] == buffer) return;
m_drawBuffers[index] = buffer;
BumpAttachmentVersion(buffer);
}
const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
return m_drawBuffers;
}
Uint FramebufferObject::GetExternalIndex() const {
return m_externalIndex;
}
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
++m_attachmentVersions[static_cast<SizeT>(type)];
++m_objectVersion;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -7,6 +7,7 @@
// End of Source File Header // End of Source File Header
#pragma once #pragma once
#include "MG_Util/Types.h"
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h> #include <MG_State/GLState/TextureState/TextureObject.h>
#include <MG_State/GLState/RenderbufferState/RenderbufferObject.h> #include <MG_State/GLState/RenderbufferState/RenderbufferObject.h>
@@ -68,81 +69,78 @@ namespace MobileGL {
Unknown = -1 Unknown = -1
}; };
namespace MG_State { namespace MG_State::GLState {
namespace GLState { class FramebufferAttachmentObject {
class FramebufferAttachmentObject { public:
public: explicit FramebufferAttachmentObject(const SharedPtr<MG_State::GLState::ITextureObject>& texture,
explicit FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0);
Int level = 0); explicit FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer);
explicit FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer); explicit FramebufferAttachmentObject(Bool IsValid = true);
explicit FramebufferAttachmentObject(Bool IsValid = true);
Bool IsTexture() const; Bool IsTexture() const;
Bool IsRenderbuffer() const; Bool IsRenderbuffer() const;
Bool IsEmpty() const; Bool IsEmpty() const;
SharedPtr<MG_State::GLState::ITextureObject> GetTexture() const; const SharedPtr<MG_State::GLState::ITextureObject>& GetTexture() const;
SharedPtr<RenderbufferObject> GetRenderbuffer() const; const SharedPtr<RenderbufferObject>& GetRenderbuffer() const;
Int GetTextureLevel() const; Int GetTextureLevel() const;
Bool IsComplete() const; Bool IsComplete() const;
IntVec3 GetSize() const; IntVec3 GetSize() const;
Bool IsValid() const; Bool IsValid() const;
private: private:
SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr; SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr;
SharedPtr<RenderbufferObject> m_renderbuffer = nullptr; SharedPtr<RenderbufferObject> m_renderbuffer = nullptr;
Int m_textureLevel = 0; Int m_textureLevel = 0;
Bool m_isValid = true; Bool m_isValid = true;
}; };
class FramebufferObject { class FramebufferObject {
public: public:
static constexpr Uint MAX_DRAW_BUFFERS = 8; static constexpr Uint MAX_DRAW_BUFFERS = 8;
using TargetEnum = FramebufferTarget; using TargetEnum = FramebufferTarget;
using FramebufferAttachmentObjectArray = using FramebufferAttachmentObjectArray =
Array<FramebufferAttachmentObject, Array<FramebufferAttachmentObject,
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
using FramebufferAttachmentArray = Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>; using FramebufferAttachmentArray = Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>;
using FramebufferAttachmentVersionArray = using FramebufferAttachmentVersionArray =
Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
FramebufferObject(Uint externalIndex); FramebufferObject(Uint externalIndex);
void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0); void AttachTexture(FramebufferAttachmentType type, const SharedPtr<ITextureObject>& texture, int level = 0);
void AttachRenderbuffer(FramebufferAttachmentType type, void AttachRenderbuffer(FramebufferAttachmentType type, const SharedPtr<RenderbufferObject>& renderbuffer);
std::shared_ptr<RenderbufferObject> renderbuffer); void Detach(FramebufferAttachmentType type);
void Detach(FramebufferAttachmentType type); const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const; const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const;
const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const; Bool CheckCompleteness() const;
Bool CheckCompleteness() const; // aka. `buffer` as in glDrawBuffers/glReadBuffers
// aka. `buffer` as in glDrawBuffers/glReadBuffers void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer); const FramebufferAttachmentArray& GetDrawBuffers() const;
const FramebufferAttachmentArray& GetDrawBuffers() const; void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; } FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
const FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const { FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
return m_attachmentVersions; return m_attachmentVersions;
} }
Uint16 GetObjectVersion() const { return m_objectVersion; } Uint16 GetObjectVersion() const { return m_objectVersion; }
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
private: private:
void BumpAttachmentVersion(FramebufferAttachmentType type); void BumpAttachmentVersion(FramebufferAttachmentType type);
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
FramebufferAttachmentObjectArray m_attachmentObjects; FramebufferAttachmentObjectArray m_attachmentObjects;
FramebufferAttachmentVersionArray m_attachmentVersions; FramebufferAttachmentVersionArray m_attachmentVersions;
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`) // This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
Uint16 m_objectVersion = 0; Uint16 m_objectVersion = 0;
}; };
} // namespace GLState } // namespace MG_State::GLState
} // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -9,74 +9,73 @@
#include "FramebufferState.h" #include "FramebufferState.h"
#include "MG_State/GLState/FramebufferState/FramebufferObject.h" #include "MG_State/GLState/FramebufferState/FramebufferObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { FramebufferState::FramebufferState() {
namespace GLState { for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
FramebufferState::FramebufferState() { m_bindingSlots[i] = BindingSlot<FramebufferObject>(static_cast<FramebufferTarget>(i));
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { }
m_bindingSlots[i] = BindingSlot<FramebufferObject>(static_cast<FramebufferTarget>(i)); }
}
}
SharedPtr<FramebufferObject> FramebufferState::GetFramebufferObject(Uint index) { const SharedPtr<FramebufferObject>& FramebufferState::GetFramebufferObject(Uint index) {
auto it = m_framebufferObjects.find(index); auto it = m_framebufferObjects.find(index);
if (it != m_framebufferObjects.end()) { if (it != m_framebufferObjects.end()) {
return it->second; return it->second;
} }
return nullptr; static SharedPtr<FramebufferObject> nullFramebufferObject = nullptr;
} return nullFramebufferObject;
}
Vector<Uint> FramebufferState::GenerateNames(Uint number) { void FramebufferState::GenerateNames(Uint number, Vector<Uint>& buffers) {
Vector<Uint> buffers(number); buffers.resize(number);
m_indexGenerator.Generate(number, buffers.data()); m_indexGenerator.Generate(number, buffers.data());
return buffers; }
}
SharedPtr<FramebufferObject> FramebufferState::CreateFramebufferObject(Uint index) { const SharedPtr<FramebufferObject>& FramebufferState::CreateFramebufferObject(Uint index) {
if (index == 0) { if (index == 0) {
if (!m_indexGenerator.IsValid(0)) { if (!m_indexGenerator.IsValid(0)) {
m_indexGenerator.Insert(0); m_indexGenerator.Insert(0);
} else { } else {
return nullptr; static SharedPtr<FramebufferObject> nullFramebufferObject = nullptr;
return nullFramebufferObject;
}
}
auto& framebufferObject = m_framebufferObjects[index];
if (!framebufferObject) {
framebufferObject = MakeShared<FramebufferObject>(index);
}
return framebufferObject;
}
BindingSlot<FramebufferObject>& FramebufferState::GetBindingSlot(FramebufferTarget target) {
for (auto& bindingSlot : m_bindingSlots) {
if (bindingSlot.GetTarget() == target) {
return bindingSlot;
}
}
MOBILEGL_ASSERT(false, "Invalid FramebufferTarget enum value: %d", static_cast<int>(target));
return m_bindingSlots[0];
}
void FramebufferState::MarkFramebufferObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) {
auto it = m_framebufferObjects.find(index);
if (it != m_framebufferObjects.end()) {
for (auto& bindingSlot : m_bindingSlots) {
if (bindingSlot.GetBoundObject() == it->second) {
bindingSlot.Bind(nullptr);
} }
} }
auto bufferObject = MakeShared<FramebufferObject>(index); m_framebufferObjects.erase(it);
m_framebufferObjects[index] = bufferObject;
return bufferObject;
} }
m_indexGenerator.Delete(index);
}
}
BindingSlot<FramebufferObject>& FramebufferState::GetBindingSlot(FramebufferTarget target) { Bool FramebufferState::ValidateName(Uint index) const {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { return m_indexGenerator.IsValid(index);
if (m_bindingSlots[i].GetTarget() == target) { }
return m_bindingSlots[i];
}
}
MOBILEGL_ASSERT(false, "Invalid FramebufferTarget enum value: %d", static_cast<int>(target));
return m_bindingSlots[0];
}
void FramebufferState::MarkFramebufferObjectForDeletion(Uint index) { Bool FramebufferState::ValidateFramebufferObject(Uint index) const {
if (m_indexGenerator.IsValid(index)) { return m_framebufferObjects.find(index) != m_framebufferObjects.end();
auto it = m_framebufferObjects.find(index); }
if (it != m_framebufferObjects.end()) { } // namespace MobileGL::MG_State::GLState
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
if (m_bindingSlots[i].GetBoundObject() == it->second) {
m_bindingSlots[i].Bind(nullptr);
}
}
m_framebufferObjects.erase(it);
}
m_indexGenerator.Delete(index);
}
}
Bool FramebufferState::ValidateName(Uint index) const {
return m_indexGenerator.IsValid(index);
}
Bool FramebufferState::ValidateFramebufferObject(Uint index) const {
return m_framebufferObjects.find(index) != m_framebufferObjects.end();
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -11,28 +11,24 @@
#include <MG_Util/Miscellany/IndexGenerator.h> #include <MG_Util/Miscellany/IndexGenerator.h>
#include "FramebufferObject.h" #include "FramebufferObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class FramebufferState {
namespace GLState { public:
class FramebufferState { FramebufferState();
public:
FramebufferState();
// FBO 0 should be created by MG_Backend when initializing the context // FBO 0 should be created by MG_Backend when initializing the context
SharedPtr<FramebufferObject> GetFramebufferObject(Uint index); const SharedPtr<FramebufferObject>& GetFramebufferObject(Uint index);
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& framebuffers);
SharedPtr<FramebufferObject> CreateFramebufferObject(Uint index); const SharedPtr<FramebufferObject>& CreateFramebufferObject(Uint index);
BindingSlot<FramebufferObject>& GetBindingSlot(FramebufferTarget target); BindingSlot<FramebufferObject>& GetBindingSlot(FramebufferTarget target);
void MarkFramebufferObjectForDeletion(Uint index); void MarkFramebufferObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateFramebufferObject(Uint index) const; Bool ValidateFramebufferObject(Uint index) const;
private: private:
UnorderedMap<Uint, SharedPtr<FramebufferObject>> m_framebufferObjects; UnorderedMap<Uint, SharedPtr<FramebufferObject>> m_framebufferObjects;
IndexGenerator<Uint> m_indexGenerator; IndexGenerator<Uint> m_indexGenerator;
Array<BindingSlot<FramebufferObject>, static_cast<SizeT>(FramebufferTarget::FramebufferTargetCount)> Array<BindingSlot<FramebufferObject>, static_cast<SizeT>(FramebufferTarget::FramebufferTargetCount)>
m_bindingSlots; m_bindingSlots;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
File diff suppressed because it is too large Load Diff
@@ -9,180 +9,176 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include "ShaderObject.h" #include "ShaderObject.h"
#include "MG_Util/Metrics/BufferMetrics.h"
#include "MG_Util/ShaderTranspiler/SpvcSession.h"
namespace MobileGL { #include <MG_Util/Metrics/BufferMetrics.h>
namespace MG_State { #include <MG_Util/ShaderTranspiler/SpvcSession.h>
namespace GLState {
class ProgramObject {
public:
ProgramObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
bool ShaderIsAttached(SharedPtr<ShaderObject> shader);
bool AttachShader(SharedPtr<ShaderObject> shader);
SizeT DetachShader(SharedPtr<ShaderObject> shader);
SizeT RemoveShader(SharedPtr<ShaderObject> shader);
void Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram = false);
void MarkAsDeleted();
void SetExplicitVertexInLocation(Uint index, const char* name); namespace MobileGL::MG_State::GLState {
void SetExplicitFragmentOutLocation(Uint index, const char* name); class ProgramObject {
Int GetFragmentDataLocation(const char* name); public:
ProgramObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
bool ShaderIsAttached(const SharedPtr<ShaderObject>& shader);
bool AttachShader(const SharedPtr<ShaderObject>& shader);
SizeT DetachShader(const SharedPtr<ShaderObject>& shader);
SizeT RemoveShader(const SharedPtr<ShaderObject>& shader);
void Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram = false);
void MarkAsDeleted();
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders(); void SetExplicitVertexInLocation(Uint index, const char* name);
const Vector<SharedPtr<ShaderObject>>& GetAttachedShaders() const; void SetExplicitFragmentOutLocation(Uint index, const char* name);
const String& GetInfoLog() const { return m_infoLog; } Int GetFragmentDataLocation(const char* name);
Int GetUniformMaxLength() const { return m_uniformNameMaxLength; }
Uint GetUniformCount() { return m_activeUniformCount; }
Uint GetMaxUniformLocation() const { return m_maxUniformLocation; }
Int GetUniformLocation(const String& name) const {
const auto it = m_uniformLocations.find(name);
if (it == m_uniformLocations.end()) return -1;
return (Int)it->second;
}
GLenum GetUniformType(Uint location) const { Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]); const Vector<SharedPtr<ShaderObject>>& GetAttachedShaders() const;
return uniform.glDefineType; const String& GetInfoLog() const { return m_infoLog; }
} Int GetUniformMaxLength() const { return m_uniformNameMaxLength; }
Uint GetUniformCount() const { return m_activeUniformCount; }
Uint GetMaxUniformLocation() const { return m_maxUniformLocation; }
Int GetUniformLocation(const String& name) const {
const auto it = m_uniformLocations.find(name);
if (it == m_uniformLocations.end()) return -1;
return (Int)it->second;
}
const glslang::TType* GetUniformTType(Uint location) const { GLenum GetUniformType(Uint location) const {
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]); auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.getType(); return uniform.glDefineType;
} }
Bool IsUniformOpaqueAtLocation(Uint location) const { return GetUniformTType(location)->isOpaque(); } const glslang::TType* GetUniformTType(Uint location) const {
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.getType();
}
const String& GetUniformName(Uint location) const { Bool IsUniformOpaqueAtLocation(Uint location) const { return GetUniformTType(location)->isOpaque(); }
auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return uniform.name;
}
Uint GetUniformOffset(Uint location) const { return m_uniformOffsets[location]; }
Uint GetUniformSizesInBytes(Uint location) const {
return MG_Util::GetGLTypeSize(GetUniformType(location));
}
Int GetAttributeLocation(const String& name) { const String& GetUniformName(Uint location) const {
const auto it = std::find(m_attribs.begin(), m_attribs.end(), name); auto& uniform = m_program->getUniform(m_uniformIndexInTProgram[location]);
return (it == m_attribs.end()) ? -1 : std::distance(m_attribs.begin(), it); return uniform.name;
} }
GLenum GetAttribType(Uint index) const { return m_attribTypes[index]; } Uint GetUniformOffset(Uint location) const { return m_uniformOffsets[location]; }
const String& GetAttribName(Uint index) const { return m_attribs[index]; } Uint GetUniformSizesInBytes(Uint location) const { return MG_Util::GetGLTypeSize(GetUniformType(location)); }
void* MapUBO() { return m_uboScratch.data(); }
const void* GetUBOData() const { return m_uboScratch.data(); }
Uint GetUBOSize() const { return static_cast<Uint>(m_uboScratch.size()); }
void SetUniformSamplerOrImageUnitIndex(Uint location, Int unit) { Int GetAttributeLocation(const String& name) {
m_uniformSamplerOrImageUnitIndex[location] = unit; const auto it = std::find(m_attribs.begin(), m_attribs.end(), name);
} return (it == m_attribs.end()) ? -1 : (Int)std::distance(m_attribs.begin(), it);
}
GLenum GetAttribType(Uint index) const { return m_attribTypes[index]; }
const String& GetAttribName(Uint index) const { return m_attribs[index]; }
void* MapUBO() { return m_uboScratch.data(); }
const void* GetUBOData() const { return m_uboScratch.data(); }
Uint GetUBOSize() const { return static_cast<Uint>(m_uboScratch.size()); }
Int GetUniformSamplerOrImageUnitIndex(Uint location) const { void SetUniformSamplerOrImageUnitIndex(Uint location, Int unit) {
return m_uniformSamplerOrImageUnitIndex[location]; m_uniformSamplerOrImageUnitIndex[location] = unit;
} }
Bool GetDeleteStatus() const { return m_deleteStatus; } Int GetUniformSamplerOrImageUnitIndex(Uint location) const {
Bool GetLinkStatus() const { return m_linkStatus; } return m_uniformSamplerOrImageUnitIndex[location];
Bool GetValidateStatus() const { return m_validateStatus; } }
Int GetActiveAtomicCounterCount() const { return m_program->getNumAtomicCounters(); }
Int GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); }
Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); }
Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; }
Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; }
Uint GetUniformBlockIndex(const char* name) const {
auto it = m_uniformBlockIndexByName.find(name);
if (it != m_uniformBlockIndexByName.end()) return it->second;
return 0xFFFFFFFFu; // GL_INVALID_INDEX
}
Bool IsActiveUniformBlock(Uint index) const {
if (index >= GetActiveUniformBlocksCount()) return false;
return true;
}
Uint GetUBOSizeAt(Uint index) const {
if (!IsActiveUniformBlock(index)) return 0;
return m_program->getUniformBlock(index).size;
}
const String& GetUniformBlockName(Uint index) const { Bool GetDeleteStatus() const { return m_deleteStatus; }
auto& ubo = m_program->getUniformBlock(index); Bool GetLinkStatus() const { return m_linkStatus; }
return ubo.name; Bool GetValidateStatus() const { return m_validateStatus; }
} Int GetActiveAtomicCounterCount() const { return m_program->getNumAtomicCounters(); }
Int GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); }
Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); }
Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; }
Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; }
Uint GetUniformBlockIndex(const char* name) const {
auto it = m_uniformBlockIndexByName.find(name);
if (it != m_uniformBlockIndexByName.end()) return it->second;
return 0xFFFFFFFFu; // GL_INVALID_INDEX
}
Bool IsActiveUniformBlock(Uint index) const {
if (index >= GetActiveUniformBlocksCount()) return false;
return true;
}
Uint GetUBOSizeAt(Uint index) const {
if (!IsActiveUniformBlock(index)) return 0;
return m_program->getUniformBlock((Int)index).size;
}
// Set by glUniformBlockBinding const String& GetUniformBlockName(Uint index) const {
void SetUniformBlockBinding(Uint index, Uint binding) { m_uniformBlockBinding[index] = binding; } auto& ubo = m_program->getUniformBlock((Int)index);
return ubo.name;
}
Uint GetUniformBlockBinding(Uint index) const { return m_uniformBlockBinding[index]; } // Set by glUniformBlockBinding
void SetUniformBlockBinding(Uint index, Uint binding) { m_uniformBlockBinding[index] = (Int)binding; }
Vector<Vector<unsigned>>& GetGeneratedSpirv() { return m_generatedSpirv; } Uint GetUniformBlockBinding(Uint index) const { return m_uniformBlockBinding[index]; }
const Vector<Vector<unsigned>>& GetGeneratedSpirv() const { return m_generatedSpirv; }
Int GetShaderIndexByStage(ShaderStage stage) const { Vector<Vector<unsigned>>& GetGeneratedSpirv() { return m_generatedSpirv; }
auto it = std::find_if(m_shaders.begin(), m_shaders.end(), const Vector<Vector<unsigned>>& GetGeneratedSpirv() const { return m_generatedSpirv; }
[stage](const SharedPtr<ShaderObject>& shader) { return shader->GetShaderStage() == stage; });
return it == m_shaders.end() ? -1 : std::distance(m_shaders.begin(), it);
}
Uint GetExternalIndex() const { return m_externalIndex; } Int GetShaderIndexByStage(ShaderStage stage) const {
auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [stage](const SharedPtr<ShaderObject>& shader) {
return shader->GetShaderStage() == stage;
});
return it == m_shaders.end() ? -1 : (Int)std::distance(m_shaders.begin(), it);
}
// const UnorderedMap<String, Uint>& GetAttribLocationMap() const { return Uint GetExternalIndex() const { return m_externalIndex; }
// m_attribLocation; }
private: // const UnorderedMap<String, Uint>& GetAttribLocationMap() const { return
void DoReflection(); // m_attribLocation; }
void GenerateBinary();
void WaitUntilGenerationCompleted();
void AddDefaultFragmentShaderIfMissing();
const Uint m_externalIndex = 0; private:
Vector<SharedPtr<ShaderObject>> m_shaders; void DoReflection();
Vector<SharedPtr<ShaderObject>> m_detachedShaders; // Store detached shaders and remove on next link void GenerateBinary();
void WaitUntilGenerationCompleted() const;
void AddDefaultFragmentShaderIfMissing();
SharedPtr<glslang::TProgram> m_program; const Uint m_externalIndex = 0;
Vector<SharedPtr<ShaderObject>> m_shaders;
Vector<SharedPtr<ShaderObject>> m_detachedShaders; // Store detached shaders and remove on next link
Vector<Vector<unsigned>> m_generatedSpirv; SharedPtr<glslang::TProgram> m_program;
// Attributes (Vertex in) Vector<Vector<unsigned>> m_generatedSpirv;
UnorderedMap<String, Uint> m_explicitAttribLocations;
Vector<String> m_attribs;
Vector<GLenum> m_attribTypes;
// For SpvcSession::SetVertexAttribLocation()
// UnorderedMap<String, Uint> m_attribLocation;
// FragData (Frag out) // Attributes (Vertex in)
UnorderedMap<String, Uint> m_explicitFragDataLocation; UnorderedMap<String, Uint> m_explicitAttribLocations;
Vector<String> m_attribs;
Vector<GLenum> m_attribTypes;
// For SpvcSession::SetVertexAttribLocation()
// UnorderedMap<String, Uint> m_attribLocation;
// Uniforms // FragData (Frag out)
UnorderedMap<String, Uint> m_uniformLocations; UnorderedMap<String, Uint> m_explicitFragDataLocation;
// Ordered by location,
// aka. m_uniformIndexInTProgram[loc] == "uniform index of TProgram at location `loc`"
Vector<Int> m_uniformIndexInTProgram;
// ditto. Will be set at glUniform1i
Vector<Int> m_uniformSamplerOrImageUnitIndex;
// Ordered by uniform block index // Uniforms
// index is DIFFERENT from binding!!! UnorderedMap<String, Uint> m_uniformLocations;
// // Ordered by location,
// Let's define UniformBlockIndex == the order at glslang getUniformBlock() // aka. m_uniformIndexInTProgram[loc] == "uniform index of TProgram at location `loc`"
// aka `i = glGetUniformBlockIndex(prog, "BlockName")` implies: Vector<Int> m_uniformIndexInTProgram;
// `prog->getUniformBlock(i) == "BlockName"` // ditto. Will be set at glUniform1i
UnorderedMap<String, Uint> m_uniformBlockIndexByName; Vector<Int> m_uniformSamplerOrImageUnitIndex;
Vector<Int> m_uniformBlockBinding;
// Need to be reflected after linking of SPIR-V binary // Ordered by uniform block index
Vector<Uint> m_uniformOffsets; // index is DIFFERENT from binding!!!
Vector<Uint> m_uniformSizesInBytes; //
Vector<Uint8> m_uboScratch; // Let's define UniformBlockIndex == the order at glslang getUniformBlock()
// aka `i = glGetUniformBlockIndex(prog, "BlockName")` implies:
// `prog->getUniformBlock(i) == "BlockName"`
UnorderedMap<String, Uint> m_uniformBlockIndexByName;
Vector<Int> m_uniformBlockBinding;
Uint m_activeUniformCount = 0; // Need to be reflected after linking of SPIR-V binary
Uint m_maxUniformLocation = 0; Vector<Uint> m_uniformOffsets;
Int m_uniformNameMaxLength = 0; Vector<Uint> m_uniformSizesInBytes;
Int m_attribInNameMaxLength = 0; Vector<Uint8> m_uboScratch;
Int m_uniformBlockNameMaxLength = 0;
String m_infoLog; Uint m_activeUniformCount = 0;
Bool m_deleteStatus = false; Uint m_maxUniformLocation = 0;
Bool m_linkStatus = false; Int m_uniformNameMaxLength = 0;
Bool m_validateStatus = true; Int m_attribInNameMaxLength = 0;
}; Int m_uniformBlockNameMaxLength = 0;
} // namespace GLState
} // namespace MG_State String m_infoLog;
} // namespace MobileGL Bool m_deleteStatus = false;
Bool m_linkStatus = false;
Bool m_validateStatus = true;
};
} // namespace MobileGL::MG_State::GLState
@@ -8,73 +8,71 @@
#include "ProgramState.h" #include "ProgramState.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { Uint ProgramState::CreateProgram() {
namespace GLState { Uint programId = 0;
Uint ProgramState::CreateProgram() { m_programIndexGenerator.Generate(1, &programId);
Uint programId = 0; EnsureIndexAvail(programId, m_programObjects);
m_programIndexGenerator.Generate(1, &programId); auto programObject = MakeShared<ProgramObject>(programId);
EnsureIndexAvail(programId, m_programObjects); if (programObject == nullptr) return 0;
auto programObject = MakeShared<ProgramObject>(programId); m_programObjects[programId] = programObject;
if (programObject == nullptr) return 0; return programId;
m_programObjects[programId] = programObject; }
return programId;
}
SharedPtr<ProgramObject> ProgramState::GetProgramObject(const Uint id) { const SharedPtr<ProgramObject>& ProgramState::GetProgramObject(const Uint id) {
if (!CheckIndexAvail(id, m_programObjects)) return nullptr; // FIXME: add error reporting here static SharedPtr<ProgramObject> nullProgramObject = nullptr;
return m_programObjects[id]; if (!CheckIndexAvail(id, m_programObjects)) return nullProgramObject; // FIXME: add error reporting here
} return m_programObjects[id];
}
void ProgramState::MarkProgramObjectForDeletion(const Uint program) { void ProgramState::MarkProgramObjectForDeletion(const Uint program) {
if (!CheckIndexAvail(program, m_programObjects)) return; // FIXME: add error reporting here if (!CheckIndexAvail(program, m_programObjects)) return; // FIXME: add error reporting here
auto& programObject = m_programObjects[program]; auto& programObject = m_programObjects[program];
if (programObject != nullptr) { if (programObject != nullptr) {
programObject->MarkAsDeleted(); programObject->MarkAsDeleted();
programObject.reset(); programObject.reset();
m_programIndexGenerator.Delete(program); m_programIndexGenerator.Delete(program);
} }
} }
Bool ProgramState::ValidateProgramObject(const Uint program) const { Bool ProgramState::ValidateProgramObject(const Uint program) const {
return CheckIndexAvail(program, m_programObjects) && m_programObjects[program] != nullptr; return CheckIndexAvail(program, m_programObjects) && m_programObjects[program] != nullptr;
} }
void ProgramState::UseProgram(Uint program) { void ProgramState::UseProgram(Uint program) {
if (program == 0) m_currentProgram.reset(); if (program == 0) m_currentProgram.reset();
if (!CheckIndexAvail(program, m_programObjects)) return; if (!CheckIndexAvail(program, m_programObjects)) return;
m_currentProgram = m_programObjects[program]; m_currentProgram = m_programObjects[program];
} }
Uint ProgramState::CreateShader(ShaderStage stage) { Uint ProgramState::CreateShader(ShaderStage stage) {
Uint shaderId = 0; Uint shaderId = 0;
m_shaderIndexGenerator.Generate(1, &shaderId); m_shaderIndexGenerator.Generate(1, &shaderId);
EnsureIndexAvail(shaderId, m_shaderObjects); EnsureIndexAvail(shaderId, m_shaderObjects);
auto shaderObject = MakeShared<ShaderObject>(stage, shaderId); auto shaderObject = MakeShared<ShaderObject>(stage, shaderId);
if (shaderObject == nullptr) return 0; if (shaderObject == nullptr) return 0;
m_shaderObjects[shaderId] = shaderObject; m_shaderObjects[shaderId] = shaderObject;
return shaderId; return shaderId;
} }
SharedPtr<ShaderObject> ProgramState::GetShaderObject(const Uint shader) { const SharedPtr<ShaderObject>& ProgramState::GetShaderObject(const Uint shader) {
if (!CheckIndexAvail(shader, m_shaderObjects)) return nullptr; static SharedPtr<ShaderObject> nullShaderObject = nullptr;
return m_shaderObjects[shader]; if (!CheckIndexAvail(shader, m_shaderObjects)) return nullShaderObject;
} return m_shaderObjects[shader];
}
void ProgramState::MarkShaderObjectForDeletion(Uint shader) { void ProgramState::MarkShaderObjectForDeletion(Uint shader) {
if (!CheckIndexAvail(shader, m_shaderObjects)) return; if (!CheckIndexAvail(shader, m_shaderObjects)) return;
auto& shaderObject = m_shaderObjects[shader]; auto& shaderObject = m_shaderObjects[shader];
if (shaderObject != nullptr) { if (shaderObject != nullptr) {
m_shaderObjects[shader]->MarkAsDeleted(); m_shaderObjects[shader]->MarkAsDeleted();
m_shaderObjects[shader].reset(); m_shaderObjects[shader].reset();
m_shaderIndexGenerator.Delete(shader); m_shaderIndexGenerator.Delete(shader);
} }
} }
Bool ProgramState::ValidateShaderObject(Uint shader) const { Bool ProgramState::ValidateShaderObject(Uint shader) const {
return CheckIndexAvail(shader, m_shaderObjects) && m_shaderObjects[shader] != nullptr; return CheckIndexAvail(shader, m_shaderObjects) && m_shaderObjects[shader] != nullptr;
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -11,49 +11,45 @@
#include <MG_Util/Miscellany/IndexGenerator.h> #include <MG_Util/Miscellany/IndexGenerator.h>
#include "ProgramObject.h" #include "ProgramObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class ProgramState {
namespace GLState { public:
class ProgramState { // This function WILL actually create the program object.
public: // To retrieve created program object, use GetProgramObject()
// This function WILL actually create the program object. Uint CreateProgram();
// To retrieve created program object, use GetProgramObject() const SharedPtr<ProgramObject>& GetProgramObject(Uint id);
Uint CreateProgram(); void MarkProgramObjectForDeletion(Uint program);
SharedPtr<ProgramObject> GetProgramObject(Uint id); Bool ValidateProgramObject(Uint program) const;
void MarkProgramObjectForDeletion(Uint program);
Bool ValidateProgramObject(Uint program) const;
void UseProgram(Uint program); void UseProgram(Uint program);
Uint CreateShader(ShaderStage stage); Uint CreateShader(ShaderStage stage);
SharedPtr<ShaderObject> GetShaderObject(Uint shader); const SharedPtr<ShaderObject>& GetShaderObject(Uint shader);
void MarkShaderObjectForDeletion(Uint shader); void MarkShaderObjectForDeletion(Uint shader);
Bool ValidateShaderObject(Uint shader) const; Bool ValidateShaderObject(Uint shader) const;
SharedPtr<ProgramObject> GetCurrentProgram() const { return m_currentProgram; } const SharedPtr<ProgramObject>& GetCurrentProgram() const { return m_currentProgram; }
private: private:
template <typename T> template <typename T>
static Bool CheckIndexAvail(const SizeT idx, const Vector<T>& vec) { static Bool CheckIndexAvail(const SizeT idx, const Vector<T>& vec) {
return idx < vec.size(); return idx < vec.size();
} }
template <typename T> template <typename T>
static void EnsureIndexAvail(const SizeT idx, Vector<T>& vec) { static void EnsureIndexAvail(const SizeT idx, Vector<T>& vec) {
if (CheckIndexAvail(idx, vec)) return; if (CheckIndexAvail(idx, vec)) return;
vec.reserve(std::bit_ceil(idx)); vec.reserve(std::bit_ceil(idx));
vec.resize(idx + 1); vec.resize(idx + 1);
} }
IndexGenerator<Uint> m_programIndexGenerator; IndexGenerator<Uint> m_programIndexGenerator;
Vector<SharedPtr<ProgramObject>> m_programObjects; Vector<SharedPtr<ProgramObject>> m_programObjects;
IndexGenerator<Uint> m_shaderIndexGenerator; IndexGenerator<Uint> m_shaderIndexGenerator;
Vector<SharedPtr<ShaderObject>> m_shaderObjects; Vector<SharedPtr<ShaderObject>> m_shaderObjects;
SharedPtr<ProgramObject> m_currentProgram; SharedPtr<ProgramObject> m_currentProgram;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -13,43 +13,40 @@
#include <MG_Util/ShaderTranspiler/ShaderSourceProcessor.h> #include <MG_Util/ShaderTranspiler/ShaderSourceProcessor.h>
#include <MG_Util/ShaderTranspiler/glslang/UniformTraverser.h> #include <MG_Util/ShaderTranspiler/glslang/UniformTraverser.h>
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { void ShaderObject::SetShaderSource(const String& source) {
namespace GLState { m_source = source;
void ShaderObject::SetShaderSource(const String& source) { }
m_source = source;
}
void ShaderObject::SetShaderSource(String&& source) { void ShaderObject::SetShaderSource(String&& source) {
m_source = Move(source); m_source = Move(source);
} }
void ShaderObject::Compile() { void ShaderObject::Compile() {
using namespace MG_Util::ShaderTranspiler; using namespace MG_Util::ShaderTranspiler;
MG_Util::ShaderTranspiler::PreprocessShaderSource(m_stage, m_source); MG_Util::ShaderTranspiler::PreprocessShaderSource(m_stage, m_source);
// Compile for OpenGL here, so that we can do validation and link // Compile for OpenGL here, so that we can do validation and link
// like a real OpenGL driver at linking stage // like a real OpenGL driver at linking stage
// Will compile for other backends later. // Will compile for other backends later.
ShaderAttrib attrib{ ShaderAttrib attrib{.shaderType = MG_Util::ConvertShaderStageToGLEnum(m_stage),
.shaderType = MG_Util::ConvertShaderStageToGLEnum(m_stage), .sourceStr = m_source, .flags = ShaderCompileBits::CompileForOpenGL}; .sourceStr = m_source,
.flags = ShaderCompileBits::CompileForOpenGL};
auto result = ShaderCompiler::CompileShader(attrib); auto result = ShaderCompiler::CompileShader(attrib);
if (result) { if (result) {
m_compileStatus = true; m_compileStatus = true;
m_shader = result.value(); m_shader = result.value();
} else { } else {
m_compileStatus = false; m_compileStatus = false;
m_infoLog = result.error().log; m_infoLog = result.error().log;
MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting " MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting "
"m_compileStatus = false as a result.", "m_compileStatus = false as a result.",
m_externalIndex, m_source.c_str(), m_infoLog.c_str()); m_externalIndex, m_source.c_str(), m_infoLog.c_str());
} }
} }
void ShaderObject::MarkAsDeleted() { void ShaderObject::MarkAsDeleted() {
m_deleteStatus = true; m_deleteStatus = true;
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -21,37 +21,35 @@ namespace MobileGL {
Unknown = -1 Unknown = -1
}; };
namespace MG_State { namespace MG_State::GLState {
namespace GLState { class ShaderObject {
class ShaderObject { public:
public: ShaderObject(const ShaderStage stage, Uint externalIndex)
ShaderObject(const ShaderStage stage, Uint externalIndex) : m_stage(stage), m_externalIndex(externalIndex) {}
: m_stage(stage), m_externalIndex(externalIndex) {} void SetShaderSource(const String& source);
void SetShaderSource(const String& source); void SetShaderSource(String&& source);
void SetShaderSource(String&& source); void Compile();
void Compile(); void MarkAsDeleted();
void MarkAsDeleted();
Uint GetExternalIndex() const { return m_externalIndex; } Uint GetExternalIndex() const { return m_externalIndex; }
ShaderStage GetShaderStage() const { return m_stage; } ShaderStage GetShaderStage() const { return m_stage; }
const String& GetShaderSource() const { return m_source; } const String& GetShaderSource() const { return m_source; }
SharedPtr<glslang::TShader> GetCompiledShader() const { return m_shader; } const SharedPtr<glslang::TShader>& GetCompiledShader() const { return m_shader; }
const String& GetInfoLog() const { return m_infoLog; } const String& GetInfoLog() const { return m_infoLog; }
const UnorderedMap<String, Uint>& GetUniformLocations() const { return m_uniforms; } const UnorderedMap<String, Uint>& GetUniformLocations() const { return m_uniforms; }
Bool GetCompileStatus() const { return m_compileStatus; } Bool GetCompileStatus() const { return m_compileStatus; }
Bool GetDeleteStatus() const { return m_deleteStatus; } Bool GetDeleteStatus() const { return m_deleteStatus; }
private: private:
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
const ShaderStage m_stage; const ShaderStage m_stage;
String m_source; String m_source;
SharedPtr<glslang::TShader> m_shader; SharedPtr<glslang::TShader> m_shader;
UnorderedMap<String, Uint> m_uniforms; UnorderedMap<String, Uint> m_uniforms;
String m_infoLog; String m_infoLog;
Bool m_deleteStatus = false; Bool m_deleteStatus = false;
Bool m_compileStatus = false; Bool m_compileStatus = false;
}; };
} // namespace GLState } // namespace MG_State::GLState
} // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -38,8 +38,8 @@ namespace MobileGL {
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) { void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
#define SET_CAPABILITY(capability, flag) \ #define SET_CAPABILITY(capability, flag) \
case CapabilityInput::capability: \ case CapabilityInput::capability: \
if (m_parameters.capability##Enabled == flag) break; \ if (m_parameters.capability##Enabled == (flag)) break; \
m_parameters.capability##Enabled = flag; \ m_parameters.capability##Enabled = (flag); \
++m_version; \ ++m_version; \
break; break;
@@ -195,7 +195,7 @@ namespace MobileGL {
++m_version; ++m_version;
} }
const BoolVec4 RenderState::GetColorMask() const { BoolVec4 RenderState::GetColorMask() const {
return m_parameters.ColorMask; return m_parameters.ColorMask;
} }
@@ -237,8 +237,8 @@ namespace MobileGL {
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) { void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \ #define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
case PixelStoreParam::paramNameHead##paramNameTail: \ case PixelStoreParam::paramNameHead##paramNameTail: \
if (m_pixelStore##paramNameHead##Parameters.paramNameTail == val) break; \ if (m_pixelStore##paramNameHead##Parameters.paramNameTail == (val)) break; \
m_pixelStore##paramNameHead##Parameters.paramNameTail = val; \ m_pixelStore##paramNameHead##Parameters.paramNameTail = (val); \
break; break;
switch (param) { switch (param) {
@@ -201,7 +201,7 @@ namespace MobileGL {
// Color Mask // Color Mask
void SetColorMask(BoolVec4 mask); void SetColorMask(BoolVec4 mask);
const BoolVec4 GetColorMask() const; BoolVec4 GetColorMask() const;
// Clear State // Clear State
void SetClearColor(FloatVec4 color); void SetClearColor(FloatVec4 color);
@@ -7,68 +7,67 @@
// End of Source File Header // End of Source File Header
#include "RenderbufferState.h" #include "RenderbufferState.h"
#include "MG_Util/Types.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { RenderbufferState::RenderbufferState() : m_indexGenerator(1024, 1) {
namespace GLState { for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
RenderbufferState::RenderbufferState() : m_indexGenerator(1024, 1) { m_bindingSlots[i] = BindingSlot<RenderbufferObject>(static_cast<RenderbufferTarget>(i));
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { }
m_bindingSlots[i] = BindingSlot<RenderbufferObject>(static_cast<RenderbufferTarget>(i)); }
}
const SharedPtr<RenderbufferObject>& RenderbufferState::GetRenderbufferObject(Uint index) {
auto it = m_renderbufferObjects.find(index);
if (it != m_renderbufferObjects.end()) {
return it->second;
}
static SharedPtr<RenderbufferObject> nullRenderbufferObject = nullptr;
return nullRenderbufferObject;
}
void RenderbufferState::GenerateNames(Uint number, Vector<Uint>& renderbuffers) {
renderbuffers.resize(number);
m_indexGenerator.Generate(number, renderbuffers.data());
}
const SharedPtr<RenderbufferObject>& RenderbufferState::CreateRenderbufferObject(Uint index) {
auto& bufferObject = m_renderbufferObjects[index];
if (!bufferObject) {
bufferObject = MakeShared<RenderbufferObject>(index);
}
return bufferObject;
}
BindingSlot<RenderbufferObject>& RenderbufferState::GetBindingSlot(RenderbufferTarget target) {
for (auto& bindingSlot : m_bindingSlots) {
if (bindingSlot.GetTarget() == target) {
return bindingSlot;
} }
}
MOBILEGL_ASSERT(false, "Invalid RenderbufferTarget enum value: %d", static_cast<int>(target));
return m_bindingSlots[0];
}
SharedPtr<RenderbufferObject> RenderbufferState::GetRenderbufferObject(Uint index) { void RenderbufferState::MarkRenderbufferObjectForDeletion(Uint index) {
auto it = m_renderbufferObjects.find(index); if (m_indexGenerator.IsValid(index)) {
if (it != m_renderbufferObjects.end()) { auto it = m_renderbufferObjects.find(index);
return it->second; if (it != m_renderbufferObjects.end()) {
} for (auto& bindingSlot : m_bindingSlots) {
return nullptr; if (bindingSlot.GetBoundObject() == it->second) {
} bindingSlot.Bind(nullptr);
Vector<Uint> RenderbufferState::GenerateNames(Uint number) {
Vector<Uint> buffers(number);
m_indexGenerator.Generate(number, buffers.data());
return buffers;
}
SharedPtr<RenderbufferObject> RenderbufferState::CreateRenderbufferObject(Uint index) {
auto bufferObject = MakeShared<RenderbufferObject>(index);
m_renderbufferObjects[index] = bufferObject;
return bufferObject;
}
BindingSlot<RenderbufferObject>& RenderbufferState::GetBindingSlot(RenderbufferTarget target) {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
if (m_bindingSlots[i].GetTarget() == target) {
return m_bindingSlots[i];
} }
} }
MOBILEGL_ASSERT(false, "Invalid RenderbufferTarget enum value: %d", static_cast<int>(target)); m_renderbufferObjects.erase(it);
return m_bindingSlots[0];
} }
m_indexGenerator.Delete(index);
}
}
void RenderbufferState::MarkRenderbufferObjectForDeletion(Uint index) { Bool RenderbufferState::ValidateName(Uint index) const {
if (m_indexGenerator.IsValid(index)) { return m_indexGenerator.IsValid(index);
auto it = m_renderbufferObjects.find(index); }
if (it != m_renderbufferObjects.end()) {
for (SizeT i = 0; i < m_bindingSlots.size(); ++i) {
if (m_bindingSlots[i].GetBoundObject() == it->second) {
m_bindingSlots[i].Bind(nullptr);
}
}
m_renderbufferObjects.erase(it);
}
m_indexGenerator.Delete(index);
}
}
Bool RenderbufferState::ValidateName(Uint index) const { Bool RenderbufferState::ValidateRenderbufferObject(Uint index) const {
return m_indexGenerator.IsValid(index); return m_renderbufferObjects.find(index) != m_renderbufferObjects.end();
} }
} // namespace MobileGL::MG_State::GLState
Bool RenderbufferState::ValidateRenderbufferObject(Uint index) const {
return m_renderbufferObjects.find(index) != m_renderbufferObjects.end();
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -11,27 +11,23 @@
#include <MG_Util/Miscellany/IndexGenerator.h> #include <MG_Util/Miscellany/IndexGenerator.h>
#include "RenderbufferObject.h" #include "RenderbufferObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class RenderbufferState {
namespace GLState { public:
class RenderbufferState { RenderbufferState();
public:
RenderbufferState();
SharedPtr<RenderbufferObject> GetRenderbufferObject(Uint index); const SharedPtr<RenderbufferObject>& GetRenderbufferObject(Uint index);
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& renderbuffers);
SharedPtr<RenderbufferObject> CreateRenderbufferObject(Uint index); const SharedPtr<RenderbufferObject>& CreateRenderbufferObject(Uint index);
BindingSlot<RenderbufferObject>& GetBindingSlot(RenderbufferTarget target); BindingSlot<RenderbufferObject>& GetBindingSlot(RenderbufferTarget target);
void MarkRenderbufferObjectForDeletion(Uint index); void MarkRenderbufferObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateRenderbufferObject(Uint index) const; Bool ValidateRenderbufferObject(Uint index) const;
private: private:
UnorderedMap<Uint, SharedPtr<RenderbufferObject>> m_renderbufferObjects; UnorderedMap<Uint, SharedPtr<RenderbufferObject>> m_renderbufferObjects;
IndexGenerator<Uint> m_indexGenerator; IndexGenerator<Uint> m_indexGenerator;
Array<BindingSlot<RenderbufferObject>, static_cast<SizeT>(RenderbufferTarget::RenderbufferTargetCount)> Array<BindingSlot<RenderbufferObject>, static_cast<SizeT>(RenderbufferTarget::RenderbufferTargetCount)>
m_bindingSlots; m_bindingSlots;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -8,42 +8,38 @@
#include "SamplerState.h" #include "SamplerState.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { SamplerState::SamplerState() : m_indexGenerator(1024, 1) {}
namespace GLState {
SamplerState::SamplerState() : m_indexGenerator(1024, 1) {}
Vector<Uint> SamplerState::GenerateNames(Uint number) { void SamplerState::GenerateNames(Uint number, Vector<Uint>& samplers) {
Vector<Uint> names(number); samplers.resize(number);
m_indexGenerator.Generate(number, names.data()); m_indexGenerator.Generate(number, samplers.data());
return names; }
}
SharedPtr<SamplerObject> SamplerState::GetSamplerObject(Uint index) { const SharedPtr<SamplerObject>& SamplerState::GetSamplerObject(Uint index) {
auto it = m_samplerObjects.find(index); auto it = m_samplerObjects.find(index);
return it != m_samplerObjects.end() ? it->second : nullptr; static SharedPtr<SamplerObject> nullSamplerObject = nullptr;
} return it != m_samplerObjects.end() ? it->second : nullSamplerObject;
}
SharedPtr<SamplerObject> SamplerState::CreateSamplerObject(Uint index) { const SharedPtr<SamplerObject>& SamplerState::CreateSamplerObject(Uint index) {
auto sampler = MakeShared<SamplerObject>(index); auto& sampler = m_samplerObjects[index];
m_samplerObjects[index] = sampler; sampler = MakeShared<SamplerObject>(index);
return sampler; return sampler;
} }
void SamplerState::MarkSamplerObjectForDeletion(Uint index) { void SamplerState::MarkSamplerObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) { if (m_indexGenerator.IsValid(index)) {
m_samplerObjects.erase(index); m_samplerObjects.erase(index);
m_indexGenerator.Delete(index); m_indexGenerator.Delete(index);
} }
} }
Bool SamplerState::ValidateName(Uint index) const { Bool SamplerState::ValidateName(Uint index) const {
return m_indexGenerator.IsValid(index); return m_indexGenerator.IsValid(index);
} }
Bool SamplerState::ValidateSamplerObject(Uint index) const { Bool SamplerState::ValidateSamplerObject(Uint index) const {
return m_samplerObjects.find(index) != m_samplerObjects.end(); return m_samplerObjects.find(index) != m_samplerObjects.end();
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -18,9 +18,9 @@ namespace MobileGL {
public: public:
SamplerState(); SamplerState();
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& samplers);
SharedPtr<SamplerObject> GetSamplerObject(Uint index); const SharedPtr<SamplerObject>& GetSamplerObject(Uint index);
SharedPtr<SamplerObject> CreateSamplerObject(Uint index); const SharedPtr<SamplerObject>& CreateSamplerObject(Uint index);
void MarkSamplerObjectForDeletion(Uint index); void MarkSamplerObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateSamplerObject(Uint index) const; Bool ValidateSamplerObject(Uint index) const;
@@ -31,7 +31,7 @@ namespace MobileGL {
return {0, 0, 0}; return {0, 0, 0};
} }
SharedPtr<SamplerObject> TextureObjectBase::GetSamplerObject() const { const SharedPtr<SamplerObject>& TextureObjectBase::GetSamplerObject() const {
return m_sampler; return m_sampler;
} }
@@ -14,113 +14,107 @@
#include <Includes.h> #include <Includes.h>
#include <MG_Util/Math/VectorTypes.h> #include <MG_Util/Math/VectorTypes.h>
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class ITextureObject {
namespace GLState { public:
class ITextureObject { using TargetEnum = TextureTarget;
public: virtual ~ITextureObject() = default;
using TargetEnum = TextureTarget;
virtual ~ITextureObject() = default;
virtual TextureStorageType GetStorageType() const = 0; virtual TextureStorageType GetStorageType() const = 0;
virtual TextureInternalFormat GetFormat() const = 0; virtual TextureInternalFormat GetFormat() const = 0;
virtual TextureTarget GetTarget() const = 0; virtual TextureTarget GetTarget() const = 0;
virtual const Vector<TextureUploadTarget>& GetUploadTargets() const = 0; virtual const Vector<TextureUploadTarget>& GetUploadTargets() const = 0;
virtual IntVec3 GetBaseSize() const = 0; virtual IntVec3 GetBaseSize() const = 0;
virtual SharedPtr<SamplerObject> GetSamplerObject() const = 0; virtual const SharedPtr<SamplerObject>& GetSamplerObject() const = 0;
virtual void SetInternalFormat(TextureInternalFormat format) = 0; virtual void SetInternalFormat(TextureInternalFormat format) = 0;
virtual Bool IsComplete() const = 0; virtual Bool IsComplete() const = 0;
virtual Uint GetExternalIndex() const = 0; virtual Uint GetExternalIndex() const = 0;
virtual const FloatVec4& GetBorderColor() const = 0; virtual const FloatVec4& GetBorderColor() const = 0;
virtual void SetBorderColor(const FloatVec4& color) = 0; virtual void SetBorderColor(const FloatVec4& color) = 0;
virtual TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const = 0; virtual TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const = 0;
virtual void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) = 0; virtual void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) = 0;
virtual void SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) = 0; virtual void SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) = 0;
virtual const Vec4<TextureSwizzleParam>& GetAllSwizzleParams() const = 0; virtual const Vec4<TextureSwizzleParam>& GetAllSwizzleParams() const = 0;
virtual const UintVec2& GetLevelRange() const = 0; virtual const UintVec2& GetLevelRange() const = 0;
virtual void SetBaseLevel(Uint baseLevel) = 0; virtual void SetBaseLevel(Uint baseLevel) = 0;
virtual void SetMaxLevel(Uint maxLevel) = 0; virtual void SetMaxLevel(Uint maxLevel) = 0;
virtual Uint16 GetTextureParamsVersion() const = 0; virtual Uint16 GetTextureParamsVersion() const = 0;
protected: protected:
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0; virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
}; };
class TextureObjectBase : public ITextureObject { class TextureObjectBase : public ITextureObject {
public: public:
TextureObjectBase(TextureTarget target, Uint externalIndex); TextureObjectBase(TextureTarget target, Uint externalIndex);
virtual ~TextureObjectBase() = default; virtual ~TextureObjectBase() = default;
TextureInternalFormat GetFormat() const override; TextureInternalFormat GetFormat() const override;
TextureTarget GetTarget() const override; TextureTarget GetTarget() const override;
IntVec3 GetBaseSize() const override; IntVec3 GetBaseSize() const override;
SharedPtr<SamplerObject> GetSamplerObject() const override; const SharedPtr<SamplerObject>& GetSamplerObject() const override;
void SetInternalFormat(TextureInternalFormat format) override; void SetInternalFormat(TextureInternalFormat format) override;
Bool IsComplete() const override; Bool IsComplete() const override;
Uint GetExternalIndex() const override; Uint GetExternalIndex() const override;
const FloatVec4& GetBorderColor() const override; const FloatVec4& GetBorderColor() const override;
void SetBorderColor(const FloatVec4& color) override; void SetBorderColor(const FloatVec4& color) override;
TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const override; TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const override;
const Vec4<TextureSwizzleParam>& GetAllSwizzleParams() const override; const Vec4<TextureSwizzleParam>& GetAllSwizzleParams() const override;
void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) override; void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) override;
void SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) override; void SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) override;
const UintVec2& GetLevelRange() const override; const UintVec2& GetLevelRange() const override;
void SetBaseLevel(Uint baseLevel) override; void SetBaseLevel(Uint baseLevel) override;
void SetMaxLevel(Uint maxLevel) override; void SetMaxLevel(Uint maxLevel) override;
Uint16 GetTextureParamsVersion() const override; Uint16 GetTextureParamsVersion() const override;
protected: protected:
const Uint m_externalIndex; const Uint m_externalIndex;
const TextureTarget m_target = TextureTarget::Unknown; const TextureTarget m_target = TextureTarget::Unknown;
TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown; TextureInternalFormat m_internalFormat = TextureInternalFormat::Unknown;
SharedPtr<SamplerObject> m_sampler = nullptr; SharedPtr<SamplerObject> m_sampler = nullptr;
FloatVec4 m_borderColor = {0.0f, 0.0f, 0.0f, 0.0f}; FloatVec4 m_borderColor = {0.0f, 0.0f, 0.0f, 0.0f};
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green, Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha}; TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
UintVec2 m_levelRange = {0, 1000}; UintVec2 m_levelRange = {0, 1000};
Uint16 m_textureParamsVersion = 0; Uint16 m_textureParamsVersion = 0;
}; };
class TextureObjectMipmap : public TextureObjectBase { class TextureObjectMipmap : public TextureObjectBase {
public: public:
TextureObjectMipmap(TextureTarget target, Uint externalIndex) TextureObjectMipmap(TextureTarget target, Uint externalIndex) : TextureObjectBase(target, externalIndex) {}
: TextureObjectBase(target, externalIndex) {}
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
virtual Uint GetMipmapLevelCount() const = 0; virtual Uint GetMipmapLevelCount() const = 0;
virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0;
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0; virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0; virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0; virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty = true) = 0;
Bool dirty = true) = 0; virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; };
};
class TextureObjectWithOneMipmap : public TextureObjectMipmap { class TextureObjectWithOneMipmap : public TextureObjectMipmap {
public: public:
TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex)
: TextureObjectMipmap(target, externalIndex) {} : TextureObjectMipmap(target, externalIndex) {}
virtual ~TextureObjectWithOneMipmap() = default; virtual ~TextureObjectWithOneMipmap() = default;
Uint GetMipmapLevelCount() const override; Uint GetMipmapLevelCount() const override;
const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const override; const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const override;
const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const override; const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const override;
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override; void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override; void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override; void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override;
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty) override; void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty) override;
bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override; bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
IntVec3 GetBaseSize() const override; IntVec3 GetBaseSize() const override;
Bool IsComplete() const override; Bool IsComplete() const override;
protected: protected:
MipmapUploadTargetArray<1> m_textureStorage; MipmapUploadTargetArray<1> m_textureStorage;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -8,7 +8,7 @@
#pragma once #pragma once
#include "TextureObject.h" #include "TextureObject.h"
#include "MG_State/GLState/BufferState/BufferObject.h" #include <MG_State/GLState/BufferState/BufferObject.h>
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
@@ -17,115 +17,111 @@
#include "TextureObjectBuffer.h" #include "TextureObjectBuffer.h"
#include "TextureObjectStubs.h" #include "TextureObjectStubs.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { TextureState::TextureState() : m_indexGenerator(1024, 1) {
namespace GLState { for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) {
TextureState::TextureState() : m_indexGenerator(1024, 1) { m_textureUnits[i] = TextureUnit();
for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) { }
m_textureUnits[i] = TextureUnit(); }
}
}
SharedPtr<ITextureObject> TextureState::GetTextureObject(Uint index) { const SharedPtr<ITextureObject>& TextureState::GetTextureObject(Uint index) {
auto it = m_textureObjects.find(index); auto it = m_textureObjects.find(index);
if (it != m_textureObjects.end()) { if (it != m_textureObjects.end()) {
return it->second; return it->second;
} }
return nullptr; static SharedPtr<ITextureObject> nullTextureObject = nullptr;
} return nullTextureObject;
}
Vector<Uint> TextureState::GenerateNames(Uint number) { void TextureState::GenerateNames(Uint number, Vector<Uint>& textures) {
Vector<Uint> textures(number); textures.resize(number);
m_indexGenerator.Generate(number, textures.data()); m_indexGenerator.Generate(number, textures.data());
return textures; }
}
SharedPtr<ITextureObject> TextureState::CreateTextureObject(Uint index, TextureTarget target) { const SharedPtr<ITextureObject>& TextureState::CreateTextureObject(Uint index, TextureTarget target) {
SharedPtr<ITextureObject> textureObject = nullptr; auto& textureObject = m_textureObjects[index];
switch (target) { switch (target) {
case TextureTarget::Texture1D: case TextureTarget::Texture1D:
textureObject = MakeShared<TextureObject1D>(index); textureObject = MakeShared<TextureObject1D>(index);
break; break;
case TextureTarget::TextureCubeMap: case TextureTarget::TextureCubeMap:
textureObject = MakeShared<TextureObject2DCube>(index); textureObject = MakeShared<TextureObject2DCube>(index);
break; break;
case TextureTarget::Texture2D: case TextureTarget::Texture2D:
textureObject = MakeShared<TextureObject2D>(index); textureObject = MakeShared<TextureObject2D>(index);
break; break;
case TextureTarget::Texture3D: case TextureTarget::Texture3D:
textureObject = MakeShared<TextureObject3D>(index); textureObject = MakeShared<TextureObject3D>(index);
break; break;
case TextureTarget::TextureBuffer: case TextureTarget::TextureBuffer:
textureObject = MakeShared<TextureObjectBuffer>(index); textureObject = MakeShared<TextureObjectBuffer>(index);
break; break;
// These texture types are stubbed: // These texture types are stubbed:
case TextureTarget::TextureRectangle: case TextureTarget::TextureRectangle:
textureObject = MakeShared<TextureObjectRectangle>(index); textureObject = MakeShared<TextureObjectRectangle>(index);
break; break;
case TextureTarget::Texture2DMultisample: case TextureTarget::Texture2DMultisample:
textureObject = MakeShared<TextureObject2DMultisample>(index); textureObject = MakeShared<TextureObject2DMultisample>(index);
break; break;
case TextureTarget::Texture1DArray: case TextureTarget::Texture1DArray:
textureObject = MakeShared<TextureObject1DArray>(index); textureObject = MakeShared<TextureObject1DArray>(index);
break; break;
case TextureTarget::Texture2DArray: case TextureTarget::Texture2DArray:
textureObject = MakeShared<TextureObject2DArray>(index); textureObject = MakeShared<TextureObject2DArray>(index);
break; break;
case TextureTarget::TextureCubeMapArray: case TextureTarget::TextureCubeMapArray:
textureObject = MakeShared<TextureObjectCubeMapArray>(index); textureObject = MakeShared<TextureObjectCubeMapArray>(index);
break; break;
case TextureTarget::Texture2DMultisampleArray: case TextureTarget::Texture2DMultisampleArray:
textureObject = MakeShared<TextureObject2DMultisampleArray>(index); textureObject = MakeShared<TextureObject2DMultisampleArray>(index);
break; break;
default: default:
MOBILEGL_ASSERT(false, "Unimplemented texture type when creating texture object!: %d", (int)target); MOBILEGL_ASSERT(false, "Unimplemented texture type when creating texture object!: %d", (int)target);
return nullptr; static SharedPtr<ITextureObject> nullTextureObject = nullptr;
} return nullTextureObject;
}
m_textureObjects[index] = textureObject; return textureObject;
return textureObject; }
}
void TextureState::MarkTextureObjectForDeletion(Uint index) { void TextureState::MarkTextureObjectForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) { if (m_indexGenerator.IsValid(index)) {
auto it = m_textureObjects.find(index); auto it = m_textureObjects.find(index);
if (it != m_textureObjects.end()) { if (it != m_textureObjects.end()) {
for (auto& unit : m_textureUnits) { for (auto& unit : m_textureUnits) {
auto& bindingSlots = unit.GetAllBindingSlots(); auto& bindingSlots = unit.GetAllBindingSlots();
for (SizeT i = 0; i < bindingSlots.size(); ++i) { for (auto& bindingSlot : bindingSlots) {
if (bindingSlots[i].GetBoundObject() == it->second) { if (bindingSlot.GetBoundObject() == it->second) {
bindingSlots[i].Bind(nullptr); bindingSlot.Bind(nullptr);
}
}
} }
m_textureObjects.erase(it);
} }
m_indexGenerator.Delete(index);
} }
m_textureObjects.erase(it);
} }
m_indexGenerator.Delete(index);
}
}
TextureUnit& TextureState::GetUnitObject(Int unit) { TextureUnit& TextureState::GetUnitObject(Int unit) {
MOBILEGL_ASSERT(unit >= 0 && unit < MAX_TEXTURE_IMAGE_UNITS, "Texture unit is out of range: %d > %d", MOBILEGL_ASSERT(unit >= 0 && unit < MAX_TEXTURE_IMAGE_UNITS, "Texture unit is out of range: %d > %d", unit,
unit, MAX_TEXTURE_IMAGE_UNITS - 1); MAX_TEXTURE_IMAGE_UNITS - 1);
return m_textureUnits[unit]; return m_textureUnits[unit];
} }
Int TextureState::GetActiveTextureUnit() const { Int TextureState::GetActiveTextureUnit() const {
return m_activeTextureUnit; return m_activeTextureUnit;
} }
void TextureState::SetActiveTextureUnit(Int unit) { void TextureState::SetActiveTextureUnit(Int unit) {
m_activeTextureUnit = unit; m_activeTextureUnit = unit;
} }
Bool TextureState::ValidateName(Uint index) const { Bool TextureState::ValidateName(Uint index) const {
return m_indexGenerator.IsValid(index); return m_indexGenerator.IsValid(index);
} }
Bool TextureState::ValidateTextureObject(Uint index) const { Bool TextureState::ValidateTextureObject(Uint index) const {
return m_textureObjects.find(index) != m_textureObjects.end(); return m_textureObjects.find(index) != m_textureObjects.end();
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -13,30 +13,26 @@
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include "TextureUnit.h" #include "TextureUnit.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class TextureState {
namespace GLState { public:
class TextureState { static constexpr int MAX_TEXTURE_IMAGE_UNITS = 32;
public:
static constexpr int MAX_TEXTURE_IMAGE_UNITS = 32;
TextureState(); TextureState();
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& textures);
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target); const SharedPtr<ITextureObject>& CreateTextureObject(Uint index, TextureTarget target);
SharedPtr<ITextureObject> GetTextureObject(Uint index); const SharedPtr<ITextureObject>& GetTextureObject(Uint index);
TextureUnit& GetUnitObject(Int unit); TextureUnit& GetUnitObject(Int unit);
Int GetActiveTextureUnit() const; Int GetActiveTextureUnit() const;
void SetActiveTextureUnit(Int unit); void SetActiveTextureUnit(Int unit);
void MarkTextureObjectForDeletion(Uint index); void MarkTextureObjectForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateTextureObject(Uint index) const; Bool ValidateTextureObject(Uint index) const;
private: private:
Int m_activeTextureUnit = 0; Int m_activeTextureUnit = 0;
Array<TextureUnit, MAX_TEXTURE_IMAGE_UNITS> m_textureUnits; Array<TextureUnit, MAX_TEXTURE_IMAGE_UNITS> m_textureUnits;
IndexGenerator<Uint> m_indexGenerator; IndexGenerator<Uint> m_indexGenerator;
UnorderedMap<GLuint, SharedPtr<ITextureObject>> m_textureObjects; UnorderedMap<GLuint, SharedPtr<ITextureObject>> m_textureObjects;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -8,31 +8,26 @@
#include "TextureUnit.h" #include "TextureUnit.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { TextureUnit::TextureUnit() : m_sampler(nullptr) {
namespace GLState { for (int i = 0; i < (int)TextureTarget::TextureTargetCount; ++i) {
TextureUnit::TextureUnit() : m_sampler(nullptr) { m_slots[i] = BindingSlot<ITextureObject>(static_cast<TextureTarget>(i));
for (int i = 0; i < (int)TextureTarget::TextureTargetCount; ++i) { }
m_slots[i] = BindingSlot<ITextureObject>(static_cast<TextureTarget>(i)); }
}
}
BindingSlot<ITextureObject>& TextureUnit::GetBindingSlot(TextureTarget target) { BindingSlot<ITextureObject>& TextureUnit::GetBindingSlot(TextureTarget target) {
return m_slots[(int)target]; return m_slots[(int)target];
} }
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& TextureUnit:: Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& TextureUnit::GetAllBindingSlots() {
GetAllBindingSlots() { return m_slots;
return m_slots; }
}
void TextureUnit::SetSamplerObject(SharedPtr<SamplerObject> sampler) { void TextureUnit::SetSamplerObject(const SharedPtr<SamplerObject>& sampler) {
m_sampler = sampler; m_sampler = sampler;
} }
SharedPtr<SamplerObject> TextureUnit::GetSamplerObject() const { const SharedPtr<SamplerObject>& TextureUnit::GetSamplerObject() const {
return m_sampler; return m_sampler;
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -11,21 +11,17 @@
#include <MG_State/GLState/SamplerState/SamplerObject.h> #include <MG_State/GLState/SamplerState/SamplerObject.h>
#include "TextureObject.h" #include "TextureObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { class TextureUnit {
namespace GLState { public:
class TextureUnit { TextureUnit();
public: BindingSlot<ITextureObject>& GetBindingSlot(TextureTarget target);
TextureUnit(); const SharedPtr<SamplerObject>& GetSamplerObject() const;
BindingSlot<ITextureObject>& GetBindingSlot(TextureTarget target); Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& GetAllBindingSlots();
SharedPtr<SamplerObject> GetSamplerObject() const; void SetSamplerObject(const SharedPtr<SamplerObject>& sampler);
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& GetAllBindingSlots();
void SetSamplerObject(SharedPtr<SamplerObject> sampler);
private: private:
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount> m_slots; Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount> m_slots;
SharedPtr<SamplerObject> m_sampler; SharedPtr<SamplerObject> m_sampler;
}; };
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -8,137 +8,132 @@
#include "VertexArrayObject.h" #include "VertexArrayObject.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { VertexArrayObject::VertexArrayObject(Uint externIndex) : m_externalIndex(externIndex) {
namespace GLState { for (int index = 0; index < MAX_VERTEX_ATTRIBS; ++index) {
VertexArrayObject::VertexArrayObject(Uint externIndex) : m_externalIndex(externIndex) { auto& attr = m_attributes[index];
for (int index = 0; index < MAX_VERTEX_ATTRIBS; ++index) { attr.Enabled = false;
auto& attr = m_attributes[index]; attr.Size = 4;
attr.Enabled = false; attr.Type = DataType::Float32;
attr.Size = 4; attr.Normalized = false;
attr.Type = DataType::Float32; attr.Stride = 0;
attr.Normalized = false; attr.Offset = 0;
attr.Stride = 0; attr.Buffer = nullptr;
attr.Offset = 0;
attr.Buffer = nullptr;
BumpAttributeFormatVersion(index); BumpAttributeFormatVersion(index);
} }
} }
void VertexArrayObject::EnableAttribute(Uint index) { void VertexArrayObject::EnableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Enabled) return; if (m_attributes[index].Enabled) return;
m_attributes[index].Enabled = true; m_attributes[index].Enabled = true;
BumpAttributeSwitchVersion(index); BumpAttributeSwitchVersion(index);
} }
void VertexArrayObject::DisableAttribute(Uint index) { void VertexArrayObject::DisableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (!m_attributes[index].Enabled) return; if (!m_attributes[index].Enabled) return;
m_attributes[index].Enabled = false; m_attributes[index].Enabled = false;
BumpAttributeSwitchVersion(index); BumpAttributeSwitchVersion(index);
} }
Bool VertexArrayObject::IsAttributeEnabled(Uint index) const { Bool VertexArrayObject::IsAttributeEnabled(Uint index) const {
if (index >= MAX_VERTEX_ATTRIBS) return false; if (index >= MAX_VERTEX_ATTRIBS) return false;
return m_attributes[index].Enabled; return m_attributes[index].Enabled;
} }
void VertexArrayObject::SetAttributeFormat(Uint index, int size, DataType type, Bool normalized, int stride, void VertexArrayObject::SetAttributeFormat(Uint index, int size, DataType type, Bool normalized, int stride,
SizeT offset, Bool isInteger) { SizeT offset, Bool isInteger) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Size == size && m_attributes[index].Type == type && if (m_attributes[index].Size == size && m_attributes[index].Type == type &&
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride && m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride &&
m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger) { m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger) {
return; return;
} }
if (size < 1 || size > 4) { if (size < 1 || size > 4) {
return; return;
} }
auto& attr = m_attributes[index]; auto& attr = m_attributes[index];
attr.Size = size; attr.Size = size;
attr.Type = type; attr.Type = type;
attr.Normalized = normalized; attr.Normalized = normalized;
attr.Stride = stride; attr.Stride = stride;
attr.Offset = offset; attr.Offset = offset;
attr.IsInteger = isInteger; attr.IsInteger = isInteger;
BumpAttributeFormatVersion(index); BumpAttributeFormatVersion(index);
} }
void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) { void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Buffer == buffer) return; if (m_attributes[index].Buffer == buffer) return;
m_attributes[index].Buffer = buffer; m_attributes[index].Buffer = buffer;
BumpAttributeBufferVersion(index); BumpAttributeBufferVersion(index);
} }
BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() { BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() {
return m_indexBufferBindingSlot; return m_indexBufferBindingSlot;
} }
const VertexAttribute& VertexArrayObject::GetAttribute(Uint index) const { const VertexAttribute& VertexArrayObject::GetAttribute(Uint index) const {
static VertexAttribute emptyAttr; static VertexAttribute emptyAttr;
if (index >= MAX_VERTEX_ATTRIBS) return emptyAttr; if (index >= MAX_VERTEX_ATTRIBS) return emptyAttr;
return m_attributes[index]; return m_attributes[index];
} }
const Array<VertexAttribute, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::GetAllAttributes() const Array<VertexAttribute, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::GetAllAttributes() const {
const { return m_attributes;
return m_attributes; }
}
Uint VertexArrayObject::GetExternalIndex() const { Uint VertexArrayObject::GetExternalIndex() const {
return m_externalIndex; return m_externalIndex;
} }
void VertexArrayObject::SetAttributeDivisor(Uint index, Uint divisor) { void VertexArrayObject::SetAttributeDivisor(Uint index, Uint divisor) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Divisor == divisor) return; if (m_attributes[index].Divisor == divisor) return;
m_attributes[index].Divisor = divisor; m_attributes[index].Divisor = divisor;
BumpAttributeFormatVersion(index); BumpAttributeFormatVersion(index);
} }
Uint VertexArrayObject::GetAttributeDivisor(Uint index) const { Uint VertexArrayObject::GetAttributeDivisor(Uint index) const {
if (index >= MAX_VERTEX_ATTRIBS) return 0; if (index >= MAX_VERTEX_ATTRIBS) return 0;
return m_attributes[index].Divisor; return m_attributes[index].Divisor;
} }
void VertexArrayObject::BumpAttributeFormatVersion(Uint index) { void VertexArrayObject::BumpAttributeFormatVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].FormatVersion; ++m_attributeVersions[index].FormatVersion;
} }
void VertexArrayObject::BumpAttributeBufferVersion(Uint index) { void VertexArrayObject::BumpAttributeBufferVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].BufferVersion; ++m_attributeVersions[index].BufferVersion;
} }
void VertexArrayObject::BumpAttributeSwitchVersion(Uint index) { void VertexArrayObject::BumpAttributeSwitchVersion(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
++m_attributeVersions[index].SwitchVersion; ++m_attributeVersions[index].SwitchVersion;
} }
const VertexAttributeVersion& VertexArrayObject::GetAttributeVersion(Uint index) const { const VertexAttributeVersion& VertexArrayObject::GetAttributeVersion(Uint index) const {
static VertexAttributeVersion emptyVersion; static VertexAttributeVersion emptyVersion;
if (index >= MAX_VERTEX_ATTRIBS) return emptyVersion; if (index >= MAX_VERTEX_ATTRIBS) return emptyVersion;
return m_attributeVersions[index]; return m_attributeVersions[index];
} }
const Array<VertexAttributeVersion, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject:: const Array<VertexAttributeVersion, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::
GetAllAttributeVersions() const { GetAllAttributeVersions() const {
return m_attributeVersions; return m_attributeVersions;
} }
} // namespace GLState } // namespace MobileGL::MG_State::GLState
} // namespace MG_State
} // namespace MobileGL
@@ -8,76 +8,74 @@
#include "VertexArrayState.h" #include "VertexArrayState.h"
namespace MobileGL { namespace MobileGL::MG_State::GLState {
namespace MG_State { VertexArrayState::VertexArrayState() : m_indexGenerator(1024, 1) {
namespace GLState { // Generate default VAO at index 0, which is not valid in core profile, but still remains for
VertexArrayState::VertexArrayState() : m_indexGenerator(1024, 1) { // compatibility reasons.
// Generate default VAO at index 0, which is not valid in core profile, but still remains for m_indexGenerator.Insert(0);
// compatibility reasons. auto defaultVAO = MakeShared<VertexArrayObject>(0);
m_indexGenerator.Insert(0); m_vertexArrays.push_back(defaultVAO);
auto defaultVAO = MakeShared<VertexArrayObject>(0); m_boundVertexArray = defaultVAO;
m_vertexArrays.push_back(defaultVAO); }
m_boundVertexArray = defaultVAO;
const SharedPtr<VertexArrayObject>& VertexArrayState::GetVertexArrayObject(Uint index) {
if (index >= m_vertexArrays.size()) {
// FIXME: report a GL error here
static SharedPtr<VertexArrayObject> nullVertexArrayObject = nullptr;
return nullVertexArrayObject;
}
return m_vertexArrays[index];
}
void VertexArrayState::GenerateNames(Uint number, Vector<Uint>& arrays) {
arrays.resize(number);
m_indexGenerator.Generate(number, arrays.data());
}
void VertexArrayState::Bind(Uint index) {
m_boundVertexArray = GetVertexArrayObject(index);
}
const SharedPtr<VertexArrayObject>& VertexArrayState::CreateVertexArrayObject(Uint index) {
if (index >= m_vertexArrays.size()) {
// power-of-2 reallocation
m_vertexArrays.reserve(std::bit_ceil(index + 1));
m_vertexArrays.resize(index + 1, nullptr);
}
auto& vao = m_vertexArrays[index];
vao = MakeShared<VertexArrayObject>(index);
return vao;
}
void VertexArrayState::MarkVertexArrayForDeletion(Uint index) {
if (m_indexGenerator.IsValid(index)) {
if (m_boundVertexArray) {
m_boundVertexArray = nullptr;
} }
SharedPtr<VertexArrayObject> VertexArrayState::GetVertexArrayObject(Uint index) { if (ValidateVertexArrayObject(index)) {
if (index >= m_vertexArrays.size()) m_vertexArrays[index] = nullptr;
// FIXME: report a GL error here
return nullptr;
return m_vertexArrays[index];
} }
Vector<Uint> VertexArrayState::GenerateNames(Uint number) { m_indexGenerator.Delete(index);
Vector<Uint> arrays(number); }
m_indexGenerator.Generate(number, arrays.data()); // FIXME: report GL error here?
return arrays; }
}
void VertexArrayState::Bind(Uint index) { Bool VertexArrayState::ValidateName(Uint index) const {
m_boundVertexArray = GetVertexArrayObject(index); return m_indexGenerator.IsValid(index);
} }
SharedPtr<VertexArrayObject> VertexArrayState::CreateVertexArrayObject(Uint index) { Bool VertexArrayState::ValidateVertexArrayObject(Uint index) const {
if (index >= m_vertexArrays.size()) { return index < m_vertexArrays.size() && m_vertexArrays[index] != nullptr;
// power-of-2 reallocation }
m_vertexArrays.reserve(std::bit_ceil(index + 1));
m_vertexArrays.resize(index + 1, nullptr);
}
auto vao = m_vertexArrays[index] = MakeShared<VertexArrayObject>(index);
return vao;
}
void VertexArrayState::MarkVertexArrayForDeletion(Uint index) { const SharedPtr<VertexArrayObject>& VertexArrayState::GetBoundVertexArray() {
if (m_indexGenerator.IsValid(index)) { return m_boundVertexArray;
if (m_boundVertexArray) { }
m_boundVertexArray = nullptr;
}
if (ValidateVertexArrayObject(index)) { Vector<SharedPtr<VertexArrayObject>>& VertexArrayState::GetAllVertexArrays() {
m_vertexArrays[index] = nullptr; return m_vertexArrays;
} }
} // namespace MobileGL::MG_State::GLState
m_indexGenerator.Delete(index);
}
// FIXME: report GL error here?
}
Bool VertexArrayState::ValidateName(Uint index) const {
return m_indexGenerator.IsValid(index);
}
Bool VertexArrayState::ValidateVertexArrayObject(Uint index) const {
return index < m_vertexArrays.size() && m_vertexArrays[index] != nullptr;
}
SharedPtr<VertexArrayObject> VertexArrayState::GetBoundVertexArray() {
return m_boundVertexArray;
}
Vector<SharedPtr<VertexArrayObject>>& VertexArrayState::GetAllVertexArrays() {
return m_vertexArrays;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -18,14 +18,14 @@ namespace MobileGL {
public: public:
VertexArrayState(); VertexArrayState();
SharedPtr<VertexArrayObject> GetVertexArrayObject(Uint index); const SharedPtr<VertexArrayObject>& GetVertexArrayObject(Uint index);
Vector<Uint> GenerateNames(Uint number); void GenerateNames(Uint number, Vector<Uint>& arrays);
void Bind(Uint index); void Bind(Uint index);
SharedPtr<VertexArrayObject> CreateVertexArrayObject(Uint index); const SharedPtr<VertexArrayObject>& CreateVertexArrayObject(Uint index);
void MarkVertexArrayForDeletion(Uint index); void MarkVertexArrayForDeletion(Uint index);
Bool ValidateName(Uint index) const; Bool ValidateName(Uint index) const;
Bool ValidateVertexArrayObject(Uint index) const; Bool ValidateVertexArrayObject(Uint index) const;
SharedPtr<VertexArrayObject> GetBoundVertexArray(); const SharedPtr<VertexArrayObject>& GetBoundVertexArray();
Vector<SharedPtr<VertexArrayObject>>& GetAllVertexArrays(); Vector<SharedPtr<VertexArrayObject>>& GetAllVertexArrays();
private: private:
+4 -4
View File
@@ -150,15 +150,15 @@ namespace MobileGL {
public: public:
using TargetEnum = typename ObjectType::TargetEnum; using TargetEnum = typename ObjectType::TargetEnum;
BindingSlot() : m_target((TargetEnum)0), m_boundObject(nullptr) {} BindingSlot() : m_target((TargetEnum)0) {}
explicit BindingSlot(TargetEnum target) : m_target(target), m_boundObject(nullptr) {} explicit BindingSlot(TargetEnum target) : m_target(target) {}
void Bind(SharedPtr<ObjectType> object) { void Bind(SharedPtr<ObjectType> object) {
if (m_boundObject == object) return; if (m_boundObject == object) return;
m_boundObject = object; m_boundObject = Move(object);
++m_version; ++m_version;
} }
SharedPtr<ObjectType> GetBoundObject() const { return m_boundObject; } SharedPtr<ObjectType> const& GetBoundObject() const noexcept { return m_boundObject; }
TargetEnum GetTarget() const { return m_target; } TargetEnum GetTarget() const { return m_target; }
Uint16 GetVersion() const { return m_version; } Uint16 GetVersion() const { return m_version; }