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