Edit

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

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2017-09-18 13:32:29
    Hash : a20af6d7
    Message : Use C++11 raw string literals instead of SHADER_SOURCE macro This is better in many ways: 1. It doesn't confuse clang format 2. \n doesn't need to be included after preprocessor directives like the version directive. 3. It's using built-in functionality instead of something custom. Raw string literals should be the preferred way to include shader source in C++ files going forward. BUG=angleproject:2157 TEST=angle_end2end_tests Change-Id: I8b236a6e2d5c25d920297e5bc5b5b143eddeba1f Reviewed-on: https://chromium-review.googlesource.com/671046 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>

  • src/tests/gl_tests/MaxTextureSizeTest.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"
    
    using namespace angle;
    
    class MaxTextureSizeTest : public ANGLETest
    {
      protected:
        MaxTextureSizeTest()
        {
            setWindowWidth(512);
            setWindowHeight(512);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    
        void SetUp() override
        {
            ANGLETest::SetUp();
    
            const std::string vsSource =
                R"(precision highp float;
                attribute vec4 position;
                varying vec2 texcoord;
    
                void main()
                {
                    gl_Position = position;
                    texcoord = (position.xy * 0.5) + 0.5;
                })";
    
            const std::string textureFSSource =
                R"(precision highp float;
                uniform sampler2D tex;
                varying vec2 texcoord;
    
                void main()
                {
                    gl_FragColor = texture2D(tex, texcoord);
                })";
    
            const std::string blueFSSource =
                R"(precision highp float;
    
                void main()
                {
                    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
                })";
    
            mTextureProgram = CompileProgram(vsSource, textureFSSource);
            mBlueProgram = CompileProgram(vsSource, blueFSSource);
            if (mTextureProgram == 0 || mBlueProgram == 0)
            {
                FAIL() << "shader compilation failed.";
            }
    
            mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
    
            glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTexture2DSize);
            glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxTextureCubeSize);
            glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
    
            ASSERT_GL_NO_ERROR();
        }
    
        void TearDown() override
        {
            glDeleteProgram(mTextureProgram);
            glDeleteProgram(mBlueProgram);
    
            ANGLETest::TearDown();
        }
    
        GLuint mTextureProgram;
        GLint mTextureUniformLocation;
    
        GLuint mBlueProgram;
    
        GLint mMaxTexture2DSize;
        GLint mMaxTextureCubeSize;
        GLint mMaxRenderbufferSize;
    };
    
    TEST_P(MaxTextureSizeTest, SpecificationTexImage)
    {
        GLuint tex;
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        GLsizei textureWidth = mMaxTexture2DSize;
        GLsizei textureHeight = 64;
    
        std::vector<GLubyte> data(textureWidth * textureHeight * 4);
        for (int y = 0; y < textureHeight; y++)
        {
            for (int x = 0; x < textureWidth; x++)
            {
                GLubyte* pixel = &data[0] + ((y * textureWidth + x) * 4);
    
                // Draw a gradient, red in direction, green in y direction
                pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
                pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
                pixel[2] = 0;
                pixel[3] = 255;
            }
        }
    
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
        EXPECT_GL_NO_ERROR();
    
        glUseProgram(mTextureProgram);
        glUniform1i(mTextureUniformLocation, 0);
    
        drawQuad(mTextureProgram, "position", 0.5f);
    
        std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
        glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
    
        for (int y = 1; y < getWindowHeight(); y++)
        {
            for (int x = 1; x < getWindowWidth(); x++)
            {
                const GLubyte* prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
                const GLubyte* curPixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
    
                EXPECT_GE(curPixel[0], prevPixel[0]);
                EXPECT_GE(curPixel[1], prevPixel[1]);
                EXPECT_EQ(curPixel[2], prevPixel[2]);
                EXPECT_EQ(curPixel[3], prevPixel[3]);
            }
        }
    }
    
    TEST_P(MaxTextureSizeTest, SpecificationTexStorage)
    {
        if (getClientMajorVersion() < 3 &&
            (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8")))
        {
            return;
        }
    
        GLuint tex;
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
        GLsizei textureWidth = 64;
        GLsizei textureHeight = mMaxTexture2DSize;
    
        std::vector<GLubyte> data(textureWidth * textureHeight * 4);
        for (int y = 0; y < textureHeight; y++)
        {
            for (int x = 0; x < textureWidth; x++)
            {
                GLubyte* pixel = &data[0] + ((y * textureWidth + x) * 4);
    
                // Draw a gradient, red in direction, green in y direction
                pixel[0] = static_cast<GLubyte>((float(x) / textureWidth) * 255);
                pixel[1] = static_cast<GLubyte>((float(y) / textureHeight) * 255);
                pixel[2] = 0;
                pixel[3] = 255;
            }
        }
    
        if (getClientMajorVersion() < 3)
        {
            glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
        }
        else
        {
            glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8_OES, textureWidth, textureHeight);
        }
        EXPECT_GL_NO_ERROR();
    
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
        EXPECT_GL_NO_ERROR();
    
        glUseProgram(mTextureProgram);
        glUniform1i(mTextureUniformLocation, 0);
    
        drawQuad(mTextureProgram, "position", 0.5f);
    
        std::vector<GLubyte> pixels(getWindowWidth() * getWindowHeight() * 4);
        glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
    
        for (int y = 1; y < getWindowHeight(); y++)
        {
            for (int x = 1; x < getWindowWidth(); x++)
            {
                const GLubyte* prevPixel = &pixels[0] + (((y - 1) * getWindowWidth() + (x - 1)) * 4);
                const GLubyte* curPixel = &pixels[0] + ((y * getWindowWidth() + x) * 4);
    
                EXPECT_GE(curPixel[0], prevPixel[0]);
                EXPECT_GE(curPixel[1], prevPixel[1]);
                EXPECT_EQ(curPixel[2], prevPixel[2]);
                EXPECT_EQ(curPixel[3], prevPixel[3]);
            }
        }
    }
    
    TEST_P(MaxTextureSizeTest, RenderToTexture)
    {
        if (getClientMajorVersion() < 3 && (!extensionEnabled("GL_ANGLE_framebuffer_blit")))
        {
            std::cout << "Test skipped due to missing glBlitFramebuffer[ANGLE] support." << std::endl;
            return;
        }
    
        GLuint fbo = 0;
        GLuint textureId = 0;
        // create a 1-level texture at maximum size
        glGenTextures(1, &textureId);
        glBindTexture(GL_TEXTURE_2D, textureId);
    
        GLsizei textureWidth = 64;
        GLsizei textureHeight = mMaxTexture2DSize;
    
        // texture setup code
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, textureWidth, textureHeight, 0, GL_BGRA_EXT,
                     GL_UNSIGNED_BYTE, nullptr);
        EXPECT_GL_NO_ERROR();
    
        // create an FBO and attach the texture
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
    
        EXPECT_GL_NO_ERROR();
        EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
    
        const int frameCount = 64;
        for (int i = 0; i < frameCount; i++)
        {
            // clear the screen
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
            GLubyte clearRed = static_cast<GLubyte>((float(i) / frameCount) * 255);
            GLubyte clearGreen = 255 - clearRed;
            GLubyte clearBlue = 0;
    
            glClearColor(clearRed / 255.0f, clearGreen / 255.0f, clearBlue / 255.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // render blue into the texture
            glBindFramebuffer(GL_FRAMEBUFFER, fbo);
            drawQuad(mBlueProgram, "position", 0.5f);
    
            // copy corner of texture to LL corner of window
            glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
            glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fbo);
            glBlitFramebufferANGLE(0, 0, textureWidth - 1, getWindowHeight() - 1,
                                   0, 0, textureWidth - 1, getWindowHeight() - 1,
                                   GL_COLOR_BUFFER_BIT, GL_NEAREST);
            glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, 0);
            EXPECT_GL_NO_ERROR();
    
            EXPECT_PIXEL_EQ(textureWidth / 2, getWindowHeight() / 2, 0, 0, 255, 255);
            EXPECT_PIXEL_EQ(textureWidth + 10, getWindowHeight() / 2, clearRed, clearGreen, clearBlue, 255);
    
            swapBuffers();
        }
    
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glBindTexture(GL_TEXTURE_2D, 0);
    
        glDeleteFramebuffers(1, &fbo);
        glDeleteTextures(1, &textureId);
    }
    
    // TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
    // default framebuffer is BGRA to enable the GL and GLES backends. (http://anglebug.com/1289)
    
    // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
    ANGLE_INSTANTIATE_TEST(MaxTextureSizeTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3());