• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 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 
7 // angle_test_instantiate.cpp: Adds support for filtering parameterized
8 // tests by platform, so we skip unsupported configs.
9 
10 #include "test_utils/angle_test_instantiate.h"
11 
12 #include <iostream>
13 #include <map>
14 
15 #include "angle_gl.h"
16 #include "common/platform.h"
17 #include "gpu_info_util/SystemInfo.h"
18 #include "test_utils/angle_test_configs.h"
19 #include "util/EGLWindow.h"
20 #include "util/OSWindow.h"
21 #include "util/system_utils.h"
22 
23 #if defined(ANGLE_PLATFORM_WINDOWS)
24 #    include "util/windows/WGLWindow.h"
25 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
26 
27 namespace angle
28 {
29 namespace
30 {
IsANGLEConfigSupported(const PlatformParameters & param,OSWindow * osWindow)31 bool IsANGLEConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
32 {
33     std::unique_ptr<angle::Library> eglLibrary;
34 
35 #if defined(ANGLE_USE_UTIL_LOADER)
36     eglLibrary.reset(
37         angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ApplicationDir));
38 #endif
39 
40     EGLWindow *eglWindow = EGLWindow::New(param.majorVersion, param.minorVersion);
41     ConfigParameters configParams;
42     bool result =
43         eglWindow->initializeGL(osWindow, eglLibrary.get(), param.eglParameters, configParams);
44     eglWindow->destroyGL();
45     EGLWindow::Delete(&eglWindow);
46     return result;
47 }
48 
IsWGLConfigSupported(const PlatformParameters & param,OSWindow * osWindow)49 bool IsWGLConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
50 {
51 #if defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER)
52     std::unique_ptr<angle::Library> openglLibrary(
53         angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir));
54 
55     WGLWindow *wglWindow = WGLWindow::New(param.majorVersion, param.minorVersion);
56     ConfigParameters configParams;
57     bool result =
58         wglWindow->initializeGL(osWindow, openglLibrary.get(), param.eglParameters, configParams);
59     wglWindow->destroyGL();
60     WGLWindow::Delete(&wglWindow);
61     return result;
62 #else
63     return false;
64 #endif  // defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER)
65 }
66 
IsNativeConfigSupported(const PlatformParameters & param,OSWindow * osWindow)67 bool IsNativeConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
68 {
69     // Not yet implemented.
70     return false;
71 }
72 
73 std::map<PlatformParameters, bool> gParamAvailabilityCache;
74 
IsAndroidDevice(const std::string & deviceName)75 bool IsAndroidDevice(const std::string &deviceName)
76 {
77     if (!IsAndroid())
78     {
79         return false;
80     }
81     SystemInfo *systemInfo = GetTestSystemInfo();
82     if (systemInfo->machineModelName == deviceName)
83     {
84         return true;
85     }
86     return false;
87 }
88 
HasSystemVendorID(VendorID vendorID)89 bool HasSystemVendorID(VendorID vendorID)
90 {
91     SystemInfo *systemInfo = GetTestSystemInfo();
92     // Unfortunately sometimes GPU info collection can fail.
93     if (systemInfo->activeGPUIndex < 0 || systemInfo->gpus.empty())
94     {
95         return false;
96     }
97     return systemInfo->gpus[systemInfo->activeGPUIndex].vendorId == vendorID;
98 }
99 }  // namespace
100 
101 std::string gSelectedConfig;
102 bool gSeparateProcessPerConfig = false;
103 
GetTestSystemInfo()104 SystemInfo *GetTestSystemInfo()
105 {
106     static SystemInfo *sSystemInfo = nullptr;
107     if (sSystemInfo == nullptr)
108     {
109         sSystemInfo = new SystemInfo;
110         if (!GetSystemInfo(sSystemInfo))
111         {
112             std::cerr << "Warning: incomplete system info collection.\n";
113         }
114 
115         // Print complete system info when available.
116         // Seems to trip up Android test expectation parsing.
117         // Also don't print info when a config is selected to prevent test spam.
118         if (!IsAndroid() && gSelectedConfig.empty())
119         {
120             PrintSystemInfo(*sSystemInfo);
121         }
122     }
123     return sSystemInfo;
124 }
125 
IsAndroid()126 bool IsAndroid()
127 {
128 #if defined(ANGLE_PLATFORM_ANDROID)
129     return true;
130 #else
131     return false;
132 #endif
133 }
134 
IsLinux()135 bool IsLinux()
136 {
137 #if defined(ANGLE_PLATFORM_LINUX)
138     return true;
139 #else
140     return false;
141 #endif
142 }
143 
IsOSX()144 bool IsOSX()
145 {
146 #if defined(ANGLE_PLATFORM_APPLE)
147     return true;
148 #else
149     return false;
150 #endif
151 }
152 
IsOzone()153 bool IsOzone()
154 {
155 #if defined(USE_OZONE)
156     return true;
157 #else
158     return false;
159 #endif
160 }
161 
IsWindows()162 bool IsWindows()
163 {
164 #if defined(ANGLE_PLATFORM_WINDOWS)
165     return true;
166 #else
167     return false;
168 #endif
169 }
170 
IsFuchsia()171 bool IsFuchsia()
172 {
173 #if defined(ANGLE_PLATFORM_FUCHSIA)
174     return true;
175 #else
176     return false;
177 #endif
178 }
179 
IsNexus5X()180 bool IsNexus5X()
181 {
182     return IsAndroidDevice("Nexus 5X");
183 }
184 
IsNexus6P()185 bool IsNexus6P()
186 {
187     return IsAndroidDevice("Nexus 6P");
188 }
189 
IsNexus9()190 bool IsNexus9()
191 {
192     return IsAndroidDevice("Nexus 9");
193 }
194 
IsPixelXL()195 bool IsPixelXL()
196 {
197     return IsAndroidDevice("Pixel XL");
198 }
199 
IsPixel2()200 bool IsPixel2()
201 {
202     return IsAndroidDevice("Pixel 2");
203 }
204 
IsNVIDIAShield()205 bool IsNVIDIAShield()
206 {
207     return IsAndroidDevice("SHIELD Android TV");
208 }
209 
IsIntel()210 bool IsIntel()
211 {
212     return HasSystemVendorID(kVendorID_Intel);
213 }
214 
IsAMD()215 bool IsAMD()
216 {
217     return HasSystemVendorID(kVendorID_AMD);
218 }
219 
IsNVIDIA()220 bool IsNVIDIA()
221 {
222 #if defined(ANGLE_PLATFORM_ANDROID)
223     // NVIDIA Shield cannot detect vendor ID (http://anglebug.com/3541)
224     if (IsNVIDIAShield())
225     {
226         return true;
227     }
228 #endif
229     return HasSystemVendorID(kVendorID_NVIDIA);
230 }
231 
IsConfigWhitelisted(const SystemInfo & systemInfo,const PlatformParameters & param)232 bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters &param)
233 {
234     VendorID vendorID = systemInfo.gpus[systemInfo.activeGPUIndex].vendorId;
235 
236     // We support the default and null back-ends on every platform.
237     if (param.driver == GLESDriverType::AngleEGL)
238     {
239         if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
240             return true;
241         if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE)
242             return true;
243     }
244 
245     if (IsWindows())
246     {
247         switch (param.driver)
248         {
249             case GLESDriverType::AngleEGL:
250                 switch (param.getRenderer())
251                 {
252                     case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
253                     case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
254                     case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
255                     case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
256                         return true;
257                     case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
258                         // ES 3.1+ back-end is not supported properly.
259                         if (param.eglParameters.majorVersion == 3 &&
260                             param.eglParameters.minorVersion > 0)
261                         {
262                             return false;
263                         }
264 
265                         // Win ES emulation is currently only supported on NVIDIA.
266                         return IsNVIDIA(vendorID);
267                     default:
268                         return false;
269                 }
270             case GLESDriverType::SystemWGL:
271                 // AMD does not support the ES compatibility extensions.
272                 return !IsAMD(vendorID);
273             default:
274                 return false;
275         }
276     }
277 
278     if (IsOSX())
279     {
280         // We do not support non-ANGLE bindings on OSX.
281         if (param.driver != GLESDriverType::AngleEGL)
282         {
283             return false;
284         }
285 
286         // OSX does not support ES 3.1 features.
287         if (param.majorVersion == 3 && param.minorVersion > 0)
288         {
289             return false;
290         }
291 
292         // Currently we only support the OpenGL back-end on OSX.
293         return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
294     }
295 
296     if (IsFuchsia())
297     {
298         // We do not support non-ANGLE bindings on Fuchsia.
299         if (param.driver != GLESDriverType::AngleEGL)
300         {
301             return false;
302         }
303 
304         // Currently we only support the Vulkan back-end on Fuchsia.
305         return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
306     }
307 
308     if (IsOzone())
309     {
310         // We do not support non-ANGLE bindings on Ozone.
311         if (param.driver != GLESDriverType::AngleEGL)
312             return false;
313 
314         // ES 3 configs do not work properly on Ozone.
315         if (param.majorVersion > 2)
316             return false;
317 
318         // Currently we only support the GLES back-end on Ozone.
319         return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
320     }
321 
322     if (IsLinux())
323     {
324         // We do not support non-ANGLE bindings on Linux.
325         if (param.driver != GLESDriverType::AngleEGL)
326         {
327             return false;
328         }
329 
330         // Currently we support the OpenGL and Vulkan back-ends on Linux.
331         switch (param.getRenderer())
332         {
333             case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
334             case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
335                 // Note that system info collection depends on Vulkan support.
336                 return true;
337             default:
338                 return false;
339         }
340     }
341 
342     if (IsAndroid())
343     {
344         // We do not support non-ANGLE bindings on Android.
345         if (param.driver != GLESDriverType::AngleEGL)
346         {
347             return false;
348         }
349 
350         // Nexus Android devices don't support backing 3.2 contexts
351         if (param.eglParameters.majorVersion == 3 && param.eglParameters.minorVersion == 2)
352         {
353             if (IsNexus5X() || IsNexus6P())
354             {
355                 return false;
356             }
357         }
358 
359         // Currently we support the GLES and Vulkan back-ends on Android.
360         switch (param.getRenderer())
361         {
362             case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
363             case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
364                 return true;
365             default:
366                 return false;
367         }
368     }
369 
370     // Unknown platform.
371     return false;
372 }
373 
IsConfigSupported(const PlatformParameters & param)374 bool IsConfigSupported(const PlatformParameters &param)
375 {
376     OSWindow *osWindow = OSWindow::New();
377     bool result        = false;
378     if (osWindow->initialize("CONFIG_TESTER", 1, 1))
379     {
380         switch (param.driver)
381         {
382             case GLESDriverType::AngleEGL:
383                 result = IsANGLEConfigSupported(param, osWindow);
384                 break;
385             case GLESDriverType::SystemEGL:
386                 result = IsNativeConfigSupported(param, osWindow);
387                 break;
388             case GLESDriverType::SystemWGL:
389                 result = IsWGLConfigSupported(param, osWindow);
390                 break;
391         }
392 
393         osWindow->destroy();
394     }
395 
396     OSWindow::Delete(&osWindow);
397     return result;
398 }
399 
IsPlatformAvailable(const PlatformParameters & param)400 bool IsPlatformAvailable(const PlatformParameters &param)
401 {
402     switch (param.getRenderer())
403     {
404         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
405             break;
406 
407         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
408 #if !defined(ANGLE_ENABLE_D3D9)
409             return false;
410 #else
411             break;
412 #endif
413 
414         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
415 #if !defined(ANGLE_ENABLE_D3D11)
416             return false;
417 #else
418             break;
419 #endif
420 
421         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
422         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
423 #if !defined(ANGLE_ENABLE_OPENGL)
424             return false;
425 #else
426             break;
427 #endif
428 
429         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
430 #if !defined(ANGLE_ENABLE_VULKAN)
431             return false;
432 #else
433             break;
434 #endif
435 
436         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
437 #ifndef ANGLE_ENABLE_NULL
438             return false;
439 #endif
440             break;
441 
442         default:
443             std::cout << "Unknown test platform: " << param << std::endl;
444             return false;
445     }
446 
447     bool result = false;
448 
449     auto iter = gParamAvailabilityCache.find(param);
450     if (iter != gParamAvailabilityCache.end())
451     {
452         result = iter->second;
453     }
454     else
455     {
456         if (!gSelectedConfig.empty())
457         {
458             std::stringstream strstr;
459             strstr << param;
460             if (strstr.str() == gSelectedConfig)
461             {
462                 result = true;
463             }
464         }
465         else
466         {
467             const SystemInfo *systemInfo = GetTestSystemInfo();
468 
469             if (systemInfo)
470             {
471                 result = IsConfigWhitelisted(*systemInfo, param);
472             }
473             else
474             {
475                 result = IsConfigSupported(param);
476             }
477         }
478 
479         gParamAvailabilityCache[param] = result;
480 
481         // Enable this unconditionally to print available platforms.
482         if (!gSelectedConfig.empty())
483         {
484             if (result)
485             {
486                 std::cout << "Test Config: " << param << "\n";
487             }
488         }
489         else if (!result)
490         {
491             std::cout << "Skipping tests using configuration " << param
492                       << " because it is not available.\n";
493         }
494     }
495 
496     // Disable all tests in the parent process when running child processes.
497     if (gSeparateProcessPerConfig)
498     {
499         return false;
500     }
501     return result;
502 }
503 
GetAvailableTestPlatformNames()504 std::vector<std::string> GetAvailableTestPlatformNames()
505 {
506     std::vector<std::string> platformNames;
507 
508     for (const auto &iter : gParamAvailabilityCache)
509     {
510         if (iter.second)
511         {
512             std::stringstream strstr;
513             strstr << iter.first;
514             platformNames.push_back(strstr.str());
515         }
516     }
517 
518     // Keep the list sorted.
519     std::sort(platformNames.begin(), platformNames.end());
520 
521     return platformNames;
522 }
523 }  // namespace angle
524