From bd01e4f99d31281ed9529934557b0645786169be Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 28 Oct 2025 10:17:56 +0800 Subject: [PATCH] [Fix] (MG_Util/TextureMetrics, MG_State/Texture): reimplement TextureMetrics, attempting to fix glTexSubImage2D --- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 24 ++- MobileGL/MG_Util/Metrics/TextureMetrics.cpp | 173 ++++++++++++++---- MobileGL/MG_Util/Metrics/TextureMetrics.h | 14 +- 3 files changed, 161 insertions(+), 50 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 2dd584b7..f2adb57b 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -59,12 +59,14 @@ namespace MobileGL { // ======================= Processing ================================ SizeT imageSize = - MG_Util::CalculateTextureImageSize(textureInternalFormat, texturePixelDataType, {width, height, 1}); + MG_Util::CalculateInputTextureImageSize(textureInternalFormat, + texturePixelDataType, + {width, height, 1}); auto& mipmap = textureObject->GetMipmap(level); Vector& data = mipmap.data; - SizeT bytesPerPixel = MG_Util::GetTexturePixelSize(textureInternalFormat) * - MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType); + SizeT bytesPerPixel = + MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType); SizeT rowStride = mipmap.size.x() * bytesPerPixel; const Uint8* srcData = reinterpret_cast(pixels); @@ -74,13 +76,17 @@ namespace MobileGL { for (GLint row = 0; row < height; ++row) { SizeT dstOffset = ((yoffset + row) * mipmap.size.x() + xoffset) * bytesPerPixel; + // Should take states from glPixelStorei/glPixelStoref into account SizeT srcOffset = row * width * bytesPerPixel; - if (dstOffset + width * bytesPerPixel <= data.size()) { - Copy(reinterpret_cast(srcData + srcOffset), - reinterpret_cast(&data[dstOffset]), width * bytesPerPixel); + if (dstOffset + width * bytesPerPixel < data.size()) { + Memcpy(srcData + srcOffset, data.data() + dstOffset, width * bytesPerPixel); } else { - return; + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "Copy failed. Dest image does not have sufficient space.")); + break; } } @@ -295,7 +301,9 @@ namespace MobileGL { // ======================= Processing ================================ SizeT imageSize = - MG_Util::CalculateTextureImageSize(textureInternalFormat, texturePixelDataType, {width, height, 1}); + MG_Util::CalculateInputTextureImageSize(textureInternalFormat, + texturePixelDataType, + {width, height, 1}); textureObject->SetInternalFormat(textureInternalFormat); MG_State::GLState::MipmapLevelInput mipmap = MG_State::GLState::MipmapLevelInput( diff --git a/MobileGL/MG_Util/Metrics/TextureMetrics.cpp b/MobileGL/MG_Util/Metrics/TextureMetrics.cpp index 32cf838b..f2d5154b 100644 --- a/MobileGL/MG_Util/Metrics/TextureMetrics.cpp +++ b/MobileGL/MG_Util/Metrics/TextureMetrics.cpp @@ -3,13 +3,14 @@ namespace MobileGL { namespace MG_Util { - SizeT GetTexturePixelSize(TextureInternalFormat internal) { + SizeT GetSizedInternalFormatSizeInBytes(TextureInternalFormat internal) { switch (internal) { case TextureInternalFormat::R8: case TextureInternalFormat::R8Snorm: case TextureInternalFormat::R8I: case TextureInternalFormat::R8UI: - return 1; + case TextureInternalFormat::R3G3B2: + return 1; case TextureInternalFormat::R16: case TextureInternalFormat::R16Snorm: @@ -22,7 +23,6 @@ namespace MobileGL { case TextureInternalFormat::RG8UI: return 2; - case TextureInternalFormat::R3G3B2: case TextureInternalFormat::RGB4: case TextureInternalFormat::RGB5: case TextureInternalFormat::RGB8: @@ -83,46 +83,143 @@ namespace MobileGL { } } - SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type) { - switch (type) { - case TexturePixelDataType::UnsignedByte: - case TexturePixelDataType::Byte: - case TexturePixelDataType::UnsignedByte332: - case TexturePixelDataType::UnsignedByte233Rev: - return 1; - case TexturePixelDataType::UnsignedShort: - case TexturePixelDataType::Short: - case TexturePixelDataType::UnsignedShort565: - case TexturePixelDataType::UnsignedShort565Rev: - case TexturePixelDataType::UnsignedShort4444: - case TexturePixelDataType::UnsignedShort4444Rev: - case TexturePixelDataType::UnsignedShort5551: - case TexturePixelDataType::UnsignedShort1555Rev: - return 2; - case TexturePixelDataType::UnsignedInt: - case TexturePixelDataType::Int: - case TexturePixelDataType::Float: - case TexturePixelDataType::UnsignedInt8888: - case TexturePixelDataType::UnsignedInt8888Rev: - case TexturePixelDataType::UnsignedInt1010102: - case TexturePixelDataType::UnsignedInt2101010Rev: - case TexturePixelDataType::UnsignedInt101111Rev: - case TexturePixelDataType::UnsignedInt5999Rev: - return 4; - default: - return 0; + SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format) { + switch (format) { + case TextureInternalFormat::DepthComponent: + case TextureInternalFormat::DepthStencil: + // Depth stencil is actually 2 components + // tho real formats always gives byte size in whole + // so we count this as one here + case TextureInternalFormat::Red: + case TextureInternalFormat::R8: + case TextureInternalFormat::R8Snorm: + case TextureInternalFormat::R8I: + case TextureInternalFormat::R8UI: + case TextureInternalFormat::R16: + case TextureInternalFormat::R16Snorm: + case TextureInternalFormat::R16I: + case TextureInternalFormat::R16UI: + case TextureInternalFormat::R16F: + return 1; + case TextureInternalFormat::RG: + case TextureInternalFormat::RG8: + case TextureInternalFormat::RG8Snorm: + case TextureInternalFormat::RG8I: + case TextureInternalFormat::RG8UI: + case TextureInternalFormat::RG16: + case TextureInternalFormat::RG16Snorm: + case TextureInternalFormat::RG16I: + case TextureInternalFormat::RG16UI: + case TextureInternalFormat::RG16F: + case TextureInternalFormat::RG32F: + case TextureInternalFormat::RG32I: + case TextureInternalFormat::RG32UI: + return 2; + case TextureInternalFormat::RGB: + case TextureInternalFormat::RGB4: + case TextureInternalFormat::RGB5: + case TextureInternalFormat::RGB8: + case TextureInternalFormat::RGB8Snorm: + case TextureInternalFormat::SRGB8: + case TextureInternalFormat::RGB8I: + case TextureInternalFormat::RGB8UI: + case TextureInternalFormat::RGB16F: + case TextureInternalFormat::RGB32F: + case TextureInternalFormat::RGB16I: + case TextureInternalFormat::RGB16UI: + case TextureInternalFormat::RGB32I: + case TextureInternalFormat::RGB32UI: + case TextureInternalFormat::R11FG11FB10F: + case TextureInternalFormat::RGB9E5: + return 3; + case TextureInternalFormat::RGBA: + case TextureInternalFormat::RGBA2: + case TextureInternalFormat::RGBA4: + case TextureInternalFormat::RGBA8: + case TextureInternalFormat::RGBA8Snorm: + case TextureInternalFormat::RGBA8I: + case TextureInternalFormat::RGBA8UI: + case TextureInternalFormat::RGBA12: + case TextureInternalFormat::RGBA16: + case TextureInternalFormat::RGBA16I: + case TextureInternalFormat::RGBA16UI: + case TextureInternalFormat::RGBA16F: + case TextureInternalFormat::RGBA32F: + case TextureInternalFormat::RGBA32I: + case TextureInternalFormat::RGBA32UI: + case TextureInternalFormat::RGB10A2: + case TextureInternalFormat::RGB10A2UI: + return 4; + default: + return 0; } } - SizeT CalculateTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType, - IntVec3 size) { - SizeT pixelSize = GetTexturePixelSize(internalFormat); - if (pixelSize == 0) return 0; + SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type) { + switch (type) { + case TexturePixelDataType::UnsignedByte332: + case TexturePixelDataType::UnsignedByte233Rev: + return 1; + case TexturePixelDataType::UnsignedShort565: + case TexturePixelDataType::UnsignedShort565Rev: + case TexturePixelDataType::UnsignedShort4444: + case TexturePixelDataType::UnsignedShort4444Rev: + case TexturePixelDataType::UnsignedShort5551: + case TexturePixelDataType::UnsignedShort1555Rev: + return 2; + case TexturePixelDataType::UnsignedInt8888: + case TexturePixelDataType::UnsignedInt8888Rev: + case TexturePixelDataType::UnsignedInt1010102: + case TexturePixelDataType::UnsignedInt2101010Rev: + case TexturePixelDataType::UnsignedInt101111Rev: + case TexturePixelDataType::UnsignedInt5999Rev: + return 4; + default: + return 0; + } + } - SizeT dataTypeSize = GetTexturePixelDataTypeSize(pixelDataType); - if (dataTypeSize == 0) return 0; + SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type) { + switch (type) { + case TexturePixelDataType::UnsignedByte: + case TexturePixelDataType::Byte: + return 1; + case TexturePixelDataType::UnsignedShort: + case TexturePixelDataType::Short: + return 2; + case TexturePixelDataType::UnsignedInt: + case TexturePixelDataType::Int: + case TexturePixelDataType::Float: + return 4; + default: + return 0; + } + } - return pixelSize * dataTypeSize * size.x() * size.y() * size.z(); + SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) { + SizeT sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat); + if (sizedTextureFormatSize > 0) + return sizedTextureFormatSize; + SizeT sizedPixelFormatSize = GetSizedTexturePixelDataTypeSize(type); + if (sizedPixelFormatSize > 0) + return sizedPixelFormatSize; + SizeT chCount = GetBaseInternalFormatComponentCount(internalformat); + SizeT bytesPerChannel = GetBaseTexturePixelDataTypeSize(type); + return chCount * bytesPerChannel; + } + + SizeT GetInputBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) { + SizeT sizedPixelFormatSize = GetSizedTexturePixelDataTypeSize(type); + if (sizedPixelFormatSize > 0) + return sizedPixelFormatSize; + SizeT bytesPerChannel = GetBaseTexturePixelDataTypeSize(type); + SizeT chCount = GetBaseInternalFormatComponentCount(internalformat); + return chCount * bytesPerChannel; + } + + SizeT CalculateInputTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType, + IntVec3 size) { + return GetInputBytesPerPixel(internalFormat, pixelDataType) * size.x() * size.y() * size.z(); } } // namespace MG_Util diff --git a/MobileGL/MG_Util/Metrics/TextureMetrics.h b/MobileGL/MG_Util/Metrics/TextureMetrics.h index 0b609c06..b08c347c 100644 --- a/MobileGL/MG_Util/Metrics/TextureMetrics.h +++ b/MobileGL/MG_Util/Metrics/TextureMetrics.h @@ -4,9 +4,15 @@ namespace MobileGL { namespace MG_Util { - SizeT GetTexturePixelSize(TextureInternalFormat internal); - SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type); - SizeT CalculateTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType, - IntVec3 size); + SizeT GetSizedInternalFormatSizeInBytes(TextureInternalFormat internal); + SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format); + SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type); + SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type); + // This should respect internal format more + SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type); + // This should respect type more, representing data passed in + SizeT GetInputBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type); + SizeT CalculateInputTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType, + IntVec3 size); } // namespace MG_Util } // namespace MobileGL