Path: blob/main_old/src/tests/egl_tests/EGLContextCompatibilityTest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56// EGLContextCompatibilityTest.cpp:7// This test will try to use all combinations of context configs and8// surface configs. If the configs are compatible, it checks that simple9// rendering works, otherwise it checks an error is generated one MakeCurrent.10//1112#include <gtest/gtest.h>1314#include <vector>1516#include "common/debug.h"17#include "test_utils/ANGLETest.h"18#include "test_utils/angle_test_configs.h"19#include "test_utils/angle_test_instantiate.h"20#include "util/OSWindow.h"21#include "util/random_utils.h"2223using namespace angle;2425namespace26{27// The only configs with 16-bits for each of red, green, blue, and alpha is GL_RGBA16F28bool IsRGBA16FConfig(EGLDisplay display, EGLConfig config)29{30EGLint red, green, blue, alpha;31eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);32eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);33eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);34eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);35return ((red == 16) && (green == 16) && (blue == 16) && (alpha == 16));36}3738bool IsRGB10_A2Config(EGLDisplay display, EGLConfig config)39{40EGLint red, green, blue, alpha;41eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);42eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);43eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);44eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);45return ((red == 10) && (green == 10) && (blue == 10) && (alpha == 2));46}4748// Queries EGL config to determine if multisampled or not49bool IsMultisampledConfig(EGLDisplay display, EGLConfig config)50{51EGLint samples = 0;52eglGetConfigAttrib(display, config, EGL_SAMPLES, &samples);53return (samples > 1);54}5556bool ShouldSkipConfig(EGLDisplay display, EGLConfig config, bool windowSurfaceTest)57{58// Skip multisampled configurations due to test instability.59if (IsMultisampledConfig(display, config))60return true;6162// Disable RGBA16F/RGB10_A2 on Android due to OSWindow on Android not providing compatible63// windows (http://anglebug.com/3156)64if (IsAndroid())65{66if (IsRGB10_A2Config(display, config))67return true;6869if (IsRGBA16FConfig(display, config))70return windowSurfaceTest;71}7273// Linux failures: http://anglebug.com/499074if (IsLinux())75return true;7677return false;78}7980std::vector<EGLConfig> GetConfigs(EGLDisplay display)81{82int nConfigs = 0;83if (eglGetConfigs(display, nullptr, 0, &nConfigs) != EGL_TRUE)84{85std::cerr << "EGLContextCompatiblityTest: eglGetConfigs error\n";86return {};87}88if (nConfigs == 0)89{90std::cerr << "EGLContextCompatiblityTest: no configs\n";91return {};92}9394std::vector<EGLConfig> configs;9596int nReturnedConfigs = 0;97configs.resize(nConfigs);98if (eglGetConfigs(display, configs.data(), nConfigs, &nReturnedConfigs) != EGL_TRUE)99{100std::cerr << "EGLContextCompatiblityTest: eglGetConfigs error\n";101return {};102}103if (nConfigs != nReturnedConfigs)104{105std::cerr << "EGLContextCompatiblityTest: eglGetConfigs returned wrong count\n";106return {};107}108109return configs;110}111112PlatformParameters FromRenderer(EGLint renderer)113{114return WithNoFixture(PlatformParameters(2, 0, EGLPlatformParameters(renderer)));115}116117std::string EGLConfigName(EGLDisplay display, EGLConfig config)118{119EGLint red;120eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);121EGLint green;122eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);123EGLint blue;124eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);125EGLint alpha;126eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);127EGLint depth;128eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth);129EGLint stencil;130eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencil);131EGLint samples;132eglGetConfigAttrib(display, config, EGL_SAMPLES, &samples);133134std::stringstream strstr;135if (red > 0)136{137strstr << "R" << red;138}139if (green > 0)140{141strstr << "G" << green;142}143if (blue > 0)144{145strstr << "B" << blue;146}147if (alpha > 0)148{149strstr << "A" << alpha;150}151if (depth > 0)152{153strstr << "D" << depth;154}155if (stencil > 0)156{157strstr << "S" << stencil;158}159if (samples > 0)160{161strstr << "MS" << samples;162}163return strstr.str();164}165166const std::array<EGLint, 3> kContextAttribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};167168class EGLContextCompatibilityTest : public ANGLETestBase, public testing::Test169{170public:171EGLContextCompatibilityTest(EGLint renderer)172: ANGLETestBase(FromRenderer(renderer)), mRenderer(renderer)173{}174175void SetUp() final176{177ANGLETestBase::ANGLETestSetUp();178ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr);179180EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, mRenderer, EGL_NONE};181mDisplay = eglGetPlatformDisplayEXT(182EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);183ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);184185ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE);186187int nConfigs = 0;188ASSERT_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs) == EGL_TRUE);189ASSERT_TRUE(nConfigs != 0);190191int nReturnedConfigs = 0;192mConfigs.resize(nConfigs);193ASSERT_TRUE(eglGetConfigs(mDisplay, mConfigs.data(), nConfigs, &nReturnedConfigs) ==194EGL_TRUE);195ASSERT_TRUE(nConfigs == nReturnedConfigs);196}197198void TearDown() final199{200eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);201eglTerminate(mDisplay);202ANGLETestBase::ANGLETestTearDown();203}204205protected:206bool areConfigsCompatible(EGLConfig c1, EGLConfig c2, EGLint surfaceBit)207{208EGLint colorBufferType1, colorBufferType2;209EGLint red1, red2, green1, green2, blue1, blue2, alpha1, alpha2;210EGLint depth1, depth2, stencil1, stencil2;211EGLint surfaceType1, surfaceType2;212213eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_BUFFER_TYPE, &colorBufferType1);214eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_BUFFER_TYPE, &colorBufferType2);215216eglGetConfigAttrib(mDisplay, c1, EGL_RED_SIZE, &red1);217eglGetConfigAttrib(mDisplay, c2, EGL_RED_SIZE, &red2);218eglGetConfigAttrib(mDisplay, c1, EGL_GREEN_SIZE, &green1);219eglGetConfigAttrib(mDisplay, c2, EGL_GREEN_SIZE, &green2);220eglGetConfigAttrib(mDisplay, c1, EGL_BLUE_SIZE, &blue1);221eglGetConfigAttrib(mDisplay, c2, EGL_BLUE_SIZE, &blue2);222eglGetConfigAttrib(mDisplay, c1, EGL_ALPHA_SIZE, &alpha1);223eglGetConfigAttrib(mDisplay, c2, EGL_ALPHA_SIZE, &alpha2);224225eglGetConfigAttrib(mDisplay, c1, EGL_DEPTH_SIZE, &depth1);226eglGetConfigAttrib(mDisplay, c2, EGL_DEPTH_SIZE, &depth2);227eglGetConfigAttrib(mDisplay, c1, EGL_STENCIL_SIZE, &stencil1);228eglGetConfigAttrib(mDisplay, c2, EGL_STENCIL_SIZE, &stencil2);229230eglGetConfigAttrib(mDisplay, c1, EGL_SURFACE_TYPE, &surfaceType1);231eglGetConfigAttrib(mDisplay, c2, EGL_SURFACE_TYPE, &surfaceType2);232233EGLint colorComponentType1 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;234EGLint colorComponentType2 = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;235if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))236{237eglGetConfigAttrib(mDisplay, c1, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType1);238eglGetConfigAttrib(mDisplay, c2, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType2);239}240241EXPECT_EGL_SUCCESS();242243return colorBufferType1 == colorBufferType2 && red1 == red2 && green1 == green2 &&244blue1 == blue2 && alpha1 == alpha2 && colorComponentType1 == colorComponentType2 &&245depth1 == depth2 && stencil1 == stencil2 && (surfaceType1 & surfaceBit) != 0 &&246(surfaceType2 & surfaceBit) != 0;247}248249void testWindowCompatibility(EGLConfig windowConfig,250EGLConfig contextConfig,251bool compatible) const252{253OSWindow *osWindow = OSWindow::New();254ASSERT_TRUE(osWindow != nullptr);255osWindow->initialize("EGLContextCompatibilityTest", 500, 500);256257EGLContext context =258eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, kContextAttribs.data());259ASSERT_TRUE(context != EGL_NO_CONTEXT);260261EGLSurface window =262eglCreateWindowSurface(mDisplay, windowConfig, osWindow->getNativeWindow(), nullptr);263ASSERT_EGL_SUCCESS();264265if (compatible)266{267testClearSurface(window, windowConfig, context);268}269else270{271testMakeCurrentFails(window, context);272}273274eglDestroySurface(mDisplay, window);275ASSERT_EGL_SUCCESS();276277eglDestroyContext(mDisplay, context);278ASSERT_EGL_SUCCESS();279280OSWindow::Delete(&osWindow);281}282283void testPbufferCompatibility(EGLConfig pbufferConfig,284EGLConfig contextConfig,285bool compatible) const286{287EGLContext context =288eglCreateContext(mDisplay, contextConfig, EGL_NO_CONTEXT, kContextAttribs.data());289ASSERT_TRUE(context != EGL_NO_CONTEXT);290291const EGLint pBufferAttribs[] = {292EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,293};294EGLSurface pbuffer = eglCreatePbufferSurface(mDisplay, pbufferConfig, pBufferAttribs);295ASSERT_TRUE(pbuffer != EGL_NO_SURFACE);296297if (compatible)298{299testClearSurface(pbuffer, pbufferConfig, context);300}301else302{303testMakeCurrentFails(pbuffer, context);304}305306eglDestroySurface(mDisplay, pbuffer);307ASSERT_EGL_SUCCESS();308309eglDestroyContext(mDisplay, context);310ASSERT_EGL_SUCCESS();311}312313std::vector<EGLConfig> mConfigs;314EGLDisplay mDisplay = EGL_NO_DISPLAY;315EGLint mRenderer = 0;316317private:318void testClearSurface(EGLSurface surface, EGLConfig surfaceConfig, EGLContext context) const319{320eglMakeCurrent(mDisplay, surface, surface, context);321ASSERT_EGL_SUCCESS();322323glViewport(0, 0, 500, 500);324glClearColor(0.0f, 0.0f, 1.0f, 1.0f);325glClear(GL_COLOR_BUFFER_BIT);326ASSERT_GL_NO_ERROR();327328EGLint surfaceCompontentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;329if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_pixel_format_float"))330{331eglGetConfigAttrib(mDisplay, surfaceConfig, EGL_COLOR_COMPONENT_TYPE_EXT,332&surfaceCompontentType);333}334335if (surfaceCompontentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)336{337EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);338}339else340{341EXPECT_PIXEL_32F_EQ(250, 250, 0, 0, 1.0f, 1.0f);342}343344eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);345ASSERT_EGL_SUCCESS();346}347348void testMakeCurrentFails(EGLSurface surface, EGLContext context) const349{350eglMakeCurrent(mDisplay, surface, surface, context);351EXPECT_EGL_ERROR(EGL_BAD_MATCH);352}353};354355// The test is split in several subtest so that simple cases356// are tested separately. Also each surface types are not tested357// together.358359// Basic test checking contexts and windows created with the360// same config can render.361class EGLContextCompatibilityTest_WindowSameConfig : public EGLContextCompatibilityTest362{363public:364EGLContextCompatibilityTest_WindowSameConfig(EGLint renderer, size_t configIndex)365: EGLContextCompatibilityTest(renderer), mConfigIndex(configIndex)366{}367368void TestBody() override369{370EGLConfig config = mConfigs[mConfigIndex];371372EGLint surfaceType;373eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);374ASSERT_EGL_SUCCESS();375376ANGLE_SKIP_TEST_IF((surfaceType & EGL_WINDOW_BIT) == 0);377378testWindowCompatibility(config, config, true);379}380381EGLint mConfigIndex;382};383384// Basic test checking contexts and pbuffers created with the385// same config can render.386class EGLContextCompatibilityTest_PbufferSameConfig : public EGLContextCompatibilityTest387{388public:389EGLContextCompatibilityTest_PbufferSameConfig(EGLint renderer, size_t configIndex)390: EGLContextCompatibilityTest(renderer), mConfigIndex(configIndex)391{}392393void TestBody() override394{395EGLConfig config = mConfigs[mConfigIndex];396397EGLint surfaceType;398eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);399ASSERT_EGL_SUCCESS();400401ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);402403testPbufferCompatibility(config, config, true);404}405406EGLint mConfigIndex;407};408409// Check that a context rendering to a window with a different410// config works or errors according to the EGL compatibility rules411class EGLContextCompatibilityTest_WindowDifferentConfig : public EGLContextCompatibilityTest412{413public:414EGLContextCompatibilityTest_WindowDifferentConfig(EGLint renderer,415size_t configIndexA,416size_t configIndexB)417: EGLContextCompatibilityTest(renderer),418mConfigIndexA(configIndexA),419mConfigIndexB(configIndexB)420{}421422void TestBody() override423{424EGLConfig config1 = mConfigs[mConfigIndexA];425EGLConfig config2 = mConfigs[mConfigIndexB];426427EGLint surfaceType;428eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);429ASSERT_EGL_SUCCESS();430431ANGLE_SKIP_TEST_IF((surfaceType & EGL_WINDOW_BIT) == 0);432433testWindowCompatibility(config1, config2,434areConfigsCompatible(config1, config2, EGL_WINDOW_BIT));435}436437EGLint mConfigIndexA;438EGLint mConfigIndexB;439};440441// Check that a context rendering to a pbuffer with a different442// config works or errors according to the EGL compatibility rules443class EGLContextCompatibilityTest_PbufferDifferentConfig : public EGLContextCompatibilityTest444{445public:446EGLContextCompatibilityTest_PbufferDifferentConfig(EGLint renderer,447size_t configIndexA,448size_t configIndexB)449: EGLContextCompatibilityTest(renderer),450mConfigIndexA(configIndexA),451mConfigIndexB(configIndexB)452{}453454void TestBody() override455{456EGLConfig config1 = mConfigs[mConfigIndexA];457EGLConfig config2 = mConfigs[mConfigIndexB];458459EGLint surfaceType;460eglGetConfigAttrib(mDisplay, config1, EGL_SURFACE_TYPE, &surfaceType);461ASSERT_EGL_SUCCESS();462463ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);464465testPbufferCompatibility(config1, config2,466areConfigsCompatible(config1, config2, EGL_PBUFFER_BIT));467}468469EGLint mConfigIndexA;470EGLint mConfigIndexB;471};472} // namespace473474void RegisterContextCompatibilityTests()475{476std::vector<EGLint> renderers = {{477EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,478EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,479EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,480EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE,481EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE,482}};483484LoadEntryPointsWithUtilLoader(angle::GLESDriverType::AngleEGL);485486if (eglGetPlatformDisplayEXT == nullptr)487{488std::cerr << "EGLContextCompatiblityTest: missing eglGetPlatformDisplayEXT\n";489return;490}491492for (EGLint renderer : renderers)493{494PlatformParameters params = FromRenderer(renderer);495if (!IsPlatformAvailable(params))496continue;497498EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, renderer, EGL_NONE};499EGLDisplay display = eglGetPlatformDisplayEXT(500EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);501if (display == EGL_NO_DISPLAY)502{503std::cerr << "EGLContextCompatiblityTest: eglGetPlatformDisplayEXT error\n";504return;505}506507if (eglInitialize(display, nullptr, nullptr) != EGL_TRUE)508{509std::cerr << "EGLContextCompatiblityTest: eglInitialize error\n";510return;511}512513std::vector<EGLConfig> configs = GetConfigs(display);514std::vector<std::string> configNames;515std::string rendererName = GetRendererName(renderer);516517for (EGLConfig config : configs)518{519configNames.push_back(EGLConfigName(display, config));520}521522for (size_t configIndex = 0; configIndex < configs.size(); ++configIndex)523{524if (ShouldSkipConfig(display, configs[configIndex], true))525continue;526527std::stringstream nameStr;528nameStr << "WindowSameConfig/" << rendererName << "_" << configNames[configIndex];529std::string name = nameStr.str();530531testing::RegisterTest(532"EGLContextCompatibilityTest", name.c_str(), nullptr, nullptr, __FILE__, __LINE__,533[renderer, configIndex]() -> EGLContextCompatibilityTest * {534return new EGLContextCompatibilityTest_WindowSameConfig(renderer, configIndex);535});536}537538for (size_t configIndex = 0; configIndex < configs.size(); ++configIndex)539{540if (ShouldSkipConfig(display, configs[configIndex], false))541continue;542543std::stringstream nameStr;544nameStr << "PbufferSameConfig/" << rendererName << "_" << configNames[configIndex];545std::string name = nameStr.str();546547testing::RegisterTest(548"EGLContextCompatibilityTest", name.c_str(), nullptr, nullptr, __FILE__, __LINE__,549[renderer, configIndex]() -> EGLContextCompatibilityTest * {550return new EGLContextCompatibilityTest_PbufferSameConfig(renderer, configIndex);551});552}553554// Because there are so many permutations, we skip some configs randomly.555// Attempt to run at most 100 tests per renderer.556RNG rng(0);557constexpr uint32_t kMaximumTestsPerRenderer = 100;558const uint32_t kTestCount = static_cast<uint32_t>(configs.size() * configs.size());559const float kSkipP =5601.0f - (static_cast<float>(std::min(kMaximumTestsPerRenderer, kTestCount)) /561static_cast<float>(kTestCount));562563for (size_t configIndexA = 0; configIndexA < configs.size(); ++configIndexA)564{565if (ShouldSkipConfig(display, configs[configIndexA], true))566continue;567568std::string configNameA = configNames[configIndexA];569570for (size_t configIndexB = 0; configIndexB < configs.size(); ++configIndexB)571{572if (ShouldSkipConfig(display, configs[configIndexB], true))573continue;574575if (rng.randomFloat() < kSkipP)576continue;577578std::string configNameB = configNames[configIndexB];579580std::stringstream nameStr;581nameStr << "WindowDifferentConfig/" << rendererName << "_" << configNameA << "_"582<< configNameB;583std::string name = nameStr.str();584585testing::RegisterTest(586"EGLContextCompatibilityTest", name.c_str(), nullptr, nullptr, __FILE__,587__LINE__,588[renderer, configIndexA, configIndexB]() -> EGLContextCompatibilityTest * {589return new EGLContextCompatibilityTest_WindowDifferentConfig(590renderer, configIndexA, configIndexB);591});592}593}594595for (size_t configIndexA = 0; configIndexA < configs.size(); ++configIndexA)596{597if (ShouldSkipConfig(display, configs[configIndexA], false))598continue;599600std::string configNameA = configNames[configIndexA];601602for (size_t configIndexB = 0; configIndexB < configs.size(); ++configIndexB)603{604if (ShouldSkipConfig(display, configs[configIndexB], false))605continue;606607if (rng.randomFloat() < kSkipP)608continue;609610std::string configNameB = configNames[configIndexB];611612std::stringstream nameStr;613nameStr << "PbufferDifferentConfig/" << rendererName << "_" << configNameA << "_"614<< configNameB;615std::string name = nameStr.str();616617testing::RegisterTest(618"EGLContextCompatibilityTest", name.c_str(), nullptr, nullptr, __FILE__,619__LINE__,620[renderer, configIndexA, configIndexB]() -> EGLContextCompatibilityTest * {621return new EGLContextCompatibilityTest_PbufferDifferentConfig(622renderer, configIndexA, configIndexB);623});624}625}626627if (eglTerminate(display) == EGL_FALSE)628{629std::cerr << "EGLContextCompatiblityTest: eglTerminate error\n";630return;631}632}633}634635636