• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Display.cpp: Implements the egl::Display class, representing the abstract
8 // display on which graphics are drawn. Implements EGLDisplay.
9 // [EGL 1.4] section 2.1.2 page 3.
10 
11 #include "libANGLE/Display.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <sstream>
16 #include <vector>
17 
18 #include <EGL/eglext.h>
19 #include <platform/PlatformMethods.h>
20 
21 #include "anglebase/no_destructor.h"
22 #include "common/android_util.h"
23 #include "common/debug.h"
24 #include "common/mathutil.h"
25 #include "common/platform_helpers.h"
26 #include "common/string_utils.h"
27 #include "common/system_utils.h"
28 #include "common/tls.h"
29 #include "common/utilities.h"
30 #include "gpu_info_util/SystemInfo.h"
31 #include "image_util/loadimage.h"
32 #include "libANGLE/Context.h"
33 #include "libANGLE/Device.h"
34 #include "libANGLE/EGLSync.h"
35 #include "libANGLE/Image.h"
36 #include "libANGLE/ResourceManager.h"
37 #include "libANGLE/Stream.h"
38 #include "libANGLE/Surface.h"
39 #include "libANGLE/Thread.h"
40 #include "libANGLE/capture/FrameCapture.h"
41 #include "libANGLE/histogram_macros.h"
42 #include "libANGLE/renderer/DeviceImpl.h"
43 #include "libANGLE/renderer/DisplayImpl.h"
44 #include "libANGLE/renderer/ImageImpl.h"
45 #include "libANGLE/trace.h"
46 
47 #if defined(ANGLE_PLATFORM_APPLE)
48 #    include <dispatch/dispatch.h>
49 #    include "common/tls.h"
50 #endif
51 
52 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
53 #    include "libANGLE/renderer/d3d/DisplayD3D.h"
54 #endif
55 
56 #if defined(ANGLE_ENABLE_OPENGL)
57 #    if defined(ANGLE_PLATFORM_WINDOWS)
58 #        include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
59 #    elif ANGLE_ENABLE_CGL
60 #        include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
61 #    elif 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::__anona8a699080111::ANGLEPlatformDisplay173     ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType)
174         : nativeDisplayType(nativeDisplayType)
175     {}
176 
ANGLEPlatformDisplayegl::__anona8a699080111::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::__anona8a699080111::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_APPLE)
585             if (rx::IsVulkanMacDisplayAvailable())
586             {
587                 impl = rx::CreateVulkanMacDisplay(state);
588             }
589             break;
590 #    else
591 #        error Unsupported Vulkan platform.
592 #    endif
593 #else
594             // Vulkan isn't available
595             break;
596 #endif  // defined(ANGLE_ENABLE_VULKAN)
597 
598         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
599 #if defined(ANGLE_ENABLE_METAL)
600             if (rx::IsMetalDisplayAvailable())
601             {
602                 impl = rx::CreateMetalDisplay(state);
603                 break;
604             }
605 #endif
606             // Metal isn't available.
607             break;
608 
609         case EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE:
610 #if defined(ANGLE_ENABLE_WGPU)
611             impl = rx::CreateWgpuDisplay(state);
612 #endif  // defined(ANGLE_ENABLE_WGPU)
613         // WebGPU isn't available.
614             break;
615 
616         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
617 #if defined(ANGLE_ENABLE_NULL)
618             impl = new rx::DisplayNULL(state);
619             break;
620 #else
621             // No display available
622             UNREACHABLE();
623             break;
624 #endif  // defined(ANGLE_ENABLE_NULL)
625 
626         default:
627             UNREACHABLE();
628             break;
629     }
630 
631     return impl;
632 }
633 
Display_logError(angle::PlatformMethods * platform,const char * errorMessage)634 void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
635 {
636     gl::Trace(gl::LOG_ERR, errorMessage);
637 }
638 
Display_logWarning(angle::PlatformMethods * platform,const char * warningMessage)639 void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
640 {
641     gl::Trace(gl::LOG_WARN, warningMessage);
642 }
643 
Display_logInfo(angle::PlatformMethods * platform,const char * infoMessage)644 void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
645 {
646     // Uncomment to get info spam
647 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
648     gl::Trace(gl::LOG_INFO, infoMessage);
649 #endif
650 }
651 
EGLStringArrayToStringVector(const char ** ary)652 const std::vector<std::string> EGLStringArrayToStringVector(const char **ary)
653 {
654     std::vector<std::string> vec;
655     if (ary != nullptr)
656     {
657         for (; *ary != nullptr; ary++)
658         {
659             vec.push_back(std::string(*ary));
660         }
661     }
662     return vec;
663 }
664 
ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)665 void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
666 {
667     angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
668 
669     ANGLEResetDisplayPlatform(display);
670     platformMethods->logError   = Display_logError;
671     platformMethods->logWarning = Display_logWarning;
672     platformMethods->logInfo    = Display_logInfo;
673 }
674 
UpdateAttribsFromEnvironment(AttributeMap & attribMap)675 void UpdateAttribsFromEnvironment(AttributeMap &attribMap)
676 {
677     EGLAttrib displayType =
678         attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
679     if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
680     {
681         displayType = GetDisplayTypeFromEnvironment();
682         attribMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType);
683     }
684     EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0);
685     if (deviceType == 0)
686     {
687         deviceType = GetDeviceTypeFromEnvironment();
688         attribMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType);
689     }
690     EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
691     if (platformType == 0)
692     {
693         platformType = GetPlatformTypeFromEnvironment();
694         attribMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType);
695     }
696 }
697 
698 static constexpr uint32_t kScratchBufferLifetime = 64u;
699 
700 }  // anonymous namespace
701 
702 // DisplayState
DisplayState(EGLNativeDisplayType nativeDisplayId)703 DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId)
704     : label(nullptr),
705       displayId(nativeDisplayId),
706       singleThreadPool(nullptr),
707       multiThreadPool(nullptr),
708       deviceLost(false)
709 {}
710 
~DisplayState()711 DisplayState::~DisplayState() {}
712 
notifyDeviceLost() const713 void DisplayState::notifyDeviceLost() const
714 {
715     if (deviceLost)
716     {
717         return;
718     }
719 
720     {
721         std::lock_guard<angle::SimpleMutex> lock(contextMapMutex);
722         for (auto context = contextMap.begin(); context != contextMap.end(); context++)
723         {
724             context->second->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
725         }
726     }
727 
728     deviceLost = true;
729 }
730 
731 // Note that ANGLE support on Ozone platform is limited. Our preferred support Matrix for
732 // EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following:
733 //
734 // |--------------------------------------------------------|
735 // | ANGLE type | DEVICE type |  PLATFORM type   | Display  |
736 // |--------------------------------------------------------|
737 // |   OPENGL   |     EGL     |       ANY        |   EGL    |
738 // |   OPENGL   |   HARDWARE  |     X11_EXT      |   GLX    |
739 // |  OPENGLES  |   HARDWARE  |     X11_EXT      |   GLX    |
740 // |  OPENGLES  |     EGL     |       ANY        |   EGL    |
741 // |   VULKAN   |   HARDWARE  |     X11_EXT      |  VkXcb   |
742 // |   VULKAN   | SWIFTSHADER |     X11_EXT      |  VkXcb   |
743 // |  OPENGLES  |   HARDWARE  | SURFACELESS_MESA |   EGL*   |
744 // |  OPENGLES  |   HARDWARE  |    DEVICE_EXT    |   EGL    |
745 // |   VULKAN   |   HARDWARE  | SURFACELESS_MESA | VkBase** |
746 // |   VULKAN   | SWIFTSHADER | SURFACELESS_MESA | VkBase** |
747 // |--------------------------------------------------------|
748 //
749 // * No surfaceless support yet.
750 // ** Not implemented yet.
751 //
752 // |-----------------------------------------------|
753 // |   OS    | BUILD type |  Default PLATFORM type |
754 // |-----------------------------------------------|
755 // |  Linux  |    X11     |        X11_EXT         |
756 // |  Linux  |   Ozone    |    SURFACELESS_MESA    |
757 // | Fuchsia |   Ozone    |        FUCHSIA***      |
758 // |-----------------------------------------------|
759 //
760 // *** Chosen implicitly. No EGLAttrib available.
761 //
762 // For more details, please refer to
763 // https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY
764 //
765 // static
GetDisplayFromNativeDisplay(EGLenum platform,EGLNativeDisplayType nativeDisplay,const AttributeMap & attribMap)766 Display *Display::GetDisplayFromNativeDisplay(EGLenum platform,
767                                               EGLNativeDisplayType nativeDisplay,
768                                               const AttributeMap &attribMap)
769 {
770     Display *display = nullptr;
771 
772     AttributeMap updatedAttribMap(attribMap);
773     UpdateAttribsFromEnvironment(updatedAttribMap);
774 
775     EGLAttrib powerPreference =
776         updatedAttribMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE);
777     EGLAttrib platformANGLEType =
778         updatedAttribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
779     EGLAttrib deviceIdHigh = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0);
780     EGLAttrib deviceIdLow  = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0);
781     EGLAttrib displayKey   = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DISPLAY_KEY_ANGLE, 0);
782     EGLAttrib enabledFeatureOverrides =
783         updatedAttribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0);
784     EGLAttrib disabledFeatureOverrides =
785         updatedAttribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0);
786     EGLAttrib disableAllNonOverriddenFeatures =
787         updatedAttribMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0);
788     ANGLEPlatformDisplay combinedDisplayKey(
789         nativeDisplay, powerPreference, platformANGLEType, deviceIdHigh, deviceIdLow, displayKey,
790         enabledFeatureOverrides, disabledFeatureOverrides, disableAllNonOverriddenFeatures);
791 
792     {
793         std::lock_guard<angle::SimpleMutex> lock(*ANGLEPlatformDisplayMapMutex());
794 
795         ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
796         const auto &iter                  = displays->find(combinedDisplayKey);
797 
798         if (iter != displays->end())
799         {
800             display = iter->second;
801         }
802 
803         if (display == nullptr)
804         {
805             // Validate the native display
806             if (!Display::isValidNativeDisplay(nativeDisplay))
807             {
808                 return nullptr;
809             }
810 
811             display = new Display(platform, nativeDisplay, nullptr);
812             displays->insert(std::make_pair(combinedDisplayKey, display));
813         }
814     }
815     // Apply new attributes if the display is not initialized yet.
816     if (!display->isInitialized())
817     {
818         display->setAttributes(updatedAttribMap);
819 
820         EGLAttrib displayType  = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
821         EGLAttrib deviceType   = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
822         EGLAttrib platformType = platform;
823         if (platform == EGL_PLATFORM_ANGLE_ANGLE)
824         {
825             platformType =
826                 display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
827         }
828         rx::DisplayImpl *impl =
829             CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState());
830         if (impl == nullptr)
831         {
832             // No valid display implementation for these attributes
833             return nullptr;
834         }
835 
836 #if defined(ANGLE_USE_ANDROID_TLS_SLOT)
837         angle::gUseAndroidOpenGLTlsSlot = displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
838 #endif  // defined(ANGLE_PLATFORM_ANDROID)
839 
840         display->setupDisplayPlatform(impl);
841     }
842 
843     return display;
844 }
845 
846 // static
GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)847 Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)
848 {
849     std::lock_guard<angle::SimpleMutex> lock(*ANGLEPlatformDisplayMapMutex());
850     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
851     const auto &iter                  = displays->find(nativeDisplay);
852 
853     // Check that there is a matching display
854     if (iter == displays->end())
855     {
856         return nullptr;
857     }
858 
859     return iter->second;
860 }
861 
862 // static
GetDisplayFromDevice(Device * device,const AttributeMap & attribMap)863 Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
864 {
865     Display *display = nullptr;
866 
867     ASSERT(Device::IsValidDevice(device));
868 
869     {
870         // First see if this eglDevice is in use by a Display created using ANGLE platform
871         std::lock_guard<angle::SimpleMutex> lock(*ANGLEPlatformDisplayMapMutex());
872         ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
873         for (auto &displayMapEntry : *anglePlatformDisplays)
874         {
875             egl::Display *iterDisplay = displayMapEntry.second;
876             if (iterDisplay->getDevice() == device)
877             {
878                 display = iterDisplay;
879             }
880         }
881     }
882 
883     if (display == nullptr)
884     {
885         // Next see if this eglDevice is in use by a Display created using the DEVICE platform
886         std::lock_guard<angle::SimpleMutex> lock(*DevicePlatformDisplayMapMutex());
887         DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
888 
889         // See if the eglDevice is in use by a Display created using the DEVICE platform
890         const auto &iter = devicePlatformDisplays->find(device);
891         if (iter != devicePlatformDisplays->end())
892         {
893             display = iter->second;
894         }
895 
896         if (display == nullptr)
897         {
898             // Otherwise create a new Display
899             display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
900             devicePlatformDisplays->insert(std::make_pair(device, display));
901         }
902     }
903 
904     // Apply new attributes if the display is not initialized yet.
905     if (!display->isInitialized())
906     {
907         display->setAttributes(attribMap);
908         rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
909         display->setupDisplayPlatform(impl);
910     }
911 
912     return display;
913 }
914 
Display(EGLenum platform,EGLNativeDisplayType displayId,Device * eglDevice)915 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
916     : mState(displayId),
917       mImplementation(nullptr),
918       mGPUSwitchedBinding(this, kGPUSwitchedSubjectIndex),
919       mAttributeMap(),
920       mConfigSet(),
921       mStreamSet(),
922       mInvalidContextMap(),
923       mInvalidImageMap(),
924       mInvalidStreamSet(),
925       mInvalidSurfaceMap(),
926       mInvalidSyncMap(),
927       mInitialized(false),
928       mCaps(),
929       mDisplayExtensions(),
930       mDisplayExtensionString(),
931       mVendorString(),
932       mVersionString(),
933       mDevice(eglDevice),
934       mSurface(nullptr),
935       mPlatform(platform),
936       mManagersMutex(nullptr),
937       mTextureManager(nullptr),
938       mSemaphoreManager(nullptr),
939       mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes),
940       mMemoryProgramCache(mBlobCache),
941       mMemoryShaderCache(mBlobCache),
942       mGlobalTextureShareGroupUsers(0),
943       mGlobalSemaphoreShareGroupUsers(0),
944       mTerminatedByApi(false)
945 {}
946 
~Display()947 Display::~Display()
948 {
949     switch (mPlatform)
950     {
951         case EGL_PLATFORM_ANGLE_ANGLE:
952         case EGL_PLATFORM_GBM_KHR:
953         case EGL_PLATFORM_WAYLAND_EXT:
954         case EGL_PLATFORM_SURFACELESS_MESA:
955         {
956             std::lock_guard<angle::SimpleMutex> lock(*ANGLEPlatformDisplayMapMutex());
957             ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
958             ANGLEPlatformDisplayMap::iterator iter = displays->find(ANGLEPlatformDisplay(
959                 mState.displayId,
960                 mAttributeMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE),
961                 mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
962                                   EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
963                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0),
964                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0),
965                 mAttributeMap.get(EGL_PLATFORM_ANGLE_DISPLAY_KEY_ANGLE, 0),
966                 mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0),
967                 mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0),
968                 mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0)));
969             if (iter != displays->end())
970             {
971                 displays->erase(iter);
972             }
973             break;
974         }
975         case EGL_PLATFORM_DEVICE_EXT:
976         {
977             std::lock_guard<angle::SimpleMutex> lock(*DevicePlatformDisplayMapMutex());
978             DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
979             DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
980             if (iter != displays->end())
981             {
982                 displays->erase(iter);
983             }
984             break;
985         }
986         default:
987         {
988             UNREACHABLE();
989         }
990     }
991 
992     SafeDelete(mDevice);
993     SafeDelete(mImplementation);
994 }
995 
setLabel(EGLLabelKHR label)996 void Display::setLabel(EGLLabelKHR label)
997 {
998     mState.label = label;
999 }
1000 
getLabel() const1001 EGLLabelKHR Display::getLabel() const
1002 {
1003     return mState.label;
1004 }
1005 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)1006 void Display::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
1007 {
1008     ASSERT(index == kGPUSwitchedSubjectIndex);
1009     ASSERT(message == angle::SubjectMessage::SubjectChanged);
1010     std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
1011     for (auto context : mState.contextMap)
1012     {
1013         context.second->onGPUSwitch();
1014     }
1015 }
1016 
setupDisplayPlatform(rx::DisplayImpl * impl)1017 void Display::setupDisplayPlatform(rx::DisplayImpl *impl)
1018 {
1019     ASSERT(!mInitialized);
1020 
1021     ASSERT(impl != nullptr);
1022     SafeDelete(mImplementation);
1023     mImplementation = impl;
1024 
1025     // TODO(anglebug.com/42265835): Remove PlatformMethods.
1026     const angle::PlatformMethods *platformMethods =
1027         reinterpret_cast<const angle::PlatformMethods *>(
1028             mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
1029     if (platformMethods != nullptr)
1030     {
1031         *ANGLEPlatformCurrent() = *platformMethods;
1032     }
1033     else
1034     {
1035         ANGLESetDefaultDisplayPlatform(this);
1036     }
1037 
1038     const char **featuresForceEnabled =
1039         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0));
1040     const char **featuresForceDisabled =
1041         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0));
1042     mState.featureOverrides.enabled  = EGLStringArrayToStringVector(featuresForceEnabled);
1043     mState.featureOverrides.disabled = EGLStringArrayToStringVector(featuresForceDisabled);
1044     mState.featureOverrides.allDisabled =
1045         static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0));
1046     mImplementation->addObserver(&mGPUSwitchedBinding);
1047 }
1048 
initialize()1049 Error Display::initialize()
1050 {
1051     mTerminatedByApi = false;
1052 
1053     ASSERT(mImplementation != nullptr);
1054     mImplementation->setBlobCache(&mBlobCache);
1055 
1056     // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
1057     // properly saved & restored on all platforms. The cache won't allocate space until it's used
1058     // and will be ignored entirely if the application / system sets it's own cache functions.
1059     if (rx::ShouldUseDebugLayers(mAttributeMap))
1060     {
1061         mBlobCache.resize(1024 * 1024);
1062     }
1063 
1064     setGlobalDebugAnnotator();
1065 
1066     gl::InitializeDebugMutexIfNeeded();
1067 
1068     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
1069 
1070     if (isInitialized())
1071     {
1072         return NoError();
1073     }
1074 
1075     Error error = mImplementation->initialize(this);
1076     if (error.isError())
1077     {
1078         // Log extended error message here
1079         ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
1080         return error;
1081     }
1082 
1083     mCaps = mImplementation->getCaps();
1084 
1085     mConfigSet = mImplementation->generateConfigs();
1086     if (mConfigSet.size() == 0)
1087     {
1088         mImplementation->terminate();
1089         return egl::Error(EGL_NOT_INITIALIZED, "No configs were generated.");
1090     }
1091 
1092     // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs
1093     for (auto &config : mConfigSet)
1094     {
1095         // TODO(geofflang): Enable the conformant bit once we pass enough tests
1096         // config.second.conformant |= EGL_OPENGL_ES_BIT;
1097 
1098         config.second.renderableType |= EGL_OPENGL_ES_BIT;
1099     }
1100 
1101     mFrontendFeatures.reset();
1102     rx::ApplyFeatureOverrides(&mFrontendFeatures, mState.featureOverrides);
1103     if (!mState.featureOverrides.allDisabled)
1104     {
1105         initializeFrontendFeatures();
1106     }
1107 
1108     mFeatures.clear();
1109     mFrontendFeatures.populateFeatureList(&mFeatures);
1110     mImplementation->populateFeatureList(&mFeatures);
1111 
1112     initDisplayExtensions();
1113     initVendorString();
1114     initVersionString();
1115     initClientAPIString();
1116 
1117     // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
1118     if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
1119     {
1120         // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
1121         // an external device
1122         ASSERT(mDevice != nullptr);
1123     }
1124     else if (GetClientExtensions().deviceQueryEXT)
1125     {
1126         std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice());
1127         ASSERT(impl);
1128         error = impl->initialize();
1129         if (error.isError())
1130         {
1131             ERR() << "Failed to initialize display because device creation failed: "
1132                   << error.getMessage();
1133             mImplementation->terminate();
1134             return error;
1135         }
1136         // Don't leak Device memory.
1137         ASSERT(mDevice == nullptr);
1138         mDevice = new Device(this, impl.release());
1139     }
1140     else
1141     {
1142         mDevice = nullptr;
1143     }
1144 
1145     mState.singleThreadPool = angle::WorkerThreadPool::Create(1, ANGLEPlatformCurrent());
1146     mState.multiThreadPool  = angle::WorkerThreadPool::Create(0, ANGLEPlatformCurrent());
1147 
1148     if (kIsContextMutexEnabled)
1149     {
1150         ASSERT(mManagersMutex == nullptr);
1151         mManagersMutex = new ContextMutex();
1152         mManagersMutex->addRef();
1153     }
1154 
1155     mInitialized = true;
1156 
1157     return NoError();
1158 }
1159 
destroyInvalidEglObjects()1160 Error Display::destroyInvalidEglObjects()
1161 {
1162     // Destroy invalid EGL objects
1163     // Note that we don't need to lock mState.contextMapMutex here.
1164     // Write and read access to mInvalidContextMap are coming from
1165     // EGL_Terminate, EGL_ReleaseThread, ThreadCleanupCallBACK.
1166     // Those functions are protected by egl global lock,
1167     // so there is no race condition on mInvalidContextMap.
1168     while (!mInvalidContextMap.empty())
1169     {
1170         gl::Context *context = mInvalidContextMap.begin()->second;
1171         // eglReleaseThread() may call to this method when there are still Contexts, that may
1172         // potentially acces shared state of the "context".
1173         // Need AddRefLock because there may be ContextMutex destruction.
1174         ScopedContextMutexAddRefLock lock(context->getContextMutex());
1175         context->setIsDestroyed();
1176         ANGLE_TRY(releaseContextImpl(eraseContextImpl(context, &mInvalidContextMap)));
1177     }
1178 
1179     while (!mInvalidImageMap.empty())
1180     {
1181         destroyImageImpl(mInvalidImageMap.begin()->second, &mInvalidImageMap);
1182     }
1183 
1184     while (!mInvalidStreamSet.empty())
1185     {
1186         destroyStreamImpl(*mInvalidStreamSet.begin(), &mInvalidStreamSet);
1187     }
1188 
1189     while (!mInvalidSurfaceMap.empty())
1190     {
1191         ANGLE_TRY(destroySurfaceImpl(mInvalidSurfaceMap.begin()->second, &mInvalidSurfaceMap));
1192     }
1193 
1194     while (!mInvalidSyncMap.empty())
1195     {
1196         destroySyncImpl(mInvalidSyncMap.begin()->second->id(), &mInvalidSyncMap);
1197     }
1198 
1199     return NoError();
1200 }
1201 
terminate(Thread * thread,TerminateReason terminateReason)1202 Error Display::terminate(Thread *thread, TerminateReason terminateReason)
1203 {
1204 
1205     if (terminateReason == TerminateReason::Api)
1206     {
1207         mTerminatedByApi = true;
1208     }
1209 
1210     // All subsequent calls assume the display to be valid and terminated by app.
1211     // If it is not terminated or if it isn't even initialized, early return.
1212     if (!mTerminatedByApi || !mInitialized)
1213     {
1214         return NoError();
1215     }
1216 
1217     // EGL 1.5 Specification
1218     // 3.2 Initialization
1219     // Termination marks all EGL-specific resources, such as contexts and surfaces, associated
1220     // with the specified display for deletion. Handles to all such resources are invalid as
1221     // soon as eglTerminate returns. Cache EGL objects that are no longer valid.
1222     //
1223     // It is fairly common for apps to call eglTerminate while some contexts and/or surfaces are
1224     // still current on some thread. Since objects are refCounted, trying to destroy them right
1225     // away would only result in a decRef. We instead cache such invalid objects and use other
1226     // EGL entrypoints like eglReleaseThread or thread exit events (on the Android platform) to
1227     // perform the necessary cleanup.
1228     mInvalidImageMap.insert(mImageMap.begin(), mImageMap.end());
1229     mImageMap.clear();
1230 
1231     mInvalidStreamSet.insert(mStreamSet.begin(), mStreamSet.end());
1232     mStreamSet.clear();
1233 
1234     mInvalidSurfaceMap.insert(mState.surfaceMap.begin(), mState.surfaceMap.end());
1235     mState.surfaceMap.clear();
1236 
1237     mInvalidSyncMap.insert(std::make_move_iterator(mSyncMap.begin()),
1238                            std::make_move_iterator(mSyncMap.end()));
1239     mSyncMap.clear();
1240 
1241     {
1242         // Lock mState.contextMapMutex to protect mState.contextMap.
1243         // mInvalidContextMap does not need protection. It just happens to fall within this scope.
1244         std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
1245         // Cache total number of contexts before invalidation. This is used as a check to verify
1246         // that no context is "lost" while being moved between the various sets.
1247         size_t contextSetSizeBeforeInvalidation =
1248             mState.contextMap.size() + mInvalidContextMap.size();
1249 
1250         // If app called eglTerminate and no active threads remain,
1251         // force release any context that is still current.
1252         ContextMap contextsStillCurrent = {};
1253         for (auto context : mState.contextMap)
1254         {
1255             if (context.second->isReferenced())
1256             {
1257                 contextsStillCurrent.emplace(context);
1258                 continue;
1259             }
1260 
1261             // Add context that is not current to mInvalidContextSet for cleanup.
1262             mInvalidContextMap.emplace(context);
1263         }
1264 
1265         // There are many methods that require contexts that are still current to be present in
1266         // display's contextSet like during context release or to notify of state changes in a
1267         // subject. So as to not interrupt this flow, do not remove contexts that are still
1268         // current on some thread from display's contextSet even though eglTerminate marks such
1269         // contexts as invalid.
1270         //
1271         // "mState.contextSet" will now contain only those contexts that are still current on
1272         // some thread.
1273         mState.contextMap = std::move(contextsStillCurrent);
1274 
1275         // Assert that the total number of contexts is the same before and after context
1276         // invalidation.
1277         ASSERT(contextSetSizeBeforeInvalidation ==
1278                mState.contextMap.size() + mInvalidContextMap.size());
1279 
1280         if (!mState.contextMap.empty())
1281         {
1282             // There was atleast 1 context that was current on some thread, early return.
1283             return NoError();
1284         }
1285     }
1286 
1287     // The global texture and semaphore managers should be deleted with the last context that uses
1288     // it.
1289     ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
1290     ASSERT(mGlobalSemaphoreShareGroupUsers == 0 && mSemaphoreManager == nullptr);
1291 
1292     if (mManagersMutex != nullptr)
1293     {
1294         mManagersMutex->release();
1295         mManagersMutex = nullptr;
1296     }
1297 
1298     // Clean up all invalid objects
1299     ANGLE_TRY(destroyInvalidEglObjects());
1300 
1301     mSyncPools.clear();
1302 
1303     mConfigSet.clear();
1304 
1305     if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
1306     {
1307         // Don't delete the device if it was created externally using eglCreateDeviceANGLE
1308         // We also shouldn't set it to null in case eglInitialize() is called again later
1309         SafeDelete(mDevice);
1310     }
1311 
1312     // Before tearing down the backend device, ensure all deferred operations are run.  It is not
1313     // possible to defer them beyond this point.
1314     GetCurrentThreadUnlockedTailCall()->run(nullptr);
1315 
1316     mImplementation->terminate();
1317 
1318     mMemoryProgramCache.clear();
1319     mMemoryShaderCache.clear();
1320     mBlobCache.setBlobCacheFuncs(nullptr, nullptr);
1321 
1322     mState.singleThreadPool.reset();
1323     mState.multiThreadPool.reset();
1324 
1325     mState.deviceLost = false;
1326 
1327     mInitialized = false;
1328 
1329     gl::UninitializeDebugAnnotations();
1330 
1331     // TODO(jmadill): Store Platform in Display and deinit here.
1332     ANGLEResetDisplayPlatform(this);
1333 
1334     return NoError();
1335 }
1336 
1337 #if ANGLE_USE_DISPLAY_PREPARE_FOR_CALL
prepareForCall()1338 Error Display::prepareForCall()
1339 {
1340     return mImplementation->prepareForCall();
1341 }
1342 #endif
1343 
releaseThread()1344 Error Display::releaseThread()
1345 {
1346     // Need to check if initialized, because makeCurrent() may terminate the Display.
1347     if (!mInitialized)
1348     {
1349         return NoError();
1350     }
1351     ANGLE_TRY(mImplementation->releaseThread());
1352     return destroyInvalidEglObjects();
1353 }
1354 
getConfigs(const egl::AttributeMap & attribs) const1355 std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
1356 {
1357     return mConfigSet.filter(attribs);
1358 }
1359 
chooseConfig(const egl::AttributeMap & attribs) const1360 std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
1361 {
1362     egl::AttributeMap attribsWithDefaults = AttributeMap();
1363 
1364     // Insert default values for attributes that have either an Exact or Mask selection criteria,
1365     // and a default value that matters (e.g. isn't EGL_DONT_CARE):
1366     attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
1367     attribsWithDefaults.insert(EGL_LEVEL, 0);
1368     attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
1369     attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
1370     attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
1371     if (getExtensions().pixelFormatFloat)
1372     {
1373         attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
1374                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
1375     }
1376 
1377     // Add the caller-specified values (Note: the poorly-named insert() method will replace any
1378     // of the default values from above):
1379     for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
1380     {
1381         attribsWithDefaults.insert(attribIter->first, attribIter->second);
1382     }
1383 
1384     return mConfigSet.filter(attribsWithDefaults);
1385 }
1386 
createWindowSurface(const Config * configuration,EGLNativeWindowType window,const AttributeMap & attribs,Surface ** outSurface)1387 Error Display::createWindowSurface(const Config *configuration,
1388                                    EGLNativeWindowType window,
1389                                    const AttributeMap &attribs,
1390                                    Surface **outSurface)
1391 {
1392     if (mImplementation->testDeviceLost())
1393     {
1394         ANGLE_TRY(restoreLostDevice());
1395     }
1396 
1397     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1398     SurfacePointer surface(new WindowSurface(mImplementation, id, configuration, window, attribs,
1399                                              mFrontendFeatures.forceRobustResourceInit.enabled),
1400                            this);
1401     ANGLE_TRY(surface->initialize(this));
1402 
1403     ASSERT(outSurface != nullptr);
1404     *outSurface = surface.release();
1405     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1406 
1407     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1408     ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
1409     windowSurfaces->insert(std::make_pair(window, *outSurface));
1410 
1411     mSurface = *outSurface;
1412 
1413     return NoError();
1414 }
1415 
createPbufferSurface(const Config * configuration,const AttributeMap & attribs,Surface ** outSurface)1416 Error Display::createPbufferSurface(const Config *configuration,
1417                                     const AttributeMap &attribs,
1418                                     Surface **outSurface)
1419 {
1420     ASSERT(isInitialized());
1421 
1422     if (mImplementation->testDeviceLost())
1423     {
1424         ANGLE_TRY(restoreLostDevice());
1425     }
1426 
1427     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1428     SurfacePointer surface(new PbufferSurface(mImplementation, id, configuration, attribs,
1429                                               mFrontendFeatures.forceRobustResourceInit.enabled),
1430                            this);
1431     ANGLE_TRY(surface->initialize(this));
1432 
1433     ASSERT(outSurface != nullptr);
1434     *outSurface = surface.release();
1435     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1436 
1437     return NoError();
1438 }
1439 
createPbufferFromClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,Surface ** outSurface)1440 Error Display::createPbufferFromClientBuffer(const Config *configuration,
1441                                              EGLenum buftype,
1442                                              EGLClientBuffer clientBuffer,
1443                                              const AttributeMap &attribs,
1444                                              Surface **outSurface)
1445 {
1446     ASSERT(isInitialized());
1447 
1448     if (mImplementation->testDeviceLost())
1449     {
1450         ANGLE_TRY(restoreLostDevice());
1451     }
1452 
1453     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1454     SurfacePointer surface(
1455         new PbufferSurface(mImplementation, id, configuration, buftype, clientBuffer, attribs,
1456                            mFrontendFeatures.forceRobustResourceInit.enabled),
1457         this);
1458     ANGLE_TRY(surface->initialize(this));
1459 
1460     ASSERT(outSurface != nullptr);
1461     *outSurface = surface.release();
1462     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1463 
1464     return NoError();
1465 }
1466 
createPixmapSurface(const Config * configuration,NativePixmapType nativePixmap,const AttributeMap & attribs,Surface ** outSurface)1467 Error Display::createPixmapSurface(const Config *configuration,
1468                                    NativePixmapType nativePixmap,
1469                                    const AttributeMap &attribs,
1470                                    Surface **outSurface)
1471 {
1472     ASSERT(isInitialized());
1473 
1474     if (mImplementation->testDeviceLost())
1475     {
1476         ANGLE_TRY(restoreLostDevice());
1477     }
1478 
1479     SurfaceID id = {mSurfaceHandleAllocator.allocate()};
1480     SurfacePointer surface(
1481         new PixmapSurface(mImplementation, id, configuration, nativePixmap, attribs,
1482                           mFrontendFeatures.forceRobustResourceInit.enabled),
1483         this);
1484     ANGLE_TRY(surface->initialize(this));
1485 
1486     ASSERT(outSurface != nullptr);
1487     *outSurface = surface.release();
1488     mState.surfaceMap.insert(std::pair((*outSurface)->id().value, *outSurface));
1489 
1490     return NoError();
1491 }
1492 
createImage(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attribs,Image ** outImage)1493 Error Display::createImage(const gl::Context *context,
1494                            EGLenum target,
1495                            EGLClientBuffer buffer,
1496                            const AttributeMap &attribs,
1497                            Image **outImage)
1498 {
1499     ASSERT(isInitialized());
1500 
1501     if (mImplementation->testDeviceLost())
1502     {
1503         ANGLE_TRY(restoreLostDevice());
1504     }
1505 
1506     egl::ImageSibling *sibling = nullptr;
1507     if (IsTextureTarget(target))
1508     {
1509         sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1510     }
1511     else if (IsRenderbufferTarget(target))
1512     {
1513         sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1514     }
1515     else if (IsExternalImageTarget(target))
1516     {
1517         sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
1518     }
1519     else
1520     {
1521         UNREACHABLE();
1522     }
1523     ASSERT(sibling != nullptr);
1524 
1525     ImageID id = {mImageHandleAllocator.allocate()};
1526     angle::UniqueObjectPointer<Image, Display> imagePtr(
1527         new Image(mImplementation, id, context, target, sibling, attribs), this);
1528     ANGLE_TRY(imagePtr->initialize(this, context));
1529 
1530     Image *image = imagePtr.release();
1531 
1532     ASSERT(outImage != nullptr);
1533     *outImage = image;
1534 
1535     // Add this image to the list of all images and hold a ref to it.
1536     image->addRef();
1537     mImageMap.insert(std::pair(image->id().value, image));
1538 
1539     return NoError();
1540 }
1541 
createStream(const AttributeMap & attribs,Stream ** outStream)1542 Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
1543 {
1544     ASSERT(isInitialized());
1545 
1546     Stream *stream = new Stream(this, attribs);
1547 
1548     ASSERT(stream != nullptr);
1549     mStreamSet.insert(stream);
1550 
1551     ASSERT(outStream != nullptr);
1552     *outStream = stream;
1553 
1554     return NoError();
1555 }
1556 
createContext(const Config * configuration,gl::Context * shareContext,const AttributeMap & attribs,gl::Context ** outContext)1557 Error Display::createContext(const Config *configuration,
1558                              gl::Context *shareContext,
1559                              const AttributeMap &attribs,
1560                              gl::Context **outContext)
1561 {
1562     ASSERT(!mTerminatedByApi);
1563     ASSERT(isInitialized());
1564 
1565     if (mImplementation->testDeviceLost())
1566     {
1567         ANGLE_TRY(restoreLostDevice());
1568     }
1569 
1570     // This display texture sharing will allow the first context to create the texture share group.
1571     bool usingDisplayTextureShareGroup =
1572         attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1573     gl::TextureManager *shareTextures = nullptr;
1574 
1575     if (usingDisplayTextureShareGroup)
1576     {
1577         ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
1578         if (mTextureManager == nullptr)
1579         {
1580             mTextureManager = new gl::TextureManager();
1581         }
1582 
1583         mGlobalTextureShareGroupUsers++;
1584         shareTextures = mTextureManager;
1585     }
1586 
1587     // This display semaphore sharing will allow the first context to create the semaphore share
1588     // group.
1589     bool usingDisplaySemaphoreShareGroup =
1590         attribs.get(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1591     gl::SemaphoreManager *shareSemaphores = nullptr;
1592     if (usingDisplaySemaphoreShareGroup)
1593     {
1594         ASSERT((mSemaphoreManager == nullptr) == (mGlobalSemaphoreShareGroupUsers == 0));
1595         if (mSemaphoreManager == nullptr)
1596         {
1597             mSemaphoreManager = new gl::SemaphoreManager();
1598         }
1599 
1600         mGlobalSemaphoreShareGroupUsers++;
1601         shareSemaphores = mSemaphoreManager;
1602     }
1603 
1604     ScopedContextMutexLock mutexLock;
1605     ContextMutex *sharedContextMutex = nullptr;
1606     if (kIsContextMutexEnabled)
1607     {
1608         ASSERT(mManagersMutex != nullptr);
1609         if (shareContext != nullptr)
1610         {
1611             sharedContextMutex = shareContext->getContextMutex().getRoot();
1612         }
1613         else if (shareTextures != nullptr || shareSemaphores != nullptr)
1614         {
1615             mutexLock          = ScopedContextMutexLock(mManagersMutex);
1616             sharedContextMutex = mManagersMutex->getRoot();
1617         }
1618         // When using shareTextures/Semaphores all Contexts in the Group must use mManagersMutex.
1619         ASSERT((shareTextures == nullptr && shareSemaphores == nullptr) ||
1620                sharedContextMutex == mManagersMutex->getRoot());
1621     }
1622 
1623     gl::MemoryProgramCache *programCachePointer = &mMemoryProgramCache;
1624     // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
1625     // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
1626     // at any time.
1627     bool usesProgramCacheControl = attribs.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
1628     if (usesProgramCacheControl)
1629     {
1630         bool programCacheControlEnabled =
1631             (attribs.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) == GL_TRUE);
1632         // A program cache size of zero indicates it should be disabled.
1633         if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
1634         {
1635             programCachePointer = nullptr;
1636         }
1637     }
1638 
1639     gl::MemoryShaderCache *shaderCachePointer = &mMemoryShaderCache;
1640     // Check if shader caching frontend feature is enabled.
1641     if (!mFrontendFeatures.cacheCompiledShader.enabled)
1642     {
1643         shaderCachePointer = nullptr;
1644     }
1645 
1646     gl::Context *context =
1647         new gl::Context(this, configuration, shareContext, shareTextures, shareSemaphores,
1648                         sharedContextMutex, programCachePointer, shaderCachePointer, attribs,
1649                         mDisplayExtensions, GetClientExtensions());
1650     Error error = context->initialize();
1651     if (error.isError())
1652     {
1653         delete context;
1654         return error;
1655     }
1656 
1657     if (shareContext != nullptr)
1658     {
1659         shareContext->setShared();
1660     }
1661 
1662     ASSERT(context != nullptr);
1663     {
1664         std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
1665         mState.contextMap.insert(std::pair(context->id().value, context));
1666     }
1667 
1668     ASSERT(outContext != nullptr);
1669     *outContext = context;
1670     return NoError();
1671 }
1672 
createSync(const gl::Context * currentContext,EGLenum type,const AttributeMap & attribs,Sync ** outSync)1673 Error Display::createSync(const gl::Context *currentContext,
1674                           EGLenum type,
1675                           const AttributeMap &attribs,
1676                           Sync **outSync)
1677 {
1678     ASSERT(isInitialized());
1679 
1680     SyncID id = {mSyncHandleAllocator.allocate()};
1681 
1682     if (mImplementation->testDeviceLost())
1683     {
1684         ANGLE_TRY(restoreLostDevice());
1685     }
1686 
1687     std::unique_ptr<Sync> sync;
1688 
1689     SyncPool &pool = mSyncPools[type];
1690     if (!pool.empty())
1691     {
1692         sync = std::move(pool.back());
1693         pool.pop_back();
1694     }
1695     else
1696     {
1697         sync.reset(new Sync(mImplementation, type));
1698     }
1699 
1700     Error err = sync->initialize(this, currentContext, id, attribs);
1701     if (err.isError())
1702     {
1703         sync->onDestroy(this);
1704         return err;
1705     }
1706 
1707     *outSync = sync.get();
1708     mSyncMap.insert(std::pair(id.value, std::move(sync)));
1709 
1710     return NoError();
1711 }
1712 
makeCurrent(Thread * thread,gl::Context * previousContext,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)1713 Error Display::makeCurrent(Thread *thread,
1714                            gl::Context *previousContext,
1715                            egl::Surface *drawSurface,
1716                            egl::Surface *readSurface,
1717                            gl::Context *context)
1718 {
1719     if (!mInitialized)
1720     {
1721         return NoError();
1722     }
1723 
1724     bool contextChanged = context != previousContext;
1725     if (previousContext != nullptr && contextChanged)
1726     {
1727         // Need AddRefLock because there may be ContextMutex destruction.
1728         ScopedContextMutexAddRefLock lock(previousContext->getContextMutex());
1729 
1730         previousContext->release();
1731         thread->setCurrent(nullptr);
1732 
1733         auto error = previousContext->unMakeCurrent(this);
1734         if (!previousContext->isReferenced() && previousContext->isDestroyed())
1735         {
1736             // The previous Context may have been created with a different Display.
1737             Display *previousDisplay = previousContext->getDisplay();
1738             ANGLE_TRY(previousDisplay->releaseContext(previousContext, thread));
1739         }
1740         ANGLE_TRY(error);
1741     }
1742 
1743     {
1744         ScopedContextMutexLock lock(context != nullptr ? &context->getContextMutex() : nullptr);
1745 
1746         thread->setCurrent(context);
1747 
1748         ANGLE_TRY(mImplementation->makeCurrent(this, drawSurface, readSurface, context));
1749 
1750         if (context != nullptr)
1751         {
1752             ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface));
1753             if (contextChanged)
1754             {
1755                 context->addRef();
1756             }
1757         }
1758     }
1759 
1760     // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being
1761     // used.
1762     {
1763         std::lock_guard<angle::SimpleMutex> lock(mScratchBufferMutex);
1764 
1765         for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers)
1766         {
1767             scatchBuffer.tick();
1768         }
1769         for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers)
1770         {
1771             zeroFilledBuffer.tick();
1772         }
1773     }
1774 
1775     // If eglTerminate() has previously been called and Context was changed, perform InternalCleanup
1776     // to invalidate any non-current Contexts, and possibly fully terminate the Display and release
1777     // all of its resources.
1778     if (mTerminatedByApi && contextChanged)
1779     {
1780         return terminate(thread, TerminateReason::InternalCleanup);
1781     }
1782 
1783     return NoError();
1784 }
1785 
restoreLostDevice()1786 Error Display::restoreLostDevice()
1787 {
1788     {
1789         std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
1790         for (ContextMap::iterator ctx = mState.contextMap.begin(); ctx != mState.contextMap.end();
1791              ctx++)
1792         {
1793             if (ctx->second->isResetNotificationEnabled())
1794             {
1795                 // If reset notifications have been requested, application must delete all contexts
1796                 // first
1797                 return egl::Error(EGL_CONTEXT_LOST);
1798             }
1799         }
1800     }
1801 
1802     return mImplementation->restoreLostDevice(this);
1803 }
1804 
destroySurfaceImpl(Surface * surface,SurfaceMap * surfaces)1805 Error Display::destroySurfaceImpl(Surface *surface, SurfaceMap *surfaces)
1806 {
1807     if (surface->getType() == EGL_WINDOW_BIT)
1808     {
1809         WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1810         ASSERT(windowSurfaces);
1811 
1812         bool surfaceRemoved = false;
1813         for (WindowSurfaceMap::iterator iter = windowSurfaces->begin();
1814              iter != windowSurfaces->end(); iter++)
1815         {
1816             if (iter->second == surface)
1817             {
1818                 windowSurfaces->erase(iter);
1819                 surfaceRemoved = true;
1820                 break;
1821             }
1822         }
1823 
1824         ASSERT(surfaceRemoved);
1825     }
1826 
1827     auto iter = surfaces->find(surface->id().value);
1828     ASSERT(iter != surfaces->end());
1829     mSurfaceHandleAllocator.release(surface->id().value);
1830     surfaces->erase(iter);
1831     ANGLE_TRY(surface->onDestroy(this));
1832     return NoError();
1833 }
1834 
destroyImageImpl(Image * image,ImageMap * images)1835 void Display::destroyImageImpl(Image *image, ImageMap *images)
1836 {
1837     auto iter = images->find(image->id().value);
1838     ASSERT(iter != images->end());
1839     mImageHandleAllocator.release(image->id().value);
1840     {
1841         // Need AddRefLock because there may be ContextMutex destruction.
1842         ScopedContextMutexAddRefLock lock(image->getContextMutex());
1843         iter->second->release(this);
1844     }
1845     images->erase(iter);
1846 }
1847 
destroyStreamImpl(Stream * stream,StreamSet * streams)1848 void Display::destroyStreamImpl(Stream *stream, StreamSet *streams)
1849 {
1850     streams->erase(stream);
1851     SafeDelete(stream);
1852 }
1853 
1854 // releaseContext must be called with the context being deleted as current.
1855 // To do that we can only call this in two places, Display::makeCurrent at the point where this
1856 // context is being made uncurrent and in Display::destroyContext where we make the context current
1857 // as part of destruction.
releaseContext(gl::Context * context,Thread * thread)1858 Error Display::releaseContext(gl::Context *context, Thread *thread)
1859 {
1860     // Use scoped_ptr to make sure the context is always freed.
1861     std::unique_ptr<gl::Context> uniqueContextPtr;
1862     {
1863         std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
1864         uniqueContextPtr = eraseContextImpl(context, &mState.contextMap);
1865     }
1866     return releaseContextImpl(std::move(uniqueContextPtr));
1867 }
1868 
eraseContextImpl(gl::Context * context,ContextMap * contexts)1869 std::unique_ptr<gl::Context> Display::eraseContextImpl(gl::Context *context, ContextMap *contexts)
1870 {
1871     ASSERT(!context->isReferenced());
1872 
1873     // Use scoped_ptr to make sure the context is always freed.
1874     std::unique_ptr<gl::Context> unique_context(context);
1875     ASSERT(contexts->find(context->id().value) != contexts->end());
1876     contexts->erase(context->id().value);
1877 
1878     return unique_context;
1879 }
1880 
releaseContextImpl(std::unique_ptr<gl::Context> && context)1881 Error Display::releaseContextImpl(std::unique_ptr<gl::Context> &&context)
1882 {
1883     if (context->usingDisplayTextureShareGroup())
1884     {
1885         ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
1886         if (mGlobalTextureShareGroupUsers == 1)
1887         {
1888             // If this is the last context using the global share group, destroy the global
1889             // texture manager so that the textures can be destroyed while a context still
1890             // exists
1891             mTextureManager->release(context.get());
1892             mTextureManager = nullptr;
1893         }
1894         mGlobalTextureShareGroupUsers--;
1895     }
1896 
1897     if (context->usingDisplaySemaphoreShareGroup())
1898     {
1899         ASSERT(mGlobalSemaphoreShareGroupUsers >= 1 && mSemaphoreManager != nullptr);
1900         if (mGlobalSemaphoreShareGroupUsers == 1)
1901         {
1902             // If this is the last context using the global share group, destroy the global
1903             // semaphore manager so that the semaphores can be destroyed while a context still
1904             // exists
1905             mSemaphoreManager->release(context.get());
1906             mSemaphoreManager = nullptr;
1907         }
1908         mGlobalSemaphoreShareGroupUsers--;
1909     }
1910 
1911     ANGLE_TRY(context->onDestroy(this));
1912 
1913     return NoError();
1914 }
1915 
destroyContext(Thread * thread,gl::Context * context)1916 Error Display::destroyContext(Thread *thread, gl::Context *context)
1917 {
1918     auto *currentContext     = thread->getContext();
1919     auto *currentDrawSurface = thread->getCurrentDrawSurface();
1920     auto *currentReadSurface = thread->getCurrentReadSurface();
1921 
1922     context->setIsDestroyed();
1923 
1924     // If the context is still current on at least 1 thread, just return since it'll be released
1925     // once no threads have it current anymore.
1926     if (context->isReferenced())
1927     {
1928         return NoError();
1929     }
1930 
1931     // For external context, we cannot change the current native context, and the API user should
1932     // make sure the native context is current.
1933     if (context->isExternal())
1934     {
1935         // Need AddRefLock because there may be ContextMutex destruction.
1936         ScopedContextMutexAddRefLock lock(context->getContextMutex());
1937         ANGLE_TRY(releaseContext(context, thread));
1938     }
1939     else
1940     {
1941         // Keep |currentContext| alive, while releasing |context|.
1942         gl::ScopedContextRef scopedContextRef(currentContext);
1943 
1944         // keep |currentDrawSurface| and |currentReadSurface| alive as well
1945         // while releasing |context|.
1946         ScopedSurfaceRef drawSurfaceRef(currentDrawSurface);
1947         ScopedSurfaceRef readSurfaceRef(
1948             currentReadSurface == currentDrawSurface ? nullptr : currentReadSurface);
1949 
1950         // Make the context current, so we can release resources belong to the context, and then
1951         // when context is released from the current, it will be destroyed.
1952         // TODO(http://anglebug.com/42264840): Don't require a Context to be current in order to
1953         // destroy it.
1954         ANGLE_TRY(makeCurrent(thread, currentContext, nullptr, nullptr, context));
1955         ANGLE_TRY(
1956             makeCurrent(thread, context, currentDrawSurface, currentReadSurface, currentContext));
1957     }
1958 
1959     return NoError();
1960 }
1961 
destroySyncImpl(SyncID syncId,SyncMap * syncs)1962 void Display::destroySyncImpl(SyncID syncId, SyncMap *syncs)
1963 {
1964     auto iter = syncs->find(syncId.value);
1965     ASSERT(iter != syncs->end());
1966     mSyncHandleAllocator.release(syncId.value);
1967 
1968     auto &sync = iter->second;
1969     sync->onDestroy(this);
1970 
1971     SyncPool &pool = mSyncPools[sync->getType()];
1972     if (pool.size() < kMaxSyncPoolSizePerType)
1973     {
1974         pool.push_back(std::move(sync));
1975     }
1976 
1977     syncs->erase(iter);
1978 }
1979 
destroyImage(Image * image)1980 void Display::destroyImage(Image *image)
1981 {
1982     return destroyImageImpl(image, &mImageMap);
1983 }
1984 
destroyStream(Stream * stream)1985 void Display::destroyStream(Stream *stream)
1986 {
1987     return destroyStreamImpl(stream, &mStreamSet);
1988 }
1989 
destroySurface(Surface * surface)1990 Error Display::destroySurface(Surface *surface)
1991 {
1992     return destroySurfaceImpl(surface, &mState.surfaceMap);
1993 }
1994 
destroySync(Sync * sync)1995 void Display::destroySync(Sync *sync)
1996 {
1997     return destroySyncImpl(sync->id(), &mSyncMap);
1998 }
1999 
isDeviceLost() const2000 bool Display::isDeviceLost() const
2001 {
2002     ASSERT(isInitialized());
2003     return mState.deviceLost;
2004 }
2005 
testDeviceLost()2006 bool Display::testDeviceLost()
2007 {
2008     ASSERT(isInitialized());
2009 
2010     if (!mState.deviceLost && mImplementation->testDeviceLost())
2011     {
2012         notifyDeviceLost();
2013     }
2014 
2015     return mState.deviceLost;
2016 }
2017 
notifyDeviceLost()2018 void Display::notifyDeviceLost()
2019 {
2020     mState.notifyDeviceLost();
2021 }
2022 
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)2023 void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
2024 {
2025     mBlobCache.setBlobCacheFuncs(set, get);
2026     mImplementation->setBlobCacheFuncs(set, get);
2027 }
2028 
2029 // static
GetNativeClientBuffer(const AHardwareBuffer * buffer)2030 EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
2031 {
2032     return angle::android::AHardwareBufferToClientBuffer(buffer);
2033 }
2034 
2035 // static
CreateNativeClientBuffer(const egl::AttributeMap & attribMap,EGLClientBuffer * eglClientBuffer)2036 Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
2037                                         EGLClientBuffer *eglClientBuffer)
2038 {
2039     int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap);
2040     int width                       = attribMap.getAsInt(EGL_WIDTH, 0);
2041     int height                      = attribMap.getAsInt(EGL_HEIGHT, 0);
2042     int usage                       = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
2043 
2044     // https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock
2045     // for AHardwareBuffer_lock()
2046     // The passed AHardwareBuffer must have one layer, otherwise the call will fail.
2047     constexpr int kLayerCount = 1;
2048 
2049     *eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer(
2050         width, height, kLayerCount, androidHardwareBufferFormat, usage);
2051 
2052     return (*eglClientBuffer == nullptr)
2053                ? egl::Error(EGL_BAD_PARAMETER, "native client buffer allocation failed.")
2054                : NoError();
2055 }
2056 
waitClient(const gl::Context * context)2057 Error Display::waitClient(const gl::Context *context)
2058 {
2059     return mImplementation->waitClient(context);
2060 }
2061 
waitNative(const gl::Context * context,EGLint engine)2062 Error Display::waitNative(const gl::Context *context, EGLint engine)
2063 {
2064     return mImplementation->waitNative(context, engine);
2065 }
2066 
getCaps() const2067 const Caps &Display::getCaps() const
2068 {
2069     return mCaps;
2070 }
2071 
isInitialized() const2072 bool Display::isInitialized() const
2073 {
2074     return mInitialized;
2075 }
2076 
isValidConfig(const Config * config) const2077 bool Display::isValidConfig(const Config *config) const
2078 {
2079     return mConfigSet.contains(config);
2080 }
2081 
isValidContext(const gl::ContextID contextID) const2082 bool Display::isValidContext(const gl::ContextID contextID) const
2083 {
2084     return getContext(contextID) != nullptr;
2085 }
2086 
isValidSurface(SurfaceID surfaceID) const2087 bool Display::isValidSurface(SurfaceID surfaceID) const
2088 {
2089     return getSurface(surfaceID) != nullptr;
2090 }
2091 
isValidImage(ImageID imageID) const2092 bool Display::isValidImage(ImageID imageID) const
2093 {
2094     return getImage(imageID) != nullptr;
2095 }
2096 
isValidStream(const Stream * stream) const2097 bool Display::isValidStream(const Stream *stream) const
2098 {
2099     return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
2100 }
2101 
isValidSync(SyncID syncID) const2102 bool Display::isValidSync(SyncID syncID) const
2103 {
2104     return getSync(syncID) != nullptr;
2105 }
2106 
hasExistingWindowSurface(EGLNativeWindowType window)2107 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
2108 {
2109     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
2110     ASSERT(windowSurfaces);
2111 
2112     return windowSurfaces->find(window) != windowSurfaces->end();
2113 }
2114 
GenerateClientExtensions()2115 static ClientExtensions GenerateClientExtensions()
2116 {
2117     ClientExtensions extensions;
2118 
2119     extensions.clientExtensions = true;
2120     extensions.platformBase     = true;
2121     extensions.platformANGLE    = true;
2122 
2123 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
2124     extensions.platformANGLED3D = true;
2125     extensions.platformDevice   = true;
2126 #endif
2127 
2128 #if defined(ANGLE_USE_GBM)
2129     extensions.platformGbmKHR = true;
2130 #endif
2131 
2132 #if defined(ANGLE_USE_WAYLAND)
2133     extensions.platformWaylandEXT = true;
2134 #endif
2135 
2136 #if defined(ANGLE_PLATFORM_LINUX) && (defined(ANGLE_ENABLE_OPENGL) || defined(ANGLE_ENABLE_VULKAN))
2137     extensions.platformSurfacelessMESA = true;
2138 #endif
2139 
2140 #if defined(ANGLE_ENABLE_D3D11)
2141     extensions.platformANGLED3D11ON12 = angle::IsWindows10OrLater();
2142     extensions.platformANGLED3DLUID   = true;
2143     extensions.platformANGLEDeviceId  = true;
2144 #endif
2145 
2146 #if defined(ANGLE_ENABLE_OPENGL)
2147     extensions.platformANGLEOpenGL = true;
2148 #endif
2149 
2150 #if defined(ANGLE_ENABLE_NULL)
2151     extensions.platformANGLENULL = true;
2152 #endif
2153 
2154 #if defined(ANGLE_ENABLE_WGPU)
2155     extensions.platformANGLEWebgpu = true;
2156 #endif
2157 
2158 #if defined(ANGLE_ENABLE_D3D11)
2159     extensions.deviceCreation          = true;
2160     extensions.deviceCreationD3D11     = true;
2161     extensions.experimentalPresentPath = true;
2162 #endif
2163 
2164 #if defined(ANGLE_ENABLE_VULKAN)
2165     extensions.platformANGLEVulkan           = true;
2166     extensions.platformANGLEVulkanDeviceUUID = true;
2167     extensions.platformANGLEDeviceId         = true;
2168 #endif
2169 
2170 #if defined(ANGLE_ENABLE_SWIFTSHADER)
2171     extensions.platformANGLEDeviceTypeSwiftShader = true;
2172 #endif
2173 
2174 #if defined(ANGLE_ENABLE_METAL)
2175     extensions.platformANGLEMetal    = true;
2176     extensions.platformANGLEDeviceId = true;
2177 #endif
2178 
2179 #if defined(ANGLE_USE_X11)
2180     extensions.x11Visual = true;
2181 #endif
2182 
2183 #if defined(ANGLE_PLATFORM_LINUX)
2184     extensions.platformANGLEDeviceTypeEGLANGLE = true;
2185 #endif
2186 
2187 #if defined(ANGLE_ENABLE_CGL)
2188     extensions.platformANGLEDeviceContextVolatileCgl = true;
2189 #endif
2190 
2191 #if defined(ANGLE_ENABLE_METAL)
2192     extensions.displayPowerPreferenceANGLE = true;
2193 #endif
2194 
2195     extensions.clientGetAllProcAddresses = true;
2196     extensions.debug                     = true;
2197     extensions.featureControlANGLE       = true;
2198     extensions.deviceQueryEXT            = true;
2199     extensions.noErrorANGLE              = true;
2200 
2201     return extensions;
2202 }
2203 
2204 template <typename T>
GenerateExtensionsString(const T & extensions)2205 static std::string GenerateExtensionsString(const T &extensions)
2206 {
2207     std::vector<std::string> extensionsVector = extensions.getStrings();
2208 
2209     std::ostringstream stream;
2210     std::copy(extensionsVector.begin(), extensionsVector.end(),
2211               std::ostream_iterator<std::string>(stream, " "));
2212     return stream.str();
2213 }
2214 
2215 // static
GetClientExtensions()2216 const ClientExtensions &Display::GetClientExtensions()
2217 {
2218     static const ClientExtensions clientExtensions = GenerateClientExtensions();
2219     return clientExtensions;
2220 }
2221 
2222 // static
GetClientExtensionString()2223 const std::string &Display::GetClientExtensionString()
2224 {
2225     static const angle::base::NoDestructor<std::string> clientExtensionsString(
2226         GenerateExtensionsString(GetClientExtensions()));
2227     return *clientExtensionsString;
2228 }
2229 
initDisplayExtensions()2230 void Display::initDisplayExtensions()
2231 {
2232     mDisplayExtensions = mImplementation->getExtensions();
2233 
2234     // Some extensions are always available because they are implemented in the EGL layer.
2235     mDisplayExtensions.createContext        = true;
2236     mDisplayExtensions.createContextNoError = !mFrontendFeatures.forceGlErrorChecking.enabled;
2237     mDisplayExtensions.createContextWebGLCompatibility    = true;
2238     mDisplayExtensions.createContextBindGeneratesResource = true;
2239     mDisplayExtensions.createContextClientArrays          = true;
2240     mDisplayExtensions.pixelFormatFloat                   = true;
2241     mDisplayExtensions.reusableSyncKHR                    = true;
2242 
2243     // Force EGL_KHR_get_all_proc_addresses on.
2244     mDisplayExtensions.getAllProcAddresses = true;
2245 
2246     // Enable program cache control since it is not back-end dependent.
2247     mDisplayExtensions.programCacheControlANGLE = true;
2248 
2249     // Request extension is implemented in the ANGLE frontend
2250     mDisplayExtensions.createContextExtensionsEnabled = true;
2251 
2252     // Blob cache extension is provided by the ANGLE frontend
2253     mDisplayExtensions.blobCache = true;
2254 
2255     // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always
2256     // say that ANativeWindow is not recordable.
2257     mDisplayExtensions.recordable = true;
2258 
2259     // All backends support specific context versions
2260     mDisplayExtensions.createContextBackwardsCompatible = true;
2261 
2262     // EGL_ANGLE_memory_usage_report is implemented on front end.
2263     mDisplayExtensions.memoryUsageReportANGLE = true;
2264 
2265     mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
2266 }
2267 
isValidNativeWindow(EGLNativeWindowType window) const2268 bool Display::isValidNativeWindow(EGLNativeWindowType window) const
2269 {
2270     return mImplementation->isValidNativeWindow(window);
2271 }
2272 
validateClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs) const2273 Error Display::validateClientBuffer(const Config *configuration,
2274                                     EGLenum buftype,
2275                                     EGLClientBuffer clientBuffer,
2276                                     const AttributeMap &attribs) const
2277 {
2278     return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
2279 }
2280 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const2281 Error Display::validateImageClientBuffer(const gl::Context *context,
2282                                          EGLenum target,
2283                                          EGLClientBuffer clientBuffer,
2284                                          const egl::AttributeMap &attribs) const
2285 {
2286     return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
2287 }
2288 
valdiatePixmap(const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes) const2289 Error Display::valdiatePixmap(const Config *config,
2290                               EGLNativePixmapType pixmap,
2291                               const AttributeMap &attributes) const
2292 {
2293     return mImplementation->validatePixmap(config, pixmap, attributes);
2294 }
2295 
isValidDisplay(const egl::Display * display)2296 bool Display::isValidDisplay(const egl::Display *display)
2297 {
2298     {
2299         std::lock_guard<angle::SimpleMutex> lock(*ANGLEPlatformDisplayMapMutex());
2300         const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
2301         for (const auto &displayPair : *anglePlatformDisplayMap)
2302         {
2303             if (displayPair.second == display)
2304             {
2305                 return true;
2306             }
2307         }
2308     }
2309 
2310     {
2311         std::lock_guard<angle::SimpleMutex> lock(*DevicePlatformDisplayMapMutex());
2312         const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
2313         for (const auto &displayPair : *devicePlatformDisplayMap)
2314         {
2315             if (displayPair.second == display)
2316             {
2317                 return true;
2318             }
2319         }
2320     }
2321 
2322     return false;
2323 }
2324 
isValidNativeDisplay(EGLNativeDisplayType display)2325 bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
2326 {
2327     // TODO(jmadill): handle this properly
2328     if (display == EGL_DEFAULT_DISPLAY)
2329     {
2330         return true;
2331     }
2332 
2333 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
2334     if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
2335         display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
2336     {
2337         return true;
2338     }
2339     return (WindowFromDC(display) != nullptr);
2340 #else
2341     return true;
2342 #endif
2343 }
2344 
initVendorString()2345 void Display::initVendorString()
2346 {
2347     mVendorString                = "Google Inc.";
2348     std::string vendorStringImpl = mImplementation->getVendorString();
2349     if (!vendorStringImpl.empty())
2350     {
2351         mVendorString += " (" + vendorStringImpl + ")";
2352     }
2353 }
2354 
initVersionString()2355 void Display::initVersionString()
2356 {
2357     mVersionString = mImplementation->getVersionString(true);
2358 }
2359 
initClientAPIString()2360 void Display::initClientAPIString()
2361 {
2362     mClientAPIString = "OpenGL_ES";
2363 }
2364 
initializeFrontendFeatures()2365 void Display::initializeFrontendFeatures()
2366 {
2367     // Enable on all Impls
2368     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, loseContextOnOutOfMemory, true);
2369     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, allowCompressedFormats, true);
2370 
2371     // Togglable until work on the extension is complete - anglebug.com/40096838.
2372     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, emulatePixelLocalStorage, true);
2373 
2374     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, forceMinimumMaxVertexAttributes, false);
2375 
2376     // Reject shaders with undefined behavior.  In the compiler, this only applies to WebGL.
2377     ANGLE_FEATURE_CONDITION(&mFrontendFeatures, rejectWebglShadersWithUndefinedBehavior, true);
2378 
2379     mImplementation->initializeFrontendFeatures(&mFrontendFeatures);
2380 }
2381 
getExtensions() const2382 const DisplayExtensions &Display::getExtensions() const
2383 {
2384     return mDisplayExtensions;
2385 }
2386 
getExtensionString() const2387 const std::string &Display::getExtensionString() const
2388 {
2389     return mDisplayExtensionString;
2390 }
2391 
getVendorString() const2392 const std::string &Display::getVendorString() const
2393 {
2394     return mVendorString;
2395 }
2396 
getVersionString() const2397 const std::string &Display::getVersionString() const
2398 {
2399     return mVersionString;
2400 }
2401 
getClientAPIString() const2402 const std::string &Display::getClientAPIString() const
2403 {
2404     return mClientAPIString;
2405 }
2406 
getBackendRendererDescription() const2407 std::string Display::getBackendRendererDescription() const
2408 {
2409     return mImplementation->getRendererDescription();
2410 }
2411 
getBackendVendorString() const2412 std::string Display::getBackendVendorString() const
2413 {
2414     return mImplementation->getVendorString();
2415 }
2416 
getBackendVersionString(bool includeFullVersion) const2417 std::string Display::getBackendVersionString(bool includeFullVersion) const
2418 {
2419     return mImplementation->getVersionString(includeFullVersion);
2420 }
2421 
getDevice() const2422 Device *Display::getDevice() const
2423 {
2424     return mDevice;
2425 }
2426 
getWGLSurface() const2427 Surface *Display::getWGLSurface() const
2428 {
2429     return mSurface;
2430 }
2431 
getMaxSupportedESVersion() const2432 gl::Version Display::getMaxSupportedESVersion() const
2433 {
2434     return mImplementation->getMaxSupportedESVersion();
2435 }
2436 
programCacheGetAttrib(EGLenum attrib) const2437 EGLint Display::programCacheGetAttrib(EGLenum attrib) const
2438 {
2439     switch (attrib)
2440     {
2441         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
2442             return static_cast<EGLint>(BlobCache::kKeyLength);
2443 
2444         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
2445             return static_cast<EGLint>(mMemoryProgramCache.entryCount());
2446 
2447         default:
2448             UNREACHABLE();
2449             return 0;
2450     }
2451 }
2452 
programCacheQuery(EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)2453 Error Display::programCacheQuery(EGLint index,
2454                                  void *key,
2455                                  EGLint *keysize,
2456                                  void *binary,
2457                                  EGLint *binarysize)
2458 {
2459     ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
2460 
2461     const BlobCache::Key *programHash = nullptr;
2462     BlobCache::Value programBinary;
2463     // TODO(jmadill): Make this thread-safe.
2464     bool result =
2465         mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
2466     if (!result)
2467     {
2468         return egl::Error(EGL_BAD_ACCESS, "Program binary not accessible.");
2469     }
2470 
2471     ASSERT(keysize && binarysize);
2472 
2473     if (key)
2474     {
2475         ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2476         memcpy(key, programHash->data(), BlobCache::kKeyLength);
2477     }
2478 
2479     if (binary)
2480     {
2481         // Note: we check the size here instead of in the validation code, since we need to
2482         // access the cache as atomically as possible. It's possible that the cache contents
2483         // could change between the validation size check and the retrieval.
2484         if (programBinary.size() > static_cast<size_t>(*binarysize))
2485         {
2486             return egl::Error(EGL_BAD_ACCESS, "Program binary too large or changed during access.");
2487         }
2488 
2489         memcpy(binary, programBinary.data(), programBinary.size());
2490     }
2491 
2492     *binarysize = static_cast<EGLint>(programBinary.size());
2493     *keysize    = static_cast<EGLint>(BlobCache::kKeyLength);
2494 
2495     return NoError();
2496 }
2497 
programCachePopulate(const void * key,EGLint keysize,const void * binary,EGLint binarysize)2498 Error Display::programCachePopulate(const void *key,
2499                                     EGLint keysize,
2500                                     const void *binary,
2501                                     EGLint binarysize)
2502 {
2503     ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength));
2504 
2505     BlobCache::Key programHash;
2506     memcpy(programHash.data(), key, BlobCache::kKeyLength);
2507 
2508     if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
2509                                        static_cast<size_t>(binarysize)))
2510     {
2511         return egl::Error(EGL_BAD_ACCESS, "Failed to copy program binary into the cache.");
2512     }
2513 
2514     return NoError();
2515 }
2516 
programCacheResize(EGLint limit,EGLenum mode)2517 EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
2518 {
2519     switch (mode)
2520     {
2521         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
2522         {
2523             size_t initialSize = mMemoryProgramCache.size();
2524             mMemoryProgramCache.resize(static_cast<size_t>(limit));
2525             return static_cast<EGLint>(initialSize);
2526         }
2527 
2528         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
2529             return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
2530 
2531         default:
2532             UNREACHABLE();
2533             return 0;
2534     }
2535 }
2536 
overrideFrontendFeatures(const std::vector<std::string> & featureNames,bool enabled)2537 void Display::overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled)
2538 {
2539     mFrontendFeatures.overrideFeatures(featureNames, enabled);
2540 }
2541 
queryStringi(const EGLint name,const EGLint index)2542 const char *Display::queryStringi(const EGLint name, const EGLint index)
2543 {
2544     const char *result = nullptr;
2545     switch (name)
2546     {
2547         case EGL_FEATURE_NAME_ANGLE:
2548             result = mFeatures[index]->name;
2549             break;
2550         case EGL_FEATURE_CATEGORY_ANGLE:
2551             result = angle::FeatureCategoryToString(mFeatures[index]->category);
2552             break;
2553         case EGL_FEATURE_STATUS_ANGLE:
2554             result = angle::FeatureStatusToString(mFeatures[index]->enabled);
2555             break;
2556         default:
2557             UNREACHABLE();
2558             return nullptr;
2559     }
2560     return result;
2561 }
2562 
queryAttrib(const EGLint attribute)2563 EGLAttrib Display::queryAttrib(const EGLint attribute)
2564 {
2565     EGLAttrib value = 0;
2566     switch (attribute)
2567     {
2568         case EGL_DEVICE_EXT:
2569             value = reinterpret_cast<EGLAttrib>(mDevice);
2570             break;
2571 
2572         case EGL_FEATURE_COUNT_ANGLE:
2573             value = mFeatures.size();
2574             break;
2575 
2576         default:
2577             UNREACHABLE();
2578     }
2579     return value;
2580 }
2581 
requestScratchBuffer()2582 angle::ScratchBuffer Display::requestScratchBuffer()
2583 {
2584     return requestScratchBufferImpl(&mScratchBuffers);
2585 }
2586 
returnScratchBuffer(angle::ScratchBuffer scratchBuffer)2587 void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer)
2588 {
2589     returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers);
2590 }
2591 
requestZeroFilledBuffer()2592 angle::ScratchBuffer Display::requestZeroFilledBuffer()
2593 {
2594     return requestScratchBufferImpl(&mZeroFilledBuffers);
2595 }
2596 
returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)2597 void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)
2598 {
2599     returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers);
2600 }
2601 
requestScratchBufferImpl(std::vector<angle::ScratchBuffer> * bufferVector)2602 angle::ScratchBuffer Display::requestScratchBufferImpl(
2603     std::vector<angle::ScratchBuffer> *bufferVector)
2604 {
2605     std::lock_guard<angle::SimpleMutex> lock(mScratchBufferMutex);
2606     if (!bufferVector->empty())
2607     {
2608         angle::ScratchBuffer buffer = std::move(bufferVector->back());
2609         bufferVector->pop_back();
2610         return buffer;
2611     }
2612 
2613     return angle::ScratchBuffer(kScratchBufferLifetime);
2614 }
2615 
returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,std::vector<angle::ScratchBuffer> * bufferVector)2616 void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
2617                                       std::vector<angle::ScratchBuffer> *bufferVector)
2618 {
2619     std::lock_guard<angle::SimpleMutex> lock(mScratchBufferMutex);
2620     bufferVector->push_back(std::move(scratchBuffer));
2621 }
2622 
handleGPUSwitch()2623 Error Display::handleGPUSwitch()
2624 {
2625     ANGLE_TRY(mImplementation->handleGPUSwitch());
2626     initVendorString();
2627     return NoError();
2628 }
2629 
forceGPUSwitch(EGLint gpuIDHigh,EGLint gpuIDLow)2630 Error Display::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
2631 {
2632     ANGLE_TRY(mImplementation->forceGPUSwitch(gpuIDHigh, gpuIDLow));
2633     initVendorString();
2634     return NoError();
2635 }
2636 
waitUntilWorkScheduled()2637 Error Display::waitUntilWorkScheduled()
2638 {
2639     ANGLE_TRY(mImplementation->waitUntilWorkScheduled());
2640     return NoError();
2641 }
2642 
lockVulkanQueue()2643 void Display::lockVulkanQueue()
2644 {
2645     return mImplementation->lockVulkanQueue();
2646 }
2647 
unlockVulkanQueue()2648 void Display::unlockVulkanQueue()
2649 {
2650     return mImplementation->unlockVulkanQueue();
2651 }
2652 
supportsDmaBufFormat(EGLint format) const2653 bool Display::supportsDmaBufFormat(EGLint format) const
2654 {
2655     return mImplementation->supportsDmaBufFormat(format);
2656 }
2657 
queryDmaBufFormats(EGLint max_formats,EGLint * formats,EGLint * num_formats)2658 Error Display::queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats)
2659 {
2660     ANGLE_TRY(mImplementation->queryDmaBufFormats(max_formats, formats, num_formats));
2661     return NoError();
2662 }
2663 
queryDmaBufModifiers(EGLint format,EGLint max_modifiers,EGLuint64KHR * modifiers,EGLBoolean * external_only,EGLint * num_modifiers)2664 Error Display::queryDmaBufModifiers(EGLint format,
2665                                     EGLint max_modifiers,
2666                                     EGLuint64KHR *modifiers,
2667                                     EGLBoolean *external_only,
2668                                     EGLint *num_modifiers)
2669 {
2670     ANGLE_TRY(mImplementation->queryDmaBufModifiers(format, max_modifiers, modifiers, external_only,
2671                                                     num_modifiers));
2672     return NoError();
2673 }
2674 
querySupportedCompressionRates(const Config * configuration,const AttributeMap & attributes,EGLint * rates,EGLint rate_size,EGLint * num_rates) const2675 Error Display::querySupportedCompressionRates(const Config *configuration,
2676                                               const AttributeMap &attributes,
2677                                               EGLint *rates,
2678                                               EGLint rate_size,
2679                                               EGLint *num_rates) const
2680 {
2681     ANGLE_TRY(mImplementation->querySupportedCompressionRates(configuration, attributes, rates,
2682                                                               rate_size, num_rates));
2683 
2684     return NoError();
2685 }
2686 
getImageLoadContext() const2687 angle::ImageLoadContext Display::getImageLoadContext() const
2688 {
2689     angle::ImageLoadContext imageLoadContext;
2690 
2691     imageLoadContext.singleThreadPool = mState.singleThreadPool;
2692     imageLoadContext.multiThreadPool  = mFrontendFeatures.singleThreadedTextureDecompression.enabled
2693                                             ? nullptr
2694                                             : mState.multiThreadPool;
2695 
2696     return imageLoadContext;
2697 }
2698 
getContext(gl::ContextID contextID) const2699 const gl::Context *Display::getContext(gl::ContextID contextID) const
2700 {
2701     std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
2702     auto iter = mState.contextMap.find(contextID.value);
2703     return iter != mState.contextMap.end() ? iter->second : nullptr;
2704 }
2705 
getSurface(egl::SurfaceID surfaceID) const2706 const egl::Surface *Display::getSurface(egl::SurfaceID surfaceID) const
2707 {
2708     auto iter = mState.surfaceMap.find(surfaceID.value);
2709     return iter != mState.surfaceMap.end() ? iter->second : nullptr;
2710 }
2711 
getImage(egl::ImageID imageID) const2712 const egl::Image *Display::getImage(egl::ImageID imageID) const
2713 {
2714     auto iter = mImageMap.find(imageID.value);
2715     return iter != mImageMap.end() ? iter->second : nullptr;
2716 }
2717 
getSync(egl::SyncID syncID) const2718 const egl::Sync *Display::getSync(egl::SyncID syncID) const
2719 {
2720     auto iter = mSyncMap.find(syncID.value);
2721     return iter != mSyncMap.end() ? iter->second.get() : nullptr;
2722 }
2723 
getContext(gl::ContextID contextID)2724 gl::Context *Display::getContext(gl::ContextID contextID)
2725 {
2726     std::lock_guard<angle::SimpleMutex> lock(mState.contextMapMutex);
2727     auto iter = mState.contextMap.find(contextID.value);
2728     return iter != mState.contextMap.end() ? iter->second : nullptr;
2729 }
2730 
getSurface(egl::SurfaceID surfaceID)2731 egl::Surface *Display::getSurface(egl::SurfaceID surfaceID)
2732 {
2733     auto iter = mState.surfaceMap.find(surfaceID.value);
2734     return iter != mState.surfaceMap.end() ? iter->second : nullptr;
2735 }
2736 
getImage(egl::ImageID imageID)2737 egl::Image *Display::getImage(egl::ImageID imageID)
2738 {
2739     auto iter = mImageMap.find(imageID.value);
2740     return iter != mImageMap.end() ? iter->second : nullptr;
2741 }
2742 
getSync(egl::SyncID syncID)2743 egl::Sync *Display::getSync(egl::SyncID syncID)
2744 {
2745     auto iter = mSyncMap.find(syncID.value);
2746     return iter != mSyncMap.end() ? iter->second.get() : nullptr;
2747 }
2748 
2749 // static
InitTLS()2750 void Display::InitTLS()
2751 {
2752     TLSData *tlsData = new TLSData;
2753 
2754 #if defined(ANGLE_PLATFORM_APPLE)
2755     SetDisplayTLS(tlsData);
2756 #else
2757     gDisplayTLS = tlsData;
2758 #endif
2759 }
2760 
2761 // static
GetCurrentThreadUnlockedTailCall()2762 angle::UnlockedTailCall *Display::GetCurrentThreadUnlockedTailCall()
2763 {
2764     return &GetDisplayTLS()->unlockedTailCall;
2765 }
2766 
2767 // static
GetCurrentThreadErrorScratchSpace()2768 Error *Display::GetCurrentThreadErrorScratchSpace()
2769 {
2770     return &GetDisplayTLS()->errorScratchSpace;
2771 }
2772 }  // namespace egl
2773