xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLFeatureControlTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // Tests the eglQueryStringiANGLE and eglQueryDisplayAttribANGLE functions exposed by the
7*8975f5c5SAndroid Build Coastguard Worker // extension EGL_ANGLE_feature_control.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <gtest/gtest.h>
10*8975f5c5SAndroid Build Coastguard Worker #include <optional>
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker class EGLFeatureControlTest : public ANGLETest<>
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker   public:
testSetUp()21*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override { mDisplay = EGL_NO_DISPLAY; }
22*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()23*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
24*8975f5c5SAndroid Build Coastguard Worker     {
25*8975f5c5SAndroid Build Coastguard Worker         if (mDisplay != EGL_NO_DISPLAY)
26*8975f5c5SAndroid Build Coastguard Worker         {
27*8975f5c5SAndroid Build Coastguard Worker             eglTerminate(mDisplay);
28*8975f5c5SAndroid Build Coastguard Worker         }
29*8975f5c5SAndroid Build Coastguard Worker     }
30*8975f5c5SAndroid Build Coastguard Worker 
31*8975f5c5SAndroid Build Coastguard Worker   protected:
32*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay mDisplay;
33*8975f5c5SAndroid Build Coastguard Worker 
initTest()34*8975f5c5SAndroid Build Coastguard Worker     bool initTest()
35*8975f5c5SAndroid Build Coastguard Worker     {
36*8975f5c5SAndroid Build Coastguard Worker         // http://anglebug.com/42262291 This test sporadically times out on Win10/Intel
37*8975f5c5SAndroid Build Coastguard Worker         if (IsWindows() && IsIntel())
38*8975f5c5SAndroid Build Coastguard Worker             return false;
39*8975f5c5SAndroid Build Coastguard Worker 
40*8975f5c5SAndroid Build Coastguard Worker         EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
41*8975f5c5SAndroid Build Coastguard Worker         mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
42*8975f5c5SAndroid Build Coastguard Worker                                                       reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
43*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(mDisplay, EGL_NO_DISPLAY);
44*8975f5c5SAndroid Build Coastguard Worker 
45*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(eglInitialize(mDisplay, nullptr, nullptr), static_cast<EGLBoolean>(EGL_TRUE));
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker         EXPECT_TRUE(IsEGLClientExtensionEnabled("EGL_ANGLE_feature_control"));
48*8975f5c5SAndroid Build Coastguard Worker 
49*8975f5c5SAndroid Build Coastguard Worker         return true;
50*8975f5c5SAndroid Build Coastguard Worker     }
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker     using FeatureNameModifier = std::function<std::string(const std::string &)>;
53*8975f5c5SAndroid Build Coastguard Worker     void testOverrideFeatures(FeatureNameModifier modifyName);
54*8975f5c5SAndroid Build Coastguard Worker };
55*8975f5c5SAndroid Build Coastguard Worker 
56*8975f5c5SAndroid Build Coastguard Worker // Ensure eglQueryStringiANGLE generates EGL_BAD_DISPLAY if the display passed in is invalid.
TEST_P(EGLFeatureControlTest,InvalidDisplay)57*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, InvalidDisplay)
58*8975f5c5SAndroid Build Coastguard Worker {
59*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
60*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, eglQueryStringiANGLE(EGL_NO_DISPLAY, EGL_FEATURE_NAME_ANGLE, 0));
61*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the index is negative.
TEST_P(EGLFeatureControlTest,NegativeIndex)65*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, NegativeIndex)
66*8975f5c5SAndroid Build Coastguard Worker {
67*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
68*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE, -1));
69*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker 
72*8975f5c5SAndroid Build Coastguard Worker // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the index is out of bounds.
TEST_P(EGLFeatureControlTest,IndexOutOfBounds)73*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, IndexOutOfBounds)
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
76*8975f5c5SAndroid Build Coastguard Worker     egl::Display *display = static_cast<egl::Display *>(mDisplay);
77*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE,
78*8975f5c5SAndroid Build Coastguard Worker                                             display->getFeatures().size()));
79*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
80*8975f5c5SAndroid Build Coastguard Worker }
81*8975f5c5SAndroid Build Coastguard Worker 
82*8975f5c5SAndroid Build Coastguard Worker // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the name is not one of the valid
83*8975f5c5SAndroid Build Coastguard Worker // options specified in EGL_ANGLE_feature_control.
TEST_P(EGLFeatureControlTest,InvalidName)84*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, InvalidName)
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
87*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, 100, 0));
88*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
89*8975f5c5SAndroid Build Coastguard Worker }
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker // For each valid name and index in the feature description arrays, query the values and ensure
92*8975f5c5SAndroid Build Coastguard Worker // that no error is generated, and that the values match the correct values frim ANGLE's display's
93*8975f5c5SAndroid Build Coastguard Worker // FeatureList.
TEST_P(EGLFeatureControlTest,QueryAll)94*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, QueryAll)
95*8975f5c5SAndroid Build Coastguard Worker {
96*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
97*8975f5c5SAndroid Build Coastguard Worker     egl::Display *display       = static_cast<egl::Display *>(mDisplay);
98*8975f5c5SAndroid Build Coastguard Worker     angle::FeatureList features = display->getFeatures();
99*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < features.size(); i++)
100*8975f5c5SAndroid Build Coastguard Worker     {
101*8975f5c5SAndroid Build Coastguard Worker         EXPECT_STREQ(features[i]->name, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE, i));
102*8975f5c5SAndroid Build Coastguard Worker         EXPECT_STREQ(FeatureCategoryToString(features[i]->category),
103*8975f5c5SAndroid Build Coastguard Worker                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_CATEGORY_ANGLE, i));
104*8975f5c5SAndroid Build Coastguard Worker         EXPECT_STREQ(FeatureStatusToString(features[i]->enabled),
105*8975f5c5SAndroid Build Coastguard Worker                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i));
106*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EGL_SUCCESS();
107*8975f5c5SAndroid Build Coastguard Worker     }
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker // Ensure eglQueryDisplayAttribANGLE returns the correct number of features when queried with
111*8975f5c5SAndroid Build Coastguard Worker // attribute EGL_FEATURE_COUNT_ANGLE
TEST_P(EGLFeatureControlTest,FeatureCount)112*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, FeatureCount)
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
115*8975f5c5SAndroid Build Coastguard Worker     egl::Display *display = static_cast<egl::Display *>(mDisplay);
116*8975f5c5SAndroid Build Coastguard Worker     EGLAttrib value       = -1;
117*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE),
118*8975f5c5SAndroid Build Coastguard Worker               eglQueryDisplayAttribANGLE(mDisplay, EGL_FEATURE_COUNT_ANGLE, &value));
119*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(display->getFeatures().size(), static_cast<size_t>(value));
120*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EGL_SUCCESS();
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker 
testOverrideFeatures(FeatureNameModifier modifyName)123*8975f5c5SAndroid Build Coastguard Worker void EGLFeatureControlTest::testOverrideFeatures(FeatureNameModifier modifyName)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
126*8975f5c5SAndroid Build Coastguard Worker     egl::Display *display       = static_cast<egl::Display *>(mDisplay);
127*8975f5c5SAndroid Build Coastguard Worker     angle::FeatureList features = display->getFeatures();
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker     // Build lists of features to enable/disabled. Toggle features we know are ok to toggle based
130*8975f5c5SAndroid Build Coastguard Worker     // from this list.
131*8975f5c5SAndroid Build Coastguard Worker     std::vector<const char *> enabled;
132*8975f5c5SAndroid Build Coastguard Worker     std::vector<const char *> disabled;
133*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> modifiedNameStorage;
134*8975f5c5SAndroid Build Coastguard Worker     std::vector<bool> shouldBe;
135*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> testedFeatures = {
136*8975f5c5SAndroid Build Coastguard Worker         // Safe to toggle on GL
137*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::AddAndTrueToLoopCondition),
138*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::ClampFragDepth),
139*8975f5c5SAndroid Build Coastguard Worker         // Safe to toggle on GL and Vulkan
140*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::ClampPointSize),
141*8975f5c5SAndroid Build Coastguard Worker         // Safe to toggle on D3D
142*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::ZeroMaxLodWorkaround),
143*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::ExpandIntegerPowExpressions),
144*8975f5c5SAndroid Build Coastguard Worker         angle::GetFeatureName(angle::Feature::RewriteUnaryMinusOperator),
145*8975f5c5SAndroid Build Coastguard Worker     };
146*8975f5c5SAndroid Build Coastguard Worker 
147*8975f5c5SAndroid Build Coastguard Worker     modifiedNameStorage.reserve(features.size());
148*8975f5c5SAndroid Build Coastguard Worker     shouldBe.reserve(features.size());
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < features.size(); i++)
151*8975f5c5SAndroid Build Coastguard Worker     {
152*8975f5c5SAndroid Build Coastguard Worker         modifiedNameStorage.push_back(modifyName(features[i]->name));
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker         bool toggle = std::find(testedFeatures.begin(), testedFeatures.end(),
155*8975f5c5SAndroid Build Coastguard Worker                                 std::string(features[i]->name)) != testedFeatures.end();
156*8975f5c5SAndroid Build Coastguard Worker         if (features[i]->enabled ^ toggle)
157*8975f5c5SAndroid Build Coastguard Worker         {
158*8975f5c5SAndroid Build Coastguard Worker             enabled.push_back(modifiedNameStorage[i].c_str());
159*8975f5c5SAndroid Build Coastguard Worker         }
160*8975f5c5SAndroid Build Coastguard Worker         else
161*8975f5c5SAndroid Build Coastguard Worker         {
162*8975f5c5SAndroid Build Coastguard Worker             disabled.push_back(modifiedNameStorage[i].c_str());
163*8975f5c5SAndroid Build Coastguard Worker         }
164*8975f5c5SAndroid Build Coastguard Worker         // Save what we expect the feature status will be when checking later.
165*8975f5c5SAndroid Build Coastguard Worker         shouldBe.push_back(features[i]->enabled ^ toggle);
166*8975f5c5SAndroid Build Coastguard Worker     }
167*8975f5c5SAndroid Build Coastguard Worker     disabled.push_back(0);
168*8975f5c5SAndroid Build Coastguard Worker     enabled.push_back(0);
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker     // Terminate the old display (we just used it to collect features)
171*8975f5c5SAndroid Build Coastguard Worker     eglTerminate(mDisplay);
172*8975f5c5SAndroid Build Coastguard Worker 
173*8975f5c5SAndroid Build Coastguard Worker     // Create a new display with these overridden features.
174*8975f5c5SAndroid Build Coastguard Worker     EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
175*8975f5c5SAndroid Build Coastguard Worker                              GetParam().getRenderer(),
176*8975f5c5SAndroid Build Coastguard Worker                              EGL_FEATURE_OVERRIDES_ENABLED_ANGLE,
177*8975f5c5SAndroid Build Coastguard Worker                              reinterpret_cast<EGLAttrib>(enabled.data()),
178*8975f5c5SAndroid Build Coastguard Worker                              EGL_FEATURE_OVERRIDES_DISABLED_ANGLE,
179*8975f5c5SAndroid Build Coastguard Worker                              reinterpret_cast<EGLAttrib>(disabled.data()),
180*8975f5c5SAndroid Build Coastguard Worker                              EGL_NONE};
181*8975f5c5SAndroid Build Coastguard Worker     mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
182*8975f5c5SAndroid Build Coastguard Worker                                                   reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
183*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EGL_SUCCESS();
184*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
185*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(eglInitialize(mDisplay, nullptr, nullptr), EGLBoolean(EGL_TRUE));
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker     // Check that all features have the correct status (even the ones we toggled).
188*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < features.size(); i++)
189*8975f5c5SAndroid Build Coastguard Worker     {
190*8975f5c5SAndroid Build Coastguard Worker         EXPECT_STREQ(FeatureStatusToString(shouldBe[i]),
191*8975f5c5SAndroid Build Coastguard Worker                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i))
192*8975f5c5SAndroid Build Coastguard Worker             << modifiedNameStorage[i];
193*8975f5c5SAndroid Build Coastguard Worker     }
194*8975f5c5SAndroid Build Coastguard Worker }
195*8975f5c5SAndroid Build Coastguard Worker 
196*8975f5c5SAndroid Build Coastguard Worker // Submit a list of features to override when creating the display with eglGetPlatformDisplay, and
197*8975f5c5SAndroid Build Coastguard Worker // ensure that the features are correctly overridden.
TEST_P(EGLFeatureControlTest,OverrideFeatures)198*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, OverrideFeatures)
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker     testOverrideFeatures([](const std::string &featureName) { return featureName; });
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker 
203*8975f5c5SAndroid Build Coastguard Worker // Similar to OverrideFeatures, but ensures that camelCase variants of the name match as well.
TEST_P(EGLFeatureControlTest,OverrideFeaturesCamelCase)204*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, OverrideFeaturesCamelCase)
205*8975f5c5SAndroid Build Coastguard Worker {
206*8975f5c5SAndroid Build Coastguard Worker     testOverrideFeatures(
207*8975f5c5SAndroid Build Coastguard Worker         [](const std::string &featureName) { return angle::ToCamelCase(featureName); });
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker 
210*8975f5c5SAndroid Build Coastguard Worker // Similar to OverrideFeatures, but ensures wildcard matching works
TEST_P(EGLFeatureControlTest,OverrideFeaturesWildcard)211*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, OverrideFeaturesWildcard)
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker     for (int j = 0; j < 2; j++)
214*8975f5c5SAndroid Build Coastguard Worker     {
215*8975f5c5SAndroid Build Coastguard Worker         const bool testEnableOverride = (j != 0);
216*8975f5c5SAndroid Build Coastguard Worker 
217*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SKIP_TEST_IF(!initTest());
218*8975f5c5SAndroid Build Coastguard Worker 
219*8975f5c5SAndroid Build Coastguard Worker         egl::Display *display       = static_cast<egl::Display *>(mDisplay);
220*8975f5c5SAndroid Build Coastguard Worker         angle::FeatureList features = display->getFeatures();
221*8975f5c5SAndroid Build Coastguard Worker 
222*8975f5c5SAndroid Build Coastguard Worker         // Note that we don't use the broader 'prefer_*' here because
223*8975f5c5SAndroid Build Coastguard Worker         // prefer_monolithic_pipelines_over_libraries may affect other feature
224*8975f5c5SAndroid Build Coastguard Worker         // flags.
225*8975f5c5SAndroid Build Coastguard Worker         std::vector<const char *> featuresToOverride = {"prefer_d*", nullptr};
226*8975f5c5SAndroid Build Coastguard Worker 
227*8975f5c5SAndroid Build Coastguard Worker         std::vector<std::string> featureNameStorage;
228*8975f5c5SAndroid Build Coastguard Worker         std::vector<bool> shouldBe;
229*8975f5c5SAndroid Build Coastguard Worker 
230*8975f5c5SAndroid Build Coastguard Worker         shouldBe.reserve(features.size());
231*8975f5c5SAndroid Build Coastguard Worker         featureNameStorage.reserve(features.size());
232*8975f5c5SAndroid Build Coastguard Worker 
233*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < features.size(); i++)
234*8975f5c5SAndroid Build Coastguard Worker         {
235*8975f5c5SAndroid Build Coastguard Worker             std::string featureName = std::string(features[i]->name);
236*8975f5c5SAndroid Build Coastguard Worker             std::transform(featureName.begin(), featureName.end(), featureName.begin(),
237*8975f5c5SAndroid Build Coastguard Worker                            [](unsigned char c) { return std::tolower(c); });
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker             const bool featureMatch = strncmp(featureName.c_str(), "preferd", 7) == 0;
240*8975f5c5SAndroid Build Coastguard Worker 
241*8975f5c5SAndroid Build Coastguard Worker             std::optional<bool> overrideState;
242*8975f5c5SAndroid Build Coastguard Worker             if (featureMatch)
243*8975f5c5SAndroid Build Coastguard Worker             {
244*8975f5c5SAndroid Build Coastguard Worker                 overrideState = testEnableOverride;
245*8975f5c5SAndroid Build Coastguard Worker             }
246*8975f5c5SAndroid Build Coastguard Worker 
247*8975f5c5SAndroid Build Coastguard Worker             // Save what we expect the feature status will be when checking later.
248*8975f5c5SAndroid Build Coastguard Worker             shouldBe.push_back(overrideState.value_or(features[i]->enabled));
249*8975f5c5SAndroid Build Coastguard Worker             featureNameStorage.push_back(features[i]->name);
250*8975f5c5SAndroid Build Coastguard Worker         }
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker         // Terminate the old display (we just used it to collect features)
253*8975f5c5SAndroid Build Coastguard Worker         eglTerminate(mDisplay);
254*8975f5c5SAndroid Build Coastguard Worker         mDisplay = nullptr;
255*8975f5c5SAndroid Build Coastguard Worker 
256*8975f5c5SAndroid Build Coastguard Worker         // Create a new display with these overridden features.
257*8975f5c5SAndroid Build Coastguard Worker         EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
258*8975f5c5SAndroid Build Coastguard Worker                                  testEnableOverride ? EGL_FEATURE_OVERRIDES_ENABLED_ANGLE
259*8975f5c5SAndroid Build Coastguard Worker                                                     : EGL_FEATURE_OVERRIDES_DISABLED_ANGLE,
260*8975f5c5SAndroid Build Coastguard Worker                                  reinterpret_cast<EGLAttrib>(featuresToOverride.data()), EGL_NONE};
261*8975f5c5SAndroid Build Coastguard Worker         mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
262*8975f5c5SAndroid Build Coastguard Worker                                                       reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
263*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EGL_SUCCESS();
264*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
265*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(eglInitialize(mDisplay, nullptr, nullptr), EGLBoolean(EGL_TRUE));
266*8975f5c5SAndroid Build Coastguard Worker 
267*8975f5c5SAndroid Build Coastguard Worker         // Check that all features have the correct status (even the ones we toggled).
268*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < features.size(); i++)
269*8975f5c5SAndroid Build Coastguard Worker         {
270*8975f5c5SAndroid Build Coastguard Worker             EXPECT_STREQ(FeatureStatusToString(shouldBe[i]),
271*8975f5c5SAndroid Build Coastguard Worker                          eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i))
272*8975f5c5SAndroid Build Coastguard Worker                 << featureNameStorage[i];
273*8975f5c5SAndroid Build Coastguard Worker         }
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker         // Clean up display for next iteration.
276*8975f5c5SAndroid Build Coastguard Worker         eglTerminate(mDisplay);
277*8975f5c5SAndroid Build Coastguard Worker         mDisplay = nullptr;
278*8975f5c5SAndroid Build Coastguard Worker     }
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker // Ensure that dependent features are affected properly by overrides
TEST_P(EGLFeatureControlTest,OverrideFeaturesDependent)282*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLFeatureControlTest, OverrideFeaturesDependent)
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!initTest());
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker     egl::Display *display       = static_cast<egl::Display *>(mDisplay);
287*8975f5c5SAndroid Build Coastguard Worker     angle::FeatureList features = display->getFeatures();
288*8975f5c5SAndroid Build Coastguard Worker 
289*8975f5c5SAndroid Build Coastguard Worker     const std::vector<const char *> featuresDisabled = {
290*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsRenderpass2),
291*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsImage2dViewOf3d), nullptr};
292*8975f5c5SAndroid Build Coastguard Worker 
293*8975f5c5SAndroid Build Coastguard Worker     const std::vector<const char *> featuresExpectDisabled = {
294*8975f5c5SAndroid Build Coastguard Worker         // Features we changed
295*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsRenderpass2),
296*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsImage2dViewOf3d),
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker         // Features that must become disabled as a result of the above
299*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsDepthStencilResolve),
300*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsDepthStencilIndependentResolveNone),
301*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsSampler2dViewOf3d),
302*8975f5c5SAndroid Build Coastguard Worker         GetFeatureName(Feature::SupportsFragmentShadingRate),
303*8975f5c5SAndroid Build Coastguard Worker     };
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> featureNameStorage;
306*8975f5c5SAndroid Build Coastguard Worker     std::vector<bool> shouldBe;
307*8975f5c5SAndroid Build Coastguard Worker 
308*8975f5c5SAndroid Build Coastguard Worker     shouldBe.reserve(features.size());
309*8975f5c5SAndroid Build Coastguard Worker     featureNameStorage.reserve(features.size());
310*8975f5c5SAndroid Build Coastguard Worker 
311*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < features.size(); i++)
312*8975f5c5SAndroid Build Coastguard Worker     {
313*8975f5c5SAndroid Build Coastguard Worker         bool featureMatch = false;
314*8975f5c5SAndroid Build Coastguard Worker         for (auto *ptr : featuresExpectDisabled)
315*8975f5c5SAndroid Build Coastguard Worker         {
316*8975f5c5SAndroid Build Coastguard Worker             if (strcmp(ptr, features[i]->name) == 0)
317*8975f5c5SAndroid Build Coastguard Worker             {
318*8975f5c5SAndroid Build Coastguard Worker                 featureMatch = true;
319*8975f5c5SAndroid Build Coastguard Worker                 break;
320*8975f5c5SAndroid Build Coastguard Worker             }
321*8975f5c5SAndroid Build Coastguard Worker         }
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker         std::string featureName = std::string(features[i]->name);
324*8975f5c5SAndroid Build Coastguard Worker         std::transform(featureName.begin(), featureName.end(), featureName.begin(),
325*8975f5c5SAndroid Build Coastguard Worker                        [](unsigned char c) { return std::tolower(c); });
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker         // Save what we expect the feature status will be when checking later.
328*8975f5c5SAndroid Build Coastguard Worker         shouldBe.push_back(features[i]->enabled && !featureMatch);
329*8975f5c5SAndroid Build Coastguard Worker 
330*8975f5c5SAndroid Build Coastguard Worker         // Store copy of the feature name string, in case we need to print for a test failure
331*8975f5c5SAndroid Build Coastguard Worker         featureNameStorage.push_back(features[i]->name);
332*8975f5c5SAndroid Build Coastguard Worker     }
333*8975f5c5SAndroid Build Coastguard Worker 
334*8975f5c5SAndroid Build Coastguard Worker     // Terminate the old display (we just used it to collect features)
335*8975f5c5SAndroid Build Coastguard Worker     eglTerminate(mDisplay);
336*8975f5c5SAndroid Build Coastguard Worker 
337*8975f5c5SAndroid Build Coastguard Worker     // Create a new display with these overridden features.
338*8975f5c5SAndroid Build Coastguard Worker     EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(),
339*8975f5c5SAndroid Build Coastguard Worker                              EGL_FEATURE_OVERRIDES_DISABLED_ANGLE,
340*8975f5c5SAndroid Build Coastguard Worker                              reinterpret_cast<EGLAttrib>(featuresDisabled.data()), EGL_NONE};
341*8975f5c5SAndroid Build Coastguard Worker     mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
342*8975f5c5SAndroid Build Coastguard Worker                                                   reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
343*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EGL_SUCCESS();
344*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mDisplay, EGL_NO_DISPLAY);
345*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(eglInitialize(mDisplay, nullptr, nullptr), EGLBoolean(EGL_TRUE));
346*8975f5c5SAndroid Build Coastguard Worker 
347*8975f5c5SAndroid Build Coastguard Worker     // Check that all features have the correct status (even the ones we toggled).
348*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < features.size(); i++)
349*8975f5c5SAndroid Build Coastguard Worker     {
350*8975f5c5SAndroid Build Coastguard Worker         EXPECT_STREQ(FeatureStatusToString(shouldBe[i]),
351*8975f5c5SAndroid Build Coastguard Worker                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i))
352*8975f5c5SAndroid Build Coastguard Worker             << featureNameStorage[i];
353*8975f5c5SAndroid Build Coastguard Worker     }
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker 
356*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST(EGLFeatureControlTest,
357*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES2_D3D9()),
358*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES2_D3D11()),
359*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES2_METAL()),
360*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES2_OPENGL()),
361*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES2_VULKAN()),
362*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES3_D3D11()),
363*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES3_METAL()),
364*8975f5c5SAndroid Build Coastguard Worker                        WithNoFixture(ES3_OPENGL()));
365