• 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::__anonda28230b0111::ANGLEPlatformDisplay106      ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType)
107          : nativeDisplayType(nativeDisplayType), powerPreference(EGL_LOW_POWER_ANGLE)
108      {}
109  
ANGLEPlatformDisplayegl::__anonda28230b0111::ANGLEPlatformDisplay110      ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType, EGLAttrib powerPreference)
111          : nativeDisplayType(nativeDisplayType), powerPreference(powerPreference)
112      {}
113  
tieegl::__anonda28230b0111::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