• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sstream>
16 #include <vector>
17 
18 #include <EGL/eglext.h>
19 #include <platform/PlatformMethods.h>
20 
21 #include "anglebase/no_destructor.h"
22 #include "common/android_util.h"
23 #include "common/debug.h"
24 #include "common/mathutil.h"
25 #include "common/platform_helpers.h"
26 #include "common/string_utils.h"
27 #include "common/system_utils.h"
28 #include "common/tls.h"
29 #include "common/utilities.h"
30 #include "gpu_info_util/SystemInfo.h"
31 #include "image_util/loadimage.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_PLATFORM_APPLE)
48 #    include <dispatch/dispatch.h>
49 #    include "common/tls.h"
50 #endif
51 
52 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
53 #    include "libANGLE/renderer/d3d/DisplayD3D.h"
54 #endif
55 
56 #if defined(ANGLE_ENABLE_OPENGL)
57 #    if defined(ANGLE_PLATFORM_WINDOWS)
58 #        include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
59 #    elif ANGLE_ENABLE_CGL
60 #        include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
61 #    elif ANGLE_ENABLE_EAGL
62 #        include "libANGLE/renderer/gl/eagl/DisplayEAGL.h"
63 #    elif defined(ANGLE_PLATFORM_LINUX)
64 #        include "libANGLE/renderer/gl/egl/DisplayEGL.h"
65 #        if defined(ANGLE_USE_X11)
66 #            include "libANGLE/renderer/gl/glx/DisplayGLX.h"
67 #        endif
68 #    elif defined(ANGLE_PLATFORM_ANDROID)
69 #        include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
70 #    else
71 #        error Unsupported OpenGL platform.
72 #    endif
73 #endif
74 
75 #if defined(ANGLE_ENABLE_NULL)
76 #    include "libANGLE/renderer/null/DisplayNULL.h"
77 #endif  // defined(ANGLE_ENABLE_NULL)
78 
79 #if defined(ANGLE_ENABLE_VULKAN)
80 #    include "libANGLE/renderer/vulkan/DisplayVk_api.h"
81 #endif  // defined(ANGLE_ENABLE_VULKAN)
82 
83 #if defined(ANGLE_ENABLE_METAL)
84 #    include "libANGLE/renderer/metal/DisplayMtl_api.h"
85 #endif  // defined(ANGLE_ENABLE_METAL)
86 
87 namespace egl
88 {
89 
90 namespace
91 {
92 // Use standard mutex for now.
93 using ContextMutexType = std::mutex;
94 
95 struct TLSData
96 {
97     angle::UnlockedTailCall unlockedTailCall;
98     Error errorScratchSpace;
99 
100     TLSData();
101 };
102 
TLSData()103 TLSData::TLSData() : errorScratchSpace(0) {}
104 
105 #if defined(ANGLE_PLATFORM_APPLE)
106 // TODO(angleproject:6479): Due to a bug in Apple's dyld loader, `thread_local` will cause
107 // excessive memory use. Temporarily avoid it by using pthread's thread
108 // local storage instead.
GetDisplayTLSIndex()109 static angle::TLSIndex GetDisplayTLSIndex()
110 {
111     static angle::TLSIndex DisplayIndex = TLS_INVALID_INDEX;
112     static dispatch_once_t once;
113     dispatch_once(&once, ^{
114       ASSERT(DisplayIndex == TLS_INVALID_INDEX);
115       DisplayIndex = angle::CreateTLSIndex(nullptr);
116     });
117     return DisplayIndex;
118 }
GetDisplayTLS()119 TLSData *GetDisplayTLS()
120 {
121     angle::TLSIndex DisplayIndex = GetDisplayTLSIndex();
122     ASSERT(DisplayIndex != TLS_INVALID_INDEX);
123     return static_cast<TLSData *>(angle::GetTLSValue(DisplayIndex));
124 }
SetDisplayTLS(TLSData * tlsData)125 void SetDisplayTLS(TLSData *tlsData)
126 {
127     angle::TLSIndex DisplayIndex = GetDisplayTLSIndex();
128     ASSERT(DisplayIndex != TLS_INVALID_INDEX);
129     angle::SetTLSValue(DisplayIndex, tlsData);
130 }
131 #else
132 // Tail calls generated during execution of the entry point, to be run at the end of the entry
133 // point.  gTLSData->unlockedTailCall.run() is called at the end of any EGL entry point that is
134 // expected to generate such calls.  At the end of every other call, it is asserted that this is
135 // empty.
136 thread_local TLSData *gDisplayTLS = nullptr;
137 
GetDisplayTLS()138 TLSData *GetDisplayTLS()
139 {
140     return gDisplayTLS;
141 }
142 #endif
143 
144 constexpr angle::SubjectIndex kGPUSwitchedSubjectIndex = 0;
145 
146 static constexpr size_t kWindowSurfaceMapSize = 32;
147 typedef angle::FlatUnorderedMap<EGLNativeWindowType, Surface *, kWindowSurfaceMapSize>
148     WindowSurfaceMap;
149 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
150 // associated with it.
GetWindowSurfaces()151 static WindowSurfaceMap *GetWindowSurfaces()
152 {
153     static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces;
154     return windowSurfaces.get();
155 }
156 
EGLStringArrayHash(const char ** ary)157 size_t EGLStringArrayHash(const char **ary)
158 {
159     size_t hash = 0;
160     if (ary != nullptr)
161     {
162         for (; *ary != nullptr; ary++)
163         {
164             hash ^= std::hash<std::string>{}(std::string(*ary));
165         }
166     }
167     return hash;
168 }
169 
170 struct ANGLEPlatformDisplay
171 {
172     ANGLEPlatformDisplay() = default;
173 
ANGLEPlatformDisplayegl::__anonad3f92f70111::ANGLEPlatformDisplay174     ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType)
175         : nativeDisplayType(nativeDisplayType)
176     {}
177 
ANGLEPlatformDisplayegl::__anonad3f92f70111::ANGLEPlatformDisplay178     ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType,
179                          EGLAttrib powerPreference,
180                          EGLAttrib platformANGLEType,
181                          EGLAttrib deviceIdHigh,
182                          EGLAttrib deviceIdLow,
183                          EGLAttrib displayKey,
184                          EGLAttrib enabledFeatureOverrides,
185                          EGLAttrib disabledFeatureOverrides,
186                          EGLAttrib disableAllNonOverriddenFeatures)
187         : nativeDisplayType(nativeDisplayType),
188           powerPreference(powerPreference),
189           platformANGLEType(platformANGLEType),
190           deviceIdHigh(deviceIdHigh),
191           deviceIdLow(deviceIdLow),
192           displayKey(displayKey),
193           disableAllNonOverriddenFeatures(static_cast<bool>(disableAllNonOverriddenFeatures))
194     {
195         enabledFeatureOverridesHash =
196             EGLStringArrayHash(reinterpret_cast<const char **>(enabledFeatureOverrides));
197         disabledFeatureOverridesHash =
198             EGLStringArrayHash(reinterpret_cast<const char **>(disabledFeatureOverrides));
199     }
200 
tieegl::__anonad3f92f70111::ANGLEPlatformDisplay201     auto tie() const
202     {
203         return std::tie(nativeDisplayType, powerPreference, platformANGLEType, deviceIdHigh,
204                         deviceIdLow, displayKey, enabledFeatureOverridesHash,
205                         disabledFeatureOverridesHash, disableAllNonOverriddenFeatures);
206     }
207 
208     EGLNativeDisplayType nativeDisplayType{EGL_DEFAULT_DISPLAY};
209     EGLAttrib powerPreference{EGL_LOW_POWER_ANGLE};
210     EGLAttrib platformANGLEType{EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE};
211     EGLAttrib deviceIdHigh{0};
212     EGLAttrib deviceIdLow{0};
213     EGLAttrib displayKey{0};
214     size_t enabledFeatureOverridesHash;
215     size_t disabledFeatureOverridesHash;
216     bool disableAllNonOverriddenFeatures;
217 };
218 
operator ==(const ANGLEPlatformDisplay & a,const ANGLEPlatformDisplay & b)219 inline bool operator==(const ANGLEPlatformDisplay &a, const ANGLEPlatformDisplay &b)
220 {
221     return a.tie() == b.tie();
222 }
223 
224 static constexpr size_t kANGLEPlatformDisplayMapSize = 9;
225 typedef angle::FlatUnorderedMap<ANGLEPlatformDisplay, Display *, kANGLEPlatformDisplayMapSize>
226     ANGLEPlatformDisplayMap;
GetANGLEPlatformDisplayMap()227 static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
228 {
229     static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays;
230     return displays.get();
231 }
232 
233 static constexpr size_t kDevicePlatformDisplayMapSize = 8;
234 typedef angle::FlatUnorderedMap<Device *, Display *, kDevicePlatformDisplayMapSize>
235     DevicePlatformDisplayMap;
GetDevicePlatformDisplayMap()236 static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
237 {
238     static angle::base::NoDestructor<DevicePlatformDisplayMap> displays;
239     return displays.get();
240 }
241 
CreateDisplayFromDevice(Device * eglDevice,const DisplayState & state)242 rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
243 {
244     rx::DisplayImpl *impl = nullptr;
245 
246     switch (eglDevice->getType())
247     {
248 #if defined(ANGLE_ENABLE_D3D11)
249         case EGL_D3D11_DEVICE_ANGLE:
250             impl = new rx::DisplayD3D(state);
251             break;
252 #endif
253 #if defined(ANGLE_ENABLE_D3D9)
254         case EGL_D3D9_DEVICE_ANGLE:
255             // Currently the only way to get EGLDeviceEXT representing a D3D9 device
256             // is to retrieve one from an already-existing EGLDisplay.
257             // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
258             // the already-existing display should be returned.
259             // Therefore this codepath to create a new display from the device
260             // should never be hit.
261             UNREACHABLE();
262             break;
263 #endif
264         default:
265             UNREACHABLE();
266             break;
267     }
268 
269     ASSERT(impl != nullptr);
270     return impl;
271 }
272 
273 // On platforms with support for multiple back-ends, allow an environment variable to control
274 // the default.  This is useful to run angle with benchmarks without having to modify the
275 // benchmark source.  Possible values for this environment variable (ANGLE_DEFAULT_PLATFORM)
276 // are: vulkan, gl, d3d11, null.
GetDisplayTypeFromEnvironment()277 EGLAttrib GetDisplayTypeFromEnvironment()
278 {
279     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
280     angle::ToLower(&angleDefaultEnv);
281 
282 #if defined(ANGLE_ENABLE_VULKAN)
283     if ((angleDefaultEnv == "vulkan") || (angleDefaultEnv == "vulkan-null") ||
284         (angleDefaultEnv == "swiftshader"))
285     {
286         return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
287     }
288 #endif
289 
290 #if defined(ANGLE_ENABLE_OPENGL)
291     if (angleDefaultEnv == "gl")
292     {
293         return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
294     }
295 #endif
296 
297 #if defined(ANGLE_ENABLE_D3D11)
298     if (angleDefaultEnv == "d3d11")
299     {
300         return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
301     }
302 #endif
303 
304 #if defined(ANGLE_ENABLE_METAL)
305     if (angleDefaultEnv == "metal")
306     {
307         return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
308     }
309 #endif
310 
311 #if defined(ANGLE_ENABLE_NULL)
312     if (angleDefaultEnv == "null")
313     {
314         return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
315     }
316 #endif
317 #if defined(ANGLE_ENABLE_D3D11)
318     return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
319 #elif defined(ANGLE_ENABLE_D3D9)
320     return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
321 #elif defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_PLATFORM_ANDROID)
322     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
323 #elif defined(ANGLE_ENABLE_OPENGL)
324 #    if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_USE_GBM)
325     return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
326 #    else
327     return EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
328 #    endif
329 #elif defined(ANGLE_ENABLE_METAL)
330     return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
331 #elif defined(ANGLE_ENABLE_VULKAN)
332     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
333 #elif defined(ANGLE_ENABLE_NULL)
334     return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
335 #else
336 #    error No default ANGLE platform type
337 #endif
338 }
339 
GetDeviceTypeFromEnvironment()340 EGLAttrib GetDeviceTypeFromEnvironment()
341 {
342     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
343     angle::ToLower(&angleDefaultEnv);
344 
345 #if defined(ANGLE_ENABLE_VULKAN)
346     if (angleDefaultEnv == "vulkan-null")
347     {
348         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
349     }
350     else if (angleDefaultEnv == "swiftshader")
351     {
352         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
353     }
354 #endif
355     return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
356 }
357 
GetPlatformTypeFromEnvironment()358 EGLAttrib GetPlatformTypeFromEnvironment()
359 {
360 #if defined(ANGLE_USE_OZONE)
361     return 0;
362 #elif defined(ANGLE_USE_X11)
363     return EGL_PLATFORM_X11_EXT;
364 #elif defined(ANGLE_USE_WAYLAND)
365     return EGL_PLATFORM_WAYLAND_EXT;
366 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_SIMPLE)
367     return EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE;
368 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_HEADLESS)
369     return EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE;
370 #else
371     return 0;
372 #endif  // defined(ANGLE_USE_OZONE)
373 }
374 
CreateDisplayFromAttribs(EGLAttrib displayType,EGLAttrib deviceType,EGLAttrib platformType,const DisplayState & state)375 rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType,
376                                           EGLAttrib deviceType,
377                                           EGLAttrib platformType,
378                                           const DisplayState &state)
379 {
380     ASSERT(displayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
381     rx::DisplayImpl *impl = nullptr;
382 
383     switch (displayType)
384     {
385         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
386             UNREACHABLE();
387             break;
388 
389         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
390         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
391 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
392             impl = new rx::DisplayD3D(state);
393             break;
394 #else
395             // A D3D display was requested on a platform that doesn't support it
396             UNREACHABLE();
397             break;
398 #endif
399 
400         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
401 #if defined(ANGLE_ENABLE_OPENGL)
402 #    if defined(ANGLE_PLATFORM_WINDOWS)
403             impl = new rx::DisplayWGL(state);
404             break;
405 
406 #    elif ANGLE_ENABLE_CGL
407             impl = new rx::DisplayCGL(state);
408             break;
409 
410 #    elif ANGLE_ENABLE_EAGL
411             impl = new rx::DisplayEAGL(state);
412             break;
413 
414 #    elif defined(ANGLE_PLATFORM_LINUX)
415 #        if defined(ANGLE_USE_GBM)
416             if (platformType == 0)
417             {
418                 impl = new rx::DisplayEGL(state);
419                 break;
420             }
421 #        endif
422             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
423             {
424                 impl = new rx::DisplayEGL(state);
425                 break;
426             }
427 #        if defined(ANGLE_USE_X11)
428             if (platformType == EGL_PLATFORM_X11_EXT)
429             {
430                 impl = new rx::DisplayGLX(state);
431                 break;
432             }
433 #        endif
434             break;
435 
436 #    elif defined(ANGLE_PLATFORM_ANDROID)
437             // No GL support on this platform, fail display creation.
438             impl = nullptr;
439             break;
440 
441 #    else
442 #        error Unsupported OpenGL platform.
443 #    endif
444 #else
445             // No display available
446             UNREACHABLE();
447             break;
448 
449 #endif  // defined(ANGLE_ENABLE_OPENGL)
450 
451         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
452 #if defined(ANGLE_ENABLE_OPENGL)
453 #    if defined(ANGLE_PLATFORM_WINDOWS)
454             impl = new rx::DisplayWGL(state);
455 #    elif defined(ANGLE_PLATFORM_LINUX)
456 #        if defined(ANGLE_USE_GBM)
457             if (platformType == 0 ||
458                 platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE)
459             {
460                 // platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE is a hack,
461                 // to allow ChromeOS GLES backend to continue functioning when Vulkan is enabled.
462                 impl = new rx::DisplayEGL(state);
463                 break;
464             }
465 #        endif
466             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
467             {
468                 impl = new rx::DisplayEGL(state);
469                 break;
470             }
471             else
472             {
473 #        if defined(ANGLE_USE_X11)
474                 if (platformType == EGL_PLATFORM_X11_EXT)
475                 {
476                     impl = new rx::DisplayGLX(state);
477                     break;
478                 }
479 #        endif
480             }
481 #    elif defined(ANGLE_PLATFORM_ANDROID)
482             impl = new rx::DisplayAndroid(state);
483 #    else
484             // No GLES support on this platform, fail display creation.
485             impl = nullptr;
486 #    endif
487 #endif  // defined(ANGLE_ENABLE_OPENGL)
488             break;
489 
490         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
491 #if defined(ANGLE_ENABLE_VULKAN)
492 #    if defined(ANGLE_USE_VULKAN_NULL_DISPLAY)
493             if (rx::IsVulkanNullDisplayAvailable())
494             {
495                 impl = rx::CreateVulkanNullDisplay(state);
496             }
497             break;
498 #    elif defined(ANGLE_PLATFORM_WINDOWS)
499             if (rx::IsVulkanWin32DisplayAvailable())
500             {
501                 impl = rx::CreateVulkanWin32Display(state);
502             }
503             break;
504 #    elif defined(ANGLE_PLATFORM_LINUX)
505 #        if defined(ANGLE_USE_GBM)
506             if (platformType == EGL_PLATFORM_GBM_KHR && rx::IsVulkanGbmDisplayAvailable())
507             {
508                 impl = rx::CreateVulkanGbmDisplay(state);
509                 break;
510             }
511 #        endif
512 #        if defined(ANGLE_USE_X11)
513             if (platformType == EGL_PLATFORM_X11_EXT && rx::IsVulkanXcbDisplayAvailable())
514             {
515                 impl = rx::CreateVulkanXcbDisplay(state);
516                 break;
517             }
518 #        endif
519 #        if defined(ANGLE_USE_WAYLAND)
520             if (platformType == EGL_PLATFORM_WAYLAND_EXT && rx::IsVulkanWaylandDisplayAvailable())
521             {
522                 impl = rx::CreateVulkanWaylandDisplay(state);
523                 break;
524             }
525 #        endif
526 #        if defined(ANGLE_USE_VULKAN_DISPLAY)
527             if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE &&
528                 rx::IsVulkanSimpleDisplayAvailable())
529             {
530                 impl = rx::CreateVulkanSimpleDisplay(state);
531             }
532             else if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE &&
533                      rx::IsVulkanHeadlessDisplayAvailable())
534             {
535                 impl = rx::CreateVulkanHeadlessDisplay(state);
536             }
537             else
538             {
539                 // Not supported creation type on vulkan display, fail display creation.
540                 impl = nullptr;
541             }
542 #        endif
543             break;
544 #    elif defined(ANGLE_PLATFORM_ANDROID)
545             if (rx::IsVulkanAndroidDisplayAvailable())
546             {
547                 impl = rx::CreateVulkanAndroidDisplay(state);
548             }
549             break;
550 #    elif defined(ANGLE_PLATFORM_FUCHSIA)
551             if (rx::IsVulkanFuchsiaDisplayAvailable())
552             {
553                 impl = rx::CreateVulkanFuchsiaDisplay(state);
554             }
555             break;
556 #    elif defined(ANGLE_PLATFORM_GGP)
557             if (rx::IsVulkanGGPDisplayAvailable())
558             {
559                 impl = rx::CreateVulkanGGPDisplay(state);
560             }
561             break;
562 #    elif defined(ANGLE_PLATFORM_APPLE)
563             if (rx::IsVulkanMacDisplayAvailable())
564             {
565                 impl = rx::CreateVulkanMacDisplay(state);
566             }
567             break;
568 #    else
569 #        error Unsupported Vulkan platform.
570 #    endif
571 #else
572             // Vulkan isn't available
573             break;
574 #endif  // defined(ANGLE_ENABLE_VULKAN)
575 
576         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
577 #if defined(ANGLE_ENABLE_METAL)
578             if (rx::IsMetalDisplayAvailable())
579             {
580                 impl = rx::CreateMetalDisplay(state);
581                 break;
582             }
583 #endif
584             // Metal isn't available.
585             break;
586 
587         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
588 #if defined(ANGLE_ENABLE_NULL)
589             impl = new rx::DisplayNULL(state);
590             break;
591 #else
592             // No display available
593             UNREACHABLE();
594             break;
595 #endif  // defined(ANGLE_ENABLE_NULL)
596 
597         default:
598             UNREACHABLE();
599             break;
600     }
601 
602     return impl;
603 }
604 
Display_logError(angle::PlatformMethods * platform,const char * errorMessage)605 void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
606 {
607     gl::Trace(gl::LOG_ERR, errorMessage);
608 }
609 
Display_logWarning(angle::PlatformMethods * platform,const char * warningMessage)610 void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
611 {
612     gl::Trace(gl::LOG_WARN, warningMessage);
613 }
614 
Display_logInfo(angle::PlatformMethods * platform,const char * infoMessage)615 void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
616 {
617     // Uncomment to get info spam
618 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
619     gl::Trace(gl::LOG_INFO, infoMessage);
620 #endif
621 }
622 
EGLStringArrayToStringVector(const char ** ary)623 const std::vector<std::string> EGLStringArrayToStringVector(const char **ary)
624 {
625     std::vector<std::string> vec;
626     if (ary != nullptr)
627     {
628         for (; *ary != nullptr; ary++)
629         {
630             vec.push_back(std::string(*ary));
631         }
632     }
633     return vec;
634 }
635 
ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)636 void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
637 {
638     angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
639 
640     ANGLEResetDisplayPlatform(display);
641     platformMethods->logError   = Display_logError;
642     platformMethods->logWarning = Display_logWarning;
643     platformMethods->logInfo    = Display_logInfo;
644 }
645 
UpdateAttribsFromEnvironment(AttributeMap & attribMap)646 void UpdateAttribsFromEnvironment(AttributeMap &attribMap)
647 {
648     EGLAttrib displayType =
649         attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
650     if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
651     {
652         displayType = GetDisplayTypeFromEnvironment();
653         attribMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType);
654     }
655     EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0);
656     if (deviceType == 0)
657     {
658         deviceType = GetDeviceTypeFromEnvironment();
659         attribMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType);
660     }
661     EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
662     if (platformType == 0)
663     {
664         platformType = GetPlatformTypeFromEnvironment();
665         attribMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType);
666     }
667 }
668 
669 static constexpr uint32_t kScratchBufferLifetime = 64u;
670 
671 }  // anonymous namespace
672 
673 // DisplayState
DisplayState(EGLNativeDisplayType nativeDisplayId)674 DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId)
675     : label(nullptr), featuresAllDisabled(false), displayId(nativeDisplayId)
676 {}
677 
~DisplayState()678 DisplayState::~DisplayState() {}
679 
680 // Note that ANGLE support on Ozone platform is limited. Our preferred support Matrix for
681 // EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following:
682 //
683 // |--------------------------------------------------------|
684 // | ANGLE type | DEVICE type |  PLATFORM type   | Display  |
685 // |--------------------------------------------------------|
686 // |   OPENGL   |     EGL     |       ANY        |   EGL    |
687 // |   OPENGL   |   HARDWARE  |     X11_EXT      |   GLX    |
688 // |  OPENGLES  |   HARDWARE  |     X11_EXT      |   GLX    |
689 // |  OPENGLES  |     EGL     |       ANY        |   EGL    |
690 // |   VULKAN   |   HARDWARE  |     X11_EXT      |  VkXcb   |
691 // |   VULKAN   | SWIFTSHADER |     X11_EXT      |  VkXcb   |
692 // |  OPENGLES  |   HARDWARE  | SURFACELESS_MESA |   EGL*   |
693 // |  OPENGLES  |   HARDWARE  |    DEVICE_EXT    |   EGL    |
694 // |   VULKAN   |   HARDWARE  | SURFACELESS_MESA | VkBase** |
695 // |   VULKAN   | SWIFTSHADER | SURFACELESS_MESA | VkBase** |
696 // |--------------------------------------------------------|
697 //
698 // * No surfaceless support yet.
699 // ** Not implemented yet.
700 //
701 // |-----------------------------------------------|
702 // |   OS    | BUILD type |  Default PLATFORM type |
703 // |-----------------------------------------------|
704 // |  Linux  |    X11     |        X11_EXT         |
705 // |  Linux  |   Ozone    |    SURFACELESS_MESA    |
706 // | Fuchsia |   Ozone    |        FUCHSIA***      |
707 // |-----------------------------------------------|
708 //
709 // *** Chosen implicitly. No EGLAttrib available.
710 //
711 // For more details, please refer to
712 // https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY
713 //
714 // static
GetDisplayFromNativeDisplay(EGLenum platform,EGLNativeDisplayType nativeDisplay,const AttributeMap & attribMap)715 Display *Display::GetDisplayFromNativeDisplay(EGLenum platform,
716                                               EGLNativeDisplayType nativeDisplay,
717                                               const AttributeMap &attribMap)
718 {
719     Display *display = nullptr;
720 
721     AttributeMap updatedAttribMap(attribMap);
722     UpdateAttribsFromEnvironment(updatedAttribMap);
723 
724     EGLAttrib powerPreference =
725         updatedAttribMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE);
726     EGLAttrib platformANGLEType =
727         updatedAttribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
728     EGLAttrib deviceIdHigh = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0);
729     EGLAttrib deviceIdLow  = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0);
730     EGLAttrib displayKey   = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DISPLAY_KEY_ANGLE, 0);
731     EGLAttrib enabledFeatureOverrides =
732         updatedAttribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0);
733     EGLAttrib disabledFeatureOverrides =
734         updatedAttribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0);
735     EGLAttrib disableAllNonOverriddenFeatures =
736         updatedAttribMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0);
737     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
738     ANGLEPlatformDisplay combinedDisplayKey(
739         nativeDisplay, powerPreference, platformANGLEType, deviceIdHigh, deviceIdLow, displayKey,
740         enabledFeatureOverrides, disabledFeatureOverrides, disableAllNonOverriddenFeatures);
741     const auto &iter = displays->find(combinedDisplayKey);
742 
743     if (iter != displays->end())
744     {
745         display = iter->second;
746     }
747 
748     if (display == nullptr)
749     {
750         // Validate the native display
751         if (!Display::isValidNativeDisplay(nativeDisplay))
752         {
753             return nullptr;
754         }
755 
756         display = new Display(platform, nativeDisplay, nullptr);
757         displays->insert(std::make_pair(combinedDisplayKey, display));
758     }
759     // Apply new attributes if the display is not initialized yet.
760     if (!display->isInitialized())
761     {
762         display->setAttributes(updatedAttribMap);
763 
764         EGLAttrib displayType  = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
765         EGLAttrib deviceType   = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
766         EGLAttrib platformType = platform;
767         if (platform == EGL_PLATFORM_ANGLE_ANGLE)
768         {
769             platformType =
770                 display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
771         }
772         rx::DisplayImpl *impl =
773             CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState());
774         if (impl == nullptr)
775         {
776             // No valid display implementation for these attributes
777             return nullptr;
778         }
779 
780 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
781         angle::gUseAndroidOpenGLTlsSlot = displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
782 #endif  // defined(ANGLE_PLATFORM_ANDROID)
783 
784         display->setupDisplayPlatform(impl);
785     }
786 
787     return display;
788 }
789 
790 // static
GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)791 Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)
792 {
793     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
794     const auto &iter                  = displays->find(nativeDisplay);
795 
796     // Check that there is a matching display
797     if (iter == displays->end())
798     {
799         return nullptr;
800     }
801 
802     return iter->second;
803 }
804 
805 // static
GetDisplayFromDevice(Device * device,const AttributeMap & attribMap)806 Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
807 {
808     Display *display = nullptr;
809 
810     ASSERT(Device::IsValidDevice(device));
811 
812     ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
813     DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
814 
815     // First see if this eglDevice is in use by a Display created using ANGLE platform
816     for (auto &displayMapEntry : *anglePlatformDisplays)
817     {
818         egl::Display *iterDisplay = displayMapEntry.second;
819         if (iterDisplay->getDevice() == device)
820         {
821             display = iterDisplay;
822         }
823     }
824 
825     if (display == nullptr)
826     {
827         // See if the eglDevice is in use by a Display created using the DEVICE platform
828         const auto &iter = devicePlatformDisplays->find(device);
829         if (iter != devicePlatformDisplays->end())
830         {
831             display = iter->second;
832         }
833     }
834 
835     if (display == nullptr)
836     {
837         // Otherwise create a new Display
838         display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
839         devicePlatformDisplays->insert(std::make_pair(device, display));
840     }
841 
842     // Apply new attributes if the display is not initialized yet.
843     if (!display->isInitialized())
844     {
845         display->setAttributes(attribMap);
846         rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
847         display->setupDisplayPlatform(impl);
848     }
849 
850     return display;
851 }
852 
853 // static
GetEglDisplaySet()854 Display::EglDisplaySet Display::GetEglDisplaySet()
855 {
856     Display::EglDisplaySet displays;
857 
858     ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
859     DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
860 
861     for (auto anglePlatformDisplayMapEntry : *anglePlatformDisplays)
862     {
863         displays.insert(anglePlatformDisplayMapEntry.second);
864     }
865 
866     for (auto devicePlatformDisplayMapEntry : *devicePlatformDisplays)
867     {
868         displays.insert(devicePlatformDisplayMapEntry.second);
869     }
870 
871     return displays;
872 }
873 
Display(EGLenum platform,EGLNativeDisplayType displayId,Device * eglDevice)874 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
875     : mState(displayId),
876       mImplementation(nullptr),
877       mGPUSwitchedBinding(this, kGPUSwitchedSubjectIndex),
878       mAttributeMap(),
879       mConfigSet(),
880       mStreamSet(),
881       mInvalidContextMap(),
882       mInvalidImageMap(),
883       mInvalidStreamSet(),
884       mInvalidSurfaceMap(),
885       mInvalidSyncMap(),
886       mInitialized(false),
887       mDeviceLost(false),
888       mCaps(),
889       mDisplayExtensions(),
890       mDisplayExtensionString(),
891       mVendorString(),
892       mVersionString(),
893       mDevice(eglDevice),
894       mSurface(nullptr),
895       mPlatform(platform),
896       mManagersMutex(nullptr),
897       mTextureManager(nullptr),
898       mSemaphoreManager(nullptr),
899       mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes),
900       mMemoryProgramCache(mBlobCache),
901       mMemoryShaderCache(mBlobCache),
902       mGlobalTextureShareGroupUsers(0),
903       mGlobalSemaphoreShareGroupUsers(0),
904       mTerminatedByApi(false),
905       mActiveThreads(),
906       mSingleThreadPool(nullptr),
907       mMultiThreadPool(nullptr)
908 {}
909 
~Display()910 Display::~Display()
911 {
912     switch (mPlatform)
913     {
914         case EGL_PLATFORM_ANGLE_ANGLE:
915         case EGL_PLATFORM_GBM_KHR:
916         case EGL_PLATFORM_WAYLAND_EXT:
917         {
918             ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
919             ANGLEPlatformDisplayMap::iterator iter = displays->find(ANGLEPlatformDisplay(
920                 mState.displayId,
921                 mAttributeMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE),
922                 mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
923                                   EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
924                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0),
925                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0),
926                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DISPLAY_KEY_ANGLE, 0),
927                 mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0),
928                 mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0),
929                 mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0)));
930             if (iter != displays->end())
931             {
932                 displays->erase(iter);
933             }
934             break;
935         }
936         case EGL_PLATFORM_DEVICE_EXT:
937         {
938             DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
939             DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
940             if (iter != displays->end())
941             {
942                 displays->erase(iter);
943             }
944             break;
945         }
946         default:
947         {
948             UNREACHABLE();
949         }
950     }
951 
952     SafeDelete(mDevice);
953     SafeDelete(mImplementation);
954 }
955 
setLabel(EGLLabelKHR label)956 void Display::setLabel(EGLLabelKHR label)
957 {
958     mState.label = label;
959 }
960 
getLabel() const961 EGLLabelKHR Display::getLabel() const
962 {
963     return mState.label;
964 }
965 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)966 void Display::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
967 {
968     ASSERT(index == kGPUSwitchedSubjectIndex);
969     ASSERT(message == angle::SubjectMessage::SubjectChanged);
970     for (auto context : mState.contextMap)
971     {
972         context.second->onGPUSwitch();
973     }
974 }
975 
setupDisplayPlatform(rx::DisplayImpl * impl)976 void Display::setupDisplayPlatform(rx::DisplayImpl *impl)
977 {
978     ASSERT(!mInitialized);
979 
980     ASSERT(impl != nullptr);
981     SafeDelete(mImplementation);
982     mImplementation = impl;
983 
984     // TODO(anglebug.com/7365): Remove PlatformMethods.
985     const angle::PlatformMethods *platformMethods =
986         reinterpret_cast<const angle::PlatformMethods *>(
987             mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
988     if (platformMethods != nullptr)
989     {
990         *ANGLEPlatformCurrent() = *platformMethods;
991     }
992     else
993     {
994         ANGLESetDefaultDisplayPlatform(this);
995     }
996 
997     const char **featuresForceEnabled =
998         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0));
999     const char **featuresForceDisabled =
1000         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0));
1001     mState.featureOverridesEnabled  = EGLStringArrayToStringVector(featuresForceEnabled);
1002     mState.featureOverridesDisabled = EGLStringArrayToStringVector(featuresForceDisabled);
1003     mState.featuresAllDisabled =
1004         static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0));
1005     mImplementation->addObserver(&mGPUSwitchedBinding);
1006 }
1007 
initialize()1008 Error Display::initialize()
1009 {
1010     mTerminatedByApi = false;
1011 
1012     ASSERT(mImplementation != nullptr);
1013     mImplementation->setBlobCache(&mBlobCache);
1014 
1015     // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
1016     // properly saved & restored on all platforms. The cache won't allocate space until it's used
1017     // and will be ignored entirely if the application / system sets it's own cache functions.
1018     if (rx::ShouldUseDebugLayers(mAttributeMap))
1019     {
1020         mBlobCache.resize(1024 * 1024);
1021     }
1022 
1023     setGlobalDebugAnnotator();
1024 
1025     gl::InitializeDebugMutexIfNeeded();
1026 
1027     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
1028 
1029     if (isInitialized())
1030     {
1031         return NoError();
1032     }
1033 
1034     Error error = mImplementation->initialize(this);
1035     if (error.isError())
1036     {
1037         // Log extended error message here
1038         ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
1039         return error;
1040     }
1041 
1042     mCaps = mImplementation->getCaps();
1043 
1044     mConfigSet = mImplementation->generateConfigs();
1045     if (mConfigSet.size() == 0)
1046     {
1047         mImplementation->terminate();
1048         return EglNotInitialized() << "No configs were generated.";
1049     }
1050 
1051     // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs
1052     for (auto &config : mConfigSet)
1053     {
1054         // TODO(geofflang): Enable the conformant bit once we pass enough tests
1055         // config.second.conformant |= EGL_OPENGL_ES_BIT;
1056 
1057         config.second.renderableType |= EGL_OPENGL_ES_BIT;
1058 
1059         // If we aren't using desktop GL entry points, remove desktop GL support from all configs
1060 #if !defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)
1061         config.second.renderableType &= ~EGL_OPENGL_BIT;
1062 #endif
1063     }
1064 
1065     mFrontendFeatures.reset();
1066     if (!mState.featuresAllDisabled)
1067     {
1068         initializeFrontendFeatures();
1069     }
1070 
1071     mFeatures.clear();
1072     mFrontendFeatures.populateFeatureList(&mFeatures);
1073     mImplementation->populateFeatureList(&mFeatures);
1074 
1075     initDisplayExtensions();
1076     initVendorString();
1077     initVersionString();
1078     initClientAPIString();
1079 
1080     // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
1081     if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
1082     {
1083         // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
1084         // an external device
1085         ASSERT(mDevice != nullptr);
1086     }
1087     else if (GetClientExtensions().deviceQueryEXT)
1088     {
1089         std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice());
1090         ASSERT(impl);
1091         error = impl->initialize();
1092         if (error.isError())
1093         {
1094             ERR() << "Failed to initialize display because device creation failed: "
1095                   << error.getMessage();
1096             mImplementation->terminate();
1097             return error;
1098         }
1099         // Don't leak Device memory.
1100         ASSERT(mDevice == nullptr);
1101         mDevice = new Device(this, impl.release());
1102     }
1103     else
1104     {
1105         mDevice = nullptr;
1106     }
1107 
1108     mSingleThreadPool = angle::WorkerThreadPool::Create(1, ANGLEPlatformCurrent());
1109     mMultiThreadPool  = angle::WorkerThreadPool::Create(0, ANGLEPlatformCurrent());
1110 
1111     if (kIsSharedContextMutexEnabled)
1112     {
1113         ASSERT(!mSharedContextMutexManager);
1114         mSharedContextMutexManager.reset(new SharedContextMutexManager<ContextMutexType>());
1115 
1116         ASSERT(mManagersMutex == nullptr);
1117         mManagersMutex = mSharedContextMutexManager->create();
1118         mManagersMutex->addRef();
1119     }
1120 
1121     mInitialized = true;
1122 
1123     return NoError();
1124 }
1125 
destroyInvalidEglObjects()1126 Error Display::destroyInvalidEglObjects()
1127 {
1128     // Destroy invalid EGL objects
1129     while (!mInvalidContextMap.empty())
1130     {
1131         gl::Context *context = mInvalidContextMap.begin()->second;
1132         // eglReleaseThread() may call to this method when there are still Contexts, that may
1133         // potentially acces shared state of the "context".
1134         // Need AddRefLock because there may be ContextMutex destruction.
1135         ScopedContextMutexAddRefLock lock(context->getContextMutex());
1136         context->setIsDestroyed();
1137         ANGLE_TRY(releaseContextImpl(context, &mInvalidContextMap));
1138     }
1139 
1140     while (!mInvalidImageMap.empty())
1141     {
1142         destroyImageImpl(mInvalidImageMap.begin()->second, &mInvalidImageMap);
1143     }
1144 
1145     while (!mInvalidStreamSet.empty())
1146     {
1147         destroyStreamImpl(*mInvalidStreamSet.begin(), &mInvalidStreamSet);
1148     }
1149 
1150     while (!mInvalidSurfaceMap.empty())
1151     {
1152         ANGLE_TRY(destroySurfaceImpl(mInvalidSurfaceMap.begin()->second, &mInvalidSurfaceMap));
1153     }
1154 
1155     while (!mInvalidSyncMap.empty())
1156     {
1157         destroySyncImpl(mInvalidSyncMap.begin()->second, &mInvalidSyncMap);
1158     }
1159 
1160     return NoError();
1161 }
1162 
terminate(Thread * thread,TerminateReason terminateReason)1163 Error Display::terminate(Thread *thread, TerminateReason terminateReason)
1164 {
1165     if (terminateReason == TerminateReason::Api)
1166     {
1167         mTerminatedByApi = true;
1168 
1169         // Remove thread from active thread set if there is no context current.
1170         if (thread->getContext() == nullptr)
1171         {
1172             mActiveThreads.erase(thread);
1173         }
1174     }
1175 
1176     // All subsequent calls assume the display to be valid and terminated by app.
1177     // If it is not terminated or if it isn't even initialized, early return.
1178     if (!mTerminatedByApi || !mInitialized)
1179     {
1180         return NoError();
1181     }
1182 
1183     // EGL 1.5 Specification
1184     // 3.2 Initialization
1185     // Termination marks all EGL-specific resources, such as contexts and surfaces, associated
1186     // with the specified display for deletion. Handles to all such resources are invalid as soon
1187     // as eglTerminate returns. Cache EGL objects that are no longer valid.
1188     //
1189     // It is fairly common for apps to call eglTerminate while some contexts and/or surfaces are
1190     // still current on some thread. Since objects are refCounted, trying to destroy them right away
1191     // would only result in a decRef. We instead cache such invalid objects and use other EGL
1192     // entrypoints like eglReleaseThread or thread exit events (on the Android platform) to
1193     // perform the necessary cleanup.
1194     mInvalidImageMap.insert(mImageMap.begin(), mImageMap.end());
1195     mImageMap.clear();
1196 
1197     mInvalidStreamSet.insert(mStreamSet.begin(), mStreamSet.end());
1198     mStreamSet.clear();
1199 
1200     mInvalidSurfaceMap.insert(mState.surfaceMap.begin(), mState.surfaceMap.end());
1201     mState.surfaceMap.clear();
1202 
1203     mInvalidSyncMap.insert(mSyncMap.begin(), mSyncMap.end());
1204     mSyncMap.clear();
1205 
1206     // Cache total number of contexts before invalidation. This is used as a check to verify that
1207     // no context is "lost" while being moved between the various sets.
1208     size_t contextSetSizeBeforeInvalidation = mState.contextMap.size() + mInvalidContextMap.size();
1209 
1210     // If app called eglTerminate and no active threads remain,
1211     // force release any context that is still current.
1212     ContextMap contextsStillCurrent = {};
1213     for (auto context : mState.contextMap)
1214     {
1215         if (context.second->isReferenced())
1216         {
1217             if (terminateReason == TerminateReason::NoActiveThreads)
1218             {
1219                 ASSERT(mTerminatedByApi);
1220                 context.second->release();
1221                 (void)context.second->unMakeCurrent(this);
1222             }
1223             else
1224             {
1225                 contextsStillCurrent.emplace(context);
1226                 continue;
1227             }
1228         }
1229 
1230         // Add context that is not current to mInvalidContextSet for cleanup.
1231         mInvalidContextMap.emplace(context);
1232     }
1233 
1234     // There are many methods that require contexts that are still current to be present in
1235     // display's contextSet like during context release or to notify of state changes in a subject.
1236     // So as to not interrupt this flow, do not remove contexts that are still current on some
1237     // thread from display's contextSet even though eglTerminate marks such contexts as invalid.
1238     //
1239     // "mState.contextSet" will now contain only those contexts that are still current on some
1240     // thread.
1241     mState.contextMap = std::move(contextsStillCurrent);
1242 
1243     // Assert that the total number of contexts is the same before and after context invalidation.
1244     ASSERT(contextSetSizeBeforeInvalidation ==
1245            mState.contextMap.size() + mInvalidContextMap.size());
1246 
1247     if (!mState.contextMap.empty())
1248     {
1249         // There was atleast 1 context that was current on some thread, early return.
1250         return NoError();
1251     }
1252 
1253     // The global texture and semaphore managers should be deleted with the last context that uses
1254     // it.
1255     ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
1256     ASSERT(mGlobalSemaphoreShareGroupUsers == 0 && mSemaphoreManager == nullptr);
1257 
1258     mSharedContextMutexManager.reset();
1259 
1260     if (mManagersMutex != nullptr)
1261     {
1262         mManagersMutex->release();
1263         mManagersMutex = nullptr;
1264     }
1265 
1266     // Clean up all invalid objects
1267     ANGLE_TRY(destroyInvalidEglObjects());
1268 
1269     mConfigSet.clear();
1270 
1271     if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
1272     {
1273         // Don't delete the device if it was created externally using eglCreateDeviceANGLE
1274         // We also shouldn't set it to null in case eglInitialize() is called again later
1275         SafeDelete(mDevice);
1276     }
1277 
1278     // Before tearing down the backend device, ensure all deferred operations are run.  It is not
1279     // possible to defer them beyond this point.
1280     GetCurrentThreadUnlockedTailCall()->run();
1281 
1282     mImplementation->terminate();
1283 
1284     mMemoryProgramCache.clear();
1285     mMemoryShaderCache.clear();
1286     mBlobCache.setBlobCacheFuncs(nullptr, nullptr);
1287 
1288     mSingleThreadPool.reset();
1289     mMultiThreadPool.reset();
1290 
1291     mDeviceLost = false;
1292 
1293     mInitialized = false;
1294 
1295     gl::UninitializeDebugAnnotations();
1296 
1297     // TODO(jmadill): Store Platform in Display and deinit here.
1298     ANGLEResetDisplayPlatform(this);
1299 
1300     return NoError();
1301 }
1302 
prepareForCall()1303 Error Display::prepareForCall()
1304 {
1305     return mImplementation->prepareForCall();
1306 }
1307 
releaseThread()1308 Error Display::releaseThread()
1309 {
1310     // Need to check if initialized, because makeCurrent() may terminate the Display.
1311     if (!mInitialized)
1312     {
1313         return NoError();
1314     }
1315     ANGLE_TRY(mImplementation->releaseThread());
1316     return destroyInvalidEglObjects();
1317 }
1318 
addActiveThread(Thread * thread)1319 void Display::addActiveThread(Thread *thread)
1320 {
1321     mActiveThreads.insert(thread);
1322 }
1323 
threadCleanup(Thread * thread)1324 void Display::threadCleanup(Thread *thread)
1325 {
1326     mActiveThreads.erase(thread);
1327     const bool noActiveThreads = mActiveThreads.size() == 0;
1328 
1329     (void)terminate(thread, noActiveThreads ? TerminateReason::NoActiveThreads
1330                                             : TerminateReason::InternalCleanup);
1331 
1332     // This "thread" is no longer active, reset its cached context
1333     thread->setCurrent(nullptr);
1334 }
1335 
getConfigs(const egl::AttributeMap & attribs) const1336 std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
1337 {
1338     return mConfigSet.filter(attribs);
1339 }
1340 
chooseConfig(const egl::AttributeMap & attribs) const1341 std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
1342 {
1343     egl::AttributeMap attribsWithDefaults = AttributeMap();
1344 
1345     // Insert default values for attributes that have either an Exact or Mask selection criteria,
1346     // and a default value that matters (e.g. isn't EGL_DONT_CARE):
1347     attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
1348     attribsWithDefaults.insert(EGL_LEVEL, 0);
1349     attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
1350     attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
1351     attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
1352     if (getExtensions().pixelFormatFloat)
1353     {
1354         attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
1355                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
1356     }
1357 
1358     // Add the caller-specified values (Note: the poorly-named insert() method will replace any
1359     // of the default values from above):
1360     for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
1361     {
1362         attribsWithDefaults.insert(attribIter->first, attribIter->second);
1363     }
1364 
1365     return mConfigSet.filter(attribsWithDefaults);
1366 }
1367 
createWindowSurface(const Config * configuration,EGLNativeWindowType window,const AttributeMap & attribs,Surface ** outSurface)1368 Error Display::createWindowSurface(const Config *configuration,
1369                                    EGLNativeWindowType window,
1370                                    const AttributeMap &attribs,
1371                                    Surface **outSurface)
1372 {
1373     if (mImplementation->testDeviceLost())
1374     {
1375         ANGLE_TRY(restoreLostDevice());
1376     }
1377 
1378     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1379     SurfacePointer surface(new WindowSurface(mImplementation, id, configuration, window, attribs,
1380                                              mFrontendFeatures.forceRobustResourceInit.enabled),
1381                            this);
1382     ANGLE_TRY(surface->initialize(this));
1383 
1384     ASSERT(outSurface != nullptr);
1385     *outSurface = surface.release();
1386     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1387 
1388     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1389     ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
1390     windowSurfaces->insert(std::make_pair(window, *outSurface));
1391 
1392     mSurface = *outSurface;
1393 
1394     return NoError();
1395 }
1396 
createPbufferSurface(const Config * configuration,const AttributeMap & attribs,Surface ** outSurface)1397 Error Display::createPbufferSurface(const Config *configuration,
1398                                     const AttributeMap &attribs,
1399                                     Surface **outSurface)
1400 {
1401     ASSERT(isInitialized());
1402 
1403     if (mImplementation->testDeviceLost())
1404     {
1405         ANGLE_TRY(restoreLostDevice());
1406     }
1407 
1408     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1409     SurfacePointer surface(new PbufferSurface(mImplementation, id, configuration, attribs,
1410                                               mFrontendFeatures.forceRobustResourceInit.enabled),
1411                            this);
1412     ANGLE_TRY(surface->initialize(this));
1413 
1414     ASSERT(outSurface != nullptr);
1415     *outSurface = surface.release();
1416     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1417 
1418     return NoError();
1419 }
1420 
createPbufferFromClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,Surface ** outSurface)1421 Error Display::createPbufferFromClientBuffer(const Config *configuration,
1422                                              EGLenum buftype,
1423                                              EGLClientBuffer clientBuffer,
1424                                              const AttributeMap &attribs,
1425                                              Surface **outSurface)
1426 {
1427     ASSERT(isInitialized());
1428 
1429     if (mImplementation->testDeviceLost())
1430     {
1431         ANGLE_TRY(restoreLostDevice());
1432     }
1433 
1434     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1435     SurfacePointer surface(
1436         new PbufferSurface(mImplementation, id, configuration, buftype, clientBuffer, attribs,
1437                            mFrontendFeatures.forceRobustResourceInit.enabled),
1438         this);
1439     ANGLE_TRY(surface->initialize(this));
1440 
1441     ASSERT(outSurface != nullptr);
1442     *outSurface = surface.release();
1443     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1444 
1445     return NoError();
1446 }
1447 
createPixmapSurface(const Config * configuration,NativePixmapType nativePixmap,const AttributeMap & attribs,Surface ** outSurface)1448 Error Display::createPixmapSurface(const Config *configuration,
1449                                    NativePixmapType nativePixmap,
1450                                    const AttributeMap &attribs,
1451                                    Surface **outSurface)
1452 {
1453     ASSERT(isInitialized());
1454 
1455     if (mImplementation->testDeviceLost())
1456     {
1457         ANGLE_TRY(restoreLostDevice());
1458     }
1459 
1460     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1461     SurfacePointer surface(
1462         new PixmapSurface(mImplementation, id, configuration, nativePixmap, attribs,
1463                           mFrontendFeatures.forceRobustResourceInit.enabled),
1464         this);
1465     ANGLE_TRY(surface->initialize(this));
1466 
1467     ASSERT(outSurface != nullptr);
1468     *outSurface = surface.release();
1469     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1470 
1471     return NoError();
1472 }
1473 
createImage(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attribs,Image ** outImage)1474 Error Display::createImage(const gl::Context *context,
1475                            EGLenum target,
1476                            EGLClientBuffer buffer,
1477                            const AttributeMap &attribs,
1478                            Image **outImage)
1479 {
1480     ASSERT(isInitialized());
1481 
1482     if (mImplementation->testDeviceLost())
1483     {
1484         ANGLE_TRY(restoreLostDevice());
1485     }
1486 
1487     egl::ImageSibling *sibling = nullptr;
1488     if (IsTextureTarget(target))
1489     {
1490         sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1491     }
1492     else if (IsRenderbufferTarget(target))
1493     {
1494         sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1495     }
1496     else if (IsExternalImageTarget(target))
1497     {
1498         sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
1499     }
1500     else
1501     {
1502         UNREACHABLE();
1503     }
1504     ASSERT(sibling != nullptr);
1505 
1506     ImageID id = {mImageHandleAllocator.allocate()};
1507     angle::UniqueObjectPointer<Image, Display> imagePtr(
1508         new Image(mImplementation, id, context, target, sibling, attribs), this);
1509     ANGLE_TRY(imagePtr->initialize(this, context));
1510 
1511     Image *image = imagePtr.release();
1512 
1513     ASSERT(outImage != nullptr);
1514     *outImage = image;
1515 
1516     // Add this image to the list of all images and hold a ref to it.
1517     image->addRef();
1518     mImageMap.insert(std::pair(image->id().value, image));
1519 
1520     return NoError();
1521 }
1522 
createStream(const AttributeMap & attribs,Stream ** outStream)1523 Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
1524 {
1525     ASSERT(isInitialized());
1526 
1527     Stream *stream = new Stream(this, attribs);
1528 
1529     ASSERT(stream != nullptr);
1530     mStreamSet.insert(stream);
1531 
1532     ASSERT(outStream != nullptr);
1533     *outStream = stream;
1534 
1535     return NoError();
1536 }
1537 
createContext(const Config * configuration,gl::Context * shareContext,EGLenum clientType,const AttributeMap & attribs,gl::Context ** outContext)1538 Error Display::createContext(const Config *configuration,
1539                              gl::Context *shareContext,
1540                              EGLenum clientType,
1541                              const AttributeMap &attribs,
1542                              gl::Context **outContext)
1543 {
1544     ASSERT(!mTerminatedByApi);
1545     ASSERT(isInitialized());
1546 
1547     if (mImplementation->testDeviceLost())
1548     {
1549         ANGLE_TRY(restoreLostDevice());
1550     }
1551 
1552     // This display texture sharing will allow the first context to create the texture share group.
1553     bool usingDisplayTextureShareGroup =
1554         attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1555     gl::TextureManager *shareTextures = nullptr;
1556 
1557     if (usingDisplayTextureShareGroup)
1558     {
1559         ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
1560         if (mTextureManager == nullptr)
1561         {
1562             mTextureManager = new gl::TextureManager();
1563         }
1564 
1565         mGlobalTextureShareGroupUsers++;
1566         shareTextures = mTextureManager;
1567     }
1568 
1569     // This display semaphore sharing will allow the first context to create the semaphore share
1570     // group.
1571     bool usingDisplaySemaphoreShareGroup =
1572         attribs.get(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1573     gl::SemaphoreManager *shareSemaphores = nullptr;
1574     if (usingDisplaySemaphoreShareGroup)
1575     {
1576         ASSERT((mSemaphoreManager == nullptr) == (mGlobalSemaphoreShareGroupUsers == 0));
1577         if (mSemaphoreManager == nullptr)
1578         {
1579             mSemaphoreManager = new gl::SemaphoreManager();
1580         }
1581 
1582         mGlobalSemaphoreShareGroupUsers++;
1583         shareSemaphores = mSemaphoreManager;
1584     }
1585 
1586     ContextMutex *sharedContextMutex = nullptr;
1587     if (kIsSharedContextMutexEnabled)
1588     {
1589         if (shareContext != nullptr)
1590         {
1591             ASSERT(shareContext->isSharedContextMutexActive());
1592             sharedContextMutex = shareContext->getContextMutex();
1593         }
1594         else if (shareTextures != nullptr || shareSemaphores != nullptr)
1595         {
1596             sharedContextMutex = mManagersMutex;
1597         }
1598         // When using shareTextures/Semaphores all Contexts in the Group must use mManagersMutex.
1599         ASSERT(mManagersMutex != nullptr);
1600         ASSERT((shareTextures == nullptr && shareSemaphores == nullptr) ||
1601                sharedContextMutex == mManagersMutex);
1602     }
1603 
1604     gl::MemoryProgramCache *programCachePointer = &mMemoryProgramCache;
1605     // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
1606     // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
1607     // at any time.
1608     bool usesProgramCacheControl = attribs.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
1609     if (usesProgramCacheControl)
1610     {
1611         bool programCacheControlEnabled =
1612             (attribs.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) == GL_TRUE);
1613         // A program cache size of zero indicates it should be disabled.
1614         if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
1615         {
1616             programCachePointer = nullptr;
1617         }
1618     }
1619 
1620     gl::MemoryShaderCache *shaderCachePointer = &mMemoryShaderCache;
1621     // Check if shader caching frontend feature is enabled.
1622     if (!mFrontendFeatures.cacheCompiledShader.enabled)
1623     {
1624         shaderCachePointer = nullptr;
1625     }
1626 
1627     gl::Context *context =
1628         new gl::Context(this, configuration, shareContext, shareTextures, shareSemaphores,
1629                         sharedContextMutex, programCachePointer, shaderCachePointer, clientType,
1630                         attribs, mDisplayExtensions, GetClientExtensions());
1631     Error error = context->initialize();
1632     if (error.isError())
1633     {
1634         delete context;
1635         return error;
1636     }
1637 
1638     if (shareContext != nullptr)
1639     {
1640         shareContext->setShared();
1641     }
1642 
1643     ASSERT(context != nullptr);
1644     mState.contextMap.insert(std::pair(context->id().value, context));
1645 
1646     ASSERT(outContext != nullptr);
1647     *outContext = context;
1648     return NoError();
1649 }
1650 
createSync(const gl::Context * currentContext,EGLenum type,const AttributeMap & attribs,Sync ** outSync)1651 Error Display::createSync(const gl::Context *currentContext,
1652                           EGLenum type,
1653                           const AttributeMap &attribs,
1654                           Sync **outSync)
1655 {
1656     ASSERT(isInitialized());
1657 
1658     SyncID id = {mSyncHandleAllocator.allocate()};
1659 
1660     if (mImplementation->testDeviceLost())
1661     {
1662         ANGLE_TRY(restoreLostDevice());
1663     }
1664 
1665     angle::UniqueObjectPointer<egl::Sync, Display> syncPtr(
1666         new Sync(mImplementation, id, type, attribs), this);
1667 
1668     ANGLE_TRY(syncPtr->initialize(this, currentContext));
1669 
1670     Sync *sync = syncPtr.release();
1671 
1672     sync->addRef();
1673     mSyncMap.insert(std::pair(sync->id().value, sync));
1674 
1675     *outSync = sync;
1676     return NoError();
1677 }
1678 
makeCurrent(Thread * thread,gl::Context * previousContext,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)1679 Error Display::makeCurrent(Thread *thread,
1680                            gl::Context *previousContext,
1681                            egl::Surface *drawSurface,
1682                            egl::Surface *readSurface,
1683                            gl::Context *context)
1684 {
1685     if (!mInitialized)
1686     {
1687         return NoError();
1688     }
1689 
1690     bool contextChanged = context != previousContext;
1691     if (previousContext != nullptr && contextChanged)
1692     {
1693         // Need AddRefLock because there may be ContextMutex destruction.
1694         ScopedContextMutexAddRefLock lock(previousContext->getContextMutex());
1695 
1696         previousContext->release();
1697         thread->setCurrent(nullptr);
1698 
1699         auto error = previousContext->unMakeCurrent(this);
1700         if (!previousContext->isReferenced() && previousContext->isDestroyed())
1701         {
1702             // The previous Context may have been created with a different Display.
1703             Display *previousDisplay = previousContext->getDisplay();
1704             ANGLE_TRY(previousDisplay->releaseContext(previousContext, thread));
1705         }
1706         ANGLE_TRY(error);
1707     }
1708 
1709     {
1710         ASSERT(context == nullptr || context->getContextMutex() != nullptr);
1711         ScopedContextMutexLock lock(context != nullptr ? context->getContextMutex() : nullptr,
1712                                     context, kContextMutexMayBeNull);
1713 
1714         thread->setCurrent(context);
1715 
1716         ANGLE_TRY(mImplementation->makeCurrent(this, drawSurface, readSurface, context));
1717 
1718         if (context != nullptr)
1719         {
1720             ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface));
1721             if (contextChanged)
1722             {
1723                 context->addRef();
1724             }
1725         }
1726     }
1727 
1728     // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being
1729     // used.
1730     {
1731         std::lock_guard<std::mutex> lock(mScratchBufferMutex);
1732 
1733         for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers)
1734         {
1735             scatchBuffer.tick();
1736         }
1737         for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers)
1738         {
1739             zeroFilledBuffer.tick();
1740         }
1741     }
1742 
1743     // If eglTerminate() has previously been called and Context was changed, perform InternalCleanup
1744     // to invalidate any non-current Contexts, and possibly fully terminate the Display and release
1745     // all of its resources.
1746     if (mTerminatedByApi && contextChanged)
1747     {
1748         return terminate(thread, TerminateReason::InternalCleanup);
1749     }
1750 
1751     return NoError();
1752 }
1753 
restoreLostDevice()1754 Error Display::restoreLostDevice()
1755 {
1756     for (ContextMap::iterator ctx = mState.contextMap.begin(); ctx != mState.contextMap.end();
1757          ctx++)
1758     {
1759         if (ctx->second->isResetNotificationEnabled())
1760         {
1761             // If reset notifications have been requested, application must delete all contexts
1762             // first
1763             return EglContextLost();
1764         }
1765     }
1766 
1767     return mImplementation->restoreLostDevice(this);
1768 }
1769 
destroySurfaceImpl(Surface * surface,SurfaceMap * surfaces)1770 Error Display::destroySurfaceImpl(Surface *surface, SurfaceMap *surfaces)
1771 {
1772     if (surface->getType() == EGL_WINDOW_BIT)
1773     {
1774         WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1775         ASSERT(windowSurfaces);
1776 
1777         bool surfaceRemoved = false;
1778         for (WindowSurfaceMap::iterator iter = windowSurfaces->begin();
1779              iter != windowSurfaces->end(); iter++)
1780         {
1781             if (iter->second == surface)
1782             {
1783                 windowSurfaces->erase(iter);
1784                 surfaceRemoved = true;
1785                 break;
1786             }
1787         }
1788 
1789         ASSERT(surfaceRemoved);
1790     }
1791 
1792     auto iter = surfaces->find(surface->id().value);
1793     ASSERT(iter != surfaces->end());
1794     mSurfaceHandleAllocator.release(surface->id().value);
1795     surfaces->erase(iter);
1796     ANGLE_TRY(surface->onDestroy(this));
1797     return NoError();
1798 }
1799 
destroyImageImpl(Image * image,ImageMap * images)1800 void Display::destroyImageImpl(Image *image, ImageMap *images)
1801 {
1802     auto iter = images->find(image->id().value);
1803     ASSERT(iter != images->end());
1804     mImageHandleAllocator.release(image->id().value);
1805     {
1806         // Need AddRefLock because there may be ContextMutex destruction.
1807         ScopedContextMutexAddRefLock lock(image->getSharedContextMutex(), kContextMutexMayBeNull);
1808         iter->second->release(this);
1809     }
1810     images->erase(iter);
1811 }
1812 
destroyStreamImpl(Stream * stream,StreamSet * streams)1813 void Display::destroyStreamImpl(Stream *stream, StreamSet *streams)
1814 {
1815     streams->erase(stream);
1816     SafeDelete(stream);
1817 }
1818 
1819 // releaseContext must be called with the context being deleted as current.
1820 // To do that we can only call this in two places, Display::makeCurrent at the point where this
1821 // context is being made uncurrent and in Display::destroyContext where we make the context current
1822 // as part of destruction.
releaseContext(gl::Context * context,Thread * thread)1823 Error Display::releaseContext(gl::Context *context, Thread *thread)
1824 {
1825     return releaseContextImpl(context, &mState.contextMap);
1826 }
1827 
releaseContextImpl(gl::Context * context,ContextMap * contexts)1828 Error Display::releaseContextImpl(gl::Context *context, ContextMap *contexts)
1829 {
1830     ASSERT(!context->isReferenced());
1831 
1832     // Use scoped_ptr to make sure the context is always freed.
1833     std::unique_ptr<gl::Context> unique_context(context);
1834     ASSERT(contexts->find(context->id().value) != contexts->end());
1835     contexts->erase(context->id().value);
1836 
1837     if (context->usingDisplayTextureShareGroup())
1838     {
1839         ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
1840         if (mGlobalTextureShareGroupUsers == 1)
1841         {
1842             // If this is the last context using the global share group, destroy the global
1843             // texture manager so that the textures can be destroyed while a context still
1844             // exists
1845             mTextureManager->release(context);
1846             mTextureManager = nullptr;
1847         }
1848         mGlobalTextureShareGroupUsers--;
1849     }
1850 
1851     if (context->usingDisplaySemaphoreShareGroup())
1852     {
1853         ASSERT(mGlobalSemaphoreShareGroupUsers >= 1 && mSemaphoreManager != nullptr);
1854         if (mGlobalSemaphoreShareGroupUsers == 1)
1855         {
1856             // If this is the last context using the global share group, destroy the global
1857             // semaphore manager so that the semaphores can be destroyed while a context still
1858             // exists
1859             mSemaphoreManager->release(context);
1860             mSemaphoreManager = nullptr;
1861         }
1862         mGlobalSemaphoreShareGroupUsers--;
1863     }
1864 
1865     ANGLE_TRY(context->onDestroy(this));
1866 
1867     return NoError();
1868 }
1869 
destroyContext(Thread * thread,gl::Context * context)1870 Error Display::destroyContext(Thread *thread, gl::Context *context)
1871 {
1872     auto *currentContext     = thread->getContext();
1873     auto *currentDrawSurface = thread->getCurrentDrawSurface();
1874     auto *currentReadSurface = thread->getCurrentReadSurface();
1875 
1876     context->setIsDestroyed();
1877 
1878     // If the context is still current on at least 1 thread, just return since it'll be released
1879     // once no threads have it current anymore.
1880     if (context->isReferenced())
1881     {
1882         return NoError();
1883     }
1884 
1885     // For external context, we cannot change the current native context, and the API user should
1886     // make sure the native context is current.
1887     if (context->isExternal())
1888     {
1889         // Need AddRefLock because there may be ContextMutex destruction.
1890         ScopedContextMutexAddRefLock lock(context->getContextMutex());
1891         ANGLE_TRY(releaseContext(context, thread));
1892     }
1893     else
1894     {
1895         // Keep |currentContext| alive, while releasing |context|.
1896         gl::ScopedContextRef scopedContextRef(currentContext);
1897 
1898         // keep |currentDrawSurface| and |currentReadSurface| alive as well
1899         // while releasing |context|.
1900         ScopedSurfaceRef drawSurfaceRef(currentDrawSurface);
1901         ScopedSurfaceRef readSurfaceRef(
1902             currentReadSurface == currentDrawSurface ? nullptr : currentReadSurface);
1903 
1904         // Make the context current, so we can release resources belong to the context, and then
1905         // when context is released from the current, it will be destroyed.
1906         // TODO(http://www.anglebug.com/6322): Don't require a Context to be current in order to
1907         // destroy it.
1908         ANGLE_TRY(makeCurrent(thread, currentContext, nullptr, nullptr, context));
1909         ANGLE_TRY(
1910             makeCurrent(thread, context, currentDrawSurface, currentReadSurface, currentContext));
1911     }
1912 
1913     return NoError();
1914 }
1915 
destroySyncImpl(Sync * sync,SyncMap * syncs)1916 void Display::destroySyncImpl(Sync *sync, SyncMap *syncs)
1917 {
1918     auto iter = syncs->find(sync->id().value);
1919     ASSERT(iter != syncs->end());
1920     mSyncHandleAllocator.release(sync->id().value);
1921     iter->second->release(this);
1922     syncs->erase(iter);
1923 }
1924 
destroyImage(Image * image)1925 void Display::destroyImage(Image *image)
1926 {
1927     return destroyImageImpl(image, &mImageMap);
1928 }
1929 
destroyStream(Stream * stream)1930 void Display::destroyStream(Stream *stream)
1931 {
1932     return destroyStreamImpl(stream, &mStreamSet);
1933 }
1934 
destroySurface(Surface * surface)1935 Error Display::destroySurface(Surface *surface)
1936 {
1937     return destroySurfaceImpl(surface, &mState.surfaceMap);
1938 }
1939 
destroySync(Sync * sync)1940 void Display::destroySync(Sync *sync)
1941 {
1942     return destroySyncImpl(sync, &mSyncMap);
1943 }
1944 
isDeviceLost() const1945 bool Display::isDeviceLost() const
1946 {
1947     ASSERT(isInitialized());
1948     return mDeviceLost;
1949 }
1950 
testDeviceLost()1951 bool Display::testDeviceLost()
1952 {
1953     ASSERT(isInitialized());
1954 
1955     if (!mDeviceLost && mImplementation->testDeviceLost())
1956     {
1957         notifyDeviceLost();
1958     }
1959 
1960     return mDeviceLost;
1961 }
1962 
notifyDeviceLost()1963 void Display::notifyDeviceLost()
1964 {
1965     if (mDeviceLost)
1966     {
1967         return;
1968     }
1969 
1970     for (auto context = mState.contextMap.begin(); context != mState.contextMap.end(); context++)
1971     {
1972         context->second->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
1973     }
1974 
1975     mDeviceLost = true;
1976 }
1977 
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)1978 void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
1979 {
1980     mBlobCache.setBlobCacheFuncs(set, get);
1981     mImplementation->setBlobCacheFuncs(set, get);
1982 }
1983 
1984 // static
GetNativeClientBuffer(const AHardwareBuffer * buffer)1985 EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
1986 {
1987     return angle::android::AHardwareBufferToClientBuffer(buffer);
1988 }
1989 
1990 // static
CreateNativeClientBuffer(const egl::AttributeMap & attribMap,EGLClientBuffer * eglClientBuffer)1991 Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
1992                                         EGLClientBuffer *eglClientBuffer)
1993 {
1994     int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap);
1995     int width                       = attribMap.getAsInt(EGL_WIDTH, 0);
1996     int height                      = attribMap.getAsInt(EGL_HEIGHT, 0);
1997     int usage                       = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
1998 
1999     // https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock
2000     // for AHardwareBuffer_lock()
2001     // The passed AHardwareBuffer must have one layer, otherwise the call will fail.
2002     constexpr int kLayerCount = 1;
2003 
2004     *eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer(
2005         width, height, kLayerCount, androidHardwareBufferFormat, usage);
2006 
2007     return (*eglClientBuffer == nullptr)
2008                ? egl::EglBadParameter() << "native client buffer allocation failed."
2009                : NoError();
2010 }
2011 
waitClient(const gl::Context * context)2012 Error Display::waitClient(const gl::Context *context)
2013 {
2014     return mImplementation->waitClient(context);
2015 }
2016 
waitNative(const gl::Context * context,EGLint engine)2017 Error Display::waitNative(const gl::Context *context, EGLint engine)
2018 {
2019     return mImplementation->waitNative(context, engine);
2020 }
2021 
getCaps() const2022 const Caps &Display::getCaps() const
2023 {
2024     return mCaps;
2025 }
2026 
isInitialized() const2027 bool Display::isInitialized() const
2028 {
2029     return mInitialized;
2030 }
2031 
isValidConfig(const Config * config) const2032 bool Display::isValidConfig(const Config *config) const
2033 {
2034     return mConfigSet.contains(config);
2035 }
2036 
isValidContext(const gl::ContextID contextID) const2037 bool Display::isValidContext(const gl::ContextID contextID) const
2038 {
2039     return getContext(contextID) != nullptr;
2040 }
2041 
isValidSurface(SurfaceID surfaceID) const2042 bool Display::isValidSurface(SurfaceID surfaceID) const
2043 {
2044     return getSurface(surfaceID) != nullptr;
2045 }
2046 
isValidImage(ImageID imageID) const2047 bool Display::isValidImage(ImageID imageID) const
2048 {
2049     return getImage(imageID) != nullptr;
2050 }
2051 
isValidStream(const Stream * stream) const2052 bool Display::isValidStream(const Stream *stream) const
2053 {
2054     return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
2055 }
2056 
isValidSync(SyncID syncID) const2057 bool Display::isValidSync(SyncID syncID) const
2058 {
2059     return getSync(syncID) != nullptr;
2060 }
2061 
hasExistingWindowSurface(EGLNativeWindowType window)2062 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
2063 {
2064     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
2065     ASSERT(windowSurfaces);
2066 
2067     return windowSurfaces->find(window) != windowSurfaces->end();
2068 }
2069 
GenerateClientExtensions()2070 static ClientExtensions GenerateClientExtensions()
2071 {
2072     ClientExtensions extensions;
2073 
2074     extensions.clientExtensions = true;
2075     extensions.platformBase     = true;
2076     extensions.platformANGLE    = true;
2077 
2078 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
2079     extensions.platformANGLED3D = true;
2080     extensions.platformDevice   = true;
2081 #endif
2082 
2083 #if defined(ANGLE_USE_GBM)
2084     extensions.platformGbmKHR = true;
2085 #endif
2086 
2087 #if defined(ANGLE_USE_WAYLAND)
2088     extensions.platformWaylandEXT = true;
2089 #endif
2090 
2091 #if defined(ANGLE_ENABLE_D3D11)
2092     extensions.platformANGLED3D11ON12 = angle::IsWindows10OrLater();
2093     extensions.platformANGLEDeviceId  = true;
2094 #endif
2095 
2096 #if defined(ANGLE_ENABLE_OPENGL)
2097     extensions.platformANGLEOpenGL = true;
2098 #endif
2099 
2100 #if defined(ANGLE_ENABLE_NULL)
2101     extensions.platformANGLENULL = true;
2102 #endif
2103 
2104 #if defined(ANGLE_ENABLE_D3D11)
2105     extensions.deviceCreation          = true;
2106     extensions.deviceCreationD3D11     = true;
2107     extensions.experimentalPresentPath = true;
2108 #endif
2109 
2110 #if defined(ANGLE_ENABLE_VULKAN)
2111     extensions.platformANGLEVulkan   = true;
2112     extensions.platformANGLEDeviceId = true;
2113 #endif
2114 
2115 #if defined(ANGLE_ENABLE_SWIFTSHADER)
2116     extensions.platformANGLEDeviceTypeSwiftShader = true;
2117 #endif
2118 
2119 #if defined(ANGLE_ENABLE_METAL)
2120     extensions.platformANGLEMetal    = true;
2121     extensions.platformANGLEDeviceId = true;
2122 #endif
2123 
2124 #if defined(ANGLE_USE_X11)
2125     extensions.x11Visual = true;
2126 #endif
2127 
2128 #if defined(ANGLE_PLATFORM_LINUX)
2129     extensions.platformANGLEDeviceTypeEGLANGLE = true;
2130 #endif
2131 
2132 #if defined(ANGLE_ENABLE_EAGL)
2133     extensions.platformANGLEDeviceContextVolatileEagl = true;
2134 #endif
2135 
2136 #if defined(ANGLE_ENABLE_CGL)
2137     extensions.platformANGLEDeviceContextVolatileCgl = true;
2138 #endif
2139 
2140 #if defined(ANGLE_ENABLE_METAL)
2141     extensions.displayPowerPreferenceANGLE = true;
2142 #endif
2143 
2144     extensions.clientGetAllProcAddresses = true;
2145     extensions.debug                     = true;
2146     extensions.featureControlANGLE       = true;
2147     extensions.deviceQueryEXT            = true;
2148 
2149     return extensions;
2150 }
2151 
2152 template <typename T>
GenerateExtensionsString(const T & extensions)2153 static std::string GenerateExtensionsString(const T &extensions)
2154 {
2155     std::vector<std::string> extensionsVector = extensions.getStrings();
2156 
2157     std::ostringstream stream;
2158     std::copy(extensionsVector.begin(), extensionsVector.end(),
2159               std::ostream_iterator<std::string>(stream, " "));
2160     return stream.str();
2161 }
2162 
2163 // static
GetClientExtensions()2164 const ClientExtensions &Display::GetClientExtensions()
2165 {
2166     static const ClientExtensions clientExtensions = GenerateClientExtensions();
2167     return clientExtensions;
2168 }
2169 
2170 // static
GetClientExtensionString()2171 const std::string &Display::GetClientExtensionString()
2172 {
2173     static const angle::base::NoDestructor<std::string> clientExtensionsString(
2174         GenerateExtensionsString(GetClientExtensions()));
2175     return *clientExtensionsString;
2176 }
2177 
initDisplayExtensions()2178 void Display::initDisplayExtensions()
2179 {
2180     mDisplayExtensions = mImplementation->getExtensions();
2181 
2182     // Some extensions are always available because they are implemented in the EGL layer.
2183     mDisplayExtensions.createContext        = true;
2184     mDisplayExtensions.createContextNoError = !mFrontendFeatures.forceGlErrorChecking.enabled;
2185     mDisplayExtensions.createContextWebGLCompatibility    = true;
2186     mDisplayExtensions.createContextBindGeneratesResource = true;
2187     mDisplayExtensions.createContextClientArrays          = true;
2188     mDisplayExtensions.pixelFormatFloat                   = true;
2189     mDisplayExtensions.reusableSyncKHR                    = true;
2190 
2191     // Force EGL_KHR_get_all_proc_addresses on.
2192     mDisplayExtensions.getAllProcAddresses = true;
2193 
2194     // Enable program cache control since it is not back-end dependent.
2195     mDisplayExtensions.programCacheControlANGLE = true;
2196 
2197     // Request extension is implemented in the ANGLE frontend
2198     mDisplayExtensions.createContextExtensionsEnabled = true;
2199 
2200     // Blob cache extension is provided by the ANGLE frontend
2201     mDisplayExtensions.blobCache = true;
2202 
2203     // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always
2204     // say that ANativeWindow is not recordable.
2205     mDisplayExtensions.recordable = true;
2206 
2207     // All backends support specific context versions
2208     mDisplayExtensions.createContextBackwardsCompatible = true;
2209 
2210     mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
2211 }
2212 
isValidNativeWindow(EGLNativeWindowType window) const2213 bool Display::isValidNativeWindow(EGLNativeWindowType window) const
2214 {
2215     return mImplementation->isValidNativeWindow(window);
2216 }
2217 
validateClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs) const2218 Error Display::validateClientBuffer(const Config *configuration,
2219                                     EGLenum buftype,
2220                                     EGLClientBuffer clientBuffer,
2221                                     const AttributeMap &attribs) const
2222 {
2223     return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
2224 }
2225 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const2226 Error Display::validateImageClientBuffer(const gl::Context *context,
2227                                          EGLenum target,
2228                                          EGLClientBuffer clientBuffer,
2229                                          const egl::AttributeMap &attribs) const
2230 {
2231     return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
2232 }
2233 
valdiatePixmap(const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes) const2234 Error Display::valdiatePixmap(const Config *config,
2235                               EGLNativePixmapType pixmap,
2236                               const AttributeMap &attributes) const
2237 {
2238     return mImplementation->validatePixmap(config, pixmap, attributes);
2239 }
2240 
isValidDisplay(const egl::Display * display)2241 bool Display::isValidDisplay(const egl::Display *display)
2242 {
2243     const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
2244     for (const auto &displayPair : *anglePlatformDisplayMap)
2245     {
2246         if (displayPair.second == display)
2247         {
2248             return true;
2249         }
2250     }
2251 
2252     const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
2253     for (const auto &displayPair : *devicePlatformDisplayMap)
2254     {
2255         if (displayPair.second == display)
2256         {
2257             return true;
2258         }
2259     }
2260 
2261     return false;
2262 }
2263 
isValidNativeDisplay(EGLNativeDisplayType display)2264 bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
2265 {
2266     // TODO(jmadill): handle this properly
2267     if (display == EGL_DEFAULT_DISPLAY)
2268     {
2269         return true;
2270     }
2271 
2272 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
2273     if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
2274         display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
2275     {
2276         return true;
2277     }
2278     return (WindowFromDC(display) != nullptr);
2279 #else
2280     return true;
2281 #endif
2282 }
2283 
initVendorString()2284 void Display::initVendorString()
2285 {
2286     mVendorString                = "Google Inc.";
2287     std::string vendorStringImpl = mImplementation->getVendorString();
2288     if (!vendorStringImpl.empty())
2289     {
2290         mVendorString += " (" + vendorStringImpl + ")";
2291     }
2292 }
2293 
initVersionString()2294 void Display::initVersionString()
2295 {
2296     mVersionString = mImplementation->getVersionString(true);
2297 }
2298 
initClientAPIString()2299 void Display::initClientAPIString()
2300 {
2301     // If the max supported desktop version is not None, we support a desktop GL frontend.
2302     if (mImplementation->getMaxSupportedDesktopVersion().valid())
2303     {
2304         mClientAPIString = "OpenGL_ES OpenGL";
2305     }
2306     else
2307     {
2308         mClientAPIString = "OpenGL_ES";
2309     }
2310 }
2311 
initializeFrontendFeatures()2312 void Display::initializeFrontendFeatures()
2313 {
2314     // Enable on all Impls
2315     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), loseContextOnOutOfMemory, true);
2316     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), allowCompressedFormats, true);
2317 
2318     // Togglable until work on the extension is complete - anglebug.com/7279.
2319     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, emulatePixelLocalStorage, true);
2320 
2321     mImplementation->initializeFrontendFeatures(&mFrontendFeatures);
2322 
2323     rx::ApplyFeatureOverrides(&mFrontendFeatures, mState);
2324 }
2325 
getExtensions() const2326 const DisplayExtensions &Display::getExtensions() const
2327 {
2328     return mDisplayExtensions;
2329 }
2330 
getExtensionString() const2331 const std::string &Display::getExtensionString() const
2332 {
2333     return mDisplayExtensionString;
2334 }
2335 
getVendorString() const2336 const std::string &Display::getVendorString() const
2337 {
2338     return mVendorString;
2339 }
2340 
getVersionString() const2341 const std::string &Display::getVersionString() const
2342 {
2343     return mVersionString;
2344 }
2345 
getClientAPIString() const2346 const std::string &Display::getClientAPIString() const
2347 {
2348     return mClientAPIString;
2349 }
2350 
getBackendRendererDescription() const2351 std::string Display::getBackendRendererDescription() const
2352 {
2353     return mImplementation->getRendererDescription();
2354 }
2355 
getBackendVendorString() const2356 std::string Display::getBackendVendorString() const
2357 {
2358     return mImplementation->getVendorString();
2359 }
2360 
getBackendVersionString(bool includeFullVersion) const2361 std::string Display::getBackendVersionString(bool includeFullVersion) const
2362 {
2363     return mImplementation->getVersionString(includeFullVersion);
2364 }
2365 
getDevice() const2366 Device *Display::getDevice() const
2367 {
2368     return mDevice;
2369 }
2370 
getWGLSurface() const2371 Surface *Display::getWGLSurface() const
2372 {
2373     return mSurface;
2374 }
2375 
getMaxSupportedESVersion() const2376 gl::Version Display::getMaxSupportedESVersion() const
2377 {
2378     return mImplementation->getMaxSupportedESVersion();
2379 }
2380 
programCacheGetAttrib(EGLenum attrib) const2381 EGLint Display::programCacheGetAttrib(EGLenum attrib) const
2382 {
2383     switch (attrib)
2384     {
2385         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
2386             return static_cast<EGLint>(BlobCache::kKeyLength);
2387 
2388         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
2389             return static_cast<EGLint>(mMemoryProgramCache.entryCount());
2390 
2391         default:
2392             UNREACHABLE();
2393             return 0;
2394     }
2395 }
2396 
programCacheQuery(EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)2397 Error Display::programCacheQuery(EGLint index,
2398                                  void *key,
2399                                  EGLint *keysize,
2400                                  void *binary,
2401                                  EGLint *binarysize)
2402 {
2403     ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
2404 
2405     const BlobCache::Key *programHash = nullptr;
2406     BlobCache::Value programBinary;
2407     // TODO(jmadill): Make this thread-safe.
2408     bool result =
2409         mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
2410     if (!result)
2411     {
2412         return EglBadAccess() << "Program binary not accessible.";
2413     }
2414 
2415     ASSERT(keysize && binarysize);
2416 
2417     if (key)
2418     {
2419         ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2420         memcpy(key, programHash->data(), BlobCache::kKeyLength);
2421     }
2422 
2423     if (binary)
2424     {
2425         // Note: we check the size here instead of in the validation code, since we need to
2426         // access the cache as atomically as possible. It's possible that the cache contents
2427         // could change between the validation size check and the retrieval.
2428         if (programBinary.size() > static_cast<size_t>(*binarysize))
2429         {
2430             return EglBadAccess() << "Program binary too large or changed during access.";
2431         }
2432 
2433         memcpy(binary, programBinary.data(), programBinary.size());
2434     }
2435 
2436     *binarysize = static_cast<EGLint>(programBinary.size());
2437     *keysize    = static_cast<EGLint>(BlobCache::kKeyLength);
2438 
2439     return NoError();
2440 }
2441 
programCachePopulate(const void * key,EGLint keysize,const void * binary,EGLint binarysize)2442 Error Display::programCachePopulate(const void *key,
2443                                     EGLint keysize,
2444                                     const void *binary,
2445                                     EGLint binarysize)
2446 {
2447     ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2448 
2449     BlobCache::Key programHash;
2450     memcpy(programHash.data(), key, BlobCache::kKeyLength);
2451 
2452     if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
2453                                        static_cast<size_t>(binarysize)))
2454     {
2455         return EglBadAccess() << "Failed to copy program binary into the cache.";
2456     }
2457 
2458     return NoError();
2459 }
2460 
programCacheResize(EGLint limit,EGLenum mode)2461 EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
2462 {
2463     switch (mode)
2464     {
2465         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
2466         {
2467             size_t initialSize = mMemoryProgramCache.size();
2468             mMemoryProgramCache.resize(static_cast<size_t>(limit));
2469             return static_cast<EGLint>(initialSize);
2470         }
2471 
2472         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
2473             return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
2474 
2475         default:
2476             UNREACHABLE();
2477             return 0;
2478     }
2479 }
2480 
overrideFrontendFeatures(const std::vector<std::string> & featureNames,bool enabled)2481 void Display::overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled)
2482 {
2483     mFrontendFeatures.overrideFeatures(featureNames, enabled);
2484 }
2485 
queryStringi(const EGLint name,const EGLint index)2486 const char *Display::queryStringi(const EGLint name, const EGLint index)
2487 {
2488     const char *result = nullptr;
2489     switch (name)
2490     {
2491         case EGL_FEATURE_NAME_ANGLE:
2492             result = mFeatures[index]->name;
2493             break;
2494         case EGL_FEATURE_CATEGORY_ANGLE:
2495             result = angle::FeatureCategoryToString(mFeatures[index]->category);
2496             break;
2497         case EGL_FEATURE_DESCRIPTION_ANGLE:
2498             result = mFeatures[index]->description;
2499             break;
2500         case EGL_FEATURE_BUG_ANGLE:
2501             result = mFeatures[index]->bug;
2502             break;
2503         case EGL_FEATURE_STATUS_ANGLE:
2504             result = angle::FeatureStatusToString(mFeatures[index]->enabled);
2505             break;
2506         case EGL_FEATURE_CONDITION_ANGLE:
2507             result = mFeatures[index]->condition;
2508             break;
2509         default:
2510             UNREACHABLE();
2511             return nullptr;
2512     }
2513     return result;
2514 }
2515 
queryAttrib(const EGLint attribute)2516 EGLAttrib Display::queryAttrib(const EGLint attribute)
2517 {
2518     EGLAttrib value = 0;
2519     switch (attribute)
2520     {
2521         case EGL_DEVICE_EXT:
2522             value = reinterpret_cast<EGLAttrib>(mDevice);
2523             break;
2524 
2525         case EGL_FEATURE_COUNT_ANGLE:
2526             value = mFeatures.size();
2527             break;
2528 
2529         default:
2530             UNREACHABLE();
2531     }
2532     return value;
2533 }
2534 
requestScratchBuffer()2535 angle::ScratchBuffer Display::requestScratchBuffer()
2536 {
2537     return requestScratchBufferImpl(&mScratchBuffers);
2538 }
2539 
returnScratchBuffer(angle::ScratchBuffer scratchBuffer)2540 void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer)
2541 {
2542     returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers);
2543 }
2544 
requestZeroFilledBuffer()2545 angle::ScratchBuffer Display::requestZeroFilledBuffer()
2546 {
2547     return requestScratchBufferImpl(&mZeroFilledBuffers);
2548 }
2549 
returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)2550 void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)
2551 {
2552     returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers);
2553 }
2554 
requestScratchBufferImpl(std::vector<angle::ScratchBuffer> * bufferVector)2555 angle::ScratchBuffer Display::requestScratchBufferImpl(
2556     std::vector<angle::ScratchBuffer> *bufferVector)
2557 {
2558     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
2559     if (!bufferVector->empty())
2560     {
2561         angle::ScratchBuffer buffer = std::move(bufferVector->back());
2562         bufferVector->pop_back();
2563         return buffer;
2564     }
2565 
2566     return angle::ScratchBuffer(kScratchBufferLifetime);
2567 }
2568 
returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,std::vector<angle::ScratchBuffer> * bufferVector)2569 void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
2570                                       std::vector<angle::ScratchBuffer> *bufferVector)
2571 {
2572     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
2573     bufferVector->push_back(std::move(scratchBuffer));
2574 }
2575 
handleGPUSwitch()2576 Error Display::handleGPUSwitch()
2577 {
2578     ANGLE_TRY(mImplementation->handleGPUSwitch());
2579     initVendorString();
2580     return NoError();
2581 }
2582 
forceGPUSwitch(EGLint gpuIDHigh,EGLint gpuIDLow)2583 Error Display::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
2584 {
2585     ANGLE_TRY(mImplementation->forceGPUSwitch(gpuIDHigh, gpuIDLow));
2586     initVendorString();
2587     return NoError();
2588 }
2589 
waitUntilWorkScheduled()2590 Error Display::waitUntilWorkScheduled()
2591 {
2592     ANGLE_TRY(mImplementation->waitUntilWorkScheduled());
2593     return NoError();
2594 }
2595 
supportsDmaBufFormat(EGLint format) const2596 bool Display::supportsDmaBufFormat(EGLint format) const
2597 {
2598     return mImplementation->supportsDmaBufFormat(format);
2599 }
2600 
queryDmaBufFormats(EGLint max_formats,EGLint * formats,EGLint * num_formats)2601 Error Display::queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats)
2602 {
2603     ANGLE_TRY(mImplementation->queryDmaBufFormats(max_formats, formats, num_formats));
2604     return NoError();
2605 }
2606 
queryDmaBufModifiers(EGLint format,EGLint max_modifiers,EGLuint64KHR * modifiers,EGLBoolean * external_only,EGLint * num_modifiers)2607 Error Display::queryDmaBufModifiers(EGLint format,
2608                                     EGLint max_modifiers,
2609                                     EGLuint64KHR *modifiers,
2610                                     EGLBoolean *external_only,
2611                                     EGLint *num_modifiers)
2612 {
2613     ANGLE_TRY(mImplementation->queryDmaBufModifiers(format, max_modifiers, modifiers, external_only,
2614                                                     num_modifiers));
2615     return NoError();
2616 }
2617 
getImageLoadContext() const2618 angle::ImageLoadContext Display::getImageLoadContext() const
2619 {
2620     angle::ImageLoadContext imageLoadContext;
2621 
2622     imageLoadContext.singleThreadPool = mSingleThreadPool;
2623     imageLoadContext.multiThreadPool =
2624         mFrontendFeatures.singleThreadedTextureDecompression.enabled ? nullptr : mMultiThreadPool;
2625 
2626     return imageLoadContext;
2627 }
2628 
getContext(gl::ContextID contextID) const2629 const gl::Context *Display::getContext(gl::ContextID contextID) const
2630 {
2631     auto iter = mState.contextMap.find(contextID.value);
2632     return iter != mState.contextMap.end() ? iter->second : nullptr;
2633 }
2634 
getSurface(egl::SurfaceID surfaceID) const2635 const egl::Surface *Display::getSurface(egl::SurfaceID surfaceID) const
2636 {
2637     auto iter = mState.surfaceMap.find(surfaceID.value);
2638     return iter != mState.surfaceMap.end() ? iter->second : nullptr;
2639 }
2640 
getImage(egl::ImageID imageID) const2641 const egl::Image *Display::getImage(egl::ImageID imageID) const
2642 {
2643     auto iter = mImageMap.find(imageID.value);
2644     return iter != mImageMap.end() ? iter->second : nullptr;
2645 }
2646 
getSync(egl::SyncID syncID) const2647 const egl::Sync *Display::getSync(egl::SyncID syncID) const
2648 {
2649     auto iter = mSyncMap.find(syncID.value);
2650     return iter != mSyncMap.end() ? iter->second : nullptr;
2651 }
2652 
getContext(gl::ContextID contextID)2653 gl::Context *Display::getContext(gl::ContextID contextID)
2654 {
2655     auto iter = mState.contextMap.find(contextID.value);
2656     return iter != mState.contextMap.end() ? iter->second : nullptr;
2657 }
2658 
getSurface(egl::SurfaceID surfaceID)2659 egl::Surface *Display::getSurface(egl::SurfaceID surfaceID)
2660 {
2661     auto iter = mState.surfaceMap.find(surfaceID.value);
2662     return iter != mState.surfaceMap.end() ? iter->second : nullptr;
2663 }
2664 
getImage(egl::ImageID imageID)2665 egl::Image *Display::getImage(egl::ImageID imageID)
2666 {
2667     auto iter = mImageMap.find(imageID.value);
2668     return iter != mImageMap.end() ? iter->second : nullptr;
2669 }
2670 
getSync(egl::SyncID syncID)2671 egl::Sync *Display::getSync(egl::SyncID syncID)
2672 {
2673     auto iter = mSyncMap.find(syncID.value);
2674     return iter != mSyncMap.end() ? iter->second : nullptr;
2675 }
2676 
2677 // static
InitTLS()2678 void Display::InitTLS()
2679 {
2680     TLSData *tlsData = new TLSData;
2681 
2682 #if defined(ANGLE_PLATFORM_APPLE)
2683     SetDisplayTLS(tlsData);
2684 #else
2685     gDisplayTLS = tlsData;
2686 #endif
2687 }
2688 
2689 // static
GetCurrentThreadUnlockedTailCall()2690 angle::UnlockedTailCall *Display::GetCurrentThreadUnlockedTailCall()
2691 {
2692     return &GetDisplayTLS()->unlockedTailCall;
2693 }
2694 
2695 // static
GetCurrentThreadErrorScratchSpace()2696 Error *Display::GetCurrentThreadErrorScratchSpace()
2697 {
2698     return &GetDisplayTLS()->errorScratchSpace;
2699 }
2700 }  // namespace egl
2701