[Fix] (MG_Util/TextureMetrics, MG_State/Texture): reimplement TextureMetrics, attempting to fix glTexSubImage2D

This commit is contained in:
2025-10-28 10:17:56 +08:00
parent 507476d513
commit bd01e4f99d
3 changed files with 161 additions and 50 deletions
+16 -8
View File
@@ -59,12 +59,14 @@ namespace MobileGL {
// ======================= Processing ================================ // ======================= Processing ================================
SizeT imageSize = SizeT imageSize =
MG_Util::CalculateTextureImageSize(textureInternalFormat, texturePixelDataType, {width, height, 1}); MG_Util::CalculateInputTextureImageSize(textureInternalFormat,
texturePixelDataType,
{width, height, 1});
auto& mipmap = textureObject->GetMipmap(level); auto& mipmap = textureObject->GetMipmap(level);
Vector<Uint8>& data = mipmap.data; Vector<Uint8>& data = mipmap.data;
SizeT bytesPerPixel = MG_Util::GetTexturePixelSize(textureInternalFormat) * SizeT bytesPerPixel =
MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType); MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType);
SizeT rowStride = mipmap.size.x() * bytesPerPixel; SizeT rowStride = mipmap.size.x() * bytesPerPixel;
const Uint8* srcData = reinterpret_cast<const Uint8*>(pixels); const Uint8* srcData = reinterpret_cast<const Uint8*>(pixels);
@@ -74,13 +76,17 @@ namespace MobileGL {
for (GLint row = 0; row < height; ++row) { for (GLint row = 0; row < height; ++row) {
SizeT dstOffset = ((yoffset + row) * mipmap.size.x() + xoffset) * bytesPerPixel; SizeT dstOffset = ((yoffset + row) * mipmap.size.x() + xoffset) * bytesPerPixel;
// Should take states from glPixelStorei/glPixelStoref into account
SizeT srcOffset = row * width * bytesPerPixel; SizeT srcOffset = row * width * bytesPerPixel;
if (dstOffset + width * bytesPerPixel <= data.size()) { if (dstOffset + width * bytesPerPixel < data.size()) {
Copy(reinterpret_cast<const Uint8*>(srcData + srcOffset), Memcpy(srcData + srcOffset, data.data() + dstOffset, width * bytesPerPixel);
reinterpret_cast<Uint8*>(&data[dstOffset]), width * bytesPerPixel);
} else { } else {
return; MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"Copy failed. Dest image does not have sufficient space."));
break;
} }
} }
@@ -295,7 +301,9 @@ namespace MobileGL {
// ======================= Processing ================================ // ======================= Processing ================================
SizeT imageSize = SizeT imageSize =
MG_Util::CalculateTextureImageSize(textureInternalFormat, texturePixelDataType, {width, height, 1}); MG_Util::CalculateInputTextureImageSize(textureInternalFormat,
texturePixelDataType,
{width, height, 1});
textureObject->SetInternalFormat(textureInternalFormat); textureObject->SetInternalFormat(textureInternalFormat);
MG_State::GLState::MipmapLevelInput mipmap = MG_State::GLState::MipmapLevelInput( MG_State::GLState::MipmapLevelInput mipmap = MG_State::GLState::MipmapLevelInput(
+135 -38
View File
@@ -3,13 +3,14 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Util { namespace MG_Util {
SizeT GetTexturePixelSize(TextureInternalFormat internal) { SizeT GetSizedInternalFormatSizeInBytes(TextureInternalFormat internal) {
switch (internal) { switch (internal) {
case TextureInternalFormat::R8: case TextureInternalFormat::R8:
case TextureInternalFormat::R8Snorm: case TextureInternalFormat::R8Snorm:
case TextureInternalFormat::R8I: case TextureInternalFormat::R8I:
case TextureInternalFormat::R8UI: case TextureInternalFormat::R8UI:
return 1; case TextureInternalFormat::R3G3B2:
return 1;
case TextureInternalFormat::R16: case TextureInternalFormat::R16:
case TextureInternalFormat::R16Snorm: case TextureInternalFormat::R16Snorm:
@@ -22,7 +23,6 @@ namespace MobileGL {
case TextureInternalFormat::RG8UI: case TextureInternalFormat::RG8UI:
return 2; return 2;
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4: case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5: case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGB8: case TextureInternalFormat::RGB8:
@@ -83,46 +83,143 @@ namespace MobileGL {
} }
} }
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type) { SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format) {
switch (type) { switch (format) {
case TexturePixelDataType::UnsignedByte: case TextureInternalFormat::DepthComponent:
case TexturePixelDataType::Byte: case TextureInternalFormat::DepthStencil:
case TexturePixelDataType::UnsignedByte332: // Depth stencil is actually 2 components
case TexturePixelDataType::UnsignedByte233Rev: // tho real formats always gives byte size in whole
return 1; // so we count this as one here
case TexturePixelDataType::UnsignedShort: case TextureInternalFormat::Red:
case TexturePixelDataType::Short: case TextureInternalFormat::R8:
case TexturePixelDataType::UnsignedShort565: case TextureInternalFormat::R8Snorm:
case TexturePixelDataType::UnsignedShort565Rev: case TextureInternalFormat::R8I:
case TexturePixelDataType::UnsignedShort4444: case TextureInternalFormat::R8UI:
case TexturePixelDataType::UnsignedShort4444Rev: case TextureInternalFormat::R16:
case TexturePixelDataType::UnsignedShort5551: case TextureInternalFormat::R16Snorm:
case TexturePixelDataType::UnsignedShort1555Rev: case TextureInternalFormat::R16I:
return 2; case TextureInternalFormat::R16UI:
case TexturePixelDataType::UnsignedInt: case TextureInternalFormat::R16F:
case TexturePixelDataType::Int: return 1;
case TexturePixelDataType::Float: case TextureInternalFormat::RG:
case TexturePixelDataType::UnsignedInt8888: case TextureInternalFormat::RG8:
case TexturePixelDataType::UnsignedInt8888Rev: case TextureInternalFormat::RG8Snorm:
case TexturePixelDataType::UnsignedInt1010102: case TextureInternalFormat::RG8I:
case TexturePixelDataType::UnsignedInt2101010Rev: case TextureInternalFormat::RG8UI:
case TexturePixelDataType::UnsignedInt101111Rev: case TextureInternalFormat::RG16:
case TexturePixelDataType::UnsignedInt5999Rev: case TextureInternalFormat::RG16Snorm:
return 4; case TextureInternalFormat::RG16I:
default: case TextureInternalFormat::RG16UI:
return 0; 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, SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type) {
IntVec3 size) { switch (type) {
SizeT pixelSize = GetTexturePixelSize(internalFormat); case TexturePixelDataType::UnsignedByte332:
if (pixelSize == 0) return 0; 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); SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type) {
if (dataTypeSize == 0) return 0; 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 } // namespace MG_Util
+10 -4
View File
@@ -4,9 +4,15 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Util { namespace MG_Util {
SizeT GetTexturePixelSize(TextureInternalFormat internal); SizeT GetSizedInternalFormatSizeInBytes(TextureInternalFormat internal);
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type); SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format);
SizeT CalculateTextureImageSize(TextureInternalFormat internalFormat, TexturePixelDataType pixelDataType, SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type);
IntVec3 size); 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 MG_Util
} // namespace MobileGL } // namespace MobileGL