diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index b18a3d2e..4710e3a4 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -879,13 +879,13 @@ namespace MobileGL::MG_Backend::DirectGLES { } backendTextureIt->second->Bind(target, activeTextureUnit); - auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + auto mgInternalFormat = textureObject->GetFormat(); GLenum format = GL_DEPTH_COMPONENT; GLenum type = GL_UNSIGNED_INT; - TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type); + TextureImpl::GenerateTextureFormatInfo(mgInternalFormat, &internalformat, &format, &type); MOBILEGL_ASSERT(format != GL_NONE && type != GL_NONE, "%s: cannot GenerateTextureFormatInfo(%s): out internalformat=%s, format=%s, type=%s", - MG_Util::ConvertTextureInternalFormatToString(mglInternalFormat).c_str(), + MG_Util::ConvertTextureInternalFormatToString(mgInternalFormat).c_str(), MG_Util::ConvertGLEnumToString(internalformat).c_str(), MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str()); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); @@ -976,10 +976,10 @@ namespace MobileGL::MG_Backend::DirectGLES { errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); + auto mgInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); - Bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat); - Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat); + Bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mgInternalFormat); + Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mgInternalFormat); if (!isDepthFormat) { MG_External::GLES::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index ba104d13..3fc71b68 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -7,26 +7,27 @@ // End of Source File Header #include "GL_Texture.h" -#include "GL/gl.h" #include "Config.h" -#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES -#include -#endif #include "MG_Util/Types.h" #include "Validators.h" #include "ProxyTexture.h" -#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" -#include "MG_Util/Converters/GLToStr/GLEnumConverter.h" -#include "MG_Util/Texture/TextureFormatProcessor.h" #include #include #include #include +#include +#include +#include #include #include #include #include +#include + +#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES +#include +#endif namespace MobileGL { namespace MG_Impl::GLImpl { @@ -1228,12 +1229,57 @@ namespace MobileGL { void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { - GLenum outInternalFormat, format, type; - MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, - &type); + auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + const auto& currentReadFBO = + MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); + if (!currentReadFBO) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared( + "MG_Impl/GLImpl", "CopyTexImage2D_State", + "No framebuffer is currently bound to the GL_READ_FRAMEBUFFER target.")); + return; + } + + Bool isDepth = MG_Util::IsDepthFormatInternalFormat(internalFormat); + Bool isStencil = MG_Util::IsStencilFormatInternalFormat(internalFormat); + TextureInternalFormat srcInternalFormat = TextureInternalFormat::Unknown; +#define GET_SRC_INTERNAL_FORMAT(AttachmentType) \ + const auto& srcAttachment = currentReadFBO->GetAttachment(AttachmentType); \ + if (srcAttachment.IsTexture()) { \ + const auto& texObj = srcAttachment.GetTexture(); \ + srcInternalFormat = texObj->GetFormat(); \ + } else if (srcAttachment.IsRenderbuffer()) { \ + const auto& rboObj = srcAttachment.GetRenderbuffer(); \ + srcInternalFormat = rboObj->GetInternalFormat(); \ + } else { \ + MG_State::pGLContext->RecordError( \ + ErrorCode::InvalidOperation, \ + MakeShared("MG_Impl/GLImpl", "CopyTexImage2D_State", \ + "The attachment specified by the read buffer is incomplete.")); \ + return; \ + } + if (isDepth) { + GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Depth); + } else if (isStencil) { + GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Stencil); + } else { + const auto& readBufferType = currentReadFBO->GetReadBuffer(); + GET_SRC_INTERNAL_FORMAT(readBufferType); + } + + if (!TextureImpl::ValidateBaseInternalFormatMatch(internalFormat, srcInternalFormat)) + THROW_UNIMPL_EXCEPTION; + + GLenum outInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(srcInternalFormat); + GLenum realInternalFormat = GL_RGBA8; + GLenum format = GL_DEPTH_COMPONENT; + GLenum type = GL_UNSIGNED_INT; + MG_Util::TextureFormatProcessor::NormalizePixelFormat( + outInternalFormat, PixelFormatNormalizeOptionBit::None, &realInternalFormat, &format, &type); const auto pixelUnpackBufferObject = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); - TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr); + TexImage2D_State(target, level, realInternalFormat, width, height, border, format, type, nullptr); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject); } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp index e2e86f49..1978765b 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp @@ -7,13 +7,12 @@ // End of Source File Header #include "Validators.h" -#include "MG_State/GLState/TextureState/TextureObject.h" -#include "MG_Util/Types.h" #include #include #include #include #include +#include #include namespace MobileGL::MG_Impl::GLImpl { @@ -170,6 +169,7 @@ namespace MobileGL::MG_Impl::GLImpl { } return true; } + Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat, TexturePixelDataType type) { @@ -303,5 +303,21 @@ namespace MobileGL::MG_Impl::GLImpl { } return true; } + + Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2) { + auto unsizedFormat1 = MG_Util::ConvertInternalFormatToUnsized(format1); + auto unsizedFormat2 = MG_Util::ConvertInternalFormatToUnsized(format2); + if (unsizedFormat1 != unsizedFormat2) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared( + std::format("MG_Impl/GLImpl", "ValidateBaseInternalFormatMatch", + "The base internal format of the two formats do not match ({} vs. {})", + MG_Util::ConvertTextureInternalFormatToString(unsizedFormat1).c_str(), + MG_Util::ConvertTextureInternalFormatToString(unsizedFormat2).c_str()))); + return false; + } + return true; + } // namespace TextureImpl } // namespace TextureImpl -} // namespace MobileGL::MG_Impl::GLImpl +} // namespace MobileGL::MG_Impl::GLImpl \ No newline at end of file diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h index 2ee4f0a4..2a15aba6 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h @@ -7,6 +7,7 @@ // End of Source File Header #pragma once +#include "MG_State/GLState/TextureState/TextureEnum.h" #include "MG_Util/Types.h" #include #include @@ -32,5 +33,6 @@ namespace MobileGL::MG_Impl::GLImpl { TextureTarget target); Bool ValidateTextureSubImageOffsets(SharedPtr textureObject, Int xoffset, Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0); + Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2); } // namespace TextureImpl } // namespace MobileGL::MG_Impl::GLImpl \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h index 2b83bffa..c0061971 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h @@ -71,7 +71,8 @@ namespace MobileGL { namespace GLState { class FramebufferAttachmentObject { public: - explicit FramebufferAttachmentObject(SharedPtr texture, Int level = 0); + explicit FramebufferAttachmentObject(SharedPtr texture, + Int level = 0); explicit FramebufferAttachmentObject(SharedPtr renderbuffer); explicit FramebufferAttachmentObject(Bool IsValid = true); @@ -98,10 +99,11 @@ namespace MobileGL { using TargetEnum = FramebufferTarget; using FramebufferAttachmentObjectArray = - Array(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; + Array(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; using FramebufferAttachmentArray = Array; using FramebufferAttachmentVersionArray = - Array(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; + Array(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>; FramebufferObject(Uint externalIndex); diff --git a/MobileGL/MG_Util/Texture/TextureFormatProcessor.h b/MobileGL/MG_Util/Texture/TextureFormatProcessor.h index 6027fd46..a8038d6b 100644 --- a/MobileGL/MG_Util/Texture/TextureFormatProcessor.h +++ b/MobileGL/MG_Util/Texture/TextureFormatProcessor.h @@ -9,11 +9,14 @@ #pragma once #include -namespace MobileGL::MG_Util::TextureFormatProcessor { +namespace MobileGL { enum class PixelFormatNormalizeOptionBit : Uint { NoNorm16 = 1 << 0, None = 0, }; - void NormalizePixelFormat(GLenum internalFormat, Flags options, - GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); -} // namespace MobileGL::MG_Util::TextureFormatProcessor \ No newline at end of file + + namespace MG_Util::TextureFormatProcessor { + void NormalizePixelFormat(GLenum internalFormat, Flags options, + GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); + } +} // namespace MobileGL \ No newline at end of file