• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "angle_deqp_libtester.h"
40 
41 #if (DE_OS == DE_OS_WIN32)
42 #    include "tcuWGLContextFactory.hpp"
43 #    include "tcuWin32EGLNativeDisplayFactory.hpp"
44 #endif  // (DE_OS == DE_OS_WIN32)
45 
46 #if (DE_OS == DE_OS_UNIX)
47 #    include "tcuLnxX11EglDisplayFactory.hpp"
48 #endif  // (DE_OKS == DE_OS_UNIX)
49 
50 static_assert(EGL_DONT_CARE == -1, "Unexpected value for EGL_DONT_CARE");
51 
52 namespace tcu
53 {
54 class ANGLEPlatform : public tcu::Platform, private glu::Platform, private eglu::Platform
55 {
56   public:
57     ANGLEPlatform(angle::LogErrorFunc logErrorFunc,
58                   uint32_t preRotation,
59                   dEQPDriverOption driverOption);
60     ~ANGLEPlatform();
61 
62     bool processEvents() override;
63 
getGLPlatform() const64     const glu::Platform &getGLPlatform() const override
65     {
66         return static_cast<const glu::Platform &>(*this);
67     }
getEGLPlatform() const68     const eglu::Platform &getEGLPlatform() const override
69     {
70         return static_cast<const eglu::Platform &>(*this);
71     }
72 
73   private:
74     // Note: -1 represents EGL_DONT_CARE, but we don't have the EGL headers here.
75     std::vector<eglw::EGLAttrib> initAttribs(eglw::EGLAttrib type,
76                                              eglw::EGLAttrib deviceType   = -1,
77                                              eglw::EGLAttrib majorVersion = -1,
78                                              eglw::EGLAttrib minorVersion = -1);
79 
80     EventState mEvents;
81     angle::PlatformMethods mPlatformMethods;
82     std::vector<const char *> mEnableFeatureOverrides;
83 
84 #if (DE_OS == DE_OS_UNIX)
85     lnx::EventState mLnxEventState;
86 #endif
87 };
88 
ANGLEPlatform(angle::LogErrorFunc logErrorFunc,uint32_t preRotation,dEQPDriverOption driverOption)89 ANGLEPlatform::ANGLEPlatform(angle::LogErrorFunc logErrorFunc,
90                              uint32_t preRotation,
91                              dEQPDriverOption driverOption)
92 {
93     angle::SetLowPriorityProcess();
94 
95     mPlatformMethods.logError = logErrorFunc;
96 
97     // Enable non-conformant ES versions and extensions for testing.  Our test expectations would
98     // suppress failing tests, but allowing continuous testing of the pieces that are implemented.
99     mEnableFeatureOverrides.push_back(
100         angle::GetFeatureName(angle::Feature::ExposeNonConformantExtensionsAndVersions));
101 
102     // Create pre-rotation attributes.
103     switch (preRotation)
104     {
105         case 90:
106             mEnableFeatureOverrides.push_back(
107                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation90));
108             break;
109         case 180:
110             mEnableFeatureOverrides.push_back(
111                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation180));
112             break;
113         case 270:
114             mEnableFeatureOverrides.push_back(
115                 angle::GetFeatureName(angle::Feature::EmulatedPrerotation270));
116             break;
117         default:
118             break;
119     }
120 
121     mEnableFeatureOverrides.push_back(nullptr);
122 
123 #if (DE_OS == DE_OS_WIN32)
124     {
125         std::vector<eglw::EGLAttrib> d3d11Attribs = initAttribs(
126             EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
127 
128         auto *d3d11Factory = new ANGLENativeDisplayFactory("angle-d3d11", "ANGLE D3D11 Display",
129                                                            d3d11Attribs, &mEvents);
130         m_nativeDisplayFactoryRegistry.registerFactory(d3d11Factory);
131     }
132 
133     {
134         std::vector<eglw::EGLAttrib> d3d11Attribs =
135             initAttribs(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
136                         EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE);
137 
138         auto *d3d11Factory = new ANGLENativeDisplayFactory(
139             "angle-d3d11-ref", "ANGLE D3D11 Reference Display", d3d11Attribs, &mEvents);
140         m_nativeDisplayFactoryRegistry.registerFactory(d3d11Factory);
141     }
142 
143     {
144         std::vector<eglw::EGLAttrib> d3d9Attribs = initAttribs(
145             EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
146 
147         auto *d3d9Factory = new ANGLENativeDisplayFactory("angle-d3d9", "ANGLE D3D9 Display",
148                                                           d3d9Attribs, &mEvents);
149         m_nativeDisplayFactoryRegistry.registerFactory(d3d9Factory);
150     }
151 
152     m_nativeDisplayFactoryRegistry.registerFactory(
153         new win32::EGLNativeDisplayFactory(GetModuleHandle(nullptr)));
154 #endif  // (DE_OS == DE_OS_WIN32)
155 
156 #if defined(ANGLE_USE_GBM) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_WIN32)
157     {
158         std::vector<eglw::EGLAttrib> glesAttribs =
159             initAttribs(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
160 
161         auto *glesFactory = new ANGLENativeDisplayFactory("angle-gles", "ANGLE OpenGL ES Display",
162                                                           glesAttribs, &mEvents);
163         m_nativeDisplayFactoryRegistry.registerFactory(glesFactory);
164     }
165 #endif
166 
167     {
168         std::vector<eglw::EGLAttrib> glAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
169 
170         auto *glFactory =
171             new ANGLENativeDisplayFactory("angle-gl", "ANGLE OpenGL Display", glAttribs, &mEvents);
172         m_nativeDisplayFactoryRegistry.registerFactory(glFactory);
173     }
174 
175 #if (DE_OS == DE_OS_ANDROID)
176     {
177         if (driverOption == dEQPDriverOption::ANGLE)
178         {
179             std::vector<eglw::EGLAttrib> vkAttribs =
180                 initAttribs(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
181             auto *vkFactory =
182                 new ANGLENativeDisplayFactory("angle-vulkan", "ANGLE Vulkan Display", vkAttribs,
183                                               &mEvents, EGL_PLATFORM_ANGLE_ANGLE);
184             m_nativeDisplayFactoryRegistry.registerFactory(vkFactory);
185         }
186         else
187         {
188             std::vector<eglw::EGLAttrib> nativeGlesAttribs = {EGL_NONE};
189             auto *nativeGLESFactory                        = new ANGLENativeDisplayFactory(
190                 "native-gles", "Native GLES Display", nativeGlesAttribs, &mEvents,
191                 EGL_PLATFORM_ANDROID_KHR);
192             m_nativeDisplayFactoryRegistry.registerFactory(nativeGLESFactory);
193         }
194     }
195 #endif
196 
197 #if ((DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX))
198     {
199         std::vector<eglw::EGLAttrib> vkAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
200 
201         auto *vkFactory = new ANGLENativeDisplayFactory("angle-vulkan", "ANGLE Vulkan Display",
202                                                         vkAttribs, &mEvents);
203         m_nativeDisplayFactoryRegistry.registerFactory(vkFactory);
204     }
205 #endif
206 
207 #if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
208     {
209         std::vector<eglw::EGLAttrib> swsAttribs = initAttribs(
210             EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE);
211         m_nativeDisplayFactoryRegistry.registerFactory(new ANGLENativeDisplayFactory(
212             "angle-swiftshader", "ANGLE SwiftShader Display", swsAttribs, &mEvents));
213     }
214 #endif
215 
216 #if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
217     {
218         std::vector<eglw::EGLAttrib> webgpuAttribs =
219             initAttribs(EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE);
220 
221         auto *webgpuFactory = new ANGLENativeDisplayFactory("angle-webgpu", "ANGLE WebGPU Display",
222                                                             webgpuAttribs, &mEvents);
223         m_nativeDisplayFactoryRegistry.registerFactory(webgpuFactory);
224     }
225 #endif
226 
227 #if (DE_OS == DE_OS_OSX)
228     {
229         std::vector<eglw::EGLAttrib> mtlAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
230 
231         auto *mtlFactory = new ANGLENativeDisplayFactory("angle-metal", "ANGLE Metal Display",
232                                                          mtlAttribs, &mEvents);
233         m_nativeDisplayFactoryRegistry.registerFactory(mtlFactory);
234     }
235 #endif
236 
237     {
238         std::vector<eglw::EGLAttrib> nullAttribs = initAttribs(EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE);
239 
240         auto *nullFactory = new ANGLENativeDisplayFactory("angle-null", "ANGLE NULL Display",
241                                                           nullAttribs, &mEvents);
242         m_nativeDisplayFactoryRegistry.registerFactory(nullFactory);
243     }
244 
245 #if (DE_OS == DE_OS_UNIX)
246     m_nativeDisplayFactoryRegistry.registerFactory(
247         lnx::x11::egl::createDisplayFactory(mLnxEventState));
248 #endif
249 
250     m_contextFactoryRegistry.registerFactory(
251         new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
252 
253     // Add Null context type for use in generating case lists
254     m_contextFactoryRegistry.registerFactory(new null::NullGLContextFactory());
255 
256 #if (DE_OS == DE_OS_WIN32)
257     // The wgl::ContextFactory can throw an exception when it fails to load WGL extension functions.
258     // Fail gracefully by catching the exception, which prevents adding the factory to the registry.
259     try
260     {
261         m_contextFactoryRegistry.registerFactory(new wgl::ContextFactory(GetModuleHandle(nullptr)));
262     }
263     catch (tcu::Exception e)
264     {}
265 #endif
266 }
267 
~ANGLEPlatform()268 ANGLEPlatform::~ANGLEPlatform() {}
269 
processEvents()270 bool ANGLEPlatform::processEvents()
271 {
272     return !mEvents.quitSignaled();
273 }
274 
initAttribs(eglw::EGLAttrib type,eglw::EGLAttrib deviceType,eglw::EGLAttrib majorVersion,eglw::EGLAttrib minorVersion)275 std::vector<eglw::EGLAttrib> ANGLEPlatform::initAttribs(eglw::EGLAttrib type,
276                                                         eglw::EGLAttrib deviceType,
277                                                         eglw::EGLAttrib majorVersion,
278                                                         eglw::EGLAttrib minorVersion)
279 {
280     std::vector<eglw::EGLAttrib> attribs;
281 
282     attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
283     attribs.push_back(type);
284 
285     if (deviceType != EGL_DONT_CARE)
286     {
287         attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
288         attribs.push_back(deviceType);
289     }
290 
291     if (majorVersion != EGL_DONT_CARE)
292     {
293         attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
294         attribs.push_back(majorVersion);
295     }
296 
297     if (minorVersion != EGL_DONT_CARE)
298     {
299         attribs.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
300         attribs.push_back(minorVersion);
301     }
302 
303     if (mPlatformMethods.logError)
304     {
305         static_assert(sizeof(eglw::EGLAttrib) == sizeof(angle::PlatformMethods *),
306                       "Unexpected pointer size");
307         attribs.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
308         attribs.push_back(reinterpret_cast<eglw::EGLAttrib>(&mPlatformMethods));
309     }
310 
311     if (!mEnableFeatureOverrides.empty())
312     {
313         attribs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
314         attribs.push_back(reinterpret_cast<EGLAttrib>(mEnableFeatureOverrides.data()));
315     }
316 
317     attribs.push_back(EGL_NONE);
318     return attribs;
319 }
320 }  // namespace tcu
321 
322 // Create platform
CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc,uint32_t preRotation,dEQPDriverOption driverOption)323 tcu::Platform *CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc,
324                                    uint32_t preRotation,
325                                    dEQPDriverOption driverOption)
326 {
327     return new tcu::ANGLEPlatform(logErrorFunc, preRotation, driverOption);
328 }
329 
createPlatform()330 tcu::Platform *createPlatform()
331 {
332     return CreateANGLEPlatform(nullptr, 0, dEQPDriverOption::ANGLE);
333 }
334