Make handling of non-RGBA sRGB textures more consistent.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 20 Mar 2014 22:35:59 +0000 (23:35 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 20 Mar 2014 22:35:59 +0000 (23:35 +0100)
Previously, we'd ask the driver to convert these to RGBA, which maybe
isn't ideal, and certainly doesn't work with GLES. Now we send in
the right format for RGB and RGBA, and refuse hardware conversions with
single-channel (which GLES doesn't accept). I don't think this is optimal,
but finding a use-case for sRGB single-channel is a bit tricky anyway,
and the fallback is fast, too.

effect_chain_test.cpp
flat_input.cpp
flat_input.h

index 5fe1862..2552b6f 100644 (file)
@@ -152,19 +152,23 @@ TEST(EffectChainTest, RewritingWorksAndGammaConversionsAreInserted) {
 
 TEST(EffectChainTest, RewritingWorksAndTexturesAreAskedForsRGB) {
        unsigned char data[] = {
-               0, 64,
-               128, 255,
+                 0,   0,   0, 255,
+                64,  64,  64, 255,
+               128, 128, 128, 255,
+               255, 255, 255, 255,
        };
-       float expected_data[4] = {
-               1.0f, 0.9771f,
-               0.8983f, 0.0f,
+       float expected_data[] = {
+               1.0000f, 1.0000f, 1.0000f, 1.0000f,
+               0.9771f, 0.9771f, 0.9771f, 1.0000f,
+               0.8983f, 0.8983f, 0.8983f, 1.0000f,
+               0.0000f, 0.0000f, 0.0000f, 1.0000f
        };
-       float out_data[4];
-       EffectChainTester tester(NULL, 2, 2);
-       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
+       float out_data[4 * 4];
+       EffectChainTester tester(NULL, 1, 4);
+       tester.add_input(data, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_sRGB);
        RewritingEffect<InvertEffect> *effect = new RewritingEffect<InvertEffect>();
        tester.get_chain()->add_effect(effect);
-       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
+       tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB);
 
        Node *node = effect->replaced_node;
        ASSERT_EQ(1, node->incoming_links.size());
@@ -172,7 +176,7 @@ TEST(EffectChainTest, RewritingWorksAndTexturesAreAskedForsRGB) {
        EXPECT_EQ("FlatInput", node->incoming_links[0]->effect->effect_type_id());
        EXPECT_EQ("GammaCompressionEffect", node->outgoing_links[0]->effect->effect_type_id());
 
-       expect_equal(expected_data, out_data, 2, 2);
+       expect_equal(expected_data, out_data, 4, 4);
 }
 
 TEST(EffectChainTest, RewritingWorksAndColorspaceConversionsAreInserted) {
index e99eba3..f6ae827 100644 (file)
@@ -102,7 +102,13 @@ void FlatInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsi
                        }
                } else if (output_linear_gamma) {
                        assert(type == GL_UNSIGNED_BYTE);
-                       internal_format = GL_SRGB8_ALPHA8;
+                       if (pixel_format == FORMAT_RGB) {
+                               internal_format = GL_SRGB8;
+                       } else if (pixel_format == FORMAT_RGBA_POSTMULTIPLIED_ALPHA) {
+                               internal_format = GL_SRGB8_ALPHA8;
+                       } else {
+                               assert(false);
+                       }
                } else {
                        assert(type == GL_UNSIGNED_BYTE);
                        if (pixel_format == FORMAT_R) {
index 8c88989..25b9091 100644 (file)
@@ -26,8 +26,14 @@ public:
        virtual std::string effect_type_id() const { return "FlatInput"; }
 
        virtual bool can_output_linear_gamma() const {
+               // On desktop OpenGL, there's also GL_SLUMINANCE8 which could give us
+               // support for single-channel sRGB decoding, but it's not supported
+               // on GLES, and we're already actively rewriting single-channel inputs
+               // to GL_RED (even on desktop), so we stick to 3- and 4-channel inputs.
                return (movit_srgb_textures_supported &&
                        type == GL_UNSIGNED_BYTE &&
+                       (pixel_format == FORMAT_RGB ||
+                        pixel_format == FORMAT_RGBA_POSTMULTIPLIED_ALPHA) &&
                        (image_format.gamma_curve == GAMMA_LINEAR ||
                         image_format.gamma_curve == GAMMA_sRGB));
        }