Edit

kc3-lang/angle/src/tests/gl_tests/SRGBTextureTest.cpp

Branch :

  • Show log

    Commit

  • Author : Geoff Lang
    Date : 2017-07-20 16:26:01
    Hash : d2391983
    Message : Skip the RGBTextureTest.SRGB[A]Validation test on Ozone. Many of the other tests in this file are already skipped on this platform but now that GL driver errors cause tests to fail, these tests that previously did not verify their results started to fail. Change-Id: I0d5c88289de42464ae56ac7238c26b384819fe02 Reviewed-on: https://chromium-review.googlesource.com/580255 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>

  • src/tests/gl_tests/SRGBTextureTest.cpp
  • //
    // Copyright 2015 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/gl_raii.h"
    
    namespace angle
    {
    
    class SRGBTextureTest : public ANGLETest
    {
      protected:
        SRGBTextureTest()
        {
            setWindowWidth(128);
            setWindowHeight(128);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    
        void SetUp() override
        {
            ANGLETest::SetUp();
    
            const std::string vs =
                "precision highp float;\n"
                "attribute vec4 position;\n"
                "varying vec2 texcoord;\n"
                "\n"
                "void main()\n"
                "{\n"
                "   gl_Position = vec4(position.xy, 0.0, 1.0);\n"
                "   texcoord = (position.xy * 0.5) + 0.5;\n"
                "}\n";
    
            const std::string fs =
                "precision highp float;\n"
                "uniform sampler2D tex;\n"
                "varying vec2 texcoord;\n"
                "\n"
                "void main()\n"
                "{\n"
                "   gl_FragColor = texture2D(tex, texcoord);\n"
                "}\n";
    
            mProgram = CompileProgram(vs, fs);
            ASSERT_NE(0u, mProgram);
    
            mTextureLocation = glGetUniformLocation(mProgram, "tex");
            ASSERT_NE(-1, mTextureLocation);
        }
    
        void TearDown() override
        {
            glDeleteProgram(mProgram);
    
            ANGLETest::TearDown();
        }
    
        GLuint mProgram        = 0;
        GLint mTextureLocation = -1;
    };
    
    TEST_P(SRGBTextureTest, SRGBValidation)
    {
        // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
        if (IsOzone() && IsIntel() && IsOpenGLES())
        {
            std::cout << "Test skipped on Ozone Intel." << std::endl;
            return;
        }
    
        bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
    
        GLuint tex = 0;
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
    
        GLubyte pixel[3] = { 0 };
        glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, 1, 1, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
        if (supported)
        {
            EXPECT_GL_NO_ERROR();
    
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel);
            EXPECT_GL_NO_ERROR();
    
            glGenerateMipmap(GL_TEXTURE_2D);
            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
        }
        else
        {
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
        }
    
        glDeleteTextures(1, &tex);
    }
    
    TEST_P(SRGBTextureTest, SRGBAValidation)
    {
        // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
        if (IsOzone() && IsIntel() && IsOpenGLES())
        {
            std::cout << "Test skipped on Ozone Intel." << std::endl;
            return;
        }
    
        bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
    
        GLuint tex = 0;
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
    
        GLubyte pixel[4] = { 0 };
        glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
        if (supported)
        {
            EXPECT_GL_NO_ERROR();
    
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel);
            EXPECT_GL_NO_ERROR();
    
            glGenerateMipmap(GL_TEXTURE_2D);
            if (getClientMajorVersion() == 2)
            {
                EXPECT_GL_ERROR(GL_INVALID_OPERATION);
            }
            else
            {
                EXPECT_GL_NO_ERROR();
            }
        }
        else
        {
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
        }
    
        glDeleteTextures(1, &tex);
    }
    
    TEST_P(SRGBTextureTest, SRGBARenderbuffer)
    {
        bool supported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
    
        GLuint rbo = 0;
        glGenRenderbuffers(1, &rbo);
        glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    
        glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8_EXT, 1, 1);
        if (supported)
        {
            EXPECT_GL_NO_ERROR();
        }
        else
        {
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
    
            // Make sure the rbo has a size for future tests
            glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, 1, 1);
            EXPECT_GL_NO_ERROR();
        }
    
        GLuint fbo = 0;
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
        EXPECT_GL_NO_ERROR();
    
        GLint colorEncoding = 0;
        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                              GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT, &colorEncoding);
        if (supported)
        {
            EXPECT_GL_NO_ERROR();
            EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
        }
        else
        {
            EXPECT_GL_ERROR(GL_INVALID_ENUM);
        }
    
        glDeleteFramebuffers(1, &fbo);
        glDeleteRenderbuffers(1, &rbo);
    }
    
    // Verify that if the srgb decode extension is available, srgb textures are too
    TEST_P(SRGBTextureTest, SRGBDecodeExtensionAvailability)
    {
        bool hasSRGBDecode = extensionEnabled("GL_EXT_texture_sRGB_decode");
        if (hasSRGBDecode)
        {
            bool hasSRGBTextures = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() >= 3;
            EXPECT_TRUE(hasSRGBTextures);
        }
    }
    
    // Test basic functionality of SRGB decode using the texture parameter
    TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
    {
        // TODO(fjhenigman): Figure out why this fails on Ozone Intel.
        if (IsOzone() && IsIntel() && IsOpenGLES())
        {
            std::cout << "Test skipped on Ozone Intel." << std::endl;
            return;
        }
    
        if (!extensionEnabled("GL_EXT_texture_sRGB_decode"))
        {
            std::cout << "Test skipped because GL_EXT_texture_sRGB_decode is not available."
                      << std::endl;
            return;
        }
    
        GLColor linearColor(64, 127, 191, 255);
        GLColor srgbColor(13, 54, 133, 255);
    
        GLTexture tex;
        glBindTexture(GL_TEXTURE_2D, tex.get());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
                     &linearColor);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
        ASSERT_GL_NO_ERROR();
    
        glUseProgram(mProgram);
        glUniform1i(mTextureLocation, 0);
    
        glDisable(GL_DEPTH_TEST);
        drawQuad(mProgram, "position", 0.5f);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
        drawQuad(mProgram, "position", 0.5f);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
    }
    
    // Test basic functionality of SRGB decode using the sampler parameter
    TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
    {
        if (!extensionEnabled("GL_EXT_texture_sRGB_decode") || getClientMajorVersion() < 3)
        {
            std::cout << "Test skipped because GL_EXT_texture_sRGB_decode or ES3 is not available."
                      << std::endl;
            return;
        }
    
        GLColor linearColor(64, 127, 191, 255);
        GLColor srgbColor(13, 54, 133, 255);
    
        GLTexture tex;
        glBindTexture(GL_TEXTURE_2D, tex.get());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
                     &linearColor);
        ASSERT_GL_NO_ERROR();
    
        GLSampler sampler;
        glBindSampler(0, sampler.get());
        glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
    
        glUseProgram(mProgram);
        glUniform1i(mTextureLocation, 0);
    
        glDisable(GL_DEPTH_TEST);
        drawQuad(mProgram, "position", 0.5f);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
    
        glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
        drawQuad(mProgram, "position", 0.5f);
    
        EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
    }
    
    // Test that mipmaps are generated correctly for sRGB textures
    TEST_P(SRGBTextureTest, GenerateMipmaps)
    {
        if (getClientMajorVersion() < 3)
        {
            std::cout << "Test skipped because ES3 is not available." << std::endl;
            return;
        }
    
        if (IsOpenGL() && (IsIntel() || IsAMD()))
        {
            std::cout << "Test skipped on Intel and AMD OpenGL drivers." << std::endl;
            return;
        }
    
        auto createAndReadBackTexture = [this](GLenum internalFormat, const GLColor &color) {
            constexpr GLsizei width  = 128;
            constexpr GLsizei height = 128;
    
            std::array<GLColor, width * height> buf;
            std::fill(buf.begin(), buf.end(), color);
    
            // Set up-left region of the texture as red color.
            // In order to make sure bi-linear interpolation operates on different colors, red region
            // is 1 pixel smaller than a quarter of the full texture on each side.
            constexpr GLsizei redWidth  = width / 2 - 1;
            constexpr GLsizei redHeight = height / 2 - 1;
            std::array<GLColor, redWidth * redHeight> redBuf;
            std::fill(redBuf.begin(), redBuf.end(), GLColor::red);
    
            GLTexture tex;
            glBindTexture(GL_TEXTURE_2D, tex.get());
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                         buf.data());
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, redWidth, redHeight, GL_RGBA, GL_UNSIGNED_BYTE,
                            redBuf.data());
            glGenerateMipmap(GL_TEXTURE_2D);
    
            constexpr GLsizei drawWidth  = 32;
            constexpr GLsizei drawHeight = 32;
            glViewport(0, 0, drawWidth, drawHeight);
    
            drawQuad(mProgram, "position", 0.5f);
    
            std::array<GLColor, drawWidth * drawHeight> result;
            glReadPixels(0, 0, drawWidth, drawHeight, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
    
            EXPECT_GL_NO_ERROR();
    
            return result;
        };
    
        GLColor srgbaColor(0, 63, 127, 255);
        auto srgbaReadback = createAndReadBackTexture(GL_SRGB8_ALPHA8, srgbaColor);
    
        GLColor linearColor(0, 13, 54, 255);
        auto rgbaReadback = createAndReadBackTexture(GL_RGBA8, linearColor);
    
        ASSERT_EQ(srgbaReadback.size(), rgbaReadback.size());
        for (size_t i = 0; i < srgbaReadback.size(); i++)
        {
            constexpr double tolerence = 7.0;
            EXPECT_COLOR_NEAR(srgbaReadback[i], rgbaReadback[i], tolerence);
        }
    }
    
    // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
    ANGLE_INSTANTIATE_TEST(SRGBTextureTest,
                           ES2_D3D9(),
                           ES2_D3D11(),
                           ES3_D3D11(),
                           ES2_OPENGL(),
                           ES3_OPENGL(),
                           ES2_OPENGLES(),
                           ES3_OPENGLES());
    
    } // namespace