Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-02-04 17:47:04
    Hash : 7085305f
    Message : Use whitelist to filter test configs. Before we would try all the configs and filter those which fail to init. Now we gather the System Info and if successful check a list of supported configs. If System Info init fails we fall back to the prior method. This speeds up end2end tests init. It also allows for more reliable profile captures with VTune. It also will cause a test failure if a config unexpectedly fails. Previously we would silently pass without running the config's test. Includes a few changes: * D3D reference tests are disabled. They don't appear to be working. * Mac ES 3.1 is disabled due to lack of support. * WGL on AMD Windows is disabled due to lack of ES compatibility. * ES 3.2 contexts are explicitly disabled. * Vulkan is limited to ES 2.0. * The Windows GLES back-end is limited to NVIDIA with ES 2.0 & 3.0. * A unit test that verifies the whitelist matches availability. Bug: angleproject:2472 Change-Id: Ib72214bfbbff13c124fa15a6494d0aabb52f2e62 Reviewed-on: https://chromium-review.googlesource.com/c/1436168 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org>

  • src/tests/gl_tests/PbufferTest.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"
    #include "util/EGLWindow.h"
    
    using namespace angle;
    
    class PbufferTest : public ANGLETest
    {
      protected:
        PbufferTest()
        {
            setWindowWidth(512);
            setWindowHeight(512);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
        }
    
        virtual void SetUp()
        {
            ANGLETest::SetUp();
    
            constexpr char kVS[] =
                R"(precision highp float;
                attribute vec4 position;
                varying vec2 texcoord;
    
                void main()
                {
                    gl_Position = position;
                    texcoord = (position.xy * 0.5) + 0.5;
                    texcoord.y = 1.0 - texcoord.y;
                })";
    
            constexpr char kFS[] =
                R"(precision highp float;
                uniform sampler2D tex;
                varying vec2 texcoord;
    
                void main()
                {
                    gl_FragColor = texture2D(tex, texcoord);
                })";
    
            mTextureProgram = CompileProgram(kVS, kFS);
            if (mTextureProgram == 0)
            {
                FAIL() << "shader compilation failed.";
            }
    
            mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
    
            EGLWindow *window = getEGLWindow();
    
            EGLint surfaceType = 0;
            eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE,
                               &surfaceType);
            mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
    
            EGLint bindToTextureRGBA = 0;
            eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA,
                               &bindToTextureRGBA);
            mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
    
            const EGLint pBufferAttributes[] = {
                EGL_WIDTH,          static_cast<EGLint>(mPbufferSize),
                EGL_HEIGHT,         static_cast<EGLint>(mPbufferSize),
                EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
                EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
                EGL_NONE,           EGL_NONE,
            };
    
            mPbuffer =
                eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
            if (mSupportsPbuffers)
            {
                ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
                ASSERT_EGL_SUCCESS();
            }
            else
            {
                ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
                ASSERT_EGL_ERROR(EGL_BAD_MATCH);
            }
    
            ASSERT_GL_NO_ERROR();
        }
    
        virtual void TearDown()
        {
            glDeleteProgram(mTextureProgram);
    
            EGLWindow *window = getEGLWindow();
            eglDestroySurface(window->getDisplay(), mPbuffer);
    
            ANGLETest::TearDown();
        }
    
        GLuint mTextureProgram;
        GLint mTextureUniformLocation;
    
        const size_t mPbufferSize = 32;
        EGLSurface mPbuffer;
        bool mSupportsPbuffers;
        bool mSupportsBindTexImage;
    };
    
    // Test clearing a Pbuffer and checking the color is correct
    TEST_P(PbufferTest, Clearing)
    {
        ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
    
        EGLWindow *window = getEGLWindow();
    
        // Clear the window surface to blue and verify
        window->makeCurrent();
        ASSERT_EGL_SUCCESS();
    
        glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
    
        // Apply the Pbuffer and clear it to purple and verify
        eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
        ASSERT_EGL_SUCCESS();
    
        glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
        glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
        EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
                        0, 255, 255);
    
        // Rebind the window surface and verify that it is still blue
        window->makeCurrent();
        ASSERT_EGL_SUCCESS();
        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
    }
    
    // Bind the Pbuffer to a texture and verify it renders correctly
    TEST_P(PbufferTest, BindTexImage)
    {
        // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
        // textures.
        ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
    
        EGLWindow *window = getEGLWindow();
    
        // Apply the Pbuffer and clear it to purple
        eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
        ASSERT_EGL_SUCCESS();
    
        glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
        glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
    
        EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
                        0, 255, 255);
    
        // Apply the window surface
        window->makeCurrent();
    
        // Create a texture and bind the Pbuffer to it
        GLuint texture = 0;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        EXPECT_GL_NO_ERROR();
    
        eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
        glViewport(0, 0, getWindowWidth(), getWindowHeight());
        ASSERT_EGL_SUCCESS();
    
        // Draw a quad and verify that it is purple
        glUseProgram(mTextureProgram);
        glUniform1i(mTextureUniformLocation, 0);
    
        drawQuad(mTextureProgram, "position", 0.5f);
        EXPECT_GL_NO_ERROR();
    
        // Unbind the texture
        eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
        ASSERT_EGL_SUCCESS();
    
        // Verify that purple was drawn
        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
    
        glDeleteTextures(1, &texture);
    }
    
    // Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
    // size information is correctly updated.
    TEST_P(PbufferTest, TextureSizeReset)
    {
        ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
        ANGLE_SKIP_TEST_IF(!mSupportsBindTexImage);
    
        GLTexture texture;
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        EXPECT_GL_NO_ERROR();
    
        glUseProgram(mTextureProgram);
        glUniform1i(mTextureUniformLocation, 0);
    
        // Fill the texture with white pixels
        std::vector<GLColor> whitePixels(mPbufferSize * mPbufferSize, GLColor::white);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
                     static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     whitePixels.data());
        EXPECT_GL_NO_ERROR();
    
        // Draw the white texture and verify that the pixels are correct
        drawQuad(mTextureProgram, "position", 0.5f);
        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
    
        // Bind the EGL surface and draw with it, results are undefined since nothing has
        // been written to it
        EGLWindow *window = getEGLWindow();
        eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
        drawQuad(mTextureProgram, "position", 0.5f);
        EXPECT_GL_NO_ERROR();
    
        // Clear the back buffer to a unique color (green)
        glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
    
        // Unbind the EGL surface and try to draw with the texture again, the texture's size should
        // now be zero and incomplete so the back buffer should be black
        eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
        drawQuad(mTextureProgram, "position", 0.5f);
        EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
    }
    
    // Bind a Pbuffer, redefine the texture, and verify it renders correctly
    TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
    {
        // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
        // textures.
        ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
    
        EGLWindow *window = getEGLWindow();
    
        // Apply the Pbuffer and clear it to purple
        eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
        ASSERT_EGL_SUCCESS();
    
        glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
        glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
    
        EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
                        0, 255, 255);
    
        // Apply the window surface
        window->makeCurrent();
    
        // Create a texture and bind the Pbuffer to it
        GLuint texture = 0;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        EXPECT_GL_NO_ERROR();
    
        eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
        glViewport(0, 0, getWindowWidth(), getWindowHeight());
        ASSERT_EGL_SUCCESS();
    
        // Redefine the texture
        unsigned int pixelValue = 0xFFFF00FF;
        std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
                     GL_UNSIGNED_BYTE, &pixelData[0]);
    
        // Draw a quad and verify that it is magenta
        glUseProgram(mTextureProgram);
        glUniform1i(mTextureUniformLocation, 0);
    
        drawQuad(mTextureProgram, "position", 0.5f);
        EXPECT_GL_NO_ERROR();
    
        // Verify that magenta was drawn
        EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
    
        glDeleteTextures(1, &texture);
    }
    
    // Use this to select which configurations (e.g. which renderer, which GLES major version) these
    // tests should be run against.
    ANGLE_INSTANTIATE_TEST(PbufferTest,
                           ES2_D3D9(),
                           ES2_D3D11(),
                           ES2_OPENGL(),
                           ES2_D3D11_WARP(),
                           ES2_OPENGLES(),
                           ES2_VULKAN());