Edit

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

Branch :

  • Show log

    Commit

  • Author : Stuart Morgan
    Date : 2019-08-14 12:25:12
    Hash : 9d737966
    Message : Standardize copyright notices to project style For all "ANGLE Project" copyrights, standardize to the format specified by the style guide. Changes: - "Copyright (c)" and "Copyright(c)" changed to just "Copyright". - Removed the second half of date ranges ("Y1Y1-Y2Y2"->"Y1Y1"). - Fixed a small number of files that had no copyright date using the initial commit year from the version control history. - Fixed one instance of copyright being "The ANGLE Project" rather than "The ANGLE Project Authors" These changes are applied both to the copyright of source file, and where applicable to copyright statements that are generated by templates. BUG=angleproject:3811 Change-Id: I973dd65e4ef9deeba232d5be74c768256a0eb2e5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754397 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/tests/egl_tests/EGLContextCompatibilityTest.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.
    //
    
    // EGLContextCompatibilityTest.cpp:
    //   This test will try to use all combinations of context configs and
    //   surface configs. If the configs are compatible, it checks that simple
    //   rendering works, otherwise it checks an error is generated one MakeCurrent.
    //
    // Only run the EGLContextCompatibilityTest on release builds.  The execution time of this test
    // scales with the square of the number of configs exposed and can time out in some debug builds.
    // http://anglebug.com/2121
    
    #include <gtest/gtest.h>
    
    #include <vector>
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/angle_test_configs.h"
    #include "test_utils/angle_test_instantiate.h"
    #include "util/OSWindow.h"
    
    using namespace angle;
    
    namespace
    {
    
    const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
    }
    
    class EGLContextCompatibilityTest : public ANGLETest
    {
      public:
        EGLContextCompatibilityTest() : mDisplay(0) {}
    
        void testSetUp() override
        {
            ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);
    
            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_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE);
    
            int nConfigs = 0;
            ASSERT_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs) == EGL_TRUE);
            ASSERT_TRUE(nConfigs != 0);
    
            int nReturnedConfigs = 0;
            mConfigs.resize(nConfigs);
            ASSERT_TRUE(eglGetConfigs(mDisplay, mConfigs.data(), nConfigs, &nReturnedConfigs) ==
                        EGL_TRUE);
            ASSERT_TRUE(nConfigs == nReturnedConfigs);
        }
    
        void testTearDown() override
        {
            eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            eglTerminate(mDisplay);
        }
    
      protected:
        // Queries EGL config to determine if multisampled or not
        bool isMultisampledConfig(EGLConfig config)
        {
            EGLint samples = 0;
            eglGetConfigAttrib(mDisplay, config, EGL_SAMPLES, &samples);
            return (samples > 1);
        }
    
        // The only configs with 16-bits for each of red, green, blue, and alpha is GL_RGBA16F
        bool isRGBA16FConfig(EGLConfig config)
        {
            EGLint red, green, blue, alpha;
            eglGetConfigAttrib(mDisplay, config, EGL_RED_SIZE, &red);
            eglGetConfigAttrib(mDisplay, config, EGL_GREEN_SIZE, &green);
            eglGetConfigAttrib(mDisplay, config, EGL_BLUE_SIZE, &blue);
            eglGetConfigAttrib(mDisplay, config, EGL_ALPHA_SIZE, &alpha);
            return ((red == 16) && (green == 16) && (blue == 16) && (alpha == 16));
        }
    
        bool isRGB10_A2Config(EGLConfig config)
        {
            EGLint red, green, blue, alpha;
            eglGetConfigAttrib(mDisplay, config, EGL_RED_SIZE, &red);
            eglGetConfigAttrib(mDisplay, config, EGL_GREEN_SIZE, &green);
            eglGetConfigAttrib(mDisplay, config, EGL_BLUE_SIZE, &blue);
            eglGetConfigAttrib(mDisplay, config, EGL_ALPHA_SIZE, &alpha);
            return ((red == 10) && (green == 10) && (blue == 10) && (alpha == 2));
        }
    
        bool areConfigsCompatible(EGLConfig c1, EGLConfig c2, EGLint surfaceBit)
        {
            EGLint colorBufferType1, colorBufferType2;
            EGLint red1, red2, green1, green2, blue1, blue2, alpha1, alpha2;
            EGLint depth1, depth2, stencil1, stencil2;
            EGLint surfaceType1, surfaceType2;
    
            eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_BUFFER_TYPE, &colorBufferType1);
            eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_BUFFER_TYPE, &colorBufferType2);
    
            eglGetConfigAttrib(mDisplay, c1, EGL_RED_SIZE, &red1);
            eglGetConfigAttrib(mDisplay, c2, EGL_RED_SIZE, &red2);
            eglGetConfigAttrib(mDisplay, c1, EGL_GREEN_SIZE, &green1);
            eglGetConfigAttrib(mDisplay, c2, EGL_GREEN_SIZE, &green2);
            eglGetConfigAttrib(mDisplay, c1, EGL_BLUE_SIZE, &blue1);
            eglGetConfigAttrib(mDisplay, c2, EGL_BLUE_SIZE, &blue2);
            eglGetConfigAttrib(mDisplay, c1, EGL_ALPHA_SIZE, &alpha1);
            eglGetConfigAttrib(mDisplay, c2, EGL_ALPHA_SIZE, &alpha2);
    
            eglGetConfigAttrib(mDisplay, c1, EGL_DEPTH_SIZE, &depth1);
            eglGetConfigAttrib(mDisplay, c2, EGL_DEPTH_SIZE, &depth2);
            eglGetConfigAttrib(mDisplay, c1, EGL_STENCIL_SIZE, &stencil1);
            eglGetConfigAttrib(mDisplay, c2, EGL_STENCIL_SIZE, &stencil2);
    
            eglGetConfigAttrib(mDisplay, c1, EGL_SURFACE_TYPE, &surfaceType1);
            eglGetConfigAttrib(mDisplay, c2, EGL_SURFACE_TYPE, &surfaceType2);
    
            EGLint colorComponentType1 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
            EGLint colorComponentType2 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
            if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))
            {
                eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType1);
                eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType2);
            }
    
            EXPECT_EGL_SUCCESS();
    
            return colorBufferType1 == colorBufferType2 && red1 == red2 && green1 == green2 &&
                   blue1 == blue2 && alpha1 == alpha2 && colorComponentType1 == colorComponentType2 &&
                   depth1 == depth2 && stencil1 == stencil2 && (surfaceType1 & surfaceBit) != 0 &&
                   (surfaceType2 & surfaceBit) != 0;
        }
    
        void testWindowCompatibility(EGLConfig windowConfig,
                                     EGLConfig contextConfig,
                                     bool compatible) const
        {
            OSWindow *osWindow = OSWindow::New();
            ASSERT_TRUE(osWindow != nullptr);
            osWindow->initialize("EGLContextCompatibilityTest", 500, 500);
            osWindow->setVisible(true);
    
            EGLContext context =
                eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, contextAttribs);
            ASSERT_TRUE(context != EGL_NO_CONTEXT);
    
            EGLSurface window =
                eglCreateWindowSurface(mDisplay, windowConfig, osWindow->getNativeWindow(), nullptr);
            ASSERT_EGL_SUCCESS();
    
            if (compatible)
            {
                testClearSurface(window, windowConfig, context);
            }
            else
            {
                testMakeCurrentFails(window, context);
            }
    
            eglDestroySurface(mDisplay, window);
            ASSERT_EGL_SUCCESS();
    
            eglDestroyContext(mDisplay, context);
            ASSERT_EGL_SUCCESS();
    
            OSWindow::Delete(&osWindow);
        }
    
        void testPbufferCompatibility(EGLConfig pbufferConfig,
                                      EGLConfig contextConfig,
                                      bool compatible) const
        {
            EGLContext context =
                eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, contextAttribs);
            ASSERT_TRUE(context != EGL_NO_CONTEXT);
    
            const EGLint pBufferAttribs[] = {
                EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,
            };
            EGLSurface pbuffer = eglCreatePbufferSurface(mDisplay, pbufferConfig, pBufferAttribs);
            ASSERT_TRUE(pbuffer != EGL_NO_SURFACE);
    
            if (compatible)
            {
                testClearSurface(pbuffer, pbufferConfig, context);
            }
            else
            {
                testMakeCurrentFails(pbuffer, context);
            }
    
            eglDestroySurface(mDisplay, pbuffer);
            ASSERT_EGL_SUCCESS();
    
            eglDestroyContext(mDisplay, context);
            ASSERT_EGL_SUCCESS();
        }
    
        std::vector<EGLConfig> mConfigs;
        EGLDisplay mDisplay;
    
      private:
        void testClearSurface(EGLSurface surface, EGLConfig surfaceConfig, EGLContext context) const
        {
            eglMakeCurrent(mDisplay, surface, surface, context);
            ASSERT_EGL_SUCCESS();
    
            glViewport(0, 0, 500, 500);
            glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            ASSERT_GL_NO_ERROR();
    
            EGLint surfaceCompontentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
            if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))
            {
                eglGetConfigAttrib(mDisplay, surfaceConfig, EGL_COLOR_COMPONENT_TYPE_EXT,
                                   &surfaceCompontentType);
            }
    
            if (surfaceCompontentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
            {
                EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);
            }
            else
            {
                EXPECT_PIXEL_32F_EQ(250, 250, 0, 0, 1.0f, 1.0f);
            }
    
            eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            ASSERT_EGL_SUCCESS();
        }
    
        void testMakeCurrentFails(EGLSurface surface, EGLContext context) const
        {
            eglMakeCurrent(mDisplay, surface, surface, context);
            EXPECT_EGL_ERROR(EGL_BAD_MATCH);
        }
    };
    
    // The test is split in several subtest so that simple cases
    // are tested separately. Also each surface types are not tested
    // together.
    
    // Basic test checking contexts and windows created with the
    // same config can render.
    TEST_P(EGLContextCompatibilityTest, WindowSameConfig)
    {
        ANGLE_SKIP_TEST_IF(IsDebug());  // http://anglebug.com/2121
    
        for (size_t i = 0; i < mConfigs.size(); i++)
        {
            EGLConfig config = mConfigs[i];
    
            EGLint surfaceType;
            eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
            ASSERT_EGL_SUCCESS();
    
            if ((surfaceType & EGL_WINDOW_BIT) != 0)
            {
                // Disabling multisampled configurations due to test instability with various graphics
                // cards, and RGBA16F/RGB10_A2 on Android due to OSWindow on Android not providing
                // compatible windows (anglebug.com/3156)
                if (isMultisampledConfig(config) ||
                    (IsAndroid() && (isRGB10_A2Config(config) || isRGBA16FConfig(config))))
                {
                    continue;
                }
                testWindowCompatibility(config, config, true);
            }
        }
    }
    
    // Basic test checking contexts and pbuffers created with the
    // same config can render.
    TEST_P(EGLContextCompatibilityTest, PbufferSameConfig)
    {
        ANGLE_SKIP_TEST_IF(IsDebug());  // http://anglebug.com/2121
    
        for (size_t i = 0; i < mConfigs.size(); i++)
        {
            EGLConfig config = mConfigs[i];
    
            EGLint surfaceType;
            eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);
            ASSERT_EGL_SUCCESS();
    
            if ((surfaceType & EGL_PBUFFER_BIT) != 0)
            {
                // Disabling multisampled configurations due to test instability with various graphics
                // cards, and RGB10_A2 on Android due to OSWindow on Android not providing compatible
                // windows (anglebug.com/3156)
                if (isMultisampledConfig(config) || (IsAndroid() && isRGB10_A2Config(config)))
                {
                    continue;
                }
                testPbufferCompatibility(config, config, true);
            }
        }
    }
    
    // Check that a context rendering to a window with a different
    // config works or errors according to the EGL compatibility rules
    TEST_P(EGLContextCompatibilityTest, WindowDifferentConfig)
    {
        ANGLE_SKIP_TEST_IF(IsDebug());  // http://anglebug.com/2121
    
        // anglebug.com/2183
        // Actually failed only on (IsIntel() && IsWindows() && IsD3D11()),
        // but it's impossible to do other tests since GL_RENDERER is NULL
        ANGLE_SKIP_TEST_IF(IsWindows());
    
        for (size_t i = 0; i < mConfigs.size(); i++)
        {
            EGLConfig config1 = mConfigs[i];
            // Disabling multisampled configurations due to test instability with various graphics
            // cards, and RGBA16F/RGB10_A2 on Android due to OSWindow on Android not providing
            // compatible windows (anglebug.com/3156)
            if (isMultisampledConfig(config1) ||
                (IsAndroid() && (isRGB10_A2Config(config1) || isRGBA16FConfig(config1))))
            {
                continue;
            }
    
            EGLint surfaceType;
            eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);
            ASSERT_EGL_SUCCESS();
    
            if ((surfaceType & EGL_WINDOW_BIT) == 0)
            {
                continue;
            }
    
            for (size_t j = 0; j < mConfigs.size(); j++)
            {
                EGLConfig config2 = mConfigs[j];
                // Disabling multisampled configurations due to test instability with various graphics
                // cards, and RGBA16F/RGB10_A2 on Android due to OSWindow on Android not providing
                // compatible windows (anglebug.com/3156)
                if (isMultisampledConfig(config2) ||
                    (IsAndroid() && (isRGB10_A2Config(config2) || isRGBA16FConfig(config2))))
                {
                    continue;
                }
                testWindowCompatibility(config1, config2,
                                        areConfigsCompatible(config1, config2, EGL_WINDOW_BIT));
            }
        }
    }
    
    // Check that a context rendering to a pbuffer with a different
    // config works or errors according to the EGL compatibility rules
    TEST_P(EGLContextCompatibilityTest, PbufferDifferentConfig)
    {
        ANGLE_SKIP_TEST_IF(IsDebug());  // http://anglebug.com/2121
    
        for (size_t i = 0; i < mConfigs.size(); i++)
        {
            EGLConfig config1 = mConfigs[i];
            // Disabling multisampled configurations due to test instability with various graphics
            // cards, and RGB10_A2 on Android due to OSWindow on Android not providing compatible
            // windows (anglebug.com/3156)
            if (isMultisampledConfig(config1) || (IsAndroid() && isRGB10_A2Config(config1)))
            {
                continue;
            }
    
            EGLint surfaceType;
            eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);
            ASSERT_EGL_SUCCESS();
    
            if ((surfaceType & EGL_PBUFFER_BIT) == 0)
            {
                continue;
            }
    
            for (size_t j = 0; j < mConfigs.size(); j++)
            {
                EGLConfig config2 = mConfigs[j];
                // Disabling multisampled configurations due to test instability with various graphics
                // cards, and RGB10_A2 on Android due to OSWindow on Android not providing compatible
                // windows (anglebug.com/3156)
                if (isMultisampledConfig(config2) || (IsAndroid() && isRGB10_A2Config(config2)))
                {
                    continue;
                }
                testPbufferCompatibility(config1, config2,
                                         areConfigsCompatible(config1, config2, EGL_PBUFFER_BIT));
            }
        }
    }
    
    ANGLE_INSTANTIATE_TEST(EGLContextCompatibilityTest,
                           WithNoFixture(ES2_D3D9()),
                           WithNoFixture(ES2_D3D11()),
                           WithNoFixture(ES2_OPENGL()),
                           WithNoFixture(ES2_OPENGLES()),
                           WithNoFixture(ES2_VULKAN()));