[Feat] (MG_Backend/DirectGLES): implement glCopyTexImage2D/CopyTexSubImage2D

This commit is contained in:
2025-11-16 12:44:41 +08:00
parent 131c9a2db6
commit 95e086442c
8 changed files with 188 additions and 8 deletions
+2
View File
@@ -85,6 +85,8 @@ set(SOURCE_FILES
MobileGL/MG_Util/Converters/GLToMG/ProgramEnumConverter.cpp MobileGL/MG_Util/Converters/GLToMG/ProgramEnumConverter.cpp
MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp
MobileGL/MG_Util/Classifiers/TextureEnumClassifier.cpp
MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp
MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp
MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp
@@ -1,6 +1,9 @@
#include "DirectGLES.h" #include "DirectGLES.h"
#include "Utils.h" #include "Utils.h"
#include "Managers.h" #include "Managers.h"
#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h"
#include "MG_Util/Classifiers/TextureEnumClassifier.h"
#include "MG_Util/Metrics/TextureMetrics.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h> #include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h> #include <MG_Util/BackendLoaders/OpenGL/Loader.h>
@@ -471,6 +474,106 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
} }
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) {
MGLOG_D("%s: Backend", __func__);
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
GLint realInternalFormat;
MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat);
internalformat = (GLenum)realInternalFormat;
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
GLenum format = GL_DEPTH_COMPONENT;
GLenum type = GL_UNSIGNED_INT;
TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
if (!isDepthFormat) {
MG_External::GLES::glCopyTexImage2D(
target, level, internalformat, x, y, width, height, border);
} else {
MGLOG_D("%s: Backend depth", __func__);
MG_External::GLES::glTexImage2D(target, level, (GLint)internalformat, width, height, border, format, type, nullptr);
FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw);
GLint currentTex;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &currentTex);
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, currentTex, level);
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// Protector will automatically revert to previous fbo states
return;
}
MG_External::GLES::glBlitFramebuffer(x, y, x + width, y + height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
// Protector will automatically revert to previous fbo states
}
// TODO: potential desync between MG_State and backend
auto activeUnit =
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
auto textureObject = bindingSlot.GetBoundObject();
const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(mglInternalFormat, texturePixelDataType);
const SizeT totalBytes = width * height * bytesPerPixel;
MG_State::GLState::MipmapLevelInput mipmap =
MG_State::GLState::MipmapLevelInput({width, height, 1}, level, false, 0,
{nullptr, totalBytes});
textureObject->SetInternalFormat(mglInternalFormat);
textureObject->SetMipmapLevel(mipmap);
}
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height) {
MGLOG_D("%s: Backend", __func__);
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Read);
GLenum internalFormat;
MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internalFormat);
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat);
bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat);
bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat);
if (!isDepthFormat) {
MG_External::GLES::glCopyTexSubImage2D(
target, level, xoffset, yoffset, x, y, width, height);
} else {
MGLOG_D("%s: Backend depth", __func__);
FramebufferImpl::BackendFramebufferBindingProtector drawFboProtector(GL_DRAW_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector readFboProtector(GL_READ_FRAMEBUFFER);
FramebufferImpl::BackendFramebufferBindingProtector::BindTempFBO(FramebufferTarget::Draw);
GLint currentTex;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &currentTex);
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, currentTex, level);
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
// Protector will automatically revert to previous fbo states
return;
}
MG_External::GLES::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);
// Protector will automatically revert to previous fbo states
}
}
const GLubyte* GetString(GLenum name) { const GLubyte* GetString(GLenum name) {
return MG_External::GLES::glGetString(name); return MG_External::GLES::glGetString(name);
} }
@@ -16,5 +16,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLsizei drawcount, const GLint* basevertex); GLsizei drawcount, const GLint* basevertex);
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 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);
const GLubyte* GetString(GLenum name); const GLubyte* GetString(GLenum name);
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
+17
View File
@@ -1,10 +1,12 @@
#include "DirectGLES.h" #include "DirectGLES.h"
#include "Utils.h" #include "Utils.h"
#include "Managers.h" #include "Managers.h"
#include "MG_Util/Converters/GLToMG/FramebufferEnumConverter.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Util/BackendLoaders/OpenGL/Loader.h> #include <MG_Util/BackendLoaders/OpenGL/Loader.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl { namespace BufferImpl {
@@ -291,6 +293,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() { BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() {
MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding); MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding);
} }
GLuint BackendFramebufferBindingProtector::GetTempFBO(FramebufferTarget target) {
GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target);
GLuint& fbo = (glTarget == GL_DRAW_FRAMEBUFFER) ? s_tempDrawFBO : s_tempReadFBO;
if (fbo == 0) {
MG_External::GLES::glGenFramebuffers(1, &fbo);
}
return fbo;
}
void BackendFramebufferBindingProtector::BindTempFBO(MobileGL::FramebufferTarget target) {
GLuint fbo = GetTempFBO(target);
GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target);
MG_External::GLES::glBindFramebuffer(glTarget, fbo);
}
} // namespace FramebufferImpl } // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
+4
View File
@@ -54,9 +54,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
~BackendFramebufferBindingProtector(); ~BackendFramebufferBindingProtector();
static GLuint GetTempFBO(FramebufferTarget target);
static void BindTempFBO(FramebufferTarget target);
private: private:
GLenum m_target; GLenum m_target;
GLint m_previousBinding = 0; GLint m_previousBinding = 0;
inline static GLuint s_tempReadFBO = 0;
inline static GLuint s_tempDrawFBO = 0;
}; };
} // namespace FramebufferImpl } // namespace FramebufferImpl
+16 -8
View File
@@ -1,5 +1,9 @@
#include "GL_Texture.h" #include "GL_Texture.h"
#include "GL/gl.h" #include "GL/gl.h"
#include "Config.h"
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
#include <MG_Backend/DirectGLES/DirectGLES.h>
#endif
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include "Validators.h" #include "Validators.h"
#include "ProxyTexture.h" #include "ProxyTexture.h"
@@ -804,18 +808,22 @@ namespace MobileGL {
// TODO: implement // TODO: implement
} }
void CopyTexSubImage2D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, void CopyTexSubImage2D_Backend(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height) { GLsizei width, GLsizei height) {
// TODO: implement #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
#endif
} }
void CopyTexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { void CopyTexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
// TODO: implement // TODO: implement
} }
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage2D_Backend(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) { GLsizei height, GLint border) {
// TODO: implement #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
#endif
} }
void CopyTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
@@ -1004,7 +1012,7 @@ namespace MobileGL {
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height) { GLsizei width, GLsizei height) {
CopyTexSubImage2D_State(target, level, xoffset, yoffset, x, y, width, height); CopyTexSubImage2D_Backend(target, level, xoffset, yoffset, x, y, width, height);
} }
void CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) { void CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
@@ -1013,7 +1021,7 @@ namespace MobileGL {
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) { GLsizei height, GLint border) {
CopyTexImage2D_State(target, level, internalformat, x, y, width, height, border); CopyTexImage2D_Backend(target, level, internalformat, x, y, width, height, border);
} }
void CopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
@@ -0,0 +1,32 @@
#include "TextureEnumClassifier.h"
namespace MobileGL {
namespace MG_Util {
bool IsDepthFormatInternalFormat(TextureInternalFormat internalformat) {
switch (internalformat) {
case TextureInternalFormat::DepthComponent16:
case TextureInternalFormat::DepthComponent24:
case TextureInternalFormat::DepthComponent32:
case TextureInternalFormat::DepthComponent32F:
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
case TextureInternalFormat::DepthComponent:
case TextureInternalFormat::DepthStencil:
return true;
default:
return false;
}
}
bool IsStencilFormatInternalFormat(TextureInternalFormat internalformat) {
switch (internalformat) {
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
case TextureInternalFormat::DepthStencil:
return true;
default:
return false;
}
}
} // namespace MG_Util
} // namespace MobileGL
@@ -0,0 +1,10 @@
#pragma once
#include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h>
namespace MobileGL {
namespace MG_Util {
bool IsDepthFormatInternalFormat(TextureInternalFormat internalformat);
bool IsStencilFormatInternalFormat(TextureInternalFormat internalformat);
} // namespace MG_Util
} // namespace MobileGL