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