[Feat|Refactor] (MG_Backend|MG_Impl): Implement BackendObject, replacing previous methods.

This commit is contained in:
BZLZHH
2026-02-18 10:36:56 +08:00
parent fe89dc82dc
commit 8413874e82
52 changed files with 5546 additions and 5863 deletions
+15
View File
@@ -0,0 +1,15 @@
// MobileGL - MobileGL/MG_Backend/BackendObject.cpp
// 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
#include "BackendObject.h"
namespace MobileGL::MG_Backend {
void BackendObject::SetWindowHandle(const WindowHandle& handle) {
m_windowHandle = handle;
}
} // namespace MobileGL::MG_Backend
+108
View File
@@ -0,0 +1,108 @@
// MobileGL - MobileGL/MG_Backend/BackendObject.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>
namespace MobileGL {
enum class BackendType {
DirectGLES,
BackendTypeCount,
Unknown = -1
};
namespace MG_Backend {
struct GLFunctionsTable {
void (*DrawArrays)(GLenum mode, GLint first, GLsizei count);
void (*DrawElements)(GLenum mode, GLsizei count, GLenum type, const void* indices);
void (*DrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLint basevertex);
void (*MultiDrawElements)(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
GLsizei drawcount);
void (*MultiDrawElementsBaseVertex)(GLenum mode, const GLsizei* count, GLenum type,
const GLvoid* const* indices, GLsizei drawcount,
const GLint* basevertex);
void (*MultiDrawElementsIndirect)(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount,
GLsizei stride);
void (*MultiDrawArraysIndirect)(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride);
void (*DrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
const void* indices, GLint basevertex);
void (*DrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type,
const void* indices);
void (*DrawElementsInstancedBaseVertexBaseInstance)(GLenum mode, GLsizei count, GLenum type,
const void* indices, GLsizei instancecount,
GLint basevertex, GLuint baseinstance);
void (*DrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLint basevertex);
void (*DrawElementsInstancedBaseInstance)(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount, GLuint baseinstance);
void (*DrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void* indices,
GLsizei instancecount);
void (*DrawArraysInstancedBaseInstance)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
GLuint baseinstance);
void (*DrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
void (*DrawElementsIndirect)(GLenum mode, GLenum type, const void* indirect);
void (*DrawArraysIndirect)(GLenum mode, const void* indirect);
void (*Clear)(GLbitfield mask);
void (*ClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void (*ClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void (*ClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint* value);
void (*ClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint* value);
void (*BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
void (*CopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border);
void (*CopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height);
void (*GenerateMipmap)(GLenum target);
void (*ReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels);
void (*GetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
};
struct GlobalBackendFunctionsTable {
GLFunctionsTable GL;
void (*Present)();
};
struct DynamicBackendParameters {
SizeT UniformBufferOffsetAlignment = 256;
};
enum class WindowBackend {
Android,
// TODO: X11, Wayland, Windows, macOS, etc.
WindowBackendCount,
Unknown = -1
};
struct WindowHandle {
WindowBackend Backend = WindowBackend::Unknown;
void* Handle = nullptr;
};
class BackendObject {
public:
virtual ~BackendObject() = default;
virtual void Initialize() = 0;
virtual void InitWindowSurface() = 0;
void SetWindowHandle(const WindowHandle& handle);
virtual const RendererInfo& GetRendererInfo() const = 0;
virtual String GetBackendAPIVersionString() const = 0;
virtual const GlobalBackendFunctionsTable& GetBackendFunctions() const = 0;
virtual const DynamicBackendParameters& GetDynamicParameters() const = 0;
virtual BackendType GetBackendType() const = 0;
protected:
WindowHandle m_windowHandle;
};
} // namespace MG_Backend
} // namespace MobileGL
+19
View File
@@ -0,0 +1,19 @@
// MobileGL - MobileGL/MG_Backend/BackendObjects.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 "BackendObject.h"
#include "DirectGLES/BackendObject_DirectGLES.h"
namespace MobileGL::MG_Backend {
extern UniquePtr<BackendObject> pActiveBackendObject;
extern GlobalBackendFunctionsTable gBackendFunctionsTable;
void Init();
} // namespace MobileGL::MG_Backend
-91
View File
@@ -1,91 +0,0 @@
// MobileGL - MobileGL/MG_Backend/Backends.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 <MG_Util/GLExtensions.h>
namespace MobileGL {
namespace MG_Backend {
namespace Unknown {
inline RendererInfo RendererInfoUnknown = {
.RendererName = "<unknown renderer of MobileGL>", // Renderer Name
.BackendName = "<unknown backend>", // Backend Name
.ExtraVendor = ", <unknown>", // Extra vendor
.RendererGLInfo =
{
// OpenGL Info
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {}, // OpenGL Extensions
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
}
namespace Diligent {
enum class SpecificBackendType {
Vulkan,
Metal
};
inline RendererInfo RendererInfoVulkan = {
.RendererName = "MG-DE-Vulkan", // Renderer Name
.BackendName = "Diligent Engine (Vulkan)", // Backend Name
.ExtraVendor = Nullopt, // Extra vendor
.RendererGLInfo =
{
// OpenGL Info
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
inline RendererInfo RendererInfoMetal = {
.RendererName = "MG-DE-Metal", // Renderer Name
.BackendName = "Diligent Engine (Metal)", // Backend Name
.ExtraVendor = Nullopt, // Extra vendor
.RendererGLInfo =
{
// OpenGL Info
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
} // namespace Diligent
namespace DirectGLES {
inline RendererInfo RendererInfo = {
.RendererName = "Espryt", // Renderer Name
.BackendName = "Direct (OpenGL ES)", // Backend Name
.ExtraVendor = Nullopt, // Extra vendor
.RendererGLInfo =
{
// OpenGL Info
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33, E_GL_ARB_draw_buffers_blend},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
} // namespace DirectGLES
void Init();
} // namespace MG_Backend
} // namespace MobileGL
@@ -0,0 +1,136 @@
// MobileGL - MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp
// 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
#include "BackendObject_DirectGLES.h"
#include "MG_Backend/BackendObject.h"
#include <MG_Backend/DirectGLES/DirectGLES.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#include <format>
namespace MobileGL::MG_Backend::DirectGLES {
BackendObject_DirectGLES::~BackendObject_DirectGLES() {
DestroyEGLContext();
}
void BackendObject_DirectGLES::InitWindowSurface() {
// Only use EGL for now
auto nativeWindow = reinterpret_cast<NativeWindowType>(m_windowHandle.Handle);
if (!DirectGLES::InitWindowSurface(nativeWindow)) {
MGLOG_E("Failed to initialize window surface for DirectGLES backend");
}
}
void BackendObject_DirectGLES::Initialize() {
if (!MG_Util::BackendLoader::AcquireEGLFunctions(m_EGLFunctions)) {
MGLOG_E("Failed to acquire EGL functions for DirectGLES backend");
return;
}
if (!MG_Util::BackendLoader::AcquireGLESFunctions(m_GLESFunctions, m_EGLFunctions.eglGetProcAddress)) {
MGLOG_E("Failed to acquire GLES functions for DirectGLES backend");
return;
}
m_initialized = true;
DirectGLES::SetEGLFuncsTable(m_EGLFunctions);
DirectGLES::SetGLESFuncsTable(m_GLESFunctions);
if (!MG_Util::BackendLoader::FillInGLESCapabilities(m_GLESCapabilities, m_GLESFunctions, m_EGLFunctions)) {
MGLOG_E("Failed to fill in GLES capabilities for DirectGLES backend");
return;
}
DirectGLES::SetGLESCapabilities(m_GLESCapabilities);
UpdateDynamicBackendParameters();
}
const RendererInfo& BackendObject_DirectGLES::GetRendererInfo() const {
static RendererInfo RendererInfo = {
.RendererName = "Espryt", // Renderer Name
.BackendName = "Direct (OpenGL ES)", // Backend Name
.ExtraVendor = Nullopt, // Extra vendor
.RendererGLInfo =
{
.TargetGLVersion = {3, 3, 0}, // Target OpenGL Version
.TargetGLSLVersion = {4, 6, 0}, // Target Shading Language Version
.Extensions = {V_OpenGL30, V_OpenGL31, V_OpenGL32, // OpenGL Extensions
V_OpenGL33, E_GL_ARB_draw_buffers_blend},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.StaticBackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
return RendererInfo;
}
String BackendObject_DirectGLES::GetBackendAPIVersionString() const {
if (!m_initialized) {
return "<uninitialized DirectGLES backend>";
}
// Format:
// <OpenGL ES Renderer>, OpenGL ES <OpenGL ES Version>
String versionString = std::format("{}, OpenGL ES {}.{}", m_GLESCapabilities.GLESRendererString,
m_GLESCapabilities.GLESVersion.Major, m_GLESCapabilities.GLESVersion.Minor);
return versionString;
}
BackendType BackendObject_DirectGLES::GetBackendType() const {
return BackendType::DirectGLES;
}
const GlobalBackendFunctionsTable& BackendObject_DirectGLES::GetBackendFunctions() const {
static GlobalBackendFunctionsTable funcsTable;
static Bool funcsTableInitialized = false;
if (!funcsTableInitialized) {
funcsTable.Present = DirectGLES::Present;
funcsTable.GL.DrawArrays = DrawArrays;
funcsTable.GL.DrawElements = DrawElements;
funcsTable.GL.DrawElementsBaseVertex = DrawElementsBaseVertex;
funcsTable.GL.MultiDrawElements = MultiDrawElements;
funcsTable.GL.MultiDrawElementsBaseVertex = MultiDrawElementsBaseVertex;
funcsTable.GL.MultiDrawElementsIndirect = MultiDrawElementsIndirect;
funcsTable.GL.MultiDrawArraysIndirect = MultiDrawArraysIndirect;
funcsTable.GL.DrawRangeElementsBaseVertex = DrawRangeElementsBaseVertex;
funcsTable.GL.DrawRangeElements = DrawRangeElements;
funcsTable.GL.DrawElementsInstancedBaseVertexBaseInstance = DrawElementsInstancedBaseVertexBaseInstance;
funcsTable.GL.DrawElementsInstancedBaseVertex = DrawElementsInstancedBaseVertex;
funcsTable.GL.DrawElementsInstancedBaseInstance = DrawElementsInstancedBaseInstance;
funcsTable.GL.DrawElementsInstanced = DrawElementsInstanced;
funcsTable.GL.DrawArraysInstancedBaseInstance = DrawArraysInstancedBaseInstance;
funcsTable.GL.DrawArraysInstanced = DrawArraysInstanced;
funcsTable.GL.DrawElementsIndirect = DrawElementsIndirect;
funcsTable.GL.DrawArraysIndirect = DrawArraysIndirect;
funcsTable.GL.Clear = Clear;
funcsTable.GL.ClearBufferfi = ClearBufferfi;
funcsTable.GL.ClearBufferfv = ClearBufferfv;
funcsTable.GL.ClearBufferuiv = ClearBufferuiv;
funcsTable.GL.ClearBufferiv = ClearBufferiv;
funcsTable.GL.BlitFramebuffer = BlitFramebuffer;
funcsTable.GL.CopyTexImage2D = CopyTexImage2D;
funcsTable.GL.CopyTexSubImage2D = CopyTexSubImage2D;
funcsTable.GL.GenerateMipmap = GenerateMipmap;
funcsTable.GL.ReadPixels = ReadPixels;
funcsTable.GL.GetTexImage = GetTexImage;
funcsTableInitialized = true;
}
return funcsTable;
}
const DynamicBackendParameters& BackendObject_DirectGLES::GetDynamicParameters() const {
return m_dynamicParameters;
}
void BackendObject_DirectGLES::UpdateDynamicBackendParameters() {
m_dynamicParameters.UniformBufferOffsetAlignment = m_GLESCapabilities.UniformBufferOffsetAlignment;
}
const MG_External::GLESFunctionsTable& BackendObject_DirectGLES::GetGLESFunctions() const {
return m_GLESFunctions;
}
const MG_External::EGLFunctionsTable& BackendObject_DirectGLES::GetEGLFunctions() const {
return m_EGLFunctions;
}
} // namespace MobileGL::MG_Backend::DirectGLES
@@ -0,0 +1,39 @@
// MobileGL - MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.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 "../BackendObject.h"
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
namespace MobileGL::MG_Backend::DirectGLES {
class BackendObject_DirectGLES : public BackendObject {
public:
~BackendObject_DirectGLES() override;
void Initialize() override;
void InitWindowSurface() override;
const RendererInfo& GetRendererInfo() const override;
String GetBackendAPIVersionString() const override;
const GlobalBackendFunctionsTable& GetBackendFunctions() const override;
const DynamicBackendParameters& GetDynamicParameters() const override;
BackendType GetBackendType() const override;
const MG_External::GLESFunctionsTable& GetGLESFunctions() const;
const MG_External::EGLFunctionsTable& GetEGLFunctions() const;
private:
void UpdateDynamicBackendParameters();
Bool m_initialized = false;
MG_External::EGLFunctionsTable m_EGLFunctions;
MG_External::GLESFunctionsTable m_GLESFunctions;
MG_External::GLESCapabilities m_GLESCapabilities;
DynamicBackendParameters m_dynamicParameters;
};
} // namespace MobileGL::MG_Backend::DirectGLES
+239 -160
View File
@@ -7,12 +7,7 @@
// End of Source File Header
#include "DirectGLES.h"
#include "GLES3/gl32.h"
#include "MG_State/GLState/ErrorState/Error.h"
#include "MG_State/GLState/RenderState/RenderState.h"
#include "MG_State/GLState/SamplerState/SamplerObject.h"
#include "MG_Util/Debug/Log.h"
#include "MG_Util/Types.h"
#include "EGL/egl.h"
#include "Utils.h"
#include "Managers.h"
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -28,6 +23,10 @@
#include <MG_Util/Texture/PixelStoreProcessor.h>
namespace MobileGL::MG_Backend::DirectGLES {
MG_External::EGLFunctionsTable g_EGLFuncs;
MG_External::GLESFunctionsTable g_GLESFuncs;
MG_External::GLESCapabilities g_GLESCapabilities;
enum class DrawSyncBit : Uint32 {
None = 0,
IndexBuffer = 1 << 0,
@@ -47,18 +46,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace DebugImpl {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
void ErrorLopper::Loop(std::function<void(GLenum)> func) {
GLenum err = MG_External::GLES::glGetError();
GLenum err = g_GLESFuncs.glGetError();
while (err != GL_NO_ERROR) {
func(err);
err = MG_External::GLES::glGetError();
err = g_GLESFuncs.glGetError();
}
}
void ErrorLopper::Clear() {
GLenum err = MG_External::GLES::glGetError();
GLenum err = g_GLESFuncs.glGetError();
while (err != GL_NO_ERROR) {
MGLOG_D("Stray GL Error cleared: %s", MG_Util::ConvertGLEnumToString(err).c_str());
err = MG_External::GLES::glGetError();
err = g_GLESFuncs.glGetError();
}
}
@@ -77,11 +76,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG
OpenGLScopeMarker::OpenGLScopeMarker(String scopeName) {
MG_External::GLES::glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, scopeName.c_str());
g_GLESFuncs.glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, scopeName.c_str());
}
OpenGLScopeMarker::~OpenGLScopeMarker() {
MG_External::GLES::glPopDebugGroup();
g_GLESFuncs.glPopDebugGroup();
}
#else
OpenGLScopeMarker::OpenGLScopeMarker(String scopeName) {}
@@ -297,16 +296,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& parameters = MG_State::pGLContext->GetRenderStateParameters();
if (parameters.Viewport != g_syncedRenderStateParameters.Viewport) {
MG_External::GLES::glViewport(parameters.Viewport.x(), parameters.Viewport.y(), parameters.Viewport.z(),
parameters.Viewport.w());
g_GLESFuncs.glViewport(parameters.Viewport.x(), parameters.Viewport.y(), parameters.Viewport.z(),
parameters.Viewport.w());
}
#define SYNC_CAPABILITY(cap_mg, cap_gl) \
if (parameters.cap_mg##Enabled != g_syncedRenderStateParameters.cap_mg##Enabled) { \
if (parameters.cap_mg##Enabled) { \
MG_External::GLES::glEnable(cap_gl); \
g_GLESFuncs.glEnable(cap_gl); \
} else { \
MG_External::GLES::glDisable(cap_gl); \
g_GLESFuncs.glDisable(cap_gl); \
} \
}
SYNC_CAPABILITY(DepthTest, GL_DEPTH_TEST);
@@ -340,19 +339,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (anyCapDirty) {
if (allEnabled) {
MG_External::GLES::glEnable(GL_BLEND);
g_GLESFuncs.glEnable(GL_BLEND);
for (auto& s : syncedStates)
s.Enabled = true;
} else if (allDisabled) {
MG_External::GLES::glDisable(GL_BLEND);
g_GLESFuncs.glDisable(GL_BLEND);
for (auto& s : syncedStates)
s.Enabled = false;
} else {
for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) {
if (targetStates[i].Enabled != syncedStates[i].Enabled) {
syncedStates[i].Enabled = targetStates[i].Enabled;
syncedStates[i].Enabled ? MG_External::GLES::glEnablei(GL_BLEND, i)
: MG_External::GLES::glDisablei(GL_BLEND, i);
syncedStates[i].Enabled ? g_GLESFuncs.glEnablei(GL_BLEND, i)
: g_GLESFuncs.glDisablei(GL_BLEND, i);
}
}
}
@@ -382,11 +381,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (anyFuncDirty) {
if (allFuncsSame) {
MG_External::GLES::glBlendFuncSeparate(
MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorAlpha),
MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorAlpha));
g_GLESFuncs.glBlendFuncSeparate(MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorAlpha),
MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorAlpha));
for (auto& syn : syncedStates) {
syn.SrcFactorRGB = first.SrcFactorRGB;
@@ -406,7 +404,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
syn.SrcFactorAlpha = cur.SrcFactorAlpha;
syn.DstFactorAlpha = cur.DstFactorAlpha;
MG_External::GLES::glBlendFuncSeparatei(
g_GLESFuncs.glBlendFuncSeparatei(
i, MG_Util::ConvertBlendFactorToGLEnum(cur.SrcFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(cur.DstFactorRGB),
MG_Util::ConvertBlendFactorToGLEnum(cur.SrcFactorAlpha),
@@ -419,42 +417,42 @@ namespace MobileGL::MG_Backend::DirectGLES {
{ // Depth state
if (parameters.DepthFunc != g_syncedRenderStateParameters.DepthFunc) {
MG_External::GLES::glDepthFunc(MG_Util::ConvertDepthTestFuncToGLEnum(parameters.DepthFunc));
g_GLESFuncs.glDepthFunc(MG_Util::ConvertDepthTestFuncToGLEnum(parameters.DepthFunc));
}
if (parameters.DepthMask != g_syncedRenderStateParameters.DepthMask) {
MG_External::GLES::glDepthMask(parameters.DepthMask ? GL_TRUE : GL_FALSE);
g_GLESFuncs.glDepthMask(parameters.DepthMask ? GL_TRUE : GL_FALSE);
}
}
{ // Color mask
if (parameters.ColorMask != g_syncedRenderStateParameters.ColorMask) {
const BoolVec4& colorMask = parameters.ColorMask;
MG_External::GLES::glColorMask(ToGLBoolean(colorMask.x()), ToGLBoolean(colorMask.y()),
ToGLBoolean(colorMask.z()), ToGLBoolean(colorMask.w()));
g_GLESFuncs.glColorMask(ToGLBoolean(colorMask.x()), ToGLBoolean(colorMask.y()),
ToGLBoolean(colorMask.z()), ToGLBoolean(colorMask.w()));
}
}
{ // Clear values
if (parameters.ClearColor != g_syncedRenderStateParameters.ClearColor) {
const FloatVec4& clearCol = parameters.ClearColor;
MG_External::GLES::glClearColor(clearCol.x(), clearCol.y(), clearCol.z(), clearCol.w());
g_GLESFuncs.glClearColor(clearCol.x(), clearCol.y(), clearCol.z(), clearCol.w());
}
if (parameters.ClearDepth != g_syncedRenderStateParameters.ClearDepth) {
MG_External::GLES::glClearDepthf(parameters.ClearDepth);
g_GLESFuncs.glClearDepthf(parameters.ClearDepth);
}
}
{ // Cull face mode
if (parameters.CullFaceModeSetting != g_syncedRenderStateParameters.CullFaceModeSetting) {
const CullFaceMode& cfm = parameters.CullFaceModeSetting;
MG_External::GLES::glCullFace(MG_Util::ConvertCullFaceModeToGLEnum(cfm));
g_GLESFuncs.glCullFace(MG_Util::ConvertCullFaceModeToGLEnum(cfm));
}
}
{ // Scissor box
if (parameters.ScissorBox != g_syncedRenderStateParameters.ScissorBox) {
const IntVec4& scissorBox = parameters.ScissorBox;
MG_External::GLES::glScissor(scissorBox.x(), scissorBox.y(), scissorBox.z(), scissorBox.w());
g_GLESFuncs.glScissor(scissorBox.x(), scissorBox.y(), scissorBox.z(), scissorBox.w());
}
}
@@ -470,7 +468,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
auto currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (!currentProgram || !currentProgram->GetLinkStatus()) {
MG_External::GLES::glUseProgram(0);
g_GLESFuncs.glUseProgram(0);
return;
}
const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram);
@@ -506,8 +504,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
} else {
MGLOG_D("Binding default framebuffer as %s FBO", (target == FramebufferTarget::Read ? "READ" : "DRAW"));
MG_External::GLES::glBindFramebuffer(
target == FramebufferTarget::Draw ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER, 0);
g_GLESFuncs.glBindFramebuffer(target == FramebufferTarget::Draw ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
0);
}
}
@@ -535,7 +533,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
backendVAOIt->second->Bind();
}
} else {
MG_External::GLES::glBindVertexArray(0);
g_GLESFuncs.glBindVertexArray(0);
}
}
@@ -592,19 +590,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedNC("UpdateGlobalUBO", TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER,
backendProgramIt->second->GetBackendGlobalUBOId());
MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(),
currentProgram->MapUBO());
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0);
g_GLESFuncs.glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId());
g_GLESFuncs.glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(),
currentProgram->MapUBO());
g_GLESFuncs.glBindBuffer(GL_UNIFORM_BUFFER, 0);
Uint blockIndex = MG_External::GLES::glGetUniformBlockIndex(
backendProgramId, MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME);
Uint blockIndex = g_GLESFuncs.glGetUniformBlockIndex(backendProgramId,
MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME);
MG_External::GLES::glUniformBlockBinding(backendProgramId, blockIndex, 0);
g_GLESFuncs.glUniformBlockBinding(backendProgramId, blockIndex, 0);
MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, 0,
backendProgramIt->second->GetBackendGlobalUBOId());
g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, 0,
backendProgramIt->second->GetBackendGlobalUBOId());
}
{
@@ -621,9 +618,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Connect program ubo index to backend binding point
auto binding = currentProgram->GetUniformBlockBinding(i);
auto& name = currentProgram->GetUniformBlockName(i);
GLuint backendBlkIdx =
MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str());
MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding);
GLuint backendBlkIdx = g_GLESFuncs.glGetUniformBlockIndex(backendProgramId, name.c_str());
g_GLESFuncs.glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding);
// Connect buffer to backend binding point
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding);
@@ -636,12 +632,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_UNIFORM_BUFFER);
if (range.end == 0) {
MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId());
g_GLESFuncs.glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId());
} else {
MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId(),
range.start, range.end - range.start);
g_GLESFuncs.glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId(),
range.start, range.end - range.start);
}
} else {
MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO.");
@@ -660,9 +656,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto unit = currentProgram->GetUniformSamplerOrImageUnitIndex(loc);
if (unit == -1) continue;
auto& name = currentProgram->GetUniformName(loc);
auto locAtBackend = MG_External::GLES::glGetUniformLocation(
auto locAtBackend = g_GLESFuncs.glGetUniformLocation(
backendProgramIt->second->GetBackendProgramId(), name.c_str());
MG_External::GLES::glUniform1i(locAtBackend, unit);
g_GLESFuncs.glUniform1i(locAtBackend, unit);
auto samplerObject = MG_State::pGLContext->GetTextureUnitObject(unit).GetSamplerObject();
@@ -682,7 +678,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
}
} else {
MG_External::GLES::glUseProgram(0);
g_GLESFuncs.glUseProgram(0);
MGLOG_E("No backend program found (maybe not synced) for current program, cannot use program.");
}
}
@@ -698,7 +694,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BindCurrentFBO(FramebufferTarget::Draw);
MG_External::GLES::glClear(mask);
g_GLESFuncs.glClear(mask);
}
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
@@ -707,7 +703,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawElements(mode, count, type, indices);
g_GLESFuncs.glDrawElements(mode, count, type, indices);
}
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
@@ -716,7 +712,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
DrawSyncBit syncBit = DrawSyncBit::None;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawArrays(mode, first, count);
g_GLESFuncs.glDrawArrays(mode, first, count);
}
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) {
@@ -725,7 +721,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawElementsBaseVertex(mode, count, type, indices, basevertex);
g_GLESFuncs.glDrawElementsBaseVertex(mode, count, type, indices, basevertex);
}
void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices,
@@ -737,7 +733,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
PrepareForDraw(syncBit);
for (GLsizei i = 0; i < drawcount; ++i) {
MG_External::GLES::glDrawElements(mode, count[i], type, indices[i]);
g_GLESFuncs.glDrawElements(mode, count[i], type, indices[i]);
}
}
@@ -750,7 +746,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
PrepareForDraw(syncBit);
for (GLsizei i = 0; i < drawcount; ++i) {
MG_External::GLES::glDrawElementsBaseVertex(mode, count[i], type, indices[i], basevertex[i]);
g_GLESFuncs.glDrawElementsBaseVertex(mode, count[i], type, indices[i], basevertex[i]);
}
}
@@ -764,7 +760,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (GLsizei i = 0; i < drawcount; ++i) {
const GLvoid* cmd = reinterpret_cast<const GLvoid*>(reinterpret_cast<const uint8_t*>(indirect) +
i * (stride ? stride : sizeof(GLsizei) * 4));
MG_External::GLES::glDrawElementsIndirect(mode, type, cmd);
g_GLESFuncs.glDrawElementsIndirect(mode, type, cmd);
}
}
@@ -778,7 +774,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (GLsizei i = 0; i < drawcount; ++i) {
const GLvoid* cmd = reinterpret_cast<const GLvoid*>(reinterpret_cast<const uint8_t*>(indirect) +
i * (stride ? stride : sizeof(GLsizei) * 4));
MG_External::GLES::glDrawArraysIndirect(mode, cmd);
g_GLESFuncs.glDrawArraysIndirect(mode, cmd);
}
}
@@ -786,13 +782,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
const void* indices, GLint basevertex) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);
g_GLESFuncs.glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);
}
void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawRangeElements(mode, start, end, count, type, indices);
g_GLESFuncs.glDrawRangeElements(mode, start, end, count, type, indices);
}
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
@@ -805,7 +801,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLsizei instancecount, GLint basevertex) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
g_GLESFuncs.glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
}
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
@@ -817,13 +813,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawElementsInstanced(mode, count, type, indices, instancecount);
g_GLESFuncs.glDrawElementsInstanced(mode, count, type, indices, instancecount);
}
void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {
DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::IndirectBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawElementsIndirect(mode, type, indirect);
g_GLESFuncs.glDrawElementsIndirect(mode, type, indirect);
}
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
@@ -835,13 +831,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
DrawSyncBit syncBit = DrawSyncBit::Instancing;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawArraysInstanced(mode, first, count, instancecount);
g_GLESFuncs.glDrawArraysInstanced(mode, first, count, instancecount);
}
void DrawArraysIndirect(GLenum mode, const void* indirect) {
DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer;
PrepareForDraw(syncBit);
MG_External::GLES::glDrawArraysIndirect(mode, indirect);
g_GLESFuncs.glDrawArraysIndirect(mode, indirect);
}
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
@@ -871,7 +867,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
});
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());
MG_External::GLES::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) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -920,23 +916,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
__func__, s_prevDrawFBO, s_prevReadFBO);
static GLuint tempFBO = 0;
if (!tempFBO) {
MG_External::GLES::glGenFramebuffers(1, &tempFBO);
g_GLESFuncs.glGenFramebuffers(1, &tempFBO);
}
if (isRead) {
MG_External::GLES::glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (GLint*)&s_prevReadFBO);
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, tempFBO);
g_GLESFuncs.glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (GLint*)&s_prevReadFBO);
g_GLESFuncs.glBindFramebuffer(GL_READ_FRAMEBUFFER, tempFBO);
} else {
MG_External::GLES::glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFBO);
g_GLESFuncs.glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&s_prevDrawFBO);
g_GLESFuncs.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFBO);
}
}
void RestoreFBOFromTemp(Bool isRead) {
if (isRead) {
MGLOG_D("%s: Restoring previous read FBO=%u", __func__, s_prevReadFBO);
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, s_prevReadFBO);
g_GLESFuncs.glBindFramebuffer(GL_READ_FRAMEBUFFER, s_prevReadFBO);
} else {
MGLOG_D("%s: Restoring previous draw FBO=%u", __func__, s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_prevDrawFBO);
g_GLESFuncs.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_prevDrawFBO);
}
}
@@ -1001,14 +997,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::IsStencilFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
if (!isDepthFormat) {
MG_External::GLES::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) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
} else {
MGLOG_D("%s: Backend depth", __func__);
MG_External::GLES::glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type,
nullptr);
g_GLESFuncs.glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type,
nullptr);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -1020,16 +1016,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder(false);
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
g_GLESFuncs.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
if (g_GLESFuncs.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("ES glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE");
return;
}
MG_External::GLES::glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height,
GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0),
GL_NEAREST);
g_GLESFuncs.glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height,
GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0),
GL_NEAREST);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -1077,7 +1073,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
GLenum internalFormat;
MG_External::GLES::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) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -1087,7 +1083,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mgInternalFormat);
if (!isDepthFormat) {
MG_External::GLES::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) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
@@ -1099,16 +1095,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
});
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder(false);
MG_External::GLES::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) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
});
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
if (g_GLESFuncs.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("ES glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE");
return;
}
MG_External::GLES::glBlitFramebuffer(
g_GLESFuncs.glBlitFramebuffer(
x, y, x + width, y + height, xoffset, yoffset, xoffset + width, yoffset + height,
GL_DEPTH_BUFFER_BIT | (isStencilFormat ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
@@ -1128,11 +1124,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto backendTexture = TextureImpl::SyncTextureObjectToBackend(texture);
backendTexture->Bind(target, unitIndex);
MG_External::GLES::glGenerateMipmap(target);
g_GLESFuncs.glGenerateMipmap(target);
}
const GLubyte* GetString(GLenum name) {
return MG_External::GLES::glGetString(name);
return g_GLESFuncs.glGetString(name);
}
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
@@ -1142,7 +1138,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BindCurrentFBO(FramebufferTarget::Draw);
MG_External::GLES::glClearBufferfi(buffer, drawbuffer, depth, stencil);
g_GLESFuncs.glClearBufferfi(buffer, drawbuffer, depth, stencil);
}
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
@@ -1152,7 +1148,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BindCurrentFBO(FramebufferTarget::Draw);
MG_External::GLES::glClearBufferfv(buffer, drawbuffer, value);
g_GLESFuncs.glClearBufferfv(buffer, drawbuffer, value);
}
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
@@ -1160,7 +1156,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
MG_External::GLES::glClearBufferiv(buffer, drawbuffer, value);
g_GLESFuncs.glClearBufferiv(buffer, drawbuffer, value);
}
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
@@ -1170,7 +1166,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
BindCurrentFBO(FramebufferTarget::Draw);
MG_External::GLES::glClearBufferuiv(buffer, drawbuffer, value);
g_GLESFuncs.glClearBufferuiv(buffer, drawbuffer, value);
}
class TempPixelStoreParameterSync {
@@ -1191,28 +1187,28 @@ namespace MobileGL::MG_Backend::DirectGLES {
PixelStoreParameters QueryCurrentGLPixelStoreParams(Bool isUnpack) {
PixelStoreParameters p;
if (!isUnpack) {
MG_External::GLES::glGetIntegerv(GL_PACK_ALIGNMENT, (GLint*)&p.Alignment);
MG_External::GLES::glGetIntegerv(GL_PACK_ROW_LENGTH, (GLint*)&p.RowLength);
MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_ROWS, (GLint*)&p.SkipRows);
MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
// MG_External::GLES::glGetIntegerv(GL_PACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
// MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
g_GLESFuncs.glGetIntegerv(GL_PACK_ALIGNMENT, (GLint*)&p.Alignment);
g_GLESFuncs.glGetIntegerv(GL_PACK_ROW_LENGTH, (GLint*)&p.RowLength);
g_GLESFuncs.glGetIntegerv(GL_PACK_SKIP_ROWS, (GLint*)&p.SkipRows);
g_GLESFuncs.glGetIntegerv(GL_PACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
// g_GLESFuncs.glGetIntegerv(GL_PACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
// g_GLESFuncs.glGetIntegerv(GL_PACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
// GLint tmp;
// MG_External::GLES::glGetIntegerv(GL_PACK_SWAP_BYTES, &tmp);
// g_GLESFuncs.glGetIntegerv(GL_PACK_SWAP_BYTES, &tmp);
// p.SwapBytes = tmp ? true : false;
// MG_External::GLES::glGetIntegerv(GL_PACK_LSB_FIRST, &tmp);
// g_GLESFuncs.glGetIntegerv(GL_PACK_LSB_FIRST, &tmp);
// p.LSBFirst = tmp ? true : false;
} else {
MG_External::GLES::glGetIntegerv(GL_UNPACK_ALIGNMENT, (GLint*)&p.Alignment);
MG_External::GLES::glGetIntegerv(GL_UNPACK_ROW_LENGTH, (GLint*)&p.RowLength);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_ROWS, (GLint*)&p.SkipRows);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
MG_External::GLES::glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_ALIGNMENT, (GLint*)&p.Alignment);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_ROW_LENGTH, (GLint*)&p.RowLength);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_SKIP_ROWS, (GLint*)&p.SkipRows);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
g_GLESFuncs.glGetIntegerv(GL_UNPACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
// GLint tmp;
// MG_External::GLES::glGetIntegerv(GL_UNPACK_SWAP_BYTES, &tmp);
// g_GLESFuncs.glGetIntegerv(GL_UNPACK_SWAP_BYTES, &tmp);
// p.SwapBytes = tmp ? true : false;
// MG_External::GLES::glGetIntegerv(GL_UNPACK_LSB_FIRST, &tmp);
// g_GLESFuncs.glGetIntegerv(GL_UNPACK_LSB_FIRST, &tmp);
// p.LSBFirst = tmp ? true : false;
}
return p;
@@ -1220,23 +1216,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
void Sync(Bool isUnpack, const PixelStoreParameters& params) {
if (!isUnpack) {
MG_External::GLES::glPixelStorei(GL_PACK_ALIGNMENT, params.Alignment);
MG_External::GLES::glPixelStorei(GL_PACK_ROW_LENGTH, params.RowLength);
MG_External::GLES::glPixelStorei(GL_PACK_SKIP_ROWS, params.SkipRows);
MG_External::GLES::glPixelStorei(GL_PACK_SKIP_PIXELS, params.SkipPixels);
// MG_External::GLES::glPixelStorei(GL_PACK_IMAGE_HEIGHT, params.ImageHeight);
// MG_External::GLES::glPixelStorei(GL_PACK_SKIP_IMAGES, params.SkipImages);
// MG_External::GLES::glPixelStorei(GL_PACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// MG_External::GLES::glPixelStorei(GL_PACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
g_GLESFuncs.glPixelStorei(GL_PACK_ALIGNMENT, params.Alignment);
g_GLESFuncs.glPixelStorei(GL_PACK_ROW_LENGTH, params.RowLength);
g_GLESFuncs.glPixelStorei(GL_PACK_SKIP_ROWS, params.SkipRows);
g_GLESFuncs.glPixelStorei(GL_PACK_SKIP_PIXELS, params.SkipPixels);
// g_GLESFuncs.glPixelStorei(GL_PACK_IMAGE_HEIGHT, params.ImageHeight);
// g_GLESFuncs.glPixelStorei(GL_PACK_SKIP_IMAGES, params.SkipImages);
// g_GLESFuncs.glPixelStorei(GL_PACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// g_GLESFuncs.glPixelStorei(GL_PACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
} else {
MG_External::GLES::glPixelStorei(GL_UNPACK_ALIGNMENT, params.Alignment);
MG_External::GLES::glPixelStorei(GL_UNPACK_ROW_LENGTH, params.RowLength);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_ROWS, params.SkipRows);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_PIXELS, params.SkipPixels);
MG_External::GLES::glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, params.ImageHeight);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_IMAGES, params.SkipImages);
// MG_External::GLES::glPixelStorei(GL_UNPACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// MG_External::GLES::glPixelStorei(GL_UNPACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
g_GLESFuncs.glPixelStorei(GL_UNPACK_ALIGNMENT, params.Alignment);
g_GLESFuncs.glPixelStorei(GL_UNPACK_ROW_LENGTH, params.RowLength);
g_GLESFuncs.glPixelStorei(GL_UNPACK_SKIP_ROWS, params.SkipRows);
g_GLESFuncs.glPixelStorei(GL_UNPACK_SKIP_PIXELS, params.SkipPixels);
g_GLESFuncs.glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, params.ImageHeight);
g_GLESFuncs.glPixelStorei(GL_UNPACK_SKIP_IMAGES, params.SkipImages);
// g_GLESFuncs.glPixelStorei(GL_UNPACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// g_GLESFuncs.glPixelStorei(GL_UNPACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
}
}
};
@@ -1266,7 +1262,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("ReadPixels: Applying TempPixelStoreParameterSync (PACK)");
TempPixelStoreParameterSync tempPackParamsSync(false);
GLenum fbStatus = MG_External::GLES::glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
GLenum fbStatus = g_GLESFuncs.glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
MGLOG_D("ReadPixels: GL_READ_FRAMEBUFFER status = %s", MG_Util::ConvertGLEnumToString(fbStatus).c_str());
if (fbStatus != GL_FRAMEBUFFER_COMPLETE) {
@@ -1292,32 +1288,32 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_PIXEL_PACK_BUFFER);
MG_External::GLES::glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
g_GLESFuncs.glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
} else {
usePBO = false;
MGLOG_D("ReadPixels: Not using PBO");
}
MGLOG_D("ReadPixels: glReadPixels()");
MG_External::GLES::glReadPixels(x, y, width, height, format, type, pixels);
g_GLESFuncs.glReadPixels(x, y, width, height, format, type, pixels);
if (usePBO) {
// pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = MG_External::GLES::glMapBufferRange(
GL_PIXEL_PACK_BUFFER, 0, pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize();
pixelPackBufferObject->UploadSubData({pboMappedPtr, size}, 0);
pixelPackBufferObject->ClearDirty();
MGLOG_D("ReadPixels: Unmapping PBO");
MG_External::GLES::glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
g_GLESFuncs.glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
} else {
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
}
MGLOG_D("ReadPixels: Restoring previous pixel pack buffer binding %u", prevPixelPackBuffer);
MG_External::GLES::glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
g_GLESFuncs.glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
}
MGLOG_D("ReadPixels: finished");
}
@@ -1332,18 +1328,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
"Only GL_RGBA, GL_RGBA_INTEGER and GL_BGRA are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(format).c_str());
MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV ||
type == GL_INT || type == GL_FLOAT ||
type == GL_UNSIGNED_INT_8_8_8_8 || type == GL_UNSIGNED_INT_8_8_8_8_REV,
type == GL_INT || type == GL_FLOAT || type == GL_UNSIGNED_INT_8_8_8_8 ||
type == GL_UNSIGNED_INT_8_8_8_8_REV,
"Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, "
"GL_INT, GL_FLOAT, GL_UNSIGNED_INT_8_8_8_8 and GL_UNSIGNED_INT_8_8_8_8_REV "
"are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(type).c_str());
GLenum esFormat = format, esType = type;
if (esFormat == GL_BGRA)
esFormat = GL_RGBA;
if (esType == GL_UNSIGNED_INT_8_8_8_8 || esType == GL_UNSIGNED_INT_8_8_8_8_REV)
esType = GL_UNSIGNED_BYTE;
if (esFormat == GL_BGRA) esFormat = GL_RGBA;
if (esType == GL_UNSIGNED_INT_8_8_8_8 || esType == GL_UNSIGNED_INT_8_8_8_8_REV) esType = GL_UNSIGNED_BYTE;
MGLOG_D("GetTexImage: SyncNeccessaryTextures()");
TextureImpl::SyncNeccessaryTextures();
@@ -1376,12 +1370,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
TempFBOBinder tempFBOBinder(true);
MGLOG_D("GetTexImage: glFramebufferTexture2D(level=%d)", level);
MG_External::GLES::glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, backendTexId,
level);
g_GLESFuncs.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, backendTexId, level);
MGLOG_D("GetTexImage: glReadBuffer(GL_COLOR_ATTACHMENT0)");
MG_External::GLES::glReadBuffer(GL_COLOR_ATTACHMENT0);
g_GLESFuncs.glReadBuffer(GL_COLOR_ATTACHMENT0);
GLenum fbStatus = MG_External::GLES::glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
GLenum fbStatus = g_GLESFuncs.glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
MGLOG_D("GetTexImage: GL_READ_FRAMEBUFFER status = %s", MG_Util::ConvertGLEnumToString(fbStatus).c_str());
if (fbStatus != GL_FRAMEBUFFER_COMPLETE) {
@@ -1444,7 +1437,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_PIXEL_PACK_BUFFER);
MG_External::GLES::glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
g_GLESFuncs.glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
} else {
usePBO = false;
MGLOG_D("GetTexImage: Not using PBO");
@@ -1454,8 +1447,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
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(),
MG_Util::ConvertGLEnumToString(esFormat).c_str(), MG_Util::ConvertGLEnumToString(esType).c_str(), pixels);
MG_External::GLES::glReadPixels(0, 0, size.x(), size.y(), esFormat, esType, pixels);
MG_Util::ConvertGLEnumToString(esFormat).c_str(), MG_Util::ConvertGLEnumToString(esType).c_str(),
pixels);
g_GLESFuncs.glReadPixels(0, 0, size.x(), size.y(), esFormat, esType, pixels);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
@@ -1463,25 +1457,25 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (usePBO) {
// pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = MG_External::GLES::glMapBufferRange(
GL_PIXEL_PACK_BUFFER, 0, pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
GLvoid* pboMappedPtr = g_GLESFuncs.glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize();
pixelPackBufferObject->UploadSubData({pboMappedPtr, size}, 0);
pixelPackBufferObject->ClearDirty();
MGLOG_D("ReadPixels: Unmapping PBO");
MG_External::GLES::glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
g_GLESFuncs.glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
} else {
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
}
MGLOG_D("ReadPixels: Restoring previous pixel pack buffer binding %u", prevPixelPackBuffer);
MG_External::GLES::glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
g_GLESFuncs.glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
} else {
if (esFormat == GL_RGBA && format == GL_BGRA && esType == GL_UNSIGNED_BYTE && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
if (esFormat == GL_RGBA && format == GL_BGRA && esType == GL_UNSIGNED_BYTE &&
type == GL_UNSIGNED_INT_8_8_8_8_REV) {
MGLOG_D("ReadPixels: ProcessColorSwizzle BGRA (not implemented)");
}
}
@@ -1491,4 +1485,89 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("GetTexImage: finished");
}
} // namespace MobileGL::MG_Backend::DirectGLES
void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs) {
g_EGLFuncs = eglFuncs;
}
void SetGLESFuncsTable(const MG_External::GLESFunctionsTable& glesFuncs) {
g_GLESFuncs = glesFuncs;
}
void SetGLESCapabilities(const MG_External::GLESCapabilities& capabilities) {
g_GLESCapabilities = capabilities;
}
static EGLDisplay g_Display = EGL_NO_DISPLAY;
static EGLContext g_Context = EGL_NO_CONTEXT;
static EGLSurface g_Surface = EGL_NO_SURFACE;
static EGLConfig g_Config = nullptr;
Bool InitWindowSurface(NativeWindowType window) {
// TODO: handle custom EGL paramters
if (!window) return false;
g_Display = g_EGLFuncs.eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (g_Display == EGL_NO_DISPLAY) return false;
if (!g_EGLFuncs.eglInitialize(g_Display, nullptr, nullptr)) return false;
g_EGLFuncs.eglBindAPI(EGL_OPENGL_ES_API);
const EGLint configAttribs[] = {EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES3_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
24,
EGL_STENCIL_SIZE,
8,
EGL_NONE};
EGLint numConfigs = 0;
if (!g_EGLFuncs.eglChooseConfig(g_Display, configAttribs, &g_Config, 1, &numConfigs) || numConfigs == 0)
return false;
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
g_Context = g_EGLFuncs.eglCreateContext(g_Display, g_Config, EGL_NO_CONTEXT, contextAttribs);
if (g_Context == EGL_NO_CONTEXT) return false;
g_Surface = g_EGLFuncs.eglCreateWindowSurface(g_Display, g_Config, window, nullptr);
if (g_Surface == EGL_NO_SURFACE) return false;
if (!g_EGLFuncs.eglMakeCurrent(g_Display, g_Surface, g_Surface, g_Context)) return false;
MGLOG_D("EGL context created successfully: display=%p, surface=%p, context=%p. window=%p", g_Display, g_Surface,
g_Context, window);
return true;
}
void Present() {
if (g_Display != EGL_NO_DISPLAY && g_Surface != EGL_NO_SURFACE) {
g_EGLFuncs.eglSwapBuffers(g_Display, g_Surface);
}
}
void DestroyEGLContext() {
if (g_Display != EGL_NO_DISPLAY) {
g_EGLFuncs.eglMakeCurrent(g_Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (g_Context != EGL_NO_CONTEXT) {
g_EGLFuncs.eglDestroyContext(g_Display, g_Context);
g_Context = EGL_NO_CONTEXT;
}
if (g_Surface != EGL_NO_SURFACE) {
g_EGLFuncs.eglDestroySurface(g_Display, g_Surface);
g_Surface = EGL_NO_SURFACE;
}
g_EGLFuncs.eglTerminate(g_Display);
g_Display = EGL_NO_DISPLAY;
}
}
} // namespace MobileGL::MG_Backend::DirectGLES
+11 -1
View File
@@ -10,6 +10,7 @@
#include <Includes.h>
#include <MG_State/GLState/TextureState/TextureState.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#define CallAndCheck(operation) \
MGLOG_D("Call GLES func: %s", #operation); \
@@ -55,5 +56,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
const GLubyte* GetString(GLenum name);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
Bool InitWindowSurface(NativeWindowType window);
void Present();
void SetEGLFuncsTable(const MG_External::EGLFunctionsTable& eglFuncs);
void SetGLESFuncsTable(const MG_External::GLESFunctionsTable& glesFuncs);
void SetGLESCapabilities(const MG_External::GLESCapabilities& capabilities);
void DestroyEGLContext();
} // namespace MobileGL::MG_Backend::DirectGLES
extern MG_External::EGLFunctionsTable g_EGLFuncs;
extern MG_External::GLESFunctionsTable g_GLESFuncs;
extern MG_External::GLESCapabilities g_GLESCapabilities;
} // namespace MobileGL::MG_Backend::DirectGLES
+102 -104
View File
@@ -35,10 +35,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenBuffers(1, &m_backendBufferId);
g_GLESFuncs.glGenBuffers(1, &m_backendBufferId);
if (m_backendBufferId == 0) {
MGLOG_E("Failed to generate buffer object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Generated buffer object with ID: %u.", m_backendBufferId);
}
@@ -117,7 +117,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLenum usage = MG_Util::ConvertBufferUsageToGLEnum(stateBufferObject->GetUsage());
Bind();
MG_External::GLES::glBufferData(TempBufferTarget, size, data, usage);
g_GLESFuncs.glBufferData(TempBufferTarget, size, data, usage);
}
void BackendBufferObject::SyncToBackend_glBufferSubData(
@@ -138,8 +138,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (const auto& range : ranges) {
Bind();
MG_External::GLES::glBufferSubData(TempBufferTarget, range.start, range.end - range.start,
reinterpret_cast<const char*>(data) + range.start);
g_GLESFuncs.glBufferSubData(TempBufferTarget, range.start, range.end - range.start,
reinterpret_cast<const char*>(data) + range.start);
}
}
@@ -159,20 +159,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
SizeT minStart = ranges.GetOverallMinStart();
SizeT maxEnd = ranges.GetOverallMaxEnd();
Bind();
void* mappedData = MG_External::GLES::glMapBufferRange(
TempBufferTarget, minStart, maxEnd - minStart,
(invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) | (unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) |
GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
void* mappedData = g_GLESFuncs.glMapBufferRange(TempBufferTarget, minStart, maxEnd - minStart,
(invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) |
(unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) |
GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
const void* data = stateBufferObject->GetDataReadOnly()->data();
if (mappedData) {
MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId);
Memcpy(mappedData, reinterpret_cast<const char*>(data) + minStart, maxEnd - minStart);
// Explicitly flush the dirty ranges
for (const auto& range : ranges) {
MG_External::GLES::glFlushMappedBufferRange(TempBufferTarget, range.start - minStart,
range.end - range.start);
g_GLESFuncs.glFlushMappedBufferRange(TempBufferTarget, range.start - minStart,
range.end - range.start);
}
MG_External::GLES::glUnmapBuffer(TempBufferTarget);
g_GLESFuncs.glUnmapBuffer(TempBufferTarget);
} else {
MGLOG_E("Failed to map buffer with ID: %u", m_backendBufferId);
}
@@ -188,7 +188,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
g_boundVertexBufferObject = this;
}
MG_External::GLES::glBindBuffer(target, m_backendBufferId);
g_GLESFuncs.glBindBuffer(target, m_backendBufferId);
}
UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>> g_backendBufferObjects;
@@ -200,10 +200,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenVertexArrays(1, &m_backendVAOId);
g_GLESFuncs.glGenVertexArrays(1, &m_backendVAOId);
if (m_backendVAOId == 0) {
MGLOG_E("Failed to generate vertex array object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Generated vertex array object with ID: %u.", m_backendVAOId);
}
@@ -213,7 +213,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindVertexArray(m_backendVAOId);
g_GLESFuncs.glBindVertexArray(m_backendVAOId);
}
void BackendVertexArrayObject::BindAttributeBuffer(Uint index,
@@ -256,9 +256,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions[attribIndex].SwitchVersion;
if (needsSyncSwitch) {
if (attrib.Enabled) {
MG_External::GLES::glEnableVertexAttribArray(attribIndex);
g_GLESFuncs.glEnableVertexAttribArray(attribIndex);
} else {
MG_External::GLES::glDisableVertexAttribArray(attribIndex);
g_GLESFuncs.glDisableVertexAttribArray(attribIndex);
}
}
@@ -271,17 +271,17 @@ namespace MobileGL::MG_Backend::DirectGLES {
BindAttributeBuffer(attribIndex, attrib);
if (!attrib.IsInteger) {
MG_External::GLES::glVertexAttribPointer(
g_GLESFuncs.glVertexAttribPointer(
attribIndex, attrib.Size, MG_Util::ConvertDataTypeToGLEnum(attrib.Type),
attrib.Normalized ? GL_TRUE : GL_FALSE, attrib.Stride, (const void*)attrib.Offset);
} else {
MG_External::GLES::glVertexAttribIPointer(attribIndex, attrib.Size,
MG_Util::ConvertDataTypeToGLEnum(attrib.Type),
attrib.Stride, (const void*)attrib.Offset);
g_GLESFuncs.glVertexAttribIPointer(attribIndex, attrib.Size,
MG_Util::ConvertDataTypeToGLEnum(attrib.Type), attrib.Stride,
(const void*)attrib.Offset);
}
if (needsSyncFormat) {
MG_External::GLES::glVertexAttribDivisor(attribIndex, attrib.Divisor);
g_GLESFuncs.glVertexAttribDivisor(attribIndex, attrib.Divisor);
}
}
@@ -312,10 +312,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenTextures(1, &m_backendTextureId);
g_GLESFuncs.glGenTextures(1, &m_backendTextureId);
if (m_backendTextureId == 0) {
MGLOG_E("Failed to generate texture object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Generated texture object with ID: %u.", m_backendTextureId);
}
@@ -332,7 +332,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto targetN = static_cast<SizeT>(MG_Util::ConvertGLEnumToTextureTarget(target));
if (this == g_boundTexturesCache[unit][targetN]) return;
MG_External::GLES::glBindTexture(target, m_backendTextureId);
g_GLESFuncs.glBindTexture(target, m_backendTextureId);
g_boundTexturesCache[unit][targetN] = this;
}
@@ -430,20 +430,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
levelDirty ? "true" : "false");
errorLopper.Clear();
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
auto textureTarget = stateTextureObject->GetTarget();
// TODO: handle more texture types
switch (textureTarget) {
case TextureTarget::Texture2D:
case TextureTarget::TextureCubeMap: {
MG_External::GLES::glTexImage2D(
glUploadTarget, static_cast<GLint>(level), glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
0, glFormat, glType, pData);
g_GLESFuncs.glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()),
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType,
pData);
break;
}
case TextureTarget::Texture3D: {
MG_External::GLES::glTexImage3D(
g_GLESFuncs.glTexImage3D(
glUploadTarget, static_cast<GLint>(level), glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
static_cast<GLsizei>(levelTexelSize.z()), 0, glFormat, glType, pData);
@@ -498,16 +498,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
textureMipmapObject->GetMipmapTexelSize(uploadTarget, level).y(), byteSize);
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
g_GLESFuncs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
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());
});
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
textureMipmapObject->MapMipmapData(uploadTarget, level));
g_GLESFuncs.glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
static_cast<GLsizei>(texelSize.x()),
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
textureMipmapObject->MapMipmapData(uploadTarget, level));
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
}
}
@@ -546,7 +546,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glFormat,
&glType);
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
g_GLESFuncs.glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
break;
}
default:
@@ -604,8 +604,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#define SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \
if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \
MG_External::GLES::glTexParameteri(target, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
g_GLESFuncs.glTexParameteri(target, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
m_cacheSamplerParameters.internalName = samplerParams.internalName; \
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, \
t = MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)](GLenum err) { \
@@ -616,14 +616,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter ||
m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) {
MG_External::GLES::glTexParameteri(
g_GLESFuncs.glTexParameteri(
target, GL_TEXTURE_MIN_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.minFilter, samplerParams.mipmapMode));
m_cacheSamplerParameters.minFilter = samplerParams.minFilter;
m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode;
}
if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) {
MG_External::GLES::glTexParameteri(
g_GLESFuncs.glTexParameteri(
target, GL_TEXTURE_MAG_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None));
m_cacheSamplerParameters.magFilter = samplerParams.magFilter;
@@ -638,11 +638,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(compareFunc, GL_TEXTURE_COMPARE_FUNC, CompareFunc)
SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(compareMode, GL_TEXTURE_COMPARE_MODE, CompareMode)
if (m_cacheSamplerParameters.minLod != samplerParams.minLod) {
MG_External::GLES::glTexParameterf(target, GL_TEXTURE_MIN_LOD, samplerParams.minLod);
g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MIN_LOD, samplerParams.minLod);
m_cacheSamplerParameters.minLod = samplerParams.minLod;
}
if (m_cacheSamplerParameters.maxLod != samplerParams.maxLod) {
MG_External::GLES::glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
g_GLESFuncs.glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
m_cacheSamplerParameters.maxLod = samplerParams.maxLod;
}
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
@@ -693,14 +693,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& levelRange = stateTextureObject->GetLevelRange();
if (m_cacheLodRange.x() != levelRange.x()) {
MG_External::GLES::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();
}
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());
});
if (m_cacheLodRange.y() != levelRange.y()) {
MG_External::GLES::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();
}
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
@@ -711,8 +711,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (swizzleParams != m_cacheSwizzleParams) {
#define SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED(func, glEnum) \
if (m_cacheSwizzleParams.func != swizzleParams.func) { \
MG_External::GLES::glTexParameteri(target, glEnum, \
MG_Util::ConvertTextureSwizzleParamToGLEnum(swizzleParams.func)); \
g_GLESFuncs.glTexParameteri(target, glEnum, MG_Util::ConvertTextureSwizzleParamToGLEnum(swizzleParams.func)); \
m_cacheSwizzleParams.func = swizzleParams.func; \
}
SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED(r(), GL_TEXTURE_SWIZZLE_R);
@@ -729,7 +728,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (m_cacheBorderColor != stateTextureObject->GetBorderColor()) {
const auto& borderColor = stateTextureObject->GetBorderColor();
GLfloat borderColorArray[4] = {borderColor.x(), borderColor.y(), borderColor.z(), borderColor.w()};
MG_External::GLES::glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColorArray);
g_GLESFuncs.glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColorArray);
m_cacheBorderColor = borderColor;
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());
@@ -741,7 +740,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (unit == g_activeTextureUnit) {
return;
}
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
g_GLESFuncs.glActiveTexture(GL_TEXTURE0 + unit);
g_activeTextureUnit = unit;
}
@@ -753,7 +752,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto targetN = static_cast<SizeT>(MG_Util::ConvertGLEnumToTextureTarget(target));
if (g_boundTexturesCache[unit][targetN] == nullptr) return;
MG_External::GLES::glBindTexture(target, 0);
g_GLESFuncs.glBindTexture(target, 0);
g_boundTexturesCache[unit][targetN] = nullptr;
}
@@ -770,10 +769,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenFramebuffers(1, &m_backendFBOId);
g_GLESFuncs.glGenFramebuffers(1, &m_backendFBOId);
if (m_backendFBOId == 0) {
MGLOG_E("Failed to generate framebuffer object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Generated framebuffer object with ID: %u.", m_backendFBOId);
}
@@ -784,9 +783,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
if (target == FramebufferTarget::Read)
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, m_backendFBOId);
g_GLESFuncs.glBindFramebuffer(GL_READ_FRAMEBUFFER, m_backendFBOId);
else
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_backendFBOId);
g_GLESFuncs.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_backendFBOId);
}
Bool BackendFramebufferObject::SyncAttachmentObject(
@@ -802,9 +801,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendTextureObject = backendTextureIt->second;
auto glTextureTarget = MG_Util::ConvertTextureTargetToGLEnum(textureObject->GetTarget());
backendTextureObject->Bind(glTextureTarget);
MG_External::GLES::glFramebufferTexture2D(glFBOTarget, glBackendAttachment, glTextureTarget,
backendTextureObject->GetBackendTextureId(),
static_cast<GLint>(attachmentObject.GetTextureLevel()));
g_GLESFuncs.glFramebufferTexture2D(glFBOTarget, glBackendAttachment, glTextureTarget,
backendTextureObject->GetBackendTextureId(),
static_cast<GLint>(attachmentObject.GetTextureLevel()));
} else if (attachmentObject.IsRenderbuffer()) {
const auto& renderbufferObject = attachmentObject.GetRenderbuffer();
const auto& backendRenderbufferIt =
@@ -819,8 +818,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
backendRenderbufferObject->SyncToBackend(renderbufferObject);
backendRenderbufferObject->Bind();
MG_External::GLES::glFramebufferRenderbuffer(glFBOTarget, glBackendAttachment, GL_RENDERBUFFER,
backendRenderbufferObject->GetBackendRenderbufferId());
g_GLESFuncs.glFramebufferRenderbuffer(glFBOTarget, glBackendAttachment, GL_RENDERBUFFER,
backendRenderbufferObject->GetBackendRenderbufferId());
}
return true;
}
@@ -872,7 +871,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
nEffectiveBuffers = i + 1;
}
MG_External::GLES::glDrawBuffers(nEffectiveBuffers, m_backendDrawBuffers);
g_GLESFuncs.glDrawBuffers(nEffectiveBuffers, m_backendDrawBuffers);
}
// 2. Remap read buffer
@@ -884,7 +883,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (m_backendReadBuffer != glBackendReadBuffer) {
m_backendReadBuffer = glBackendReadBuffer;
MG_External::GLES::glReadBuffer(glBackendReadBuffer);
g_GLESFuncs.glReadBuffer(glBackendReadBuffer);
}
}
@@ -917,14 +916,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertGLEnumToString(glBackendAttachment).c_str(),
m_syncedFrontendAttachmentVersions[i]);
GLint objectType = GL_NONE;
MG_External::GLES::glGetFramebufferAttachmentParameteriv(
g_GLESFuncs.glGetFramebufferAttachmentParameteriv(
glFBOTarget, glBackendAttachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &objectType);
MOBILEGL_ASSERT((objectType == GL_NONE) ||
(attachmentObject.IsTexture() && objectType == GL_TEXTURE) ||
(attachmentObject.IsRenderbuffer() && objectType == GL_RENDERBUFFER),
"Attachment type not match!");
GLint objectName = 0;
MG_External::GLES::glGetFramebufferAttachmentParameteriv(
g_GLESFuncs.glGetFramebufferAttachmentParameteriv(
glFBOTarget, glBackendAttachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &objectName);
// Verify that the backend object's name and parameters match the frontend attachment state
if (attachmentObject.IsTexture()) {
@@ -939,7 +938,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
objectName, backendTexId, textureObject->GetExternalIndex());
GLint texLevel = 0;
MG_External::GLES::glGetFramebufferAttachmentParameteriv(
g_GLESFuncs.glGetFramebufferAttachmentParameteriv(
glFBOTarget, glBackendAttachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &texLevel);
MOBILEGL_ASSERT(texLevel == static_cast<GLint>(attachmentObject.GetTextureLevel()),
"Attachment texture level mismatch between GLES and state object.");
@@ -989,10 +988,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_backendProgramId = MG_External::GLES::glCreateProgram();
m_backendProgramId = g_GLESFuncs.glCreateProgram();
if (m_backendProgramId == 0) {
MGLOG_E("Failed to create program object in backend.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Created backend program object with ID: %u", m_backendProgramId);
@@ -1005,7 +1004,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
if (m_backendProgramId != 0) {
MGLOG_D("Deleting backend program object with ID: %u", m_backendProgramId);
MG_External::GLES::glDeleteProgram(m_backendProgramId);
g_GLESFuncs.glDeleteProgram(m_backendProgramId);
}
}
@@ -1029,19 +1028,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Detach all existing shaders
GLint attachedCount = 0;
MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_ATTACHED_SHADERS, &attachedCount);
g_GLESFuncs.glGetProgramiv(m_backendProgramId, GL_ATTACHED_SHADERS, &attachedCount);
MGLOG_D("Currently attached shaders count: %d", attachedCount);
if (attachedCount > 0) {
Vector<GLuint> attachedShaders(attachedCount);
GLsizei actualCount;
MG_External::GLES::glGetAttachedShaders(m_backendProgramId, attachedCount, &actualCount,
attachedShaders.data());
g_GLESFuncs.glGetAttachedShaders(m_backendProgramId, attachedCount, &actualCount,
attachedShaders.data());
MGLOG_D("Detaching %d existing shaders from program %u", actualCount, m_backendProgramId);
for (GLsizei i = 0; i < actualCount; ++i) {
MGLOG_D("Detaching shader ID: %u from program %u", attachedShaders[i], m_backendProgramId);
MG_External::GLES::glDetachShader(m_backendProgramId, attachedShaders[i]);
g_GLESFuncs.glDetachShader(m_backendProgramId, attachedShaders[i]);
}
}
@@ -1060,7 +1059,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (int index = 0; index < attachedShaders.size(); ++index) {
auto& shader = attachedShaders[index];
GLenum glShaderType = MG_Util::ConvertShaderStageToGLEnum(shader->GetShaderStage());
GLuint backendShaderId = MG_External::GLES::glCreateShader(glShaderType);
GLuint backendShaderId = g_GLESFuncs.glCreateShader(glShaderType);
if (backendShaderId == 0) {
MGLOG_E("Failed to create backend shader for attachment.");
@@ -1111,37 +1110,37 @@ namespace MobileGL::MG_Backend::DirectGLES {
const char* sourceCStr = source.c_str();
MGLOG_D("Setting shader source for backend shader ID: %u\nsrc:\n%s", backendShaderId, sourceCStr);
MG_External::GLES::glShaderSource(backendShaderId, 1, &sourceCStr, nullptr);
MG_External::GLES::glCompileShader(backendShaderId);
g_GLESFuncs.glShaderSource(backendShaderId, 1, &sourceCStr, nullptr);
g_GLESFuncs.glCompileShader(backendShaderId);
GLint compileStatus;
MG_External::GLES::glGetShaderiv(backendShaderId, GL_COMPILE_STATUS, &compileStatus);
g_GLESFuncs.glGetShaderiv(backendShaderId, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus == GL_FALSE) {
GLint logLength;
MG_External::GLES::glGetShaderiv(backendShaderId, GL_INFO_LOG_LENGTH, &logLength);
g_GLESFuncs.glGetShaderiv(backendShaderId, GL_INFO_LOG_LENGTH, &logLength);
Vector<GLchar> log(logLength);
MG_External::GLES::glGetShaderInfoLog(backendShaderId, logLength, nullptr, log.data());
g_GLESFuncs.glGetShaderInfoLog(backendShaderId, logLength, nullptr, log.data());
MGLOG_E("Shader compilation failed for backend ID %u: %s", backendShaderId, log.data());
continue;
}
MGLOG_D("Attaching shader ID: %u to program %u", backendShaderId, m_backendProgramId);
MG_External::GLES::glAttachShader(m_backendProgramId, backendShaderId);
g_GLESFuncs.glAttachShader(m_backendProgramId, backendShaderId);
MGLOG_D("Processed shader source length: %zu", source.length());
}
// Link program
MGLOG_D("Linking program %u", m_backendProgramId);
MG_External::GLES::glLinkProgram(m_backendProgramId);
g_GLESFuncs.glLinkProgram(m_backendProgramId);
GLint linkStatus;
MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_LINK_STATUS, &linkStatus);
g_GLESFuncs.glGetProgramiv(m_backendProgramId, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
GLint logLength;
MG_External::GLES::glGetProgramiv(m_backendProgramId, GL_INFO_LOG_LENGTH, &logLength);
g_GLESFuncs.glGetProgramiv(m_backendProgramId, GL_INFO_LOG_LENGTH, &logLength);
Vector<GLchar> log(logLength);
MG_External::GLES::glGetProgramInfoLog(m_backendProgramId, logLength, nullptr, log.data());
g_GLESFuncs.glGetProgramInfoLog(m_backendProgramId, logLength, nullptr, log.data());
MGLOG_E("Program %u linking failed for %u: %s", stateProgramObject->GetExternalIndex(),
m_backendProgramId, log.data());
} else {
@@ -1150,11 +1149,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Create global UBO
if (stateProgramObject->GetUBOSize() > 0) {
MG_External::GLES::glGenBuffers(1, &m_backendGlobalUBOId);
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, m_backendGlobalUBOId);
MG_External::GLES::glBufferData(GL_UNIFORM_BUFFER, stateProgramObject->GetUBOSize(), nullptr,
GL_STREAM_DRAW);
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0);
g_GLESFuncs.glGenBuffers(1, &m_backendGlobalUBOId);
g_GLESFuncs.glBindBuffer(GL_UNIFORM_BUFFER, m_backendGlobalUBOId);
g_GLESFuncs.glBufferData(GL_UNIFORM_BUFFER, stateProgramObject->GetUBOSize(), nullptr, GL_STREAM_DRAW);
g_GLESFuncs.glBindBuffer(GL_UNIFORM_BUFFER, 0);
} else {
m_backendGlobalUBOId = 0;
}
@@ -1168,7 +1166,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MGLOG_D("Using program %u", m_backendProgramId);
MG_External::GLES::glUseProgram(m_backendProgramId);
g_GLESFuncs.glUseProgram(m_backendProgramId);
}
} // namespace PrgramImpl
@@ -1177,10 +1175,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenSamplers(1, &m_backendSamplerId);
g_GLESFuncs.glGenSamplers(1, &m_backendSamplerId);
if (m_backendSamplerId == 0) {
MGLOG_E("Failed to generate sampler object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
} else {
MGLOG_D("Generated sampler object with ID: %u.", m_backendSamplerId);
}
@@ -1211,21 +1209,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
#define SYNC_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \
if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \
MG_External::GLES::glSamplerParameteri(m_backendSamplerId, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
g_GLESFuncs.glSamplerParameteri(m_backendSamplerId, glName, \
MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \
m_cacheSamplerParameters.internalName = samplerParams.internalName; \
}
if (m_cacheSamplerParameters.minFilter != samplerParams.minFilter ||
m_cacheSamplerParameters.mipmapMode != samplerParams.mipmapMode) {
MG_External::GLES::glSamplerParameteri(
g_GLESFuncs.glSamplerParameteri(
m_backendSamplerId, GL_TEXTURE_MIN_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.minFilter, samplerParams.mipmapMode));
m_cacheSamplerParameters.minFilter = samplerParams.minFilter;
m_cacheSamplerParameters.mipmapMode = samplerParams.mipmapMode;
}
if (m_cacheSamplerParameters.magFilter != samplerParams.magFilter) {
MG_External::GLES::glSamplerParameteri(
g_GLESFuncs.glSamplerParameteri(
m_backendSamplerId, GL_TEXTURE_MAG_FILTER,
MG_Util::ConvertSamplerFilterModeToGLEnum(samplerParams.magFilter, SamplerMipmapMode::None));
m_cacheSamplerParameters.magFilter = samplerParams.magFilter;
@@ -1237,11 +1235,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
SYNC_SAMPLER_PARAM_IF_CHANGED(compareFunc, GL_TEXTURE_COMPARE_FUNC, CompareFunc)
SYNC_SAMPLER_PARAM_IF_CHANGED(compareMode, GL_TEXTURE_COMPARE_MODE, CompareMode)
if (m_cacheSamplerParameters.minLod != samplerParams.minLod) {
MG_External::GLES::glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MIN_LOD, samplerParams.minLod);
g_GLESFuncs.glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MIN_LOD, samplerParams.minLod);
m_cacheSamplerParameters.minLod = samplerParams.minLod;
}
if (m_cacheSamplerParameters.maxLod != samplerParams.maxLod) {
MG_External::GLES::glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
g_GLESFuncs.glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MAX_LOD, samplerParams.maxLod);
m_cacheSamplerParameters.maxLod = samplerParams.maxLod;
}
#undef SYNC_SAMPLER_PARAM_IF_CHANGED
@@ -1254,7 +1252,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
if (g_boundSamplersCache[unit] == this) return;
MG_External::GLES::glBindSampler(static_cast<GLenum>(unit), m_backendSamplerId);
g_GLESFuncs.glBindSampler(static_cast<GLenum>(unit), m_backendSamplerId);
g_boundSamplersCache[unit] = this;
}
@@ -1268,7 +1266,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
void UnbindSampler(Uint unit) {
if (g_boundSamplersCache[unit] == nullptr) return;
MG_External::GLES::glBindSampler(static_cast<GLenum>(unit), 0);
g_GLESFuncs.glBindSampler(static_cast<GLenum>(unit), 0);
g_boundSamplersCache[unit] = nullptr;
}
@@ -1282,10 +1280,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGenRenderbuffers(1, &m_backendRBOId);
g_GLESFuncs.glGenRenderbuffers(1, &m_backendRBOId);
if (m_backendRBOId == 0) {
MGLOG_E("Failed to generate renderbuffer object.");
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str());
MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(g_GLESFuncs.glGetError()).c_str());
}
}
@@ -1293,7 +1291,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindRenderbuffer(GL_RENDERBUFFER, m_backendRBOId);
g_GLESFuncs.glBindRenderbuffer(GL_RENDERBUFFER, m_backendRBOId);
}
void BackendRenderbufferObject::SyncToBackend(
@@ -1325,8 +1323,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType);
MG_External::GLES::glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
static_cast<GLsizei>(height));
g_GLESFuncs.glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast<GLsizei>(width),
static_cast<GLsizei>(height));
m_cacheInternalFormat = internalFormat;
m_cacheWidth = width;
+3 -3
View File
@@ -30,8 +30,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
using namespace MobileGL::MG_Util::TextureFormatProcessor;
auto options = (MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None
: PixelFormatNormalizeOptionBit::NoNorm16;
auto options = (g_GLESCapabilities.SupportsNorm16Texture) ? PixelFormatNormalizeOptionBit::None
: PixelFormatNormalizeOptionBit::NoNorm16;
NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), options,
outInternalFormat, outFormat, outType);
}
@@ -125,7 +125,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
while (GLenum err = MG_External::GLES::glGetError() != GL_NO_ERROR) {
while (GLenum err = g_GLESFuncs.glGetError() != GL_NO_ERROR) {
MGLOG_E("-> GLES Error: %s", MG_Util::ConvertGLEnumToString(err).c_str());
}
}
+50 -70
View File
@@ -6,83 +6,63 @@
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#include "Backends.h"
#include "MG_Util/Types.h"
#include "BackendObjects.h"
#include <Config.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#include <MG_Util/Converters/MGToStr/GLExtensionConverter.h>
namespace MobileGL {
namespace MG_Config {
UniquePtr<RendererInfo> RendererInfoPtr = nullptr;
} // namespace MG_Config
namespace MG_Backend {
void LogBackendInfo() {
if (MG_Config::RendererInfoPtr) {
MGLOG_I("MobileGL Backend Info:");
MGLOG_I(" Renderer Name: %s", MG_Config::RendererInfoPtr->RendererName.c_str());
MGLOG_I(" Backend Name: %s", MG_Config::RendererInfoPtr->BackendName.c_str());
if (MG_Config::RendererInfoPtr->ExtraVendor) {
MGLOG_I(" Extra Vendor Info: %s", MG_Config::RendererInfoPtr->ExtraVendor->c_str());
}
MGLOG_I(" Target OpenGL Version: %d.%d",
MG_Config::RendererInfoPtr->RendererGLInfo.TargetGLVersion.Major,
MG_Config::RendererInfoPtr->RendererGLInfo.TargetGLVersion.Minor);
MGLOG_I(" Target GLSL Version: %d.%d",
MG_Config::RendererInfoPtr->RendererGLInfo.TargetGLSLVersion.Major,
MG_Config::RendererInfoPtr->RendererGLInfo.TargetGLSLVersion.Minor);
MGLOG_I(" OpenGL Extensions:");
for (const auto& ext : MG_Config::RendererInfoPtr->RendererGLInfo.Extensions) {
MGLOG_I(" - %s", MG_Util::ConvertGLExtToString(ext).c_str());
}
} else {
MGLOG_W(" No renderer info available");
}
namespace MobileGL::MG_Backend {
void LogBackendInfo() {
if (!pActiveBackendObject) {
MGLOG_W("No active backend object, cannot log backend info");
return;
}
Bool InitSpecificBackendLibs() {
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_DILIGENT
// Nothing to do
MGLOG_D("Diligent Engine backend loaded");
return true;
#elif MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
Bool result = MG_Util::BackendLoader::GLES::Init();
MGLOG_D("DirectGLES backend loaded, GLES version: %d.%d", MG_External::GLES::g_glesCaps.version.Major,
MG_External::GLES::g_glesCaps.version.Minor);
return result;
#else
MGLOG_W("Unknown backend, skipping backend initialization");
const auto& rendererInfo = pActiveBackendObject->GetRendererInfo();
MGLOG_I("MobileGL Backend Info:");
MGLOG_I(" Renderer Name: %s", rendererInfo.RendererName.c_str());
MGLOG_I(" Backend Name: %s", rendererInfo.BackendName.c_str());
if (rendererInfo.ExtraVendor) {
MGLOG_I(" Extra Vendor Info: %s", rendererInfo.ExtraVendor->c_str());
}
MGLOG_I(" Target OpenGL Version: %d.%d", rendererInfo.RendererGLInfo.TargetGLVersion.Major,
rendererInfo.RendererGLInfo.TargetGLVersion.Minor);
MGLOG_I(" Target GLSL Version: %d.%d", rendererInfo.RendererGLInfo.TargetGLSLVersion.Major,
rendererInfo.RendererGLInfo.TargetGLSLVersion.Minor);
MGLOG_I(" OpenGL Extensions:");
for (const auto& ext : rendererInfo.RendererGLInfo.Extensions) {
MGLOG_I(" - %s", MG_Util::ConvertGLExtToString(ext).c_str());
}
}
Bool InitSpecificBackendLibs() {
if (!pActiveBackendObject) {
MGLOG_W("No active backend object, cannot initialize backend libraries");
return false;
#endif
}
pActiveBackendObject->Initialize();
gBackendFunctionsTable = pActiveBackendObject->GetBackendFunctions();
return true;
}
void Init() {
MGLOG_D("Initializing MobileGL Backend...");
switch (MG_Config::ActiveBackendType) {
case BackendType::DirectGLES:
pActiveBackendObject = MakeUnique<DirectGLES::BackendObject_DirectGLES>();
break;
case BackendType::Unknown:
default:
MGLOG_W("Unknown backend type, defaulting to unknown backend");
pActiveBackendObject = nullptr;
}
void Init() {
MGLOG_D("Initializing MobileGL Backend...");
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_DILIGENT
switch (MG_Config::Backend::Diligent::SpecificBackend) {
case MG_Backend::Diligent::SpecificBackendType::Vulkan:
MG_Config::RendererInfoPtr = MakeUnique<RendererInfo>(Diligent::RendererInfoVulkan);
break;
case MG_Backend::Diligent::SpecificBackendType::Metal:
MG_Config::RendererInfoPtr = MakeUnique<RendererInfo>(Diligent::RendererInfoMetal);
break;
default:
throw RuntimeError("Unsupported renderer type");
}
#elif MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Config::RendererInfoPtr = MakeUnique<RendererInfo>(DirectGLES::RendererInfo);
#else
MG_Config::RendererInfoPtr = MakeUnique<RendererInfo>(Unknown::RendererInfoUnknown);
#endif
Bool result = InitSpecificBackendLibs();
if (!result) {
MGLOG_W("Failed to initialize MobileGL backend libraries");
return;
}
LogBackendInfo();
Bool result = InitSpecificBackendLibs();
if (!result) {
MGLOG_W("Failed to initialize MobileGL backend libraries");
return;
}
} // namespace MG_Backend
} // namespace MobileGL
LogBackendInfo();
}
} // namespace MobileGL::MG_Backend