Edit

kc3-lang/angle/src/tests/egl_tests/EGLSurfacelessContextTest.cpp

Branch :

  • Show log

    Commit

  • Author : Ian Elliott
    Date : 2020-08-24 17:17:17
    Hash : 09924221
    Message : Convert the EGL end2end tests to use RAII types/macros These tests are frequently cloned to make new tests, and so it's good to do a more-global refactor so that these and future tests will use RAII. Bug: angleproject:4947 Change-Id: I2973e70ee075629965b18c685793975537e96b6c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2372627 Reviewed-by: Ian Elliott <ianelliott@google.com> Reviewed-by: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>

  • src/tests/egl_tests/EGLSurfacelessContextTest.cpp
  • //
    // Copyright 2017 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.
    //
    
    // EGLSurfacelessContextTest.cpp:
    //   Tests for the EGL_KHR_surfaceless_context and GL_OES_surfaceless_context
    
    #include <gtest/gtest.h>
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/angle_test_configs.h"
    #include "test_utils/gl_raii.h"
    
    using namespace angle;
    
    namespace
    {
    
    class EGLSurfacelessContextTest : public ANGLETest
    {
      public:
        EGLSurfacelessContextTest() : mDisplay(0) {}
    
        void testSetUp() override
        {
            EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
            mDisplay           = eglGetPlatformDisplayEXT(
                EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
            ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
    
            ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
    
            int nConfigs = 0;
            ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs));
            ASSERT_TRUE(nConfigs != 0);
    
            int nReturnedConfigs = 0;
            std::vector<EGLConfig> configs(nConfigs);
            ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), nConfigs, &nReturnedConfigs));
            ASSERT_TRUE(nConfigs == nReturnedConfigs);
    
            for (auto config : configs)
            {
                EGLint surfaceType;
                eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
                if (surfaceType & EGL_PBUFFER_BIT)
                {
                    mConfig           = config;
                    mSupportsPbuffers = true;
                    break;
                }
            }
    
            if (!mConfig)
            {
                mConfig = configs[0];
            }
    
            ASSERT_NE(nullptr, mConfig);
        }
    
        void testTearDown() override
        {
            eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    
            if (mContext != EGL_NO_CONTEXT)
            {
                eglDestroyContext(mDisplay, mContext);
            }
    
            if (mPbuffer != EGL_NO_SURFACE)
            {
                eglDestroySurface(mDisplay, mPbuffer);
            }
    
            eglTerminate(mDisplay);
        }
    
      protected:
        EGLContext createContext()
        {
            const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
    
            mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, contextAttribs);
            EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
            return mContext;
        }
    
        EGLSurface createPbuffer(int width, int height)
        {
            if (!mSupportsPbuffers)
            {
                return EGL_NO_SURFACE;
            }
    
            const EGLint pbufferAttribs[] = {
                EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,
            };
            mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs);
            EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE);
            return mPbuffer;
        }
    
        void createFramebuffer(GLFramebuffer *fbo, GLTexture *tex) const
        {
            glBindFramebuffer(GL_FRAMEBUFFER, fbo->get());
    
            glBindTexture(GL_TEXTURE_2D, tex->get());
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 500, 500, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->get(), 0);
            ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
        }
    
        bool checkExtension(bool verbose = true) const
        {
            if (!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_surfaceless_context"))
            {
                if (verbose)
                {
                    std::cout << "Test skipped because EGL_KHR_surfaceless_context is not available."
                              << std::endl;
                }
                return false;
            }
            return true;
        }
    
        EGLContext mContext    = EGL_NO_CONTEXT;
        EGLSurface mPbuffer    = EGL_NO_SURFACE;
        bool mSupportsPbuffers = false;
        EGLConfig mConfig      = 0;
        EGLDisplay mDisplay    = EGL_NO_DISPLAY;
    };
    
    // Test surfaceless MakeCurrent returns the correct value.
    TEST_P(EGLSurfacelessContextTest, MakeCurrentSurfaceless)
    {
        EGLContext context = createContext();
    
        if (eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context))
        {
            ASSERT_TRUE(checkExtension(false));
        }
        else
        {
            // The extension allows EGL_BAD_MATCH with the extension too, but ANGLE
            // shouldn't do that.
            ASSERT_FALSE(checkExtension(false));
        }
    }
    
    // Test that the scissor and viewport are set correctly
    TEST_P(EGLSurfacelessContextTest, DefaultScissorAndViewport)
    {
        if (!checkExtension())
        {
            return;
        }
    
        EGLContext context = createContext();
        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
    
        GLint scissor[4] = {1, 2, 3, 4};
        glGetIntegerv(GL_SCISSOR_BOX, scissor);
        ASSERT_GL_NO_ERROR();
        ASSERT_EQ(0, scissor[0]);
        ASSERT_EQ(0, scissor[1]);
        ASSERT_EQ(0, scissor[2]);
        ASSERT_EQ(0, scissor[3]);
    
        GLint viewport[4] = {1, 2, 3, 4};
        glGetIntegerv(GL_VIEWPORT, viewport);
        ASSERT_GL_NO_ERROR();
        ASSERT_EQ(0, viewport[0]);
        ASSERT_EQ(0, viewport[1]);
        ASSERT_EQ(0, viewport[2]);
        ASSERT_EQ(0, viewport[3]);
    }
    
    // Test the CheckFramebufferStatus returns the correct value.
    TEST_P(EGLSurfacelessContextTest, CheckFramebufferStatus)
    {
        if (!checkExtension())
        {
            return;
        }
    
        EGLContext context = createContext();
        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
    
        ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_UNDEFINED_OES, glCheckFramebufferStatus(GL_FRAMEBUFFER));
    
        GLFramebuffer fbo;
        GLTexture tex;
        createFramebuffer(&fbo, &tex);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
        ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
    }
    
    // Test that clearing and readpixels work when done in an FBO.
    TEST_P(EGLSurfacelessContextTest, ClearReadPixelsInFBO)
    {
        if (!checkExtension())
        {
            return;
        }
    
        EGLContext context = createContext();
        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
    
        GLFramebuffer fbo;
        GLTexture tex;
        createFramebuffer(&fbo, &tex);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
    
        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR();
    
        EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);
        ASSERT_GL_NO_ERROR();
    }
    
    // Test clear+readpixels in an FBO in surfaceless and in the default FBO in a pbuffer
    TEST_P(EGLSurfacelessContextTest, Switcheroo)
    {
        ANGLE_SKIP_TEST_IF(!checkExtension());
        ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
    
        // Fails on NVIDIA Shield TV (http://anglebug.com/4924)
        ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIA());
    
        EGLContext context = createContext();
        EGLSurface pbuffer = createPbuffer(500, 500);
    
        // We need to make the context current to do the one time setup of the FBO
        ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
        GLFramebuffer fbo;
        GLTexture tex;
        createFramebuffer(&fbo, &tex);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
    
        for (int i = 0; i < 4; ++i)
        {
            // Clear to red in the FBO in surfaceless mode
            ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
    
            glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
            glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            ASSERT_GL_NO_ERROR();
    
            EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);
            ASSERT_GL_NO_ERROR();
    
            // Clear to green in the pbuffer
            ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, pbuffer, pbuffer, context));
    
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            ASSERT_GL_NO_ERROR();
    
            EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::green);
            ASSERT_GL_NO_ERROR();
        }
    }
    
    }  // anonymous namespace
    
    ANGLE_INSTANTIATE_TEST(EGLSurfacelessContextTest,
                           WithNoFixture(ES2_D3D9()),
                           WithNoFixture(ES2_D3D11()),
                           WithNoFixture(ES2_METAL()),
                           WithNoFixture(ES2_OPENGL()),
                           WithNoFixture(ES2_OPENGLES()),
                           WithNoFixture(ES2_VULKAN()));