• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Tests the eglQueryStringiANGLE and eglQueryDisplayAttribANGLE functions exposed by the
7 // extension EGL_ANGLE_feature_control.
8 
9 #include <gtest/gtest.h>
10 
11 #include "libANGLE/Display.h"
12 #include "test_utils/ANGLETest.h"
13 
14 using namespace angle;
15 
16 class EGLFeatureControlTest : public ANGLETest
17 {
18   public:
testSetUp()19     void testSetUp() override { mDisplay = EGL_NO_DISPLAY; }
20 
testTearDown()21     void testTearDown() override
22     {
23         if (mDisplay != EGL_NO_DISPLAY)
24         {
25             eglTerminate(mDisplay);
26         }
27     }
28 
29   protected:
30     EGLDisplay mDisplay;
31 
initTest()32     bool initTest()
33     {
34         // http://anglebug.com/3629 This test sporadically times out on Win10/Intel
35         if (IsWindows() && IsIntel())
36             return false;
37 
38         EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
39         mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
40                                          reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
41         EXPECT_NE(mDisplay, EGL_NO_DISPLAY);
42 
43         EXPECT_EQ(eglInitialize(mDisplay, nullptr, nullptr), static_cast<EGLBoolean>(EGL_TRUE));
44 
45         EXPECT_TRUE(IsEGLClientExtensionEnabled("EGL_ANGLE_feature_control"));
46 
47         return true;
48     }
49 };
50 
51 // Ensure eglQueryStringiANGLE generates EGL_BAD_DISPLAY if the display passed in is invalid.
TEST_P(EGLFeatureControlTest,InvalidDisplay)52 TEST_P(EGLFeatureControlTest, InvalidDisplay)
53 {
54     ANGLE_SKIP_TEST_IF(!initTest());
55     EXPECT_EQ(nullptr, eglQueryStringiANGLE(EGL_NO_DISPLAY, EGL_FEATURE_NAME_ANGLE, 0));
56     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
57 }
58 
59 // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the index is negative.
TEST_P(EGLFeatureControlTest,NegativeIndex)60 TEST_P(EGLFeatureControlTest, NegativeIndex)
61 {
62     ANGLE_SKIP_TEST_IF(!initTest());
63     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE, -1));
64     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
65 }
66 
67 // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the index is out of bounds.
TEST_P(EGLFeatureControlTest,IndexOutOfBounds)68 TEST_P(EGLFeatureControlTest, IndexOutOfBounds)
69 {
70     ANGLE_SKIP_TEST_IF(!initTest());
71     egl::Display *display = static_cast<egl::Display *>(mDisplay);
72     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE,
73                                             display->getFeatures().size()));
74     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
75 }
76 
77 // Ensure eglQueryStringiANGLE generates EGL_BAD_PARAMETER if the name is not one of the valid
78 // options specified in EGL_ANGLE_feature_control.
TEST_P(EGLFeatureControlTest,InvalidName)79 TEST_P(EGLFeatureControlTest, InvalidName)
80 {
81     ANGLE_SKIP_TEST_IF(!initTest());
82     EXPECT_EQ(nullptr, eglQueryStringiANGLE(mDisplay, 100, 0));
83     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
84 }
85 
86 // For each valid name and index in the feature description arrays, query the values and ensure
87 // that no error is generated, and that the values match the correct values frim ANGLE's display's
88 // FeatureList.
TEST_P(EGLFeatureControlTest,QueryAll)89 TEST_P(EGLFeatureControlTest, QueryAll)
90 {
91     ANGLE_SKIP_TEST_IF(!initTest());
92     egl::Display *display       = static_cast<egl::Display *>(mDisplay);
93     angle::FeatureList features = display->getFeatures();
94     for (size_t i = 0; i < features.size(); i++)
95     {
96         EXPECT_STREQ(features[i]->name, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_NAME_ANGLE, i));
97         EXPECT_STREQ(FeatureCategoryToString(features[i]->category),
98                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_CATEGORY_ANGLE, i));
99         EXPECT_STREQ(features[i]->description,
100                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_DESCRIPTION_ANGLE, i));
101         EXPECT_STREQ(features[i]->bug, eglQueryStringiANGLE(mDisplay, EGL_FEATURE_BUG_ANGLE, i));
102         EXPECT_STREQ(FeatureStatusToString(features[i]->enabled),
103                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_STATUS_ANGLE, i));
104         EXPECT_STREQ(features[i]->condition,
105                      eglQueryStringiANGLE(mDisplay, EGL_FEATURE_CONDITION_ANGLE, i));
106         ASSERT_EGL_SUCCESS();
107     }
108 }
109 
110 // Ensure eglQueryDisplayAttribANGLE returns the correct number of features when queried with
111 // attribute EGL_FEATURE_COUNT_ANGLE
TEST_P(EGLFeatureControlTest,FeatureCount)112 TEST_P(EGLFeatureControlTest, FeatureCount)
113 {
114     ANGLE_SKIP_TEST_IF(!initTest());
115     egl::Display *display = static_cast<egl::Display *>(mDisplay);
116     EGLAttrib value       = -1;
117     EXPECT_EQ(static_cast<EGLBoolean>(EGL_TRUE),
118               eglQueryDisplayAttribANGLE(mDisplay, EGL_FEATURE_COUNT_ANGLE, &value));
119     EXPECT_EQ(display->getFeatures().size(), static_cast<size_t>(value));
120     ASSERT_EGL_SUCCESS();
121 }
122 
123 // Submit a list of features to override when creating the display with eglGetPlatformDisplay, and
124 // ensure that the features are correctly overridden.
TEST_P(EGLFeatureControlTest,OverrideFeatures)125 TEST_P(EGLFeatureControlTest, OverrideFeatures)
126 {
127     ANGLE_SKIP_TEST_IF(!initTest());
128     egl::Display *display       = static_cast<egl::Display *>(mDisplay);
129     angle::FeatureList features = display->getFeatures();
130 
131     // Build lists of features to enable/disabled. Toggle features we know are ok to toggle based
132     // from this list.
133     std::vector<const char *> enabled       = std::vector<const char *>();
134     std::vector<const char *> disabled      = std::vector<const char *>();
135     std::vector<bool> shouldBe              = std::vector<bool>();
136     std::vector<std::string> testedFeatures = {
137         "add_and_true_to_loop_condition",  // Safe to toggle GL
138         "clamp_frag_depth",                // Safe to toggle GL
139         "clamp_point_size",                // Safe to toggle GL and Vulkan
140         "flip_viewport_y",                 // Safe to toggle on Vulkan
141         "zero_max_lod",                    // Safe to toggle on D3D
142         "expand_integer_pow_expressions",  // Safe to toggle on D3D
143         "rewrite_unary_minus_operator",    // Safe to toggle on D3D
144     };
145     for (size_t i = 0; i < features.size(); i++)
146     {
147         bool toggle = std::find(testedFeatures.begin(), testedFeatures.end(),
148                                 std::string(features[i]->name)) != testedFeatures.end();
149         if (features[i]->enabled ^ toggle)
150         {
151             enabled.push_back(features[i]->name);
152         }
153         else
154         {
155             disabled.push_back(features[i]->name);
156         }
157         // Save what we expect the feature status will be when checking later.
158         shouldBe.push_back(features[i]->enabled ^ toggle);
159     }
160     disabled.push_back(0);
161     enabled.push_back(0);
162 
163     // Terminate the old display (we just used it to collect features)
164     eglTerminate(mDisplay);
165 
166     // Create a new display with these overridden features.
167     EGLAttrib dispattrs[]   = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
168                              GetParam().getRenderer(),
169                              EGL_FEATURE_OVERRIDES_ENABLED_ANGLE,
170                              reinterpret_cast<EGLAttrib>(enabled.data()),
171                              EGL_FEATURE_OVERRIDES_DISABLED_ANGLE,
172                              reinterpret_cast<EGLAttrib>(disabled.data()),
173                              EGL_NONE};
174     EGLDisplay dpy_override = eglGetPlatformDisplay(
175         EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
176     ASSERT_EGL_SUCCESS();
177     ASSERT_TRUE(dpy_override != EGL_NO_DISPLAY);
178     ASSERT_TRUE(eglInitialize(dpy_override, nullptr, nullptr) == EGL_TRUE);
179 
180     // Check that all features have the correct status (even the ones we toggled).
181     for (size_t i = 0; i < features.size(); i++)
182     {
183         EXPECT_STREQ(FeatureStatusToString(shouldBe[i]),
184                      eglQueryStringiANGLE(dpy_override, EGL_FEATURE_STATUS_ANGLE, i));
185     }
186 }
187 
188 ANGLE_INSTANTIATE_TEST(EGLFeatureControlTest,
189                        WithNoFixture(ES2_D3D9()),
190                        WithNoFixture(ES2_D3D11()),
191                        WithNoFixture(ES2_OPENGL()),
192                        WithNoFixture(ES2_VULKAN()),
193                        WithNoFixture(ES3_D3D11()),
194                        WithNoFixture(ES3_OPENGL()));
195