xref: /aosp_15_r20/external/angle/src/tests/deqp_support/tcuANGLEPlatform.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20 
21 #include "tcuANGLEPlatform.h"
22 
23 #include "egluGLContextFactory.hpp"
24 #include "gluPlatform.hpp"
25 #include "tcuANGLENativeDisplayFactory.h"
26 #include "tcuDefs.hpp"
27 #include "tcuNullContextFactory.hpp"
28 #include "tcuPlatform.hpp"
29 #include "util/autogen/angle_features_autogen.h"
30 #include "util/test_utils.h"
31 
32 #ifndef _EGLUPLATFORM_HPP
33 #    include "egluPlatform.hpp"
34 #endif
35 
36 #include <EGL/egl.h>
37 #include <EGL/eglext.h>
38 
39 #if (DE_OS == DE_OS_WIN32)
40 #    include "tcuWGLContextFactory.hpp"
41 #    include "tcuWin32EGLNativeDisplayFactory.hpp"
42 #endif  // (DE_OS == DE_OS_WIN32)
43 
44 #if (DE_OS == DE_OS_UNIX)
45 #    include "tcuLnxX11EglDisplayFactory.hpp"
46 #endif  // (DE_OKS == DE_OS_UNIX)
47 
48 static_assert(EGL_DONT_CARE == -1, "Unexpected value for EGL_DONT_CARE");
49 
50 namespace tcu
51 {
52 class ANGLEPlatform : public tcu::Platform, private glu::Platform, private eglu::Platform
53 {
54   public:
55     ANGLEPlatform(angle::LogErrorFunc logErrorFunc, uint32_t preRotation);
56     ~ANGLEPlatform();
57 
58     bool processEvents() override;
59 
getGLPlatform() const60     const glu::Platform &getGLPlatform() const override
61     {
62         return static_cast<const glu::Platform &>(*this);
63     }
getEGLPlatform() const64     const eglu::Platform &getEGLPlatform() const override
65     {
66         return static_cast<const eglu::Platform &>(*this);
67     }
68 
69   private:
70     // Note: -1 represents EGL_DONT_CARE, but we don't have the EGL headers here.
71     std::vector<eglw::EGLAttrib> initAttribs(eglw::EGLAttrib type,
72                                              eglw::EGLAttrib deviceType   = -1,
73                                              eglw::EGLAttrib majorVersion = -1,
74                                              eglw::EGLAttrib minorVersion = -1);
75 
76     EventState mEvents;
77     angle::PlatformMethods mPlatformMethods;
78     std::vector<const char *> mEnableFeatureOverrides;
79 
80 #if (DE_OS == DE_OS_UNIX)
81     lnx::EventState mLnxEventState;
82 #endif
83 };
84 
ANGLEPlatform(angle::LogErrorFunc logErrorFunc,uint32_t preRotation)85 ANGLEPlatform::ANGLEPlatform(angle::LogErrorFunc logErrorFunc, uint32_t preRotation)
86 {
87     angle::SetLowPriorityProcess();
88 
89     mPlatformMethods.logError = logErrorFunc;
90 
91     // Enable non-conformant ES versions and extensions for testing.  Our test expectations would
92     // suppress failing tests, but allowing continuous testing of the pieces that are implemented.
93     mEnableFeatureOverrides.push_back(
94         angle::GetFeatureName(angle::Feature::ExposeNonConformantExtensionsAndVersions));
95 
96     // Create pre-rotation attributes.
97     switch (preRotation)
98     {
99         case 90:
100             mEnableFeatureOverrides.push_back(
101                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation90));
102             break;
103         case 180:
104             mEnableFeatureOverrides.push_back(
105                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation180));
106             break;
107         case 270:
108             mEnableFeatureOverrides.push_back(
109                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation270));
110             break;
111         default:
112             break;
113     }
114 
115     mEnableFeatureOverrides.push_back(nullptr);
116 
117 #if (DE_OS == DE_OS_WIN32)
118     {
119         std::vector<eglw::EGLAttrib> d3d11Attribs = initAttribs(
120             EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
121 
122         auto *d3d11Factory = new ANGLENativeDisplayFactory("angle-d3d11", "ANGLE D3D11 Display",
123                                                            d3d11Attribs, &mEvents);
124         m_nativeDisplayFactoryRegistry.registerFactory(d3d11Factory);
125     }
126 
127     {
128         std::vector<eglw::EGLAttrib> d3d11Attribs =
129             initAttribs(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
130                         EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE);
131 
132         auto *d3d11Factory = new ANGLENativeDisplayFactory(
133             "angle-d3d11-ref", "ANGLE D3D11 Reference Display", d3d11Attribs, &mEvents);
134         m_nativeDisplayFactoryRegistry.registerFactory(d3d11Factory);
135     }
136 
137     {
138         std::vector<eglw::EGLAttrib> d3d9Attribs = initAttribs(
139             EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
140 
141         auto *d3d9Factory = new ANGLENativeDisplayFactory("angle-d3d9", "ANGLE D3D9 Display",
142                                                           d3d9Attribs, &mEvents);
143         m_nativeDisplayFactoryRegistry.registerFactory(d3d9Factory);
144     }
145 
146     m_nativeDisplayFactoryRegistry.registerFactory(
147         new win32::EGLNativeDisplayFactory(GetModuleHandle(nullptr)));
148 #endif  // (DE_OS == DE_OS_WIN32)
149 
150 #if defined(ANGLE_USE_GBM) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_WIN32)
151     {
152         std::vector<eglw::EGLAttrib> glesAttribs =
153             initAttribs(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
154 
155         auto *glesFactory = new ANGLENativeDisplayFactory("angle-gles", "ANGLE OpenGL ES Display",
156                                                           glesAttribs, &mEvents);
157         m_nativeDisplayFactoryRegistry.registerFactory(glesFactory);
158     }
159 #endif
160 
161     {
162         std::vector<eglw::EGLAttrib> glAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
163 
164         auto *glFactory =
165             new ANGLENativeDisplayFactory("angle-gl", "ANGLE OpenGL Display", glAttribs, &mEvents);
166         m_nativeDisplayFactoryRegistry.registerFactory(glFactory);
167     }
168 
169 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX)
170     {
171         std::vector<eglw::EGLAttrib> vkAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
172 
173         auto *vkFactory = new ANGLENativeDisplayFactory("angle-vulkan", "ANGLE Vulkan Display",
174                                                         vkAttribs, &mEvents);
175         m_nativeDisplayFactoryRegistry.registerFactory(vkFactory);
176     }
177 #endif
178 
179 #if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
180     {
181         std::vector<eglw::EGLAttrib> swsAttribs = initAttribs(
182             EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE);
183         m_nativeDisplayFactoryRegistry.registerFactory(new ANGLENativeDisplayFactory(
184             "angle-swiftshader", "ANGLE SwiftShader Display", swsAttribs, &mEvents));
185     }
186 #endif
187 
188 #if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
189     {
190         std::vector<eglw::EGLAttrib> webgpuAttribs =
191             initAttribs(EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE);
192 
193         auto *webgpuFactory = new ANGLENativeDisplayFactory("angle-webgpu", "ANGLE WebGPU Display",
194                                                             webgpuAttribs, &mEvents);
195         m_nativeDisplayFactoryRegistry.registerFactory(webgpuFactory);
196     }
197 #endif
198 
199 #if (DE_OS == DE_OS_OSX)
200     {
201         std::vector<eglw::EGLAttrib> mtlAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
202 
203         auto *mtlFactory = new ANGLENativeDisplayFactory("angle-metal", "ANGLE Metal Display",
204                                                          mtlAttribs, &mEvents);
205         m_nativeDisplayFactoryRegistry.registerFactory(mtlFactory);
206     }
207 #endif
208 
209     {
210         std::vector<eglw::EGLAttrib> nullAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE);
211 
212         auto *nullFactory = new ANGLENativeDisplayFactory("angle-null", "ANGLE NULL Display",
213                                                           nullAttribs, &mEvents);
214         m_nativeDisplayFactoryRegistry.registerFactory(nullFactory);
215     }
216 
217 #if (DE_OS == DE_OS_UNIX)
218     m_nativeDisplayFactoryRegistry.registerFactory(
219         lnx::x11::egl::createDisplayFactory(mLnxEventState));
220 #endif
221 
222     m_contextFactoryRegistry.registerFactory(
223         new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
224 
225     // Add Null context type for use in generating case lists
226     m_contextFactoryRegistry.registerFactory(new null::NullGLContextFactory());
227 
228 #if (DE_OS == DE_OS_WIN32)
229     // The wgl::ContextFactory can throw an exception when it fails to load WGL extension functions.
230     // Fail gracefully by catching the exception, which prevents adding the factory to the registry.
231     try
232     {
233         m_contextFactoryRegistry.registerFactory(new wgl::ContextFactory(GetModuleHandle(nullptr)));
234     }
235     catch (tcu::Exception e)
236     {}
237 #endif
238 }
239 
~ANGLEPlatform()240 ANGLEPlatform::~ANGLEPlatform() {}
241 
processEvents()242 bool ANGLEPlatform::processEvents()
243 {
244     return !mEvents.quitSignaled();
245 }
246 
initAttribs(eglw::EGLAttrib type,eglw::EGLAttrib deviceType,eglw::EGLAttrib majorVersion,eglw::EGLAttrib minorVersion)247 std::vector<eglw::EGLAttrib> ANGLEPlatform::initAttribs(eglw::EGLAttrib type,
248                                                         eglw::EGLAttrib deviceType,
249                                                         eglw::EGLAttrib majorVersion,
250                                                         eglw::EGLAttrib minorVersion)
251 {
252     std::vector<eglw::EGLAttrib> attribs;
253 
254     attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
255     attribs.push_back(type);
256 
257     if (deviceType != EGL_DONT_CARE)
258     {
259         attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
260         attribs.push_back(deviceType);
261     }
262 
263     if (majorVersion != EGL_DONT_CARE)
264     {
265         attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
266         attribs.push_back(majorVersion);
267     }
268 
269     if (minorVersion != EGL_DONT_CARE)
270     {
271         attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
272         attribs.push_back(minorVersion);
273     }
274 
275     if (mPlatformMethods.logError)
276     {
277         static_assert(sizeof(eglw::EGLAttrib) == sizeof(angle::PlatformMethods *),
278                       "Unexpected pointer size");
279         attribs.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
280         attribs.push_back(reinterpret_cast<eglw::EGLAttrib>(&mPlatformMethods));
281     }
282 
283     if (!mEnableFeatureOverrides.empty())
284     {
285         attribs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
286         attribs.push_back(reinterpret_cast<EGLAttrib>(mEnableFeatureOverrides.data()));
287     }
288 
289     attribs.push_back(EGL_NONE);
290     return attribs;
291 }
292 }  // namespace tcu
293 
294 // Create platform
CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc,uint32_t preRotation)295 tcu::Platform *CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc, uint32_t preRotation)
296 {
297     return new tcu::ANGLEPlatform(logErrorFunc, preRotation);
298 }
299 
createPlatform()300 tcu::Platform *createPlatform()
301 {
302     return CreateANGLEPlatform(nullptr, 0);
303 }
304