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