diff --git a/MobileGL/MG_Test/Texture/TextureTest.cpp b/MobileGL/MG_Test/Texture/TextureTest.cpp index 40534417..08339cf3 100644 --- a/MobileGL/MG_Test/Texture/TextureTest.cpp +++ b/MobileGL/MG_Test/Texture/TextureTest.cpp @@ -4033,6 +4033,8 @@ TEST_F(TextureTest, ThreeChannelWideningRetargetsInternalFormatAndTransferPairTo const Flags widenNoSnorm16 = PixelFormatNormalizeOptionBit::NoThreeChannelRenderTarget | PixelFormatNormalizeOptionBit::NoSnorm16RenderTarget; + const Flags widenNoNorm16 = + PixelFormatNormalizeOptionBit::NoThreeChannelRenderTarget | PixelFormatNormalizeOptionBit::NoNorm16; const Case cases[] = { // Complementary's colortex1 and colortex2. The transfer pair used to stay three-channel @@ -4047,10 +4049,16 @@ TEST_F(TextureTest, ThreeChannelWideningRetargetsInternalFormatAndTransferPairTo // cannot render to the encoding gets the 32-bit float rather than the half. {GL_RGB16_SNORM, widen, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, {GL_RGB16_SNORM, widenNoSnorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT}, - // 16-bit UNORM and the legacy 10/12-bit formats stored as RGB16. - {GL_RGB16, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT}, - {GL_RGB10, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT}, - {GL_RGB12, widen, GL_RGBA32F, GL_RGBA, GL_FLOAT}, + // 16-bit UNORM and the legacy 10/12-bit formats stored as RGB16. The same-width sibling + // whenever the driver has EXT_texture_norm16 - which is what keeps the whole 48-bit + // ARB_texture_view class on one ES view class, so a GL_RGB16 texture can be viewed as + // GL_RGB16UI - and the 32-bit float only when it does not. + {GL_RGB16, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, + {GL_RGB10, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, + {GL_RGB12, widen, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, + {GL_RGB16, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT}, + {GL_RGB10, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT}, + {GL_RGB12, widenNoNorm16, GL_RGBA32F, GL_RGBA, GL_FLOAT}, // sRGB and the integer formats: the base format has to move to the four-channel one of the // right class, GL_RGBA_INTEGER included. {GL_SRGB8, widen, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, diff --git a/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp b/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp index 7ae3886d..df504d4e 100644 --- a/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp +++ b/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp @@ -134,7 +134,21 @@ namespace MobileGL::MG_Util::TextureFormatProcessor { case GL_RGB16: case GL_RGB10: case GL_RGB12: - return {GL_RGBA32F, GL_RGBA, GL_FLOAT}; + // Same reasoning as GL_RGB16_SNORM above, and the same shape: keep the + // unsigned-normalized encoding whenever the driver has it, because + // GL_RGBA16 is the SAME-WIDTH four-channel sibling and GL_RGBA32F is not. + // That matters beyond storage size. ARB_texture_view puts all five 48-bit + // formats in one view class, so a GL_RGB16 texture viewed as GL_RGB16UI has + // to alias storage the ES driver also considers compatible; against a + // GL_RGBA32F carrier the view is a different class and glTextureView is + // refused outright (KHR-GL4x.texture_view.view_classes). Against GL_RGBA16 + // the whole class lands on ES's 64-bit class and every channel reinterprets + // bit-exactly. EXT_texture_norm16 - the absence of which is what NoNorm16 + // means - is also what makes GL_RGBA16 colour-renderable, so the two + // questions have one answer. + return (options & PixelFormatNormalizeOptionBit::NoNorm16) + ? ThreeChannelWidening{GL_RGBA32F, GL_RGBA, GL_FLOAT} + : ThreeChannelWidening{GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}; // Floating point. case GL_RGB16F: return {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT};