1 //
2 // Copyright 2002 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 // Display.cpp: Implements the egl::Display class, representing the abstract
8 // display on which graphics are drawn. Implements EGLDisplay.
9 // [EGL 1.4] section 2.1.2 page 3.
10 
11 #include "libANGLE/Display.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <map>
16 #include <sstream>
17 #include <vector>
18 
19 #include <EGL/eglext.h>
20 #include <platform/Platform.h>
21 
22 #include "anglebase/no_destructor.h"
23 #include "common/android_util.h"
24 #include "common/debug.h"
25 #include "common/mathutil.h"
26 #include "common/platform.h"
27 #include "common/string_utils.h"
28 #include "common/system_utils.h"
29 #include "common/tls.h"
30 #include "common/utilities.h"
31 #include "gpu_info_util/SystemInfo.h"
32 #include "libANGLE/Context.h"
33 #include "libANGLE/Device.h"
34 #include "libANGLE/EGLSync.h"
35 #include "libANGLE/Image.h"
36 #include "libANGLE/ResourceManager.h"
37 #include "libANGLE/Stream.h"
38 #include "libANGLE/Surface.h"
39 #include "libANGLE/Thread.h"
40 #include "libANGLE/capture/FrameCapture.h"
41 #include "libANGLE/histogram_macros.h"
42 #include "libANGLE/renderer/DeviceImpl.h"
43 #include "libANGLE/renderer/DisplayImpl.h"
44 #include "libANGLE/renderer/ImageImpl.h"
45 #include "libANGLE/trace.h"
46 
47 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
48 #    include <versionhelpers.h>
49 
50 #    include "libANGLE/renderer/d3d/DisplayD3D.h"
51 #endif
52 
53 #if defined(ANGLE_ENABLE_OPENGL)
54 #    if defined(ANGLE_PLATFORM_WINDOWS)
55 #        include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
56 #    elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS)
57 #        include "libANGLE/renderer/gl/apple/DisplayApple_api.h"
58 #    elif defined(ANGLE_PLATFORM_LINUX)
59 #        include "libANGLE/renderer/gl/egl/DisplayEGL.h"
60 #        if defined(ANGLE_USE_GBM)
61 #            include "libANGLE/renderer/gl/egl/gbm/DisplayGbm.h"
62 #        endif
63 #        if defined(ANGLE_USE_X11)
64 #            include "libANGLE/renderer/gl/glx/DisplayGLX.h"
65 #        endif
66 #    elif defined(ANGLE_PLATFORM_ANDROID)
67 #        include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
68 #    else
69 #        error Unsupported OpenGL platform.
70 #    endif
71 #endif
72 
73 #if defined(ANGLE_ENABLE_NULL)
74 #    include "libANGLE/renderer/null/DisplayNULL.h"
75 #endif  // defined(ANGLE_ENABLE_NULL)
76 
77 #if defined(ANGLE_ENABLE_VULKAN)
78 #    include "libANGLE/renderer/vulkan/DisplayVk_api.h"
79 #endif  // defined(ANGLE_ENABLE_VULKAN)
80 
81 #if defined(ANGLE_ENABLE_METAL)
82 #    include "libANGLE/renderer/metal/DisplayMtl_api.h"
83 #endif  // defined(ANGLE_ENABLE_METAL)
84 
85 namespace egl
86 {
87 
88 namespace
89 {
90 
91 constexpr angle::SubjectIndex kGPUSwitchedSubjectIndex = 0;
92 
93 typedef std::map<EGLNativeWindowType, Surface *> WindowSurfaceMap;
94 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
95 // associated with it.
GetWindowSurfaces()96 static WindowSurfaceMap *GetWindowSurfaces()
97 {
98     static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces;
99     return windowSurfaces.get();
100 }
101 
102 typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
GetANGLEPlatformDisplayMap()103 static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
104 {
105     static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays;
106     return displays.get();
107 }
108 
109 typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
GetDevicePlatformDisplayMap()110 static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
111 {
112     static angle::base::NoDestructor<DevicePlatformDisplayMap> displays;
113     return displays.get();
114 }
115 
CreateDisplayFromDevice(Device * eglDevice,const DisplayState & state)116 rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
117 {
118     rx::DisplayImpl *impl = nullptr;
119 
120     switch (eglDevice->getType())
121     {
122 #if defined(ANGLE_ENABLE_D3D11)
123         case EGL_D3D11_DEVICE_ANGLE:
124             impl = new rx::DisplayD3D(state);
125             break;
126 #endif
127 #if defined(ANGLE_ENABLE_D3D9)
128         case EGL_D3D9_DEVICE_ANGLE:
129             // Currently the only way to get EGLDeviceEXT representing a D3D9 device
130             // is to retrieve one from an already-existing EGLDisplay.
131             // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
132             // the already-existing display should be returned.
133             // Therefore this codepath to create a new display from the device
134             // should never be hit.
135             UNREACHABLE();
136             break;
137 #endif
138         default:
139             UNREACHABLE();
140             break;
141     }
142 
143     ASSERT(impl != nullptr);
144     return impl;
145 }
146 
147 // On platforms with support for multiple back-ends, allow an environment variable to control
148 // the default.  This is useful to run angle with benchmarks without having to modify the
149 // benchmark source.  Possible values for this environment variable (ANGLE_DEFAULT_PLATFORM)
150 // are: vulkan, gl, d3d11, null.
GetDisplayTypeFromEnvironment()151 EGLAttrib GetDisplayTypeFromEnvironment()
152 {
153     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
154     angle::ToLower(&angleDefaultEnv);
155 
156 #if defined(ANGLE_ENABLE_VULKAN)
157     if ((angleDefaultEnv == "vulkan") || (angleDefaultEnv == "vulkan-null") ||
158         (angleDefaultEnv == "swiftshader"))
159     {
160         return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
161     }
162 #endif
163 
164 #if defined(ANGLE_ENABLE_OPENGL)
165     if (angleDefaultEnv == "gl")
166     {
167         return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
168     }
169 #endif
170 
171 #if defined(ANGLE_ENABLE_D3D11)
172     if (angleDefaultEnv == "d3d11")
173     {
174         return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
175     }
176 #endif
177 
178 #if defined(ANGLE_ENABLE_METAL)
179     if (angleDefaultEnv == "metal")
180     {
181         return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
182     }
183 #endif
184 
185 #if defined(ANGLE_ENABLE_NULL)
186     if (angleDefaultEnv == "null")
187     {
188         return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
189     }
190 #endif
191 #if defined(ANGLE_ENABLE_METAL)
192     if (angleDefaultEnv == "metal")
193     {
194         return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
195     }
196 
197 #endif
198 #if defined(ANGLE_ENABLE_D3D11)
199     return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
200 #elif defined(ANGLE_ENABLE_D3D9)
201     return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
202 #elif defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_PLATFORM_ANDROID)
203     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
204 #elif defined(ANGLE_ENABLE_OPENGL)
205 #    if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_USE_GBM)
206     return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
207 #    else
208     return EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
209 #    endif
210 #elif defined(ANGLE_ENABLE_METAL)
211     return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
212 #elif defined(ANGLE_ENABLE_VULKAN)
213     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
214 #elif defined(ANGLE_ENABLE_NULL)
215     return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
216 #else
217 #    error No default ANGLE platform type
218 #endif
219 }
220 
GetDeviceTypeFromEnvironment()221 EGLAttrib GetDeviceTypeFromEnvironment()
222 {
223     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
224     angle::ToLower(&angleDefaultEnv);
225 
226 #if defined(ANGLE_ENABLE_VULKAN)
227     if (angleDefaultEnv == "vulkan-null")
228     {
229         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
230     }
231     else if (angleDefaultEnv == "swiftshader")
232     {
233         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
234     }
235 #endif
236     return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
237 }
238 
GetPlatformTypeFromEnvironment()239 EGLAttrib GetPlatformTypeFromEnvironment()
240 {
241 #if defined(ANGLE_USE_OZONE)
242     return 0;
243 #elif defined(ANGLE_USE_X11)
244     return EGL_PLATFORM_X11_EXT;
245 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_SIMPLE)
246     return EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE;
247 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_HEADLESS)
248     return EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE;
249 #else
250     return 0;
251 #endif  // defined(ANGLE_USE_OZONE)
252 }
253 
CreateDisplayFromAttribs(EGLAttrib displayType,EGLAttrib deviceType,EGLAttrib platformType,const DisplayState & state)254 rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType,
255                                           EGLAttrib deviceType,
256                                           EGLAttrib platformType,
257                                           const DisplayState &state)
258 {
259     ASSERT(displayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
260     rx::DisplayImpl *impl = nullptr;
261 
262     switch (displayType)
263     {
264         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
265             UNREACHABLE();
266 #if !UNREACHABLE_IS_NORETURN
267             break;
268 #endif
269 
270         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
271         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
272 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
273             impl = new rx::DisplayD3D(state);
274             break;
275 #else
276             // A D3D display was requested on a platform that doesn't support it
277             UNREACHABLE();
278 #    if !UNREACHABLE_IS_NORETURN
279             break;
280 #    endif
281 #endif
282 
283         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
284 #if defined(ANGLE_ENABLE_OPENGL)
285 #    if defined(ANGLE_PLATFORM_WINDOWS)
286             impl = new rx::DisplayWGL(state);
287             break;
288 
289 #    elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS)
290             impl = rx::CreateDisplayCGLOrEAGL(state);
291             break;
292 
293 #    elif defined(ANGLE_PLATFORM_LINUX)
294 #        if defined(ANGLE_USE_GBM)
295             if (platformType == 0)
296             {
297                 // If platformType is unknown, use DisplayGbm now. In the future, it should use
298                 // DisplayEGL letting native EGL decide what display to use.
299                 impl = new rx::DisplayGbm(state);
300                 break;
301             }
302 #        endif
303             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
304             {
305                 impl = new rx::DisplayEGL(state);
306                 break;
307             }
308 #        if defined(ANGLE_USE_X11)
309             if (platformType == EGL_PLATFORM_X11_EXT)
310             {
311                 impl = new rx::DisplayGLX(state);
312                 break;
313             }
314 #        endif
315             break;
316 
317 #    elif defined(ANGLE_PLATFORM_ANDROID)
318             // No GL support on this platform, fail display creation.
319             impl = nullptr;
320             break;
321 
322 #    else
323 #        error Unsupported OpenGL platform.
324 #    endif
325 #else
326             // No display available
327             UNREACHABLE();
328 #    if !UNREACHABLE_IS_NORETURN
329             break;
330 #    endif
331 
332 #endif  // defined(ANGLE_ENABLE_OPENGL)
333 
334         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
335 #if defined(ANGLE_ENABLE_OPENGL)
336 #    if defined(ANGLE_PLATFORM_WINDOWS)
337             impl = new rx::DisplayWGL(state);
338 #    elif defined(ANGLE_PLATFORM_LINUX)
339 #        if defined(ANGLE_USE_GBM)
340             if (platformType == 0)
341             {
342                 // If platformType is unknown, use DisplayGbm now. In the future, it should use
343                 // DisplayEGL letting native EGL decide what display to use.
344                 impl = new rx::DisplayGbm(state);
345                 break;
346             }
347 #        endif
348             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
349             {
350                 impl = new rx::DisplayEGL(state);
351                 break;
352             }
353             else
354             {
355 #        if defined(ANGLE_USE_X11)
356                 if (platformType == EGL_PLATFORM_X11_EXT)
357                 {
358                     impl = new rx::DisplayGLX(state);
359                     break;
360                 }
361 #        endif
362             }
363 #    elif defined(ANGLE_PLATFORM_ANDROID)
364             impl = new rx::DisplayAndroid(state);
365 #    else
366             // No GLES support on this platform, fail display creation.
367             impl = nullptr;
368 #    endif
369 #endif  // defined(ANGLE_ENABLE_OPENGL)
370             break;
371 
372         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
373 #if defined(ANGLE_ENABLE_VULKAN)
374 #    if defined(ANGLE_USE_VULKAN_NULL_DISPLAY)
375             if (rx::IsVulkanNullDisplayAvailable())
376             {
377                 impl = rx::CreateVulkanNullDisplay(state);
378             }
379             break;
380 #    elif defined(ANGLE_PLATFORM_WINDOWS)
381             if (rx::IsVulkanWin32DisplayAvailable())
382             {
383                 impl = rx::CreateVulkanWin32Display(state);
384             }
385             break;
386 #    elif defined(ANGLE_PLATFORM_LINUX)
387 #        if defined(ANGLE_USE_X11)
388             if (platformType == EGL_PLATFORM_X11_EXT && rx::IsVulkanXcbDisplayAvailable())
389             {
390                 impl = rx::CreateVulkanXcbDisplay(state);
391                 break;
392             }
393             break;
394 #        elif defined(ANGLE_USE_VULKAN_DISPLAY)
395             if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE &&
396                 rx::IsVulkanSimpleDisplayAvailable())
397             {
398                 impl = rx::CreateVulkanSimpleDisplay(state);
399             }
400             else if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE &&
401                      rx::IsVulkanHeadlessDisplayAvailable())
402             {
403                 impl = rx::CreateVulkanHeadlessDisplay(state);
404             }
405             else
406             {
407                 // Not supported creation type on vulkan display, fail display creation.
408                 impl = nullptr;
409             }
410             break;
411 #        endif
412 #    elif defined(ANGLE_PLATFORM_ANDROID)
413             if (rx::IsVulkanAndroidDisplayAvailable())
414             {
415                 impl = rx::CreateVulkanAndroidDisplay(state);
416             }
417             break;
418 #    elif defined(ANGLE_PLATFORM_FUCHSIA)
419             if (rx::IsVulkanFuchsiaDisplayAvailable())
420             {
421                 impl = rx::CreateVulkanFuchsiaDisplay(state);
422             }
423             break;
424 #    elif defined(ANGLE_PLATFORM_GGP)
425             if (rx::IsVulkanGGPDisplayAvailable())
426             {
427                 impl = rx::CreateVulkanGGPDisplay(state);
428             }
429             break;
430 #    elif defined(ANGLE_PLATFORM_APPLE)
431             if (rx::IsVulkanMacDisplayAvailable())
432             {
433                 impl = rx::CreateVulkanMacDisplay(state);
434             }
435             break;
436 #    else
437 #        error Unsupported Vulkan platform.
438 #    endif
439 #else
440             // No display available
441             UNREACHABLE();
442 #    if !UNREACHABLE_IS_NORETURN
443             break;
444 #    endif
445 #endif  // defined(ANGLE_ENABLE_VULKAN)
446 
447         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
448 #if defined(ANGLE_ENABLE_METAL)
449             if (rx::IsMetalDisplayAvailable())
450             {
451                 impl = rx::CreateMetalDisplay(state);
452                 break;
453             }
454 #endif
455             // No display available
456             UNREACHABLE();
457 #if !UNREACHABLE_IS_NORETURN
458             break;
459 #endif
460 
461         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
462 #if defined(ANGLE_ENABLE_NULL)
463             impl = new rx::DisplayNULL(state);
464             break;
465 #else
466             // No display available
467             UNREACHABLE();
468 #    if !UNREACHABLE_IS_NORETURN
469             break;
470 #    endif
471 #endif  // defined(ANGLE_ENABLE_NULL)
472 
473         default:
474             UNREACHABLE();
475 #if !UNREACHABLE_IS_NORETURN
476             break;
477 #endif
478     }
479 
480     return impl;
481 }
482 
Display_logError(angle::PlatformMethods * platform,const char * errorMessage)483 void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
484 {
485     gl::Trace(gl::LOG_ERR, errorMessage);
486 }
487 
Display_logWarning(angle::PlatformMethods * platform,const char * warningMessage)488 void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
489 {
490     gl::Trace(gl::LOG_WARN, warningMessage);
491 }
492 
Display_logInfo(angle::PlatformMethods * platform,const char * infoMessage)493 void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
494 {
495     // Uncomment to get info spam
496 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
497     gl::Trace(gl::LOG_INFO, infoMessage);
498 #endif
499 }
500 
EGLStringArrayToStringVector(const char ** ary)501 const std::vector<std::string> EGLStringArrayToStringVector(const char **ary)
502 {
503     std::vector<std::string> vec;
504     if (ary != nullptr)
505     {
506         for (; *ary != nullptr; ary++)
507         {
508             vec.push_back(std::string(*ary));
509         }
510     }
511     return vec;
512 }
513 
ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)514 void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
515 {
516     angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
517 
518     ANGLEResetDisplayPlatform(display);
519     platformMethods->logError   = Display_logError;
520     platformMethods->logWarning = Display_logWarning;
521     platformMethods->logInfo    = Display_logInfo;
522 }
523 
524 static constexpr uint32_t kScratchBufferLifetime = 64u;
525 
526 }  // anonymous namespace
527 
528 // ShareGroup
ShareGroup(rx::EGLImplFactory * factory)529 ShareGroup::ShareGroup(rx::EGLImplFactory *factory)
530     : mRefCount(1),
531       mImplementation(factory->createShareGroup()),
532       mFrameCaptureShared(new angle::FrameCaptureShared)
533 {}
534 
~ShareGroup()535 ShareGroup::~ShareGroup()
536 {
537     SafeDelete(mImplementation);
538 }
539 
addRef()540 void ShareGroup::addRef()
541 {
542     // This is protected by global lock, so no atomic is required
543     mRefCount++;
544 }
545 
release(const Display * display)546 void ShareGroup::release(const Display *display)
547 {
548     if (--mRefCount == 0)
549     {
550         if (mImplementation)
551         {
552             mImplementation->onDestroy(display);
553         }
554         delete this;
555     }
556 }
557 
558 // DisplayState
DisplayState(EGLNativeDisplayType nativeDisplayId)559 DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId)
560     : label(nullptr), featuresAllDisabled(false), displayId(nativeDisplayId)
561 {}
562 
~DisplayState()563 DisplayState::~DisplayState() {}
564 
565 // Note that ANGLE support on Ozone platform is limited. Our prefered support Matrix for
566 // EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following:
567 //
568 // |--------------------------------------------------------|
569 // | ANGLE type | DEVICE type |  PLATFORM type   | Display  |
570 // |--------------------------------------------------------|
571 // |   OPENGL   |     EGL     |       ANY        |   EGL    |
572 // |   OPENGL   |   HARDWARE  |     X11_EXT      |   GLX    |
573 // |  OPENGLES  |   HARDWARE  |     X11_EXT      |   GLX    |
574 // |  OPENGLES  |     EGL     |       ANY        |   EGL    |
575 // |   VULKAN   |   HARDWARE  |     X11_EXT      |  VkXcb   |
576 // |   VULKAN   | SWIFTSHADER |     X11_EXT      |  VkXcb   |
577 // |  OPENGLES  |   HARDWARE  | SURFACELESS_MESA |   EGL*   |
578 // |  OPENGLES  |   HARDWARE  |    DEVICE_EXT    |   EGL    |
579 // |   VULKAN   |   HARDWARE  | SURFACELESS_MESA | VkBase** |
580 // |   VULKAN   | SWIFTSHADER | SURFACELESS_MESA | VkBase** |
581 // |--------------------------------------------------------|
582 //
583 // * No surfaceless support yet.
584 // ** Not implemented yet.
585 //
586 // |-----------------------------------------------|
587 // |   OS    | BUILD type |  Default PLATFORM type |
588 // |-----------------------------------------------|
589 // |  Linux  |    X11     |        X11_EXT         |
590 // |  Linux  |   Ozone    |    SURFACELESS_MESA    |
591 // | Fuchsia |   Ozone    |        FUCHSIA***      |
592 // |-----------------------------------------------|
593 //
594 // *** Chosen implicitly. No EGLAttrib available.
595 //
596 // For more details, please refer to
597 // https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY
598 //
599 // static
GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,const AttributeMap & attribMap)600 Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
601                                               const AttributeMap &attribMap)
602 {
603     Display *display = nullptr;
604 
605     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
606     const auto &iter                  = displays->find(nativeDisplay);
607     if (iter != displays->end())
608     {
609         display = iter->second;
610     }
611 
612     if (display == nullptr)
613     {
614         // Validate the native display
615         if (!Display::isValidNativeDisplay(nativeDisplay))
616         {
617             return nullptr;
618         }
619 
620         display = new Display(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, nullptr);
621         displays->insert(std::make_pair(nativeDisplay, display));
622     }
623 
624     // Apply new attributes if the display is not initialized yet.
625     if (!display->isInitialized())
626     {
627         display->setAttributes(attribMap);
628 
629         display->updateAttribsFromEnvironment(attribMap);
630 
631         EGLAttrib displayType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
632         EGLAttrib deviceType  = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
633         EGLAttrib platformType =
634             display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
635         rx::DisplayImpl *impl =
636             CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState());
637         if (impl == nullptr)
638         {
639             // No valid display implementation for these attributes
640             return nullptr;
641         }
642 
643 #if defined(ANGLE_PLATFORM_ANDROID)
644         angle::gUseAndroidOpenGLTlsSlot = displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
645 #endif  // defined(ANGLE_PLATFORM_ANDROID)
646 
647         display->setupDisplayPlatform(impl);
648     }
649 
650     return display;
651 }
652 
653 // static
GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)654 Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)
655 {
656     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
657     const auto &iter                  = displays->find(nativeDisplay);
658 
659     // Check that there is a matching display
660     if (iter == displays->end())
661     {
662         return nullptr;
663     }
664 
665     return iter->second;
666 }
667 
668 // static
GetDisplayFromDevice(Device * device,const AttributeMap & attribMap)669 Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
670 {
671     Display *display = nullptr;
672 
673     ASSERT(Device::IsValidDevice(device));
674 
675     ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
676     DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
677 
678     // First see if this eglDevice is in use by a Display created using ANGLE platform
679     for (auto &displayMapEntry : *anglePlatformDisplays)
680     {
681         egl::Display *iterDisplay = displayMapEntry.second;
682         if (iterDisplay->getDevice() == device)
683         {
684             display = iterDisplay;
685         }
686     }
687 
688     if (display == nullptr)
689     {
690         // See if the eglDevice is in use by a Display created using the DEVICE platform
691         const auto &iter = devicePlatformDisplays->find(device);
692         if (iter != devicePlatformDisplays->end())
693         {
694             display = iter->second;
695         }
696     }
697 
698     if (display == nullptr)
699     {
700         // Otherwise create a new Display
701         display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
702         devicePlatformDisplays->insert(std::make_pair(device, display));
703     }
704 
705     // Apply new attributes if the display is not initialized yet.
706     if (!display->isInitialized())
707     {
708         display->setAttributes(attribMap);
709         rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
710         display->setupDisplayPlatform(impl);
711     }
712 
713     return display;
714 }
715 
Display(EGLenum platform,EGLNativeDisplayType displayId,Device * eglDevice)716 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
717     : mState(displayId),
718       mImplementation(nullptr),
719       mGPUSwitchedBinding(this, kGPUSwitchedSubjectIndex),
720       mAttributeMap(),
721       mConfigSet(),
722       mContextSet(),
723       mStreamSet(),
724       mInitialized(false),
725       mDeviceLost(false),
726       mCaps(),
727       mDisplayExtensions(),
728       mDisplayExtensionString(),
729       mVendorString(),
730       mVersionString(),
731       mDevice(eglDevice),
732       mSurface(nullptr),
733       mPlatform(platform),
734       mTextureManager(nullptr),
735       mSemaphoreManager(nullptr),
736       mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes),
737       mMemoryProgramCache(mBlobCache),
738       mGlobalTextureShareGroupUsers(0),
739       mGlobalSemaphoreShareGroupUsers(0)
740 {}
741 
~Display()742 Display::~Display()
743 {
744     // TODO(jmadill): When is this called?
745     // terminate();
746 
747     if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
748     {
749         ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
750         ANGLEPlatformDisplayMap::iterator iter = displays->find(mState.displayId);
751         if (iter != displays->end())
752         {
753             displays->erase(iter);
754         }
755     }
756     else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
757     {
758         DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
759         DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
760         if (iter != displays->end())
761         {
762             displays->erase(iter);
763         }
764     }
765     else
766     {
767         UNREACHABLE();
768     }
769 
770     SafeDelete(mDevice);
771     SafeDelete(mImplementation);
772 }
773 
setLabel(EGLLabelKHR label)774 void Display::setLabel(EGLLabelKHR label)
775 {
776     mState.label = label;
777 }
778 
getLabel() const779 EGLLabelKHR Display::getLabel() const
780 {
781     return mState.label;
782 }
783 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)784 void Display::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
785 {
786     ASSERT(index == kGPUSwitchedSubjectIndex);
787     ASSERT(message == angle::SubjectMessage::SubjectChanged);
788     for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
789     {
790         (*ctx)->onGPUSwitch();
791     }
792 }
793 
setupDisplayPlatform(rx::DisplayImpl * impl)794 void Display::setupDisplayPlatform(rx::DisplayImpl *impl)
795 {
796     ASSERT(!mInitialized);
797 
798     ASSERT(impl != nullptr);
799     SafeDelete(mImplementation);
800     mImplementation = impl;
801 
802     // TODO(jmadill): Store Platform in Display and init here.
803     const angle::PlatformMethods *platformMethods =
804         reinterpret_cast<const angle::PlatformMethods *>(
805             mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
806     if (platformMethods != nullptr)
807     {
808         *ANGLEPlatformCurrent() = *platformMethods;
809     }
810     else
811     {
812         ANGLESetDefaultDisplayPlatform(this);
813     }
814 
815     const char **featuresForceEnabled =
816         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0));
817     const char **featuresForceDisabled =
818         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0));
819     mState.featureOverridesEnabled  = EGLStringArrayToStringVector(featuresForceEnabled);
820     mState.featureOverridesDisabled = EGLStringArrayToStringVector(featuresForceDisabled);
821     mState.featuresAllDisabled =
822         static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0));
823     mImplementation->addObserver(&mGPUSwitchedBinding);
824 }
825 
updateAttribsFromEnvironment(const AttributeMap & attribMap)826 void Display::updateAttribsFromEnvironment(const AttributeMap &attribMap)
827 {
828     EGLAttrib displayType =
829         attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
830     if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
831     {
832         displayType = GetDisplayTypeFromEnvironment();
833         mAttributeMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType);
834     }
835     EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0);
836     if (deviceType == 0)
837     {
838         deviceType = GetDeviceTypeFromEnvironment();
839         mAttributeMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType);
840     }
841     EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
842     if (platformType == 0)
843     {
844         platformType = GetPlatformTypeFromEnvironment();
845         mAttributeMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType);
846     }
847 }
848 
initialize()849 Error Display::initialize()
850 {
851     ASSERT(mImplementation != nullptr);
852     mImplementation->setBlobCache(&mBlobCache);
853 
854     // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
855     // properly saved & restored on all platforms. The cache won't allocate space until it's used
856     // and will be ignored entirely if the application / system sets it's own cache functions.
857     if (rx::ShouldUseDebugLayers(mAttributeMap))
858     {
859         mBlobCache.resize(1024 * 1024);
860     }
861 
862     setGlobalDebugAnnotator();
863 
864     gl::InitializeDebugMutexIfNeeded();
865 
866     SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
867     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
868 
869     if (isInitialized())
870     {
871         return NoError();
872     }
873 
874     Error error = mImplementation->initialize(this);
875     if (error.isError())
876     {
877         // Log extended error message here
878         ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
879         return error;
880     }
881 
882     mCaps = mImplementation->getCaps();
883 
884     mConfigSet = mImplementation->generateConfigs();
885     if (mConfigSet.size() == 0)
886     {
887         mImplementation->terminate();
888         return EglNotInitialized();
889     }
890 
891     // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs
892     for (auto &config : mConfigSet)
893     {
894         // TODO(geofflang): Enable the conformant bit once we pass enough tests
895         // config.second.conformant |= EGL_OPENGL_ES_BIT;
896 
897         config.second.renderableType |= EGL_OPENGL_ES_BIT;
898     }
899 
900     if (!mState.featuresAllDisabled)
901     {
902         initializeFrontendFeatures();
903     }
904 
905     mFeatures.clear();
906     mFrontendFeatures.populateFeatureList(&mFeatures);
907     mImplementation->populateFeatureList(&mFeatures);
908 
909     initDisplayExtensions();
910     initVendorString();
911     initVersionString();
912 
913     // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
914     if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
915     {
916         // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
917         // an external device
918         ASSERT(mDevice != nullptr);
919     }
920     else if (GetClientExtensions().deviceQueryEXT)
921     {
922         std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice());
923         ASSERT(impl);
924         error = impl->initialize();
925         if (error.isError())
926         {
927             ERR() << "Failed to initialize display because device creation failed: "
928                   << error.getMessage();
929             mImplementation->terminate();
930             return error;
931         }
932         mDevice = new Device(this, impl.release());
933     }
934     else
935     {
936         mDevice = nullptr;
937     }
938 
939     mInitialized = true;
940 
941     return NoError();
942 }
943 
terminate(Thread * thread)944 Error Display::terminate(Thread *thread)
945 {
946     if (!mInitialized)
947     {
948         return NoError();
949     }
950 
951     mMemoryProgramCache.clear();
952     mBlobCache.setBlobCacheFuncs(nullptr, nullptr);
953 
954     if (auto *context = thread->getContext())
955     {
956         auto refCount = context->getRefCount();
957         ASSERT(refCount <= 2);
958         // If eglDestroyContext is not called for the current context, we destroy the context.
959         if (context->getRefCount() == 2)
960         {
961             ANGLE_TRY(destroyContext(thread, context));
962         }
963         // unMakeCurrent the context, so it will be released.
964         ANGLE_TRY(makeCurrent(thread, thread->getContext(), nullptr, nullptr, nullptr));
965         ASSERT(!thread->getContext());
966     }
967 
968     while (!mContextSet.empty())
969     {
970         auto *context = *mContextSet.begin();
971         // If the context is never be current, so context resources are not allocated,
972         // and we don't need to make the context current for releasing resources.
973         if (!context->isExternal() && context->hasBeenCurrent())
974         {
975             ANGLE_TRY(mImplementation->makeCurrent(this, nullptr, nullptr, context));
976         }
977 
978         // Force to release all refs, since the context could be current on other threads.
979         while (context->getRefCount())
980         {
981             context->release();
982         }
983 
984         ANGLE_TRY(releaseContext(context));
985     }
986 
987     // The global texture and semaphore managers should be deleted with the last context that uses
988     // it.
989     ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
990     ASSERT(mGlobalSemaphoreShareGroupUsers == 0 && mSemaphoreManager == nullptr);
991 
992     while (!mImageSet.empty())
993     {
994         destroyImage(*mImageSet.begin());
995     }
996 
997     while (!mStreamSet.empty())
998     {
999         destroyStream(*mStreamSet.begin());
1000     }
1001 
1002     while (!mSyncSet.empty())
1003     {
1004         destroySync(*mSyncSet.begin());
1005     }
1006 
1007     while (!mState.surfaceSet.empty())
1008     {
1009         ANGLE_TRY(destroySurface(*mState.surfaceSet.begin()));
1010     }
1011 
1012     mConfigSet.clear();
1013 
1014     if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
1015     {
1016         // Don't delete the device if it was created externally using eglCreateDeviceANGLE
1017         // We also shouldn't set it to null in case eglInitialize() is called again later
1018         SafeDelete(mDevice);
1019     }
1020 
1021     mImplementation->terminate();
1022 
1023     mDeviceLost = false;
1024 
1025     mInitialized = false;
1026 
1027     gl::UninitializeDebugAnnotations();
1028 
1029     // TODO(jmadill): Store Platform in Display and deinit here.
1030     ANGLEResetDisplayPlatform(this);
1031 
1032     return NoError();
1033 }
1034 
prepareForCall()1035 Error Display::prepareForCall()
1036 {
1037     return mImplementation->prepareForCall();
1038 }
1039 
releaseThread()1040 Error Display::releaseThread()
1041 {
1042     return mImplementation->releaseThread();
1043 }
1044 
getConfigs(const egl::AttributeMap & attribs) const1045 std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
1046 {
1047     return mConfigSet.filter(attribs);
1048 }
1049 
chooseConfig(const egl::AttributeMap & attribs) const1050 std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
1051 {
1052     egl::AttributeMap attribsWithDefaults = AttributeMap();
1053 
1054     // Insert default values for attributes that have either an Exact or Mask selection criteria,
1055     // and a default value that matters (e.g. isn't EGL_DONT_CARE):
1056     attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
1057     attribsWithDefaults.insert(EGL_LEVEL, 0);
1058     attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
1059     attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
1060     attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
1061     if (getExtensions().pixelFormatFloat)
1062     {
1063         attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
1064                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
1065     }
1066 
1067     // Add the caller-specified values (Note: the poorly-named insert() method will replace any
1068     // of the default values from above):
1069     for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
1070     {
1071         attribsWithDefaults.insert(attribIter->first, attribIter->second);
1072     }
1073 
1074     return mConfigSet.filter(attribsWithDefaults);
1075 }
1076 
createWindowSurface(const Config * configuration,EGLNativeWindowType window,const AttributeMap & attribs,Surface ** outSurface)1077 Error Display::createWindowSurface(const Config *configuration,
1078                                    EGLNativeWindowType window,
1079                                    const AttributeMap &attribs,
1080                                    Surface **outSurface)
1081 {
1082     if (mImplementation->testDeviceLost())
1083     {
1084         ANGLE_TRY(restoreLostDevice());
1085     }
1086 
1087     SurfacePointer surface(new WindowSurface(mImplementation, configuration, window, attribs,
1088                                              mFrontendFeatures.forceRobustResourceInit.enabled),
1089                            this);
1090     ANGLE_TRY(surface->initialize(this));
1091 
1092     ASSERT(outSurface != nullptr);
1093     *outSurface = surface.release();
1094     mState.surfaceSet.insert(*outSurface);
1095 
1096     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1097     ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
1098     windowSurfaces->insert(std::make_pair(window, *outSurface));
1099 
1100     mSurface = *outSurface;
1101 
1102     return NoError();
1103 }
1104 
createPbufferSurface(const Config * configuration,const AttributeMap & attribs,Surface ** outSurface)1105 Error Display::createPbufferSurface(const Config *configuration,
1106                                     const AttributeMap &attribs,
1107                                     Surface **outSurface)
1108 {
1109     ASSERT(isInitialized());
1110 
1111     if (mImplementation->testDeviceLost())
1112     {
1113         ANGLE_TRY(restoreLostDevice());
1114     }
1115 
1116     SurfacePointer surface(new PbufferSurface(mImplementation, configuration, attribs,
1117                                               mFrontendFeatures.forceRobustResourceInit.enabled),
1118                            this);
1119     ANGLE_TRY(surface->initialize(this));
1120 
1121     ASSERT(outSurface != nullptr);
1122     *outSurface = surface.release();
1123     mState.surfaceSet.insert(*outSurface);
1124 
1125     return NoError();
1126 }
1127 
createPbufferFromClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,Surface ** outSurface)1128 Error Display::createPbufferFromClientBuffer(const Config *configuration,
1129                                              EGLenum buftype,
1130                                              EGLClientBuffer clientBuffer,
1131                                              const AttributeMap &attribs,
1132                                              Surface **outSurface)
1133 {
1134     ASSERT(isInitialized());
1135 
1136     if (mImplementation->testDeviceLost())
1137     {
1138         ANGLE_TRY(restoreLostDevice());
1139     }
1140 
1141     SurfacePointer surface(
1142         new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs,
1143                            mFrontendFeatures.forceRobustResourceInit.enabled),
1144         this);
1145     ANGLE_TRY(surface->initialize(this));
1146 
1147     ASSERT(outSurface != nullptr);
1148     *outSurface = surface.release();
1149     mState.surfaceSet.insert(*outSurface);
1150 
1151     return NoError();
1152 }
1153 
createPixmapSurface(const Config * configuration,NativePixmapType nativePixmap,const AttributeMap & attribs,Surface ** outSurface)1154 Error Display::createPixmapSurface(const Config *configuration,
1155                                    NativePixmapType nativePixmap,
1156                                    const AttributeMap &attribs,
1157                                    Surface **outSurface)
1158 {
1159     ASSERT(isInitialized());
1160 
1161     if (mImplementation->testDeviceLost())
1162     {
1163         ANGLE_TRY(restoreLostDevice());
1164     }
1165 
1166     SurfacePointer surface(new PixmapSurface(mImplementation, configuration, nativePixmap, attribs,
1167                                              mFrontendFeatures.forceRobustResourceInit.enabled),
1168                            this);
1169     ANGLE_TRY(surface->initialize(this));
1170 
1171     ASSERT(outSurface != nullptr);
1172     *outSurface = surface.release();
1173     mState.surfaceSet.insert(*outSurface);
1174 
1175     return NoError();
1176 }
1177 
createImage(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attribs,Image ** outImage)1178 Error Display::createImage(const gl::Context *context,
1179                            EGLenum target,
1180                            EGLClientBuffer buffer,
1181                            const AttributeMap &attribs,
1182                            Image **outImage)
1183 {
1184     ASSERT(isInitialized());
1185 
1186     if (mImplementation->testDeviceLost())
1187     {
1188         ANGLE_TRY(restoreLostDevice());
1189     }
1190 
1191     egl::ImageSibling *sibling = nullptr;
1192     if (IsTextureTarget(target))
1193     {
1194         sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1195     }
1196     else if (IsRenderbufferTarget(target))
1197     {
1198         sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1199     }
1200     else if (IsExternalImageTarget(target))
1201     {
1202         sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
1203     }
1204     else
1205     {
1206         UNREACHABLE();
1207     }
1208     ASSERT(sibling != nullptr);
1209 
1210     angle::UniqueObjectPointer<Image, Display> imagePtr(
1211         new Image(mImplementation, context, target, sibling, attribs), this);
1212     ANGLE_TRY(imagePtr->initialize(this));
1213 
1214     Image *image = imagePtr.release();
1215 
1216     ASSERT(outImage != nullptr);
1217     *outImage = image;
1218 
1219     // Add this image to the list of all images and hold a ref to it.
1220     image->addRef();
1221     mImageSet.insert(image);
1222 
1223     return NoError();
1224 }
1225 
createStream(const AttributeMap & attribs,Stream ** outStream)1226 Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
1227 {
1228     ASSERT(isInitialized());
1229 
1230     Stream *stream = new Stream(this, attribs);
1231 
1232     ASSERT(stream != nullptr);
1233     mStreamSet.insert(stream);
1234 
1235     ASSERT(outStream != nullptr);
1236     *outStream = stream;
1237 
1238     return NoError();
1239 }
1240 
createContext(const Config * configuration,gl::Context * shareContext,EGLenum clientType,const AttributeMap & attribs,gl::Context ** outContext)1241 Error Display::createContext(const Config *configuration,
1242                              gl::Context *shareContext,
1243                              EGLenum clientType,
1244                              const AttributeMap &attribs,
1245                              gl::Context **outContext)
1246 {
1247     ASSERT(isInitialized());
1248 
1249     if (mImplementation->testDeviceLost())
1250     {
1251         ANGLE_TRY(restoreLostDevice());
1252     }
1253 
1254     // This display texture sharing will allow the first context to create the texture share group.
1255     bool usingDisplayTextureShareGroup =
1256         attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1257     gl::TextureManager *shareTextures = nullptr;
1258 
1259     if (usingDisplayTextureShareGroup)
1260     {
1261         ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
1262         if (mTextureManager == nullptr)
1263         {
1264             mTextureManager = new gl::TextureManager();
1265         }
1266 
1267         mGlobalTextureShareGroupUsers++;
1268         shareTextures = mTextureManager;
1269     }
1270 
1271     // This display semaphore sharing will allow the first context to create the semaphore share
1272     // group.
1273     bool usingDisplaySemaphoreShareGroup =
1274         attribs.get(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1275     gl::SemaphoreManager *shareSemaphores = nullptr;
1276     if (usingDisplaySemaphoreShareGroup)
1277     {
1278         ASSERT((mSemaphoreManager == nullptr) == (mGlobalSemaphoreShareGroupUsers == 0));
1279         if (mSemaphoreManager == nullptr)
1280         {
1281             mSemaphoreManager = new gl::SemaphoreManager();
1282         }
1283 
1284         mGlobalSemaphoreShareGroupUsers++;
1285         shareSemaphores = mSemaphoreManager;
1286     }
1287 
1288     gl::MemoryProgramCache *cachePointer = &mMemoryProgramCache;
1289 
1290     // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
1291     // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
1292     // at any time.
1293     bool usesProgramCacheControl =
1294         mAttributeMap.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
1295     if (usesProgramCacheControl)
1296     {
1297         bool programCacheControlEnabled =
1298             (mAttributeMap.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) ==
1299              GL_TRUE);
1300         // A program cache size of zero indicates it should be disabled.
1301         if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
1302         {
1303             cachePointer = nullptr;
1304         }
1305     }
1306 
1307     gl::Context *context = new gl::Context(this, configuration, shareContext, shareTextures,
1308                                            shareSemaphores, cachePointer, clientType, attribs,
1309                                            mDisplayExtensions, GetClientExtensions());
1310     Error error          = context->initialize();
1311     if (error.isError())
1312     {
1313         delete context;
1314         return error;
1315     }
1316 
1317     if (shareContext != nullptr)
1318     {
1319         shareContext->setShared();
1320     }
1321 
1322     ASSERT(context != nullptr);
1323     context->addRef();
1324     mContextSet.insert(context);
1325 
1326     ASSERT(outContext != nullptr);
1327     *outContext = context;
1328     return NoError();
1329 }
1330 
createSync(const gl::Context * currentContext,EGLenum type,const AttributeMap & attribs,Sync ** outSync)1331 Error Display::createSync(const gl::Context *currentContext,
1332                           EGLenum type,
1333                           const AttributeMap &attribs,
1334                           Sync **outSync)
1335 {
1336     ASSERT(isInitialized());
1337 
1338     if (mImplementation->testDeviceLost())
1339     {
1340         ANGLE_TRY(restoreLostDevice());
1341     }
1342 
1343     angle::UniqueObjectPointer<egl::Sync, Display> syncPtr(new Sync(mImplementation, type, attribs),
1344                                                            this);
1345 
1346     ANGLE_TRY(syncPtr->initialize(this, currentContext));
1347 
1348     Sync *sync = syncPtr.release();
1349 
1350     sync->addRef();
1351     mSyncSet.insert(sync);
1352 
1353     *outSync = sync;
1354     return NoError();
1355 }
1356 
makeCurrent(Thread * thread,gl::Context * previousContext,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)1357 Error Display::makeCurrent(Thread *thread,
1358                            gl::Context *previousContext,
1359                            egl::Surface *drawSurface,
1360                            egl::Surface *readSurface,
1361                            gl::Context *context)
1362 {
1363     if (!mInitialized)
1364     {
1365         return NoError();
1366     }
1367 
1368     // If the context is changing we need to update the reference counts. If it's not, e.g. just
1369     // changing the surfaces leave the reference count alone. Otherwise the reference count might go
1370     // to zero even though we know we are not done with the context.
1371     bool contextChanged = context != previousContext;
1372     if (previousContext != nullptr && contextChanged)
1373     {
1374         previousContext->release();
1375         thread->setCurrent(nullptr);
1376 
1377         auto error = previousContext->unMakeCurrent(this);
1378         if (previousContext->getRefCount() == 0)
1379         {
1380             ANGLE_TRY(releaseContext(previousContext));
1381         }
1382         ANGLE_TRY(error);
1383     }
1384 
1385     ANGLE_TRY(mImplementation->makeCurrent(this, drawSurface, readSurface, context));
1386 
1387     if (context != nullptr)
1388     {
1389         ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface));
1390         thread->setCurrent(context);
1391     }
1392 
1393     if (context != nullptr && contextChanged)
1394     {
1395         context->addRef();
1396     }
1397 
1398     // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being
1399     // used.
1400     {
1401         std::lock_guard<std::mutex> lock(mScratchBufferMutex);
1402 
1403         for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers)
1404         {
1405             scatchBuffer.tick();
1406         }
1407         for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers)
1408         {
1409             zeroFilledBuffer.tick();
1410         }
1411     }
1412 
1413     return NoError();
1414 }
1415 
restoreLostDevice()1416 Error Display::restoreLostDevice()
1417 {
1418     for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
1419     {
1420         if ((*ctx)->isResetNotificationEnabled())
1421         {
1422             // If reset notifications have been requested, application must delete all contexts
1423             // first
1424             return EglContextLost();
1425         }
1426     }
1427 
1428     return mImplementation->restoreLostDevice(this);
1429 }
1430 
destroySurface(Surface * surface)1431 Error Display::destroySurface(Surface *surface)
1432 {
1433     if (surface->getType() == EGL_WINDOW_BIT)
1434     {
1435         WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1436         ASSERT(windowSurfaces);
1437 
1438         bool surfaceRemoved = false;
1439         for (WindowSurfaceMap::iterator iter = windowSurfaces->begin();
1440              iter != windowSurfaces->end(); iter++)
1441         {
1442             if (iter->second == surface)
1443             {
1444                 windowSurfaces->erase(iter);
1445                 surfaceRemoved = true;
1446                 break;
1447             }
1448         }
1449 
1450         ASSERT(surfaceRemoved);
1451     }
1452 
1453     mState.surfaceSet.erase(surface);
1454     ANGLE_TRY(surface->onDestroy(this));
1455     return NoError();
1456 }
1457 
destroyImage(egl::Image * image)1458 void Display::destroyImage(egl::Image *image)
1459 {
1460     auto iter = mImageSet.find(image);
1461     ASSERT(iter != mImageSet.end());
1462     (*iter)->release(this);
1463     mImageSet.erase(iter);
1464 }
1465 
destroyStream(egl::Stream * stream)1466 void Display::destroyStream(egl::Stream *stream)
1467 {
1468     mStreamSet.erase(stream);
1469     SafeDelete(stream);
1470 }
1471 
1472 // releaseContext must be called with the context being deleted as current.
1473 // To do that we can only call this in two places, Display::makeCurrent at the point where this
1474 // context is being made uncurrent and in Display::destroyContext where we make the context current
1475 // as part of destruction.
releaseContext(gl::Context * context)1476 Error Display::releaseContext(gl::Context *context)
1477 {
1478     ASSERT(context->getRefCount() == 0);
1479 
1480     // Use scoped_ptr to make sure the context is always freed.
1481     std::unique_ptr<gl::Context> unique_context(context);
1482     ASSERT(mContextSet.find(context) != mContextSet.end());
1483     mContextSet.erase(context);
1484 
1485     if (context->usingDisplayTextureShareGroup())
1486     {
1487         ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
1488         if (mGlobalTextureShareGroupUsers == 1)
1489         {
1490             // If this is the last context using the global share group, destroy the global
1491             // texture manager so that the textures can be destroyed while a context still
1492             // exists
1493             mTextureManager->release(context);
1494             mTextureManager = nullptr;
1495         }
1496         mGlobalTextureShareGroupUsers--;
1497     }
1498 
1499     if (context->usingDisplaySemaphoreShareGroup())
1500     {
1501         ASSERT(mGlobalSemaphoreShareGroupUsers >= 1 && mSemaphoreManager != nullptr);
1502         if (mGlobalSemaphoreShareGroupUsers == 1)
1503         {
1504             // If this is the last context using the global share group, destroy the global
1505             // semaphore manager so that the semaphores can be destroyed while a context still
1506             // exists
1507             mSemaphoreManager->release(context);
1508             mSemaphoreManager = nullptr;
1509         }
1510         mGlobalSemaphoreShareGroupUsers--;
1511     }
1512 
1513     ANGLE_TRY(context->onDestroy(this));
1514 
1515     return NoError();
1516 }
1517 
destroyContext(Thread * thread,gl::Context * context)1518 Error Display::destroyContext(Thread *thread, gl::Context *context)
1519 {
1520     context->release();
1521 
1522     auto *currentContext     = thread->getContext();
1523     auto *currentDrawSurface = thread->getCurrentDrawSurface();
1524     auto *currentReadSurface = thread->getCurrentReadSurface();
1525 
1526     if (context->isCurrent())
1527     {
1528         ASSERT(context->getRefCount() == 1);
1529         // If the context is current, we just return, since the context has been marked destroyed,
1530         // so the context will be destroyed when the context is released from the current.
1531         return NoError();
1532     }
1533 
1534     ASSERT(context->getRefCount() == 0);
1535 
1536     // For external context, we cannot change the current native context, and the API user should
1537     // make sure the native context is current.
1538     if (context->isExternal())
1539     {
1540         ANGLE_TRY(releaseContext(context));
1541     }
1542     else
1543     {
1544         // Keep |currentContext| alive, while releasing |context|.
1545         gl::ScopedContextRef scopedContextRef(currentContext);
1546 
1547         // Make the context current, so we can release resources belong to the context, and then
1548         // when context is released from the current, it will be destroyed.
1549         ANGLE_TRY(makeCurrent(thread, currentContext, nullptr, nullptr, context));
1550         ANGLE_TRY(
1551             makeCurrent(thread, context, currentDrawSurface, currentReadSurface, currentContext));
1552     }
1553     return NoError();
1554 }
1555 
destroySync(egl::Sync * sync)1556 void Display::destroySync(egl::Sync *sync)
1557 {
1558     auto iter = mSyncSet.find(sync);
1559     ASSERT(iter != mSyncSet.end());
1560     (*iter)->release(this);
1561     mSyncSet.erase(iter);
1562 }
1563 
isDeviceLost() const1564 bool Display::isDeviceLost() const
1565 {
1566     ASSERT(isInitialized());
1567     return mDeviceLost;
1568 }
1569 
testDeviceLost()1570 bool Display::testDeviceLost()
1571 {
1572     ASSERT(isInitialized());
1573 
1574     if (!mDeviceLost && mImplementation->testDeviceLost())
1575     {
1576         notifyDeviceLost();
1577     }
1578 
1579     return mDeviceLost;
1580 }
1581 
notifyDeviceLost()1582 void Display::notifyDeviceLost()
1583 {
1584     if (mDeviceLost)
1585     {
1586         return;
1587     }
1588 
1589     for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end();
1590          context++)
1591     {
1592         (*context)->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
1593     }
1594 
1595     mDeviceLost = true;
1596 }
1597 
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)1598 void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
1599 {
1600     mBlobCache.setBlobCacheFuncs(set, get);
1601     mImplementation->setBlobCacheFuncs(set, get);
1602 }
1603 
1604 // static
GetNativeClientBuffer(const AHardwareBuffer * buffer)1605 EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
1606 {
1607     return angle::android::AHardwareBufferToClientBuffer(buffer);
1608 }
1609 
1610 // static
CreateNativeClientBuffer(const egl::AttributeMap & attribMap,EGLClientBuffer * eglClientBuffer)1611 Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
1612                                         EGLClientBuffer *eglClientBuffer)
1613 {
1614     int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap);
1615     int width                       = attribMap.getAsInt(EGL_WIDTH, 0);
1616     int height                      = attribMap.getAsInt(EGL_HEIGHT, 0);
1617     int usage                       = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
1618 
1619     // https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock
1620     // for AHardwareBuffer_lock()
1621     // The passed AHardwareBuffer must have one layer, otherwise the call will fail.
1622     constexpr int kLayerCount = 1;
1623 
1624     *eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer(
1625         width, height, kLayerCount, androidHardwareBufferFormat, usage);
1626 
1627     return (*eglClientBuffer == nullptr)
1628                ? egl::EglBadParameter() << "native client buffer allocation failed."
1629                : NoError();
1630 }
1631 
waitClient(const gl::Context * context)1632 Error Display::waitClient(const gl::Context *context)
1633 {
1634     return mImplementation->waitClient(context);
1635 }
1636 
waitNative(const gl::Context * context,EGLint engine)1637 Error Display::waitNative(const gl::Context *context, EGLint engine)
1638 {
1639     return mImplementation->waitNative(context, engine);
1640 }
1641 
getCaps() const1642 const Caps &Display::getCaps() const
1643 {
1644     return mCaps;
1645 }
1646 
isInitialized() const1647 bool Display::isInitialized() const
1648 {
1649     return mInitialized;
1650 }
1651 
isValidConfig(const Config * config) const1652 bool Display::isValidConfig(const Config *config) const
1653 {
1654     return mConfigSet.contains(config);
1655 }
1656 
isValidContext(const gl::Context * context) const1657 bool Display::isValidContext(const gl::Context *context) const
1658 {
1659     return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
1660 }
1661 
isValidSurface(const Surface * surface) const1662 bool Display::isValidSurface(const Surface *surface) const
1663 {
1664     return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end();
1665 }
1666 
isValidImage(const Image * image) const1667 bool Display::isValidImage(const Image *image) const
1668 {
1669     return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
1670 }
1671 
isValidStream(const Stream * stream) const1672 bool Display::isValidStream(const Stream *stream) const
1673 {
1674     return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
1675 }
1676 
isValidSync(const Sync * sync) const1677 bool Display::isValidSync(const Sync *sync) const
1678 {
1679     return mSyncSet.find(const_cast<Sync *>(sync)) != mSyncSet.end();
1680 }
1681 
hasExistingWindowSurface(EGLNativeWindowType window)1682 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
1683 {
1684     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1685     ASSERT(windowSurfaces);
1686 
1687     return windowSurfaces->find(window) != windowSurfaces->end();
1688 }
1689 
GenerateClientExtensions()1690 static ClientExtensions GenerateClientExtensions()
1691 {
1692     ClientExtensions extensions;
1693 
1694     extensions.clientExtensions = true;
1695     extensions.platformBase     = true;
1696     extensions.platformANGLE    = true;
1697 
1698 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
1699     extensions.platformANGLED3D = true;
1700     extensions.platformDevice   = true;
1701 #endif
1702 
1703 #if defined(ANGLE_ENABLE_D3D11)
1704 #    if defined(ANGLE_ENABLE_WINDOWS_UWP)
1705     extensions.platformANGLED3D11ON12 = true;
1706 #    else
1707     extensions.platformANGLED3D11ON12 = IsWindows10OrGreater();
1708 #    endif
1709 #endif
1710 
1711 #if defined(ANGLE_ENABLE_OPENGL)
1712     extensions.platformANGLEOpenGL = true;
1713 
1714     // Selecting context virtualization is currently only supported in the OpenGL backend.
1715     extensions.platformANGLEContextVirtualization = true;
1716 #endif
1717 
1718 #if defined(ANGLE_ENABLE_NULL)
1719     extensions.platformANGLENULL = true;
1720 #endif
1721 
1722 #if defined(ANGLE_ENABLE_D3D11)
1723     extensions.deviceCreation          = true;
1724     extensions.deviceCreationD3D11     = true;
1725     extensions.experimentalPresentPath = true;
1726 #endif
1727 
1728 #if defined(ANGLE_ENABLE_VULKAN)
1729     extensions.platformANGLEVulkan = true;
1730 #endif
1731 
1732 #if defined(ANGLE_ENABLE_SWIFTSHADER)
1733     extensions.platformANGLEDeviceTypeSwiftShader = true;
1734 #endif
1735 
1736 #if defined(ANGLE_ENABLE_METAL)
1737     extensions.platformANGLEMetal = true;
1738 #endif
1739 
1740 #if defined(ANGLE_USE_X11)
1741     extensions.x11Visual = true;
1742 #endif
1743 
1744 #if defined(ANGLE_PLATFORM_LINUX)
1745     extensions.platformANGLEDeviceTypeEGLANGLE = true;
1746 #endif
1747 
1748 #if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || \
1749     (defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64))
1750     extensions.platformANGLEDeviceContextVolatileEagl = true;
1751 #endif
1752 
1753 #if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
1754     extensions.platformANGLEDeviceContextVolatileCgl = true;
1755 #endif
1756 
1757     extensions.clientGetAllProcAddresses = true;
1758     extensions.debug                     = true;
1759     extensions.featureControlANGLE       = true;
1760     extensions.deviceQueryEXT            = true;
1761 
1762     return extensions;
1763 }
1764 
1765 template <typename T>
GenerateExtensionsString(const T & extensions)1766 static std::string GenerateExtensionsString(const T &extensions)
1767 {
1768     std::vector<std::string> extensionsVector = extensions.getStrings();
1769 
1770     std::ostringstream stream;
1771     std::copy(extensionsVector.begin(), extensionsVector.end(),
1772               std::ostream_iterator<std::string>(stream, " "));
1773     return stream.str();
1774 }
1775 
1776 // static
GetClientExtensions()1777 const ClientExtensions &Display::GetClientExtensions()
1778 {
1779     static const ClientExtensions clientExtensions = GenerateClientExtensions();
1780     return clientExtensions;
1781 }
1782 
1783 // static
GetClientExtensionString()1784 const std::string &Display::GetClientExtensionString()
1785 {
1786     static const angle::base::NoDestructor<std::string> clientExtensionsString(
1787         GenerateExtensionsString(GetClientExtensions()));
1788     return *clientExtensionsString;
1789 }
1790 
initDisplayExtensions()1791 void Display::initDisplayExtensions()
1792 {
1793     mDisplayExtensions = mImplementation->getExtensions();
1794 
1795     // Some extensions are always available because they are implemented in the EGL layer.
1796     mDisplayExtensions.createContext                      = true;
1797     mDisplayExtensions.createContextNoError               = true;
1798     mDisplayExtensions.createContextWebGLCompatibility    = true;
1799     mDisplayExtensions.createContextBindGeneratesResource = true;
1800     mDisplayExtensions.createContextClientArrays          = true;
1801     mDisplayExtensions.pixelFormatFloat                   = true;
1802     mDisplayExtensions.reusableSyncKHR                    = true;
1803 
1804     // Force EGL_KHR_get_all_proc_addresses on.
1805     mDisplayExtensions.getAllProcAddresses = true;
1806 
1807     // Enable program cache control since it is not back-end dependent.
1808     mDisplayExtensions.programCacheControl = true;
1809 
1810     // Request extension is implemented in the ANGLE frontend
1811     mDisplayExtensions.createContextExtensionsEnabled = true;
1812 
1813     // Blob cache extension is provided by the ANGLE frontend
1814     mDisplayExtensions.blobCache = true;
1815 
1816     // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always
1817     // say that ANativeWindow is not recordable.
1818     mDisplayExtensions.recordable = true;
1819 
1820     // All backends support specific context versions
1821     mDisplayExtensions.createContextBackwardsCompatible = true;
1822 
1823     // Note: we don't notify the back-end of a change to the renderbuffer right now. This extension
1824     // is implemented only in the front-end. A full implementation involves notifying the back-end.
1825     mDisplayExtensions.mutableRenderBufferKHR = true;
1826 
1827     mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
1828 }
1829 
isValidNativeWindow(EGLNativeWindowType window) const1830 bool Display::isValidNativeWindow(EGLNativeWindowType window) const
1831 {
1832     return mImplementation->isValidNativeWindow(window);
1833 }
1834 
validateClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs) const1835 Error Display::validateClientBuffer(const Config *configuration,
1836                                     EGLenum buftype,
1837                                     EGLClientBuffer clientBuffer,
1838                                     const AttributeMap &attribs) const
1839 {
1840     return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
1841 }
1842 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const1843 Error Display::validateImageClientBuffer(const gl::Context *context,
1844                                          EGLenum target,
1845                                          EGLClientBuffer clientBuffer,
1846                                          const egl::AttributeMap &attribs) const
1847 {
1848     return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
1849 }
1850 
valdiatePixmap(const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes) const1851 Error Display::valdiatePixmap(const Config *config,
1852                               EGLNativePixmapType pixmap,
1853                               const AttributeMap &attributes) const
1854 {
1855     return mImplementation->validatePixmap(config, pixmap, attributes);
1856 }
1857 
isValidDisplay(const egl::Display * display)1858 bool Display::isValidDisplay(const egl::Display *display)
1859 {
1860     const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
1861     for (const auto &displayPair : *anglePlatformDisplayMap)
1862     {
1863         if (displayPair.second == display)
1864         {
1865             return true;
1866         }
1867     }
1868 
1869     const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
1870     for (const auto &displayPair : *devicePlatformDisplayMap)
1871     {
1872         if (displayPair.second == display)
1873         {
1874             return true;
1875         }
1876     }
1877 
1878     return false;
1879 }
1880 
isValidNativeDisplay(EGLNativeDisplayType display)1881 bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
1882 {
1883     // TODO(jmadill): handle this properly
1884     if (display == EGL_DEFAULT_DISPLAY)
1885     {
1886         return true;
1887     }
1888 
1889 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
1890     if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
1891         display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
1892     {
1893         return true;
1894     }
1895     return (WindowFromDC(display) != nullptr);
1896 #else
1897     return true;
1898 #endif
1899 }
1900 
initVendorString()1901 void Display::initVendorString()
1902 {
1903     mVendorString                = "Google Inc.";
1904     std::string vendorStringImpl = mImplementation->getVendorString();
1905     if (!vendorStringImpl.empty())
1906     {
1907         mVendorString += " (" + vendorStringImpl + ")";
1908     }
1909 }
1910 
initVersionString()1911 void Display::initVersionString()
1912 {
1913     mVersionString = mImplementation->getVersionString();
1914 }
1915 
initializeFrontendFeatures()1916 void Display::initializeFrontendFeatures()
1917 {
1918     // Enable on all Impls
1919     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), loseContextOnOutOfMemory, true);
1920     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), allowCompressedFormats, true);
1921 
1922     // No longer enable this on any Impl - crbug.com/1165751
1923     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), scalarizeVecAndMatConstructorArgs, false);
1924 
1925     mImplementation->initializeFrontendFeatures(&mFrontendFeatures);
1926 
1927     rx::ApplyFeatureOverrides(&mFrontendFeatures, mState);
1928 
1929     // Disabled by default. To reduce the risk, create a feature to enable
1930     // compressing pipeline cache in multi-thread pool.
1931     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, enableCompressingPipelineCacheInThreadPool, false);
1932 }
1933 
getExtensions() const1934 const DisplayExtensions &Display::getExtensions() const
1935 {
1936     return mDisplayExtensions;
1937 }
1938 
getExtensionString() const1939 const std::string &Display::getExtensionString() const
1940 {
1941     return mDisplayExtensionString;
1942 }
1943 
getVendorString() const1944 const std::string &Display::getVendorString() const
1945 {
1946     return mVendorString;
1947 }
1948 
getVersionString() const1949 const std::string &Display::getVersionString() const
1950 {
1951     return mVersionString;
1952 }
1953 
getBackendRendererDescription() const1954 std::string Display::getBackendRendererDescription() const
1955 {
1956     return mImplementation->getRendererDescription();
1957 }
1958 
getBackendVendorString() const1959 std::string Display::getBackendVendorString() const
1960 {
1961     return mImplementation->getVendorString();
1962 }
1963 
getBackendVersionString() const1964 std::string Display::getBackendVersionString() const
1965 {
1966     return mImplementation->getVersionString();
1967 }
1968 
getDevice() const1969 Device *Display::getDevice() const
1970 {
1971     return mDevice;
1972 }
1973 
getWGLSurface() const1974 Surface *Display::getWGLSurface() const
1975 {
1976     return mSurface;
1977 }
1978 
getMaxSupportedESVersion() const1979 gl::Version Display::getMaxSupportedESVersion() const
1980 {
1981     return mImplementation->getMaxSupportedESVersion();
1982 }
1983 
programCacheGetAttrib(EGLenum attrib) const1984 EGLint Display::programCacheGetAttrib(EGLenum attrib) const
1985 {
1986     switch (attrib)
1987     {
1988         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
1989             return static_cast<EGLint>(BlobCache::kKeyLength);
1990 
1991         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
1992             return static_cast<EGLint>(mMemoryProgramCache.entryCount());
1993 
1994         default:
1995             UNREACHABLE();
1996             return 0;
1997     }
1998 }
1999 
programCacheQuery(EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)2000 Error Display::programCacheQuery(EGLint index,
2001                                  void *key,
2002                                  EGLint *keysize,
2003                                  void *binary,
2004                                  EGLint *binarysize)
2005 {
2006     ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
2007 
2008     const BlobCache::Key *programHash = nullptr;
2009     BlobCache::Value programBinary;
2010     // TODO(jmadill): Make this thread-safe.
2011     bool result =
2012         mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
2013     if (!result)
2014     {
2015         return EglBadAccess() << "Program binary not accessible.";
2016     }
2017 
2018     ASSERT(keysize && binarysize);
2019 
2020     if (key)
2021     {
2022         ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2023         memcpy(key, programHash->data(), BlobCache::kKeyLength);
2024     }
2025 
2026     if (binary)
2027     {
2028         // Note: we check the size here instead of in the validation code, since we need to
2029         // access the cache as atomically as possible. It's possible that the cache contents
2030         // could change between the validation size check and the retrieval.
2031         if (programBinary.size() > static_cast<size_t>(*binarysize))
2032         {
2033             return EglBadAccess() << "Program binary too large or changed during access.";
2034         }
2035 
2036         memcpy(binary, programBinary.data(), programBinary.size());
2037     }
2038 
2039     *binarysize = static_cast<EGLint>(programBinary.size());
2040     *keysize    = static_cast<EGLint>(BlobCache::kKeyLength);
2041 
2042     return NoError();
2043 }
2044 
programCachePopulate(const void * key,EGLint keysize,const void * binary,EGLint binarysize)2045 Error Display::programCachePopulate(const void *key,
2046                                     EGLint keysize,
2047                                     const void *binary,
2048                                     EGLint binarysize)
2049 {
2050     ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2051 
2052     BlobCache::Key programHash;
2053     memcpy(programHash.data(), key, BlobCache::kKeyLength);
2054 
2055     if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
2056                                        static_cast<size_t>(binarysize)))
2057     {
2058         return EglBadAccess() << "Failed to copy program binary into the cache.";
2059     }
2060 
2061     return NoError();
2062 }
2063 
programCacheResize(EGLint limit,EGLenum mode)2064 EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
2065 {
2066     switch (mode)
2067     {
2068         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
2069         {
2070             size_t initialSize = mMemoryProgramCache.size();
2071             mMemoryProgramCache.resize(static_cast<size_t>(limit));
2072             return static_cast<EGLint>(initialSize);
2073         }
2074 
2075         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
2076             return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
2077 
2078         default:
2079             UNREACHABLE();
2080             return 0;
2081     }
2082 }
2083 
overrideFrontendFeatures(const std::vector<std::string> & featureNames,bool enabled)2084 void Display::overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled)
2085 {
2086     mFrontendFeatures.overrideFeatures(featureNames, enabled);
2087 }
2088 
queryStringi(const EGLint name,const EGLint index)2089 const char *Display::queryStringi(const EGLint name, const EGLint index)
2090 {
2091     const char *result = nullptr;
2092     switch (name)
2093     {
2094         case EGL_FEATURE_NAME_ANGLE:
2095             result = mFeatures[index]->name;
2096             break;
2097         case EGL_FEATURE_CATEGORY_ANGLE:
2098             result = angle::FeatureCategoryToString(mFeatures[index]->category);
2099             break;
2100         case EGL_FEATURE_DESCRIPTION_ANGLE:
2101             result = mFeatures[index]->description;
2102             break;
2103         case EGL_FEATURE_BUG_ANGLE:
2104             result = mFeatures[index]->bug;
2105             break;
2106         case EGL_FEATURE_STATUS_ANGLE:
2107             result = angle::FeatureStatusToString(mFeatures[index]->enabled);
2108             break;
2109         case EGL_FEATURE_CONDITION_ANGLE:
2110             result = mFeatures[index]->condition;
2111             break;
2112         default:
2113             UNREACHABLE();
2114             return nullptr;
2115     }
2116     return result;
2117 }
2118 
queryAttrib(const EGLint attribute)2119 EGLAttrib Display::queryAttrib(const EGLint attribute)
2120 {
2121     EGLAttrib value = 0;
2122     switch (attribute)
2123     {
2124         case EGL_DEVICE_EXT:
2125             value = reinterpret_cast<EGLAttrib>(mDevice);
2126             break;
2127 
2128         case EGL_FEATURE_COUNT_ANGLE:
2129             value = mFeatures.size();
2130             break;
2131 
2132         default:
2133             UNREACHABLE();
2134     }
2135     return value;
2136 }
2137 
requestScratchBuffer()2138 angle::ScratchBuffer Display::requestScratchBuffer()
2139 {
2140     return requestScratchBufferImpl(&mScratchBuffers);
2141 }
2142 
returnScratchBuffer(angle::ScratchBuffer scratchBuffer)2143 void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer)
2144 {
2145     returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers);
2146 }
2147 
requestZeroFilledBuffer()2148 angle::ScratchBuffer Display::requestZeroFilledBuffer()
2149 {
2150     return requestScratchBufferImpl(&mZeroFilledBuffers);
2151 }
2152 
returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)2153 void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)
2154 {
2155     returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers);
2156 }
2157 
requestScratchBufferImpl(std::vector<angle::ScratchBuffer> * bufferVector)2158 angle::ScratchBuffer Display::requestScratchBufferImpl(
2159     std::vector<angle::ScratchBuffer> *bufferVector)
2160 {
2161     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
2162     if (!bufferVector->empty())
2163     {
2164         angle::ScratchBuffer buffer = std::move(bufferVector->back());
2165         bufferVector->pop_back();
2166         return buffer;
2167     }
2168 
2169     return angle::ScratchBuffer(kScratchBufferLifetime);
2170 }
2171 
returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,std::vector<angle::ScratchBuffer> * bufferVector)2172 void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
2173                                       std::vector<angle::ScratchBuffer> *bufferVector)
2174 {
2175     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
2176     bufferVector->push_back(std::move(scratchBuffer));
2177 }
2178 
handleGPUSwitch()2179 Error Display::handleGPUSwitch()
2180 {
2181     ANGLE_TRY(mImplementation->handleGPUSwitch());
2182     initVendorString();
2183     return NoError();
2184 }
2185 
2186 }  // namespace egl
2187