mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Fix] (MG_Util/Converters): resolve the GL_COMPRESSED_* internal formats to the uncompressed storage that backs them instead of rejecting them as unknown - GL prescribes this base-format fallback for the six generic formats, and RGTC stores uncompressed because ES exposes no compressor
This commit is contained in:
@@ -1516,6 +1516,47 @@ TEST_F(TextureTest, TexStorage2DTrimsALongerPreExistingMipChain) {
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// glTexImage2D used to reject every GL_COMPRESSED_* internal format with GL_INVALID_ENUM, because
|
||||
// none of them mapped to a TextureInternalFormat and the "unknown format" gate fired. They now
|
||||
// resolve to the uncompressed storage that backs them - what GL prescribes for the generic formats,
|
||||
// and a deliberate deviation for RGTC, which ES cannot compress. The (format, type) pairs below are
|
||||
// the ones KHR-GL33.packed_pixels uploads with, so this table doubles as a pin for those 480 cases.
|
||||
TEST_F(TextureTest, CompressedInternalFormatsResolveToTheirUncompressedStorage) {
|
||||
struct Case {
|
||||
GLenum internalFormat;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
TextureInternalFormat expected;
|
||||
};
|
||||
const Case cases[] = {
|
||||
{GL_COMPRESSED_RED, GL_RED, GL_UNSIGNED_BYTE, TextureInternalFormat::R8},
|
||||
{GL_COMPRESSED_RG, GL_RG, GL_UNSIGNED_BYTE, TextureInternalFormat::RG8},
|
||||
{GL_COMPRESSED_RGB, GL_RGB, GL_UNSIGNED_BYTE, TextureInternalFormat::RGB8},
|
||||
{GL_COMPRESSED_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, TextureInternalFormat::RGBA8},
|
||||
{GL_COMPRESSED_SRGB, GL_RGB, GL_UNSIGNED_BYTE, TextureInternalFormat::SRGB8},
|
||||
{GL_COMPRESSED_SRGB_ALPHA, GL_RGBA, GL_UNSIGNED_BYTE, TextureInternalFormat::SRGB8Alpha8},
|
||||
{GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, TextureInternalFormat::R8},
|
||||
{GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, TextureInternalFormat::RG8},
|
||||
// The signed RGTC pair is uploaded as GL_BYTE and must land on SNORM storage - resolving
|
||||
// them to plain R8/RG8 would silently reinterpret negative texels.
|
||||
{GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_BYTE, TextureInternalFormat::R8Snorm},
|
||||
{GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_BYTE, TextureInternalFormat::RG8Snorm},
|
||||
};
|
||||
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for (const auto& c : cases) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, texture);
|
||||
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, c.internalFormat, 4, 4, 0, c.format, c.type, nullptr);
|
||||
|
||||
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
|
||||
ASSERT_NE(textureObject, nullptr) << "internalFormat 0x" << std::hex << c.internalFormat;
|
||||
EXPECT_EQ(textureObject->GetFormat(), c.expected) << "internalFormat 0x" << std::hex << c.internalFormat;
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR) << "internalFormat 0x" << std::hex << c.internalFormat;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TextureTest, TextureStorage3DAndSubImageModifyNamedObjectOnly) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_3D, 1, &texture);
|
||||
|
||||
@@ -255,6 +255,37 @@ namespace MobileGL {
|
||||
return TextureInternalFormat::DepthComponent;
|
||||
case GL_DEPTH_STENCIL:
|
||||
return TextureInternalFormat::DepthStencil;
|
||||
// Compressed internal formats resolve to the uncompressed storage that backs them.
|
||||
//
|
||||
// For the six generic formats this is exactly what GL prescribes: the implementation
|
||||
// picks a specific compressed format, and when none is available it falls back to the
|
||||
// corresponding base format. Nothing downstream ever sees a compressed enum, so the
|
||||
// metrics, pixel-store and backend tables keep their "one format, N bytes per texel"
|
||||
// invariant instead of each needing a compressed-aware arm.
|
||||
//
|
||||
// The four RGTC formats are a deliberate deviation: they are specific formats that GL
|
||||
// 3.3 requires, but ES exposes no RGTC compressor to hand the data to. Storing the
|
||||
// texels uncompressed keeps them renderable at the cost of the memory saving, which is
|
||||
// strictly better than the INVALID_ENUM the application used to get. Note the signed
|
||||
// variants must land on SNORM storage - CTS uploads them as GL_BYTE.
|
||||
case GL_COMPRESSED_RED:
|
||||
case GL_COMPRESSED_RED_RGTC1:
|
||||
return TextureInternalFormat::R8;
|
||||
case GL_COMPRESSED_SIGNED_RED_RGTC1:
|
||||
return TextureInternalFormat::R8Snorm;
|
||||
case GL_COMPRESSED_RG:
|
||||
case GL_COMPRESSED_RG_RGTC2:
|
||||
return TextureInternalFormat::RG8;
|
||||
case GL_COMPRESSED_SIGNED_RG_RGTC2:
|
||||
return TextureInternalFormat::RG8Snorm;
|
||||
case GL_COMPRESSED_RGB:
|
||||
return TextureInternalFormat::RGB8;
|
||||
case GL_COMPRESSED_RGBA:
|
||||
return TextureInternalFormat::RGBA8;
|
||||
case GL_COMPRESSED_SRGB:
|
||||
return TextureInternalFormat::SRGB8;
|
||||
case GL_COMPRESSED_SRGB_ALPHA:
|
||||
return TextureInternalFormat::SRGB8Alpha8;
|
||||
case GL_ALPHA:
|
||||
case GL_RED:
|
||||
return TextureInternalFormat::Red;
|
||||
|
||||
Reference in New Issue
Block a user