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