• 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/utilities.h"
30 #include "libANGLE/Context.h"
31 #include "libANGLE/Device.h"
32 #include "libANGLE/EGLSync.h"
33 #include "libANGLE/Image.h"
34 #include "libANGLE/ResourceManager.h"
35 #include "libANGLE/Stream.h"
36 #include "libANGLE/Surface.h"
37 #include "libANGLE/Thread.h"
38 #include "libANGLE/histogram_macros.h"
39 #include "libANGLE/renderer/DeviceImpl.h"
40 #include "libANGLE/renderer/DisplayImpl.h"
41 #include "libANGLE/renderer/ImageImpl.h"
42 #include "libANGLE/trace.h"
43 
44 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
45 #    include <versionhelpers.h>
46 
47 #    include "libANGLE/renderer/d3d/DisplayD3D.h"
48 #endif
49 
50 #if defined(ANGLE_ENABLE_OPENGL)
51 #    if defined(ANGLE_PLATFORM_WINDOWS)
52 #        include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
53 #    elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
54 #        include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
55 #    elif defined(ANGLE_PLATFORM_IOS)
56 #        include "libANGLE/renderer/gl/eagl/DisplayEAGL.h"
57 #    elif defined(ANGLE_PLATFORM_LINUX)
58 #        include "libANGLE/renderer/gl/egl/DisplayEGL.h"
59 #        if defined(ANGLE_USE_GBM)
60 #            include "libANGLE/renderer/gl/egl/gbm/DisplayGbm.h"
61 #        endif
62 #        if defined(ANGLE_USE_X11)
63 #            include "libANGLE/renderer/gl/glx/DisplayGLX.h"
64 #        endif
65 #    elif defined(ANGLE_PLATFORM_ANDROID)
66 #        include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
67 #    else
68 #        error Unsupported OpenGL platform.
69 #    endif
70 #endif
71 
72 #if defined(ANGLE_ENABLE_NULL)
73 #    include "libANGLE/renderer/null/DisplayNULL.h"
74 #endif  // defined(ANGLE_ENABLE_NULL)
75 
76 #if defined(ANGLE_ENABLE_VULKAN)
77 #    include "libANGLE/renderer/vulkan/DisplayVk_api.h"
78 #endif  // defined(ANGLE_ENABLE_VULKAN)
79 
80 #if defined(ANGLE_ENABLE_METAL)
81 #    include "libANGLE/renderer/metal/DisplayMtl_api.h"
82 #endif  // defined(ANGLE_ENABLE_METAL)
83 
84 namespace egl
85 {
86 
87 namespace
88 {
89 
90 typedef std::map<EGLNativeWindowType, Surface *> WindowSurfaceMap;
91 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
92 // associated with it.
GetWindowSurfaces()93 static WindowSurfaceMap *GetWindowSurfaces()
94 {
95     static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces;
96     return windowSurfaces.get();
97 }
98 
99 typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
GetANGLEPlatformDisplayMap()100 static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
101 {
102     static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays;
103     return displays.get();
104 }
105 
106 typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
GetDevicePlatformDisplayMap()107 static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
108 {
109     static angle::base::NoDestructor<DevicePlatformDisplayMap> displays;
110     return displays.get();
111 }
112 
CreateDisplayFromDevice(Device * eglDevice,const DisplayState & state)113 rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
114 {
115     rx::DisplayImpl *impl = nullptr;
116 
117     switch (eglDevice->getType())
118     {
119 #if defined(ANGLE_ENABLE_D3D11)
120         case EGL_D3D11_DEVICE_ANGLE:
121             impl = new rx::DisplayD3D(state);
122             break;
123 #endif
124 #if defined(ANGLE_ENABLE_D3D9)
125         case EGL_D3D9_DEVICE_ANGLE:
126             // Currently the only way to get EGLDeviceEXT representing a D3D9 device
127             // is to retrieve one from an already-existing EGLDisplay.
128             // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
129             // the already-existing display should be returned.
130             // Therefore this codepath to create a new display from the device
131             // should never be hit.
132             UNREACHABLE();
133             break;
134 #endif
135         default:
136             UNREACHABLE();
137             break;
138     }
139 
140     ASSERT(impl != nullptr);
141     return impl;
142 }
143 
144 // On platforms with support for multiple back-ends, allow an environment variable to control
145 // the default.  This is useful to run angle with benchmarks without having to modify the
146 // benchmark source.  Possible values for this environment variable (ANGLE_DEFAULT_PLATFORM)
147 // are: vulkan, gl, d3d11, null.
GetDisplayTypeFromEnvironment()148 EGLAttrib GetDisplayTypeFromEnvironment()
149 {
150     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
151     angle::ToLower(&angleDefaultEnv);
152 
153 #if defined(ANGLE_ENABLE_VULKAN)
154     if ((angleDefaultEnv == "vulkan") || (angleDefaultEnv == "vulkan-null") ||
155         (angleDefaultEnv == "swiftshader"))
156     {
157         return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
158     }
159 #endif
160 
161 #if defined(ANGLE_ENABLE_OPENGL)
162     if (angleDefaultEnv == "gl")
163     {
164         return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
165     }
166 #endif
167 
168 #if defined(ANGLE_ENABLE_D3D11)
169     if (angleDefaultEnv == "d3d11")
170     {
171         return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
172     }
173 #endif
174 
175 #if defined(ANGLE_ENABLE_NULL)
176     if (angleDefaultEnv == "null")
177     {
178         return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
179     }
180 #endif
181 
182 #if defined(ANGLE_ENABLE_D3D11)
183     return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
184 #elif defined(ANGLE_ENABLE_D3D9)
185     return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
186 #elif defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_PLATFORM_ANDROID)
187     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
188 #elif defined(ANGLE_ENABLE_OPENGL)
189 #    if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_USE_GBM)
190     return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
191 #    else
192     return EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
193 #    endif
194 #elif defined(ANGLE_ENABLE_METAL)
195     return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
196 #elif defined(ANGLE_ENABLE_VULKAN)
197     return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
198 #elif defined(ANGLE_ENABLE_NULL)
199     return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
200 #else
201 #    error No default ANGLE platform type
202 #endif
203 }
204 
GetDeviceTypeFromEnvironment()205 EGLAttrib GetDeviceTypeFromEnvironment()
206 {
207     std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
208     angle::ToLower(&angleDefaultEnv);
209 
210 #if defined(ANGLE_ENABLE_VULKAN)
211     if (angleDefaultEnv == "vulkan-null")
212     {
213         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
214     }
215     else if (angleDefaultEnv == "swiftshader")
216     {
217         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
218     }
219 #endif
220     return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
221 }
222 
GetPlatformTypeFromEnvironment()223 EGLAttrib GetPlatformTypeFromEnvironment()
224 {
225 #if defined(ANGLE_USE_X11) && !defined(ANGLE_USE_OZONE)
226     return EGL_PLATFORM_X11_EXT;
227 #else
228     return 0;
229 #endif
230 }
231 
CreateDisplayFromAttribs(EGLAttrib displayType,EGLAttrib deviceType,EGLAttrib platformType,const DisplayState & state)232 rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType,
233                                           EGLAttrib deviceType,
234                                           EGLAttrib platformType,
235                                           const DisplayState &state)
236 {
237     ASSERT(displayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
238     rx::DisplayImpl *impl = nullptr;
239 
240     switch (displayType)
241     {
242         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
243             UNREACHABLE();
244             break;
245 
246         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
247         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
248 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
249             impl = new rx::DisplayD3D(state);
250 #else
251             // A D3D display was requested on a platform that doesn't support it
252             UNREACHABLE();
253 #endif
254             break;
255 
256         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
257 #if defined(ANGLE_ENABLE_OPENGL)
258 #    if defined(ANGLE_PLATFORM_WINDOWS)
259             impl = new rx::DisplayWGL(state);
260 #    elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
261             impl = new rx::DisplayCGL(state);
262 #    elif defined(ANGLE_PLATFORM_IOS)
263             impl = new rx::DisplayEAGL(state);
264 #    elif defined(ANGLE_PLATFORM_LINUX)
265 #        if defined(ANGLE_USE_GBM)
266             if (platformType == 0)
267             {
268                 // If platformType is unknown, use DisplayGbm now. In the future, it should use
269                 // DisplayEGL letting native EGL decide what display to use.
270                 impl = new rx::DisplayGbm(state);
271                 break;
272             }
273 #        endif
274             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
275             {
276                 impl = new rx::DisplayEGL(state);
277                 break;
278             }
279             else
280             {
281 #        if defined(ANGLE_USE_X11)
282                 if (platformType == EGL_PLATFORM_X11_EXT)
283                 {
284                     impl = new rx::DisplayGLX(state);
285                     break;
286                 }
287 #        endif
288             }
289 #    elif defined(ANGLE_PLATFORM_ANDROID)
290             // No GL support on this platform, fail display creation.
291             impl = nullptr;
292 #    else
293 #        error Unsupported OpenGL platform.
294 #    endif
295 #else
296             // No display available
297             UNREACHABLE();
298 #endif  // defined(ANGLE_ENABLE_OPENGL)
299             break;
300 
301         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
302 #if defined(ANGLE_ENABLE_OPENGL)
303 #    if defined(ANGLE_PLATFORM_WINDOWS)
304             impl = new rx::DisplayWGL(state);
305 #    elif defined(ANGLE_PLATFORM_LINUX)
306 #        if defined(ANGLE_USE_GBM)
307             if (platformType == 0)
308             {
309                 // If platformType is unknown, use DisplayGbm now. In the future, it should use
310                 // DisplayEGL letting native EGL decide what display to use.
311                 impl = new rx::DisplayGbm(state);
312                 break;
313             }
314 #        endif
315             if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
316             {
317                 impl = new rx::DisplayEGL(state);
318                 break;
319             }
320             else
321             {
322 #        if defined(ANGLE_USE_X11)
323                 if (platformType == EGL_PLATFORM_X11_EXT)
324                 {
325                     impl = new rx::DisplayGLX(state);
326                     break;
327                 }
328 #        endif
329             }
330 #    elif defined(ANGLE_PLATFORM_ANDROID)
331             impl = new rx::DisplayAndroid(state);
332 #    else
333             // No GLES support on this platform, fail display creation.
334             impl = nullptr;
335 #    endif
336 #endif  // defined(ANGLE_ENABLE_OPENGL)
337             break;
338 
339         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
340 #if defined(ANGLE_ENABLE_VULKAN)
341 #    if defined(ANGLE_PLATFORM_WINDOWS)
342             if (rx::IsVulkanWin32DisplayAvailable())
343             {
344                 impl = rx::CreateVulkanWin32Display(state);
345             }
346 #    elif defined(ANGLE_PLATFORM_LINUX)
347 #        if defined(ANGLE_USE_X11)
348             if (platformType == EGL_PLATFORM_X11_EXT && rx::IsVulkanXcbDisplayAvailable())
349             {
350                 impl = rx::CreateVulkanXcbDisplay(state);
351                 break;
352             }
353 #        endif
354 #    elif defined(ANGLE_PLATFORM_ANDROID)
355             if (rx::IsVulkanAndroidDisplayAvailable())
356             {
357                 impl = rx::CreateVulkanAndroidDisplay(state);
358             }
359 #    elif defined(ANGLE_PLATFORM_FUCHSIA)
360             if (rx::IsVulkanFuchsiaDisplayAvailable())
361             {
362                 impl = rx::CreateVulkanFuchsiaDisplay(state);
363             }
364 #    elif defined(ANGLE_PLATFORM_GGP)
365             if (rx::IsVulkanGGPDisplayAvailable())
366             {
367                 impl = rx::CreateVulkanGGPDisplay(state);
368             }
369 #    elif defined(ANGLE_PLATFORM_APPLE)
370             if (rx::IsVulkanMacDisplayAvailable())
371             {
372                 impl = rx::CreateVulkanMacDisplay(state);
373             }
374 #    else
375 #        error Unsupported Vulkan platform.
376 #    endif
377 #else
378             // No display available
379             UNREACHABLE();
380 #endif  // defined(ANGLE_ENABLE_VULKAN)
381             break;
382         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
383 #if defined(ANGLE_ENABLE_METAL)
384             if (rx::IsMetalDisplayAvailable())
385             {
386                 impl = rx::CreateMetalDisplay(state);
387                 break;
388             }
389 #endif
390             // No display available
391             UNREACHABLE();
392             break;
393         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
394 #if defined(ANGLE_ENABLE_NULL)
395             impl = new rx::DisplayNULL(state);
396 #else
397             // No display available
398             UNREACHABLE();
399 #endif  // defined(ANGLE_ENABLE_NULL)
400             break;
401 
402         default:
403             UNREACHABLE();
404             break;
405     }
406 
407     return impl;
408 }
409 
Display_logError(angle::PlatformMethods * platform,const char * errorMessage)410 void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
411 {
412     gl::Trace(gl::LOG_ERR, errorMessage);
413 }
414 
Display_logWarning(angle::PlatformMethods * platform,const char * warningMessage)415 void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
416 {
417     gl::Trace(gl::LOG_WARN, warningMessage);
418 }
419 
Display_logInfo(angle::PlatformMethods * platform,const char * infoMessage)420 void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
421 {
422     // Uncomment to get info spam
423 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
424     gl::Trace(gl::LOG_INFO, infoMessage);
425 #endif
426 }
427 
EGLStringArrayToStringVector(const char ** ary)428 const std::vector<std::string> EGLStringArrayToStringVector(const char **ary)
429 {
430     std::vector<std::string> vec;
431     if (ary != nullptr)
432     {
433         for (; *ary != nullptr; ary++)
434         {
435             vec.push_back(std::string(*ary));
436         }
437     }
438     return vec;
439 }
440 
ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)441 void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
442 {
443     angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
444 
445     ANGLEResetDisplayPlatform(display);
446     platformMethods->logError   = Display_logError;
447     platformMethods->logWarning = Display_logWarning;
448     platformMethods->logInfo    = Display_logInfo;
449 }
450 
451 static constexpr uint32_t kScratchBufferLifetime = 64u;
452 
453 }  // anonymous namespace
454 
455 // ShareGroup
ShareGroup(rx::EGLImplFactory * factory)456 ShareGroup::ShareGroup(rx::EGLImplFactory *factory)
457     : mRefCount(1), mImplementation(factory->createShareGroup())
458 {}
459 
~ShareGroup()460 ShareGroup::~ShareGroup()
461 {
462     SafeDelete(mImplementation);
463 }
464 
addRef()465 void ShareGroup::addRef()
466 {
467     // This is protected by global lock, so no atomic is required
468     mRefCount++;
469 }
470 
release(const gl::Context * context)471 void ShareGroup::release(const gl::Context *context)
472 {
473     if (--mRefCount == 0)
474     {
475         delete this;
476     }
477 }
478 
479 // DisplayState
DisplayState(EGLNativeDisplayType nativeDisplayId)480 DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId)
481     : label(nullptr), featuresAllDisabled(false), displayId(nativeDisplayId)
482 {}
483 
~DisplayState()484 DisplayState::~DisplayState() {}
485 
486 // Note that ANGLE support on Ozone platform is limited. Our prefered support Matrix for
487 // EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following:
488 //
489 // |--------------------------------------------------------|
490 // | ANGLE type | DEVICE type |  PLATFORM type   | Display  |
491 // |--------------------------------------------------------|
492 // |   OPENGL   |     EGL     |       ANY        |   EGL    |
493 // |   OPENGL   |   HARDWARE  |     X11_EXT      |   GLX    |
494 // |  OPENGLES  |   HARDWARE  |     X11_EXT      |   GLX    |
495 // |  OPENGLES  |     EGL     |       ANY        |   EGL    |
496 // |   VULKAN   |   HARDWARE  |     X11_EXT      |  VkXcb   |
497 // |   VULKAN   | SWIFTSHADER |     X11_EXT      |  VkXcb   |
498 // |  OPENGLES  |   HARDWARE  | SURFACELESS_MESA |   EGL*   |
499 // |  OPENGLES  |   HARDWARE  |    DEVICE_EXT    |   EGL    |
500 // |   VULKAN   |   HARDWARE  | SURFACELESS_MESA | VkBase** |
501 // |   VULKAN   | SWIFTSHADER | SURFACELESS_MESA | VkBase** |
502 // |--------------------------------------------------------|
503 //
504 // * No surfaceless support yet.
505 // ** Not implemented yet.
506 //
507 // |-----------------------------------------------|
508 // |   OS    | BUILD type |  Default PLATFORM type |
509 // |-----------------------------------------------|
510 // |  Linux  |    X11     |        X11_EXT         |
511 // |  Linux  |   Ozone    |    SURFACELESS_MESA    |
512 // | Fuchsia |   Ozone    |        FUCHSIA***      |
513 // |-----------------------------------------------|
514 //
515 // *** Chosen implicitly. No EGLAttrib available.
516 //
517 // For more details, please refer to
518 // https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY
519 //
520 // static
GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,const AttributeMap & attribMap)521 Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
522                                               const AttributeMap &attribMap)
523 {
524     Display *display = nullptr;
525 
526     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
527     const auto &iter                  = displays->find(nativeDisplay);
528     if (iter != displays->end())
529     {
530         display = iter->second;
531     }
532 
533     if (display == nullptr)
534     {
535         // Validate the native display
536         if (!Display::isValidNativeDisplay(nativeDisplay))
537         {
538             return nullptr;
539         }
540 
541         display = new Display(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, nullptr);
542         displays->insert(std::make_pair(nativeDisplay, display));
543     }
544 
545     // Apply new attributes if the display is not initialized yet.
546     if (!display->isInitialized())
547     {
548         display->setAttributes(attribMap);
549 
550         display->updateAttribsFromEnvironment(attribMap);
551 
552         EGLAttrib displayType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
553         EGLAttrib deviceType  = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
554         EGLAttrib platformType =
555             display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
556         rx::DisplayImpl *impl =
557             CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState());
558         if (impl == nullptr)
559         {
560             // No valid display implementation for these attributes
561             return nullptr;
562         }
563 
564         display->setupDisplayPlatform(impl);
565     }
566 
567     return display;
568 }
569 
570 // static
GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)571 Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)
572 {
573     ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
574     const auto &iter                  = displays->find(nativeDisplay);
575 
576     // Check that there is a matching display
577     if (iter == displays->end())
578     {
579         return nullptr;
580     }
581 
582     return iter->second;
583 }
584 
585 // static
GetDisplayFromDevice(Device * device,const AttributeMap & attribMap)586 Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
587 {
588     Display *display = nullptr;
589 
590     ASSERT(Device::IsValidDevice(device));
591 
592     ANGLEPlatformDisplayMap *anglePlatformDisplays   = GetANGLEPlatformDisplayMap();
593     DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
594 
595     // First see if this eglDevice is in use by a Display created using ANGLE platform
596     for (auto &displayMapEntry : *anglePlatformDisplays)
597     {
598         egl::Display *iterDisplay = displayMapEntry.second;
599         if (iterDisplay->getDevice() == device)
600         {
601             display = iterDisplay;
602         }
603     }
604 
605     if (display == nullptr)
606     {
607         // See if the eglDevice is in use by a Display created using the DEVICE platform
608         const auto &iter = devicePlatformDisplays->find(device);
609         if (iter != devicePlatformDisplays->end())
610         {
611             display = iter->second;
612         }
613     }
614 
615     if (display == nullptr)
616     {
617         // Otherwise create a new Display
618         display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
619         devicePlatformDisplays->insert(std::make_pair(device, display));
620     }
621 
622     // Apply new attributes if the display is not initialized yet.
623     if (!display->isInitialized())
624     {
625         display->setAttributes(attribMap);
626         rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
627         display->setupDisplayPlatform(impl);
628     }
629 
630     return display;
631 }
632 
Display(EGLenum platform,EGLNativeDisplayType displayId,Device * eglDevice)633 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
634     : mState(displayId),
635       mImplementation(nullptr),
636       mAttributeMap(),
637       mConfigSet(),
638       mContextSet(),
639       mStreamSet(),
640       mInitialized(false),
641       mDeviceLost(false),
642       mCaps(),
643       mDisplayExtensions(),
644       mDisplayExtensionString(),
645       mVendorString(),
646       mDevice(eglDevice),
647       mSurface(nullptr),
648       mPlatform(platform),
649       mTextureManager(nullptr),
650       mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes),
651       mMemoryProgramCache(mBlobCache),
652       mGlobalTextureShareGroupUsers(0)
653 {}
654 
~Display()655 Display::~Display()
656 {
657     // TODO(jmadill): When is this called?
658     // terminate();
659 
660     if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
661     {
662         ANGLEPlatformDisplayMap *displays      = GetANGLEPlatformDisplayMap();
663         ANGLEPlatformDisplayMap::iterator iter = displays->find(mState.displayId);
664         if (iter != displays->end())
665         {
666             displays->erase(iter);
667         }
668     }
669     else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
670     {
671         DevicePlatformDisplayMap *displays      = GetDevicePlatformDisplayMap();
672         DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
673         if (iter != displays->end())
674         {
675             displays->erase(iter);
676         }
677     }
678     else
679     {
680         UNREACHABLE();
681     }
682 
683     SafeDelete(mDevice);
684     SafeDelete(mImplementation);
685 }
686 
setLabel(EGLLabelKHR label)687 void Display::setLabel(EGLLabelKHR label)
688 {
689     mState.label = label;
690 }
691 
getLabel() const692 EGLLabelKHR Display::getLabel() const
693 {
694     return mState.label;
695 }
696 
setupDisplayPlatform(rx::DisplayImpl * impl)697 void Display::setupDisplayPlatform(rx::DisplayImpl *impl)
698 {
699     ASSERT(!mInitialized);
700 
701     ASSERT(impl != nullptr);
702     SafeDelete(mImplementation);
703     mImplementation = impl;
704 
705     // TODO(jmadill): Store Platform in Display and init here.
706     const angle::PlatformMethods *platformMethods =
707         reinterpret_cast<const angle::PlatformMethods *>(
708             mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
709     if (platformMethods != nullptr)
710     {
711         *ANGLEPlatformCurrent() = *platformMethods;
712     }
713     else
714     {
715         ANGLESetDefaultDisplayPlatform(this);
716     }
717 
718     const char **featuresForceEnabled =
719         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0));
720     const char **featuresForceDisabled =
721         reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0));
722     mState.featureOverridesEnabled  = EGLStringArrayToStringVector(featuresForceEnabled);
723     mState.featureOverridesDisabled = EGLStringArrayToStringVector(featuresForceDisabled);
724     mState.featuresAllDisabled =
725         static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0));
726 }
727 
updateAttribsFromEnvironment(const AttributeMap & attribMap)728 void Display::updateAttribsFromEnvironment(const AttributeMap &attribMap)
729 {
730     EGLAttrib displayType =
731         attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
732     if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
733     {
734         displayType = GetDisplayTypeFromEnvironment();
735         mAttributeMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType);
736     }
737     EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0);
738     if (deviceType == 0)
739     {
740         deviceType = GetDeviceTypeFromEnvironment();
741         mAttributeMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType);
742     }
743     EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
744     if (platformType == 0)
745     {
746         platformType = GetPlatformTypeFromEnvironment();
747         mAttributeMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType);
748     }
749 }
750 
initialize()751 Error Display::initialize()
752 {
753     ASSERT(mImplementation != nullptr);
754     mImplementation->setBlobCache(&mBlobCache);
755 
756     // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
757     // properly saved & restored on all platforms. The cache won't allocate space until it's used
758     // and will be ignored entirely if the application / system sets it's own cache functions.
759     if (rx::ShouldUseDebugLayers(mAttributeMap))
760     {
761         mBlobCache.resize(1024 * 1024);
762     }
763 
764     gl::InitializeDebugAnnotations(&mAnnotator);
765 
766     gl::InitializeDebugMutexIfNeeded();
767 
768     SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
769     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
770 
771     if (isInitialized())
772     {
773         return NoError();
774     }
775 
776     Error error = mImplementation->initialize(this);
777     if (error.isError())
778     {
779         // Log extended error message here
780         ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
781         return error;
782     }
783 
784     mCaps = mImplementation->getCaps();
785 
786     mConfigSet = mImplementation->generateConfigs();
787     if (mConfigSet.size() == 0)
788     {
789         mImplementation->terminate();
790         return EglNotInitialized();
791     }
792 
793     // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs
794     for (auto &config : mConfigSet)
795     {
796         // TODO(geofflang): Enable the conformant bit once we pass enough tests
797         // config.second.conformant |= EGL_OPENGL_ES_BIT;
798 
799         config.second.renderableType |= EGL_OPENGL_ES_BIT;
800     }
801 
802     if (!mState.featuresAllDisabled)
803     {
804         initializeFrontendFeatures();
805     }
806 
807     mFeatures.clear();
808     mFrontendFeatures.populateFeatureList(&mFeatures);
809     mImplementation->populateFeatureList(&mFeatures);
810 
811     initDisplayExtensions();
812     initVendorString();
813 
814     // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
815     if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
816     {
817         if (mDisplayExtensions.deviceQuery)
818         {
819             std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice());
820             ASSERT(impl != nullptr);
821             error = impl->initialize();
822             if (error.isError())
823             {
824                 ERR() << "Failed to initialize display because device creation failed: "
825                       << error.getMessage();
826                 mImplementation->terminate();
827                 return error;
828             }
829             mDevice = new Device(this, impl.release());
830         }
831         else
832         {
833             mDevice = nullptr;
834         }
835     }
836     else
837     {
838         // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
839         // an external device
840         ASSERT(mDevice != nullptr);
841     }
842 
843     mInitialized = true;
844 
845     return NoError();
846 }
847 
terminate(const Thread * thread)848 Error Display::terminate(const Thread *thread)
849 {
850     if (!mInitialized)
851     {
852         return NoError();
853     }
854 
855     mMemoryProgramCache.clear();
856     mBlobCache.setBlobCacheFuncs(nullptr, nullptr);
857 
858     while (!mContextSet.empty())
859     {
860         ANGLE_TRY(destroyContext(thread, *mContextSet.begin()));
861     }
862 
863     ANGLE_TRY(makeCurrent(thread, nullptr, nullptr, nullptr));
864 
865     // The global texture manager should be deleted with the last context that uses it.
866     ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
867 
868     while (!mImageSet.empty())
869     {
870         destroyImage(*mImageSet.begin());
871     }
872 
873     while (!mStreamSet.empty())
874     {
875         destroyStream(*mStreamSet.begin());
876     }
877 
878     while (!mSyncSet.empty())
879     {
880         destroySync(*mSyncSet.begin());
881     }
882 
883     while (!mState.surfaceSet.empty())
884     {
885         ANGLE_TRY(destroySurface(*mState.surfaceSet.begin()));
886     }
887 
888     mConfigSet.clear();
889 
890     if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
891     {
892         // Don't delete the device if it was created externally using eglCreateDeviceANGLE
893         // We also shouldn't set it to null in case eglInitialize() is called again later
894         SafeDelete(mDevice);
895     }
896 
897     mImplementation->terminate();
898 
899     mDeviceLost = false;
900 
901     mInitialized = false;
902 
903     gl::UninitializeDebugAnnotations();
904 
905     // TODO(jmadill): Store Platform in Display and deinit here.
906     ANGLEResetDisplayPlatform(this);
907 
908     return NoError();
909 }
910 
getConfigs(const egl::AttributeMap & attribs) const911 std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
912 {
913     return mConfigSet.filter(attribs);
914 }
915 
chooseConfig(const egl::AttributeMap & attribs) const916 std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
917 {
918     egl::AttributeMap attribsWithDefaults = AttributeMap();
919 
920     // Insert default values for attributes that have either an Exact or Mask selection criteria,
921     // and a default value that matters (e.g. isn't EGL_DONT_CARE):
922     attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
923     attribsWithDefaults.insert(EGL_LEVEL, 0);
924     attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
925     attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
926     attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
927     if (getExtensions().pixelFormatFloat)
928     {
929         attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
930                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
931     }
932 
933     // Add the caller-specified values (Note: the poorly-named insert() method will replace any
934     // of the default values from above):
935     for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
936     {
937         attribsWithDefaults.insert(attribIter->first, attribIter->second);
938     }
939 
940     return mConfigSet.filter(attribsWithDefaults);
941 }
942 
createWindowSurface(const Config * configuration,EGLNativeWindowType window,const AttributeMap & attribs,Surface ** outSurface)943 Error Display::createWindowSurface(const Config *configuration,
944                                    EGLNativeWindowType window,
945                                    const AttributeMap &attribs,
946                                    Surface **outSurface)
947 {
948     if (mImplementation->testDeviceLost())
949     {
950         ANGLE_TRY(restoreLostDevice());
951     }
952 
953     SurfacePointer surface(new WindowSurface(mImplementation, configuration, window, attribs),
954                            this);
955     ANGLE_TRY(surface->initialize(this));
956 
957     ASSERT(outSurface != nullptr);
958     *outSurface = surface.release();
959     mState.surfaceSet.insert(*outSurface);
960 
961     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
962     ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
963     windowSurfaces->insert(std::make_pair(window, *outSurface));
964 
965     mSurface = *outSurface;
966 
967     return NoError();
968 }
969 
createPbufferSurface(const Config * configuration,const AttributeMap & attribs,Surface ** outSurface)970 Error Display::createPbufferSurface(const Config *configuration,
971                                     const AttributeMap &attribs,
972                                     Surface **outSurface)
973 {
974     ASSERT(isInitialized());
975 
976     if (mImplementation->testDeviceLost())
977     {
978         ANGLE_TRY(restoreLostDevice());
979     }
980 
981     SurfacePointer surface(new PbufferSurface(mImplementation, configuration, attribs), this);
982     ANGLE_TRY(surface->initialize(this));
983 
984     ASSERT(outSurface != nullptr);
985     *outSurface = surface.release();
986     mState.surfaceSet.insert(*outSurface);
987 
988     return NoError();
989 }
990 
createPbufferFromClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,Surface ** outSurface)991 Error Display::createPbufferFromClientBuffer(const Config *configuration,
992                                              EGLenum buftype,
993                                              EGLClientBuffer clientBuffer,
994                                              const AttributeMap &attribs,
995                                              Surface **outSurface)
996 {
997     ASSERT(isInitialized());
998 
999     if (mImplementation->testDeviceLost())
1000     {
1001         ANGLE_TRY(restoreLostDevice());
1002     }
1003 
1004     SurfacePointer surface(
1005         new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs), this);
1006     ANGLE_TRY(surface->initialize(this));
1007 
1008     ASSERT(outSurface != nullptr);
1009     *outSurface = surface.release();
1010     mState.surfaceSet.insert(*outSurface);
1011 
1012     return NoError();
1013 }
1014 
createPixmapSurface(const Config * configuration,NativePixmapType nativePixmap,const AttributeMap & attribs,Surface ** outSurface)1015 Error Display::createPixmapSurface(const Config *configuration,
1016                                    NativePixmapType nativePixmap,
1017                                    const AttributeMap &attribs,
1018                                    Surface **outSurface)
1019 {
1020     ASSERT(isInitialized());
1021 
1022     if (mImplementation->testDeviceLost())
1023     {
1024         ANGLE_TRY(restoreLostDevice());
1025     }
1026 
1027     SurfacePointer surface(new PixmapSurface(mImplementation, configuration, nativePixmap, attribs),
1028                            this);
1029     ANGLE_TRY(surface->initialize(this));
1030 
1031     ASSERT(outSurface != nullptr);
1032     *outSurface = surface.release();
1033     mState.surfaceSet.insert(*outSurface);
1034 
1035     return NoError();
1036 }
1037 
createImage(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attribs,Image ** outImage)1038 Error Display::createImage(const gl::Context *context,
1039                            EGLenum target,
1040                            EGLClientBuffer buffer,
1041                            const AttributeMap &attribs,
1042                            Image **outImage)
1043 {
1044     ASSERT(isInitialized());
1045 
1046     if (mImplementation->testDeviceLost())
1047     {
1048         ANGLE_TRY(restoreLostDevice());
1049     }
1050 
1051     egl::ImageSibling *sibling = nullptr;
1052     if (IsTextureTarget(target))
1053     {
1054         sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1055     }
1056     else if (IsRenderbufferTarget(target))
1057     {
1058         sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
1059     }
1060     else if (IsExternalImageTarget(target))
1061     {
1062         sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
1063     }
1064     else
1065     {
1066         UNREACHABLE();
1067     }
1068     ASSERT(sibling != nullptr);
1069 
1070     angle::UniqueObjectPointer<Image, Display> imagePtr(
1071         new Image(mImplementation, context, target, sibling, attribs), this);
1072     ANGLE_TRY(imagePtr->initialize(this));
1073 
1074     Image *image = imagePtr.release();
1075 
1076     ASSERT(outImage != nullptr);
1077     *outImage = image;
1078 
1079     // Add this image to the list of all images and hold a ref to it.
1080     image->addRef();
1081     mImageSet.insert(image);
1082 
1083     return NoError();
1084 }
1085 
createStream(const AttributeMap & attribs,Stream ** outStream)1086 Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
1087 {
1088     ASSERT(isInitialized());
1089 
1090     Stream *stream = new Stream(this, attribs);
1091 
1092     ASSERT(stream != nullptr);
1093     mStreamSet.insert(stream);
1094 
1095     ASSERT(outStream != nullptr);
1096     *outStream = stream;
1097 
1098     return NoError();
1099 }
1100 
createContext(const Config * configuration,gl::Context * shareContext,EGLenum clientType,const AttributeMap & attribs,gl::Context ** outContext)1101 Error Display::createContext(const Config *configuration,
1102                              gl::Context *shareContext,
1103                              EGLenum clientType,
1104                              const AttributeMap &attribs,
1105                              gl::Context **outContext)
1106 {
1107     ASSERT(isInitialized());
1108 
1109     if (mImplementation->testDeviceLost())
1110     {
1111         ANGLE_TRY(restoreLostDevice());
1112     }
1113 
1114     // This display texture sharing will allow the first context to create the texture share group.
1115     bool usingDisplayTextureShareGroup =
1116         attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
1117     gl::TextureManager *shareTextures = nullptr;
1118 
1119     if (usingDisplayTextureShareGroup)
1120     {
1121         ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
1122         if (mTextureManager == nullptr)
1123         {
1124             mTextureManager = new gl::TextureManager();
1125         }
1126 
1127         mGlobalTextureShareGroupUsers++;
1128         shareTextures = mTextureManager;
1129     }
1130 
1131     gl::MemoryProgramCache *cachePointer = &mMemoryProgramCache;
1132 
1133     // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
1134     // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
1135     // at any time.
1136     bool usesProgramCacheControl =
1137         mAttributeMap.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
1138     if (usesProgramCacheControl)
1139     {
1140         bool programCacheControlEnabled =
1141             (mAttributeMap.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) ==
1142              GL_TRUE);
1143         // A program cache size of zero indicates it should be disabled.
1144         if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
1145         {
1146             cachePointer = nullptr;
1147         }
1148     }
1149 
1150     gl::Context *context =
1151         new gl::Context(this, configuration, shareContext, shareTextures, cachePointer, clientType,
1152                         attribs, mDisplayExtensions, GetClientExtensions());
1153     if (shareContext != nullptr)
1154     {
1155         shareContext->setShared();
1156     }
1157 
1158     ASSERT(context != nullptr);
1159     mContextSet.insert(context);
1160 
1161     ASSERT(outContext != nullptr);
1162     *outContext = context;
1163     return NoError();
1164 }
1165 
createSync(const gl::Context * currentContext,EGLenum type,const AttributeMap & attribs,Sync ** outSync)1166 Error Display::createSync(const gl::Context *currentContext,
1167                           EGLenum type,
1168                           const AttributeMap &attribs,
1169                           Sync **outSync)
1170 {
1171     ASSERT(isInitialized());
1172 
1173     if (mImplementation->testDeviceLost())
1174     {
1175         ANGLE_TRY(restoreLostDevice());
1176     }
1177 
1178     angle::UniqueObjectPointer<egl::Sync, Display> syncPtr(new Sync(mImplementation, type, attribs),
1179                                                            this);
1180 
1181     ANGLE_TRY(syncPtr->initialize(this, currentContext));
1182 
1183     Sync *sync = syncPtr.release();
1184 
1185     sync->addRef();
1186     mSyncSet.insert(sync);
1187 
1188     *outSync = sync;
1189     return NoError();
1190 }
1191 
makeCurrent(const Thread * thread,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)1192 Error Display::makeCurrent(const Thread *thread,
1193                            egl::Surface *drawSurface,
1194                            egl::Surface *readSurface,
1195                            gl::Context *context)
1196 {
1197     if (!mInitialized)
1198     {
1199         return NoError();
1200     }
1201 
1202     gl::Context *previousContext = thread->getContext();
1203     if (previousContext)
1204     {
1205         ANGLE_TRY(previousContext->unMakeCurrent(this));
1206     }
1207 
1208     ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
1209 
1210     if (context != nullptr)
1211     {
1212         ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface));
1213     }
1214 
1215     // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being
1216     // used.
1217     {
1218         std::lock_guard<std::mutex> lock(mScratchBufferMutex);
1219 
1220         for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers)
1221         {
1222             scatchBuffer.tick();
1223         }
1224         for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers)
1225         {
1226             zeroFilledBuffer.tick();
1227         }
1228     }
1229 
1230     return NoError();
1231 }
1232 
restoreLostDevice()1233 Error Display::restoreLostDevice()
1234 {
1235     for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
1236     {
1237         if ((*ctx)->isResetNotificationEnabled())
1238         {
1239             // If reset notifications have been requested, application must delete all contexts
1240             // first
1241             return EglContextLost();
1242         }
1243     }
1244 
1245     return mImplementation->restoreLostDevice(this);
1246 }
1247 
destroySurface(Surface * surface)1248 Error Display::destroySurface(Surface *surface)
1249 {
1250     if (surface->getType() == EGL_WINDOW_BIT)
1251     {
1252         WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1253         ASSERT(windowSurfaces);
1254 
1255         bool surfaceRemoved = false;
1256         for (WindowSurfaceMap::iterator iter = windowSurfaces->begin();
1257              iter != windowSurfaces->end(); iter++)
1258         {
1259             if (iter->second == surface)
1260             {
1261                 windowSurfaces->erase(iter);
1262                 surfaceRemoved = true;
1263                 break;
1264             }
1265         }
1266 
1267         ASSERT(surfaceRemoved);
1268     }
1269 
1270     mState.surfaceSet.erase(surface);
1271     ANGLE_TRY(surface->onDestroy(this));
1272     return NoError();
1273 }
1274 
destroyImage(egl::Image * image)1275 void Display::destroyImage(egl::Image *image)
1276 {
1277     auto iter = mImageSet.find(image);
1278     ASSERT(iter != mImageSet.end());
1279     (*iter)->release(this);
1280     mImageSet.erase(iter);
1281 }
1282 
destroyStream(egl::Stream * stream)1283 void Display::destroyStream(egl::Stream *stream)
1284 {
1285     mStreamSet.erase(stream);
1286     SafeDelete(stream);
1287 }
1288 
destroyContext(const Thread * thread,gl::Context * context)1289 Error Display::destroyContext(const Thread *thread, gl::Context *context)
1290 {
1291     gl::Context *currentContext   = thread->getContext();
1292     Surface *currentDrawSurface   = thread->getCurrentDrawSurface();
1293     Surface *currentReadSurface   = thread->getCurrentReadSurface();
1294     bool changeContextForDeletion = context != currentContext;
1295 
1296     // Make the context being deleted current during it's deletion.  This allows it to delete
1297     // any resources it's holding.
1298     if (changeContextForDeletion)
1299     {
1300         ANGLE_TRY(makeCurrent(thread, nullptr, nullptr, context));
1301     }
1302 
1303     if (context->usingDisplayTextureShareGroup())
1304     {
1305         ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
1306         if (mGlobalTextureShareGroupUsers == 1)
1307         {
1308             // If this is the last context using the global share group, destroy the global
1309             // texture manager so that the textures can be destroyed while a context still
1310             // exists
1311             mTextureManager->release(context);
1312             mTextureManager = nullptr;
1313         }
1314         mGlobalTextureShareGroupUsers--;
1315     }
1316 
1317     ANGLE_TRY(context->onDestroy(this));
1318     mContextSet.erase(context);
1319     SafeDelete(context);
1320 
1321     // Set the previous context back to current
1322     if (changeContextForDeletion)
1323     {
1324         ANGLE_TRY(makeCurrent(thread, currentDrawSurface, currentReadSurface, currentContext));
1325     }
1326 
1327     return NoError();
1328 }
1329 
destroySync(egl::Sync * sync)1330 void Display::destroySync(egl::Sync *sync)
1331 {
1332     auto iter = mSyncSet.find(sync);
1333     ASSERT(iter != mSyncSet.end());
1334     (*iter)->release(this);
1335     mSyncSet.erase(iter);
1336 }
1337 
isDeviceLost() const1338 bool Display::isDeviceLost() const
1339 {
1340     ASSERT(isInitialized());
1341     return mDeviceLost;
1342 }
1343 
testDeviceLost()1344 bool Display::testDeviceLost()
1345 {
1346     ASSERT(isInitialized());
1347 
1348     if (!mDeviceLost && mImplementation->testDeviceLost())
1349     {
1350         notifyDeviceLost();
1351     }
1352 
1353     return mDeviceLost;
1354 }
1355 
notifyDeviceLost()1356 void Display::notifyDeviceLost()
1357 {
1358     if (mDeviceLost)
1359     {
1360         return;
1361     }
1362 
1363     for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end();
1364          context++)
1365     {
1366         (*context)->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
1367     }
1368 
1369     mDeviceLost = true;
1370 }
1371 
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)1372 void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
1373 {
1374     mBlobCache.setBlobCacheFuncs(set, get);
1375     mImplementation->setBlobCacheFuncs(set, get);
1376 }
1377 
1378 // static
GetNativeClientBuffer(const AHardwareBuffer * buffer)1379 EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
1380 {
1381     return angle::android::AHardwareBufferToClientBuffer(buffer);
1382 }
1383 
waitClient(const gl::Context * context)1384 Error Display::waitClient(const gl::Context *context)
1385 {
1386     return mImplementation->waitClient(context);
1387 }
1388 
waitNative(const gl::Context * context,EGLint engine)1389 Error Display::waitNative(const gl::Context *context, EGLint engine)
1390 {
1391     return mImplementation->waitNative(context, engine);
1392 }
1393 
getCaps() const1394 const Caps &Display::getCaps() const
1395 {
1396     return mCaps;
1397 }
1398 
isInitialized() const1399 bool Display::isInitialized() const
1400 {
1401     return mInitialized;
1402 }
1403 
isValidConfig(const Config * config) const1404 bool Display::isValidConfig(const Config *config) const
1405 {
1406     return mConfigSet.contains(config);
1407 }
1408 
isValidContext(const gl::Context * context) const1409 bool Display::isValidContext(const gl::Context *context) const
1410 {
1411     return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
1412 }
1413 
isValidSurface(const Surface * surface) const1414 bool Display::isValidSurface(const Surface *surface) const
1415 {
1416     return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end();
1417 }
1418 
isValidImage(const Image * image) const1419 bool Display::isValidImage(const Image *image) const
1420 {
1421     return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
1422 }
1423 
isValidStream(const Stream * stream) const1424 bool Display::isValidStream(const Stream *stream) const
1425 {
1426     return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
1427 }
1428 
isValidSync(const Sync * sync) const1429 bool Display::isValidSync(const Sync *sync) const
1430 {
1431     return mSyncSet.find(const_cast<Sync *>(sync)) != mSyncSet.end();
1432 }
1433 
hasExistingWindowSurface(EGLNativeWindowType window)1434 bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
1435 {
1436     WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
1437     ASSERT(windowSurfaces);
1438 
1439     return windowSurfaces->find(window) != windowSurfaces->end();
1440 }
1441 
GenerateClientExtensions()1442 static ClientExtensions GenerateClientExtensions()
1443 {
1444     ClientExtensions extensions;
1445 
1446     extensions.clientExtensions = true;
1447     extensions.platformBase     = true;
1448     extensions.platformANGLE    = true;
1449 
1450 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
1451     extensions.platformANGLED3D = true;
1452     extensions.platformDevice   = true;
1453 #endif
1454 
1455 #if defined(ANGLE_ENABLE_D3D11)
1456 #    if defined(ANGLE_ENABLE_WINDOWS_UWP)
1457     extensions.platformANGLED3D11ON12 = true;
1458 #    else
1459     extensions.platformANGLED3D11ON12 = IsWindows10OrGreater();
1460 #    endif
1461 #endif
1462 
1463 #if defined(ANGLE_ENABLE_OPENGL)
1464     extensions.platformANGLEOpenGL = true;
1465 
1466     // Selecting context virtualization is currently only supported in the OpenGL backend.
1467     extensions.platformANGLEContextVirtualization = true;
1468 #endif
1469 
1470 #if defined(ANGLE_ENABLE_NULL)
1471     extensions.platformANGLENULL = true;
1472 #endif
1473 
1474 #if defined(ANGLE_ENABLE_D3D11)
1475     extensions.deviceCreation          = true;
1476     extensions.deviceCreationD3D11     = true;
1477     extensions.experimentalPresentPath = true;
1478 #endif
1479 
1480 #if defined(ANGLE_ENABLE_VULKAN)
1481     extensions.platformANGLEVulkan = true;
1482 #endif
1483 
1484 #if defined(ANGLE_ENABLE_SWIFTSHADER)
1485     extensions.platformANGLEDeviceTypeSwiftShader = true;
1486 #endif
1487 
1488 #if defined(ANGLE_ENABLE_METAL)
1489     extensions.platformANGLEMetal = true;
1490 #endif
1491 
1492 #if defined(ANGLE_USE_X11)
1493     extensions.x11Visual = true;
1494 #endif
1495 
1496 #if defined(ANGLE_PLATFORM_LINUX)
1497     extensions.platformANGLEDeviceTypeEGLANGLE = true;
1498 #endif
1499 
1500     extensions.clientGetAllProcAddresses = true;
1501     extensions.debug                     = true;
1502     extensions.explicitContext           = true;
1503     extensions.featureControlANGLE       = true;
1504 
1505     return extensions;
1506 }
1507 
1508 template <typename T>
GenerateExtensionsString(const T & extensions)1509 static std::string GenerateExtensionsString(const T &extensions)
1510 {
1511     std::vector<std::string> extensionsVector = extensions.getStrings();
1512 
1513     std::ostringstream stream;
1514     std::copy(extensionsVector.begin(), extensionsVector.end(),
1515               std::ostream_iterator<std::string>(stream, " "));
1516     return stream.str();
1517 }
1518 
1519 // static
GetClientExtensions()1520 const ClientExtensions &Display::GetClientExtensions()
1521 {
1522     static const ClientExtensions clientExtensions = GenerateClientExtensions();
1523     return clientExtensions;
1524 }
1525 
1526 // static
GetClientExtensionString()1527 const std::string &Display::GetClientExtensionString()
1528 {
1529     static const angle::base::NoDestructor<std::string> clientExtensionsString(
1530         GenerateExtensionsString(GetClientExtensions()));
1531     return *clientExtensionsString;
1532 }
1533 
initDisplayExtensions()1534 void Display::initDisplayExtensions()
1535 {
1536     mDisplayExtensions = mImplementation->getExtensions();
1537 
1538     // Some extensions are always available because they are implemented in the EGL layer.
1539     mDisplayExtensions.createContext                      = true;
1540     mDisplayExtensions.createContextNoError               = true;
1541     mDisplayExtensions.createContextWebGLCompatibility    = true;
1542     mDisplayExtensions.createContextBindGeneratesResource = true;
1543     mDisplayExtensions.createContextClientArrays          = true;
1544     mDisplayExtensions.pixelFormatFloat                   = true;
1545 
1546     // Force EGL_KHR_get_all_proc_addresses on.
1547     mDisplayExtensions.getAllProcAddresses = true;
1548 
1549     // Enable program cache control since it is not back-end dependent.
1550     mDisplayExtensions.programCacheControl = true;
1551 
1552     // Request extension is implemented in the ANGLE frontend
1553     mDisplayExtensions.createContextExtensionsEnabled = true;
1554 
1555     // Blob cache extension is provided by the ANGLE frontend
1556     mDisplayExtensions.blobCache = true;
1557 
1558     // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always
1559     // say that ANativeWindow is not recordable.
1560     mDisplayExtensions.recordable = true;
1561 
1562     // All backends support specific context versions
1563     mDisplayExtensions.createContextBackwardsCompatible = true;
1564 
1565     mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
1566 }
1567 
isValidNativeWindow(EGLNativeWindowType window) const1568 bool Display::isValidNativeWindow(EGLNativeWindowType window) const
1569 {
1570     return mImplementation->isValidNativeWindow(window);
1571 }
1572 
validateClientBuffer(const Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs) const1573 Error Display::validateClientBuffer(const Config *configuration,
1574                                     EGLenum buftype,
1575                                     EGLClientBuffer clientBuffer,
1576                                     const AttributeMap &attribs) const
1577 {
1578     return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
1579 }
1580 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const1581 Error Display::validateImageClientBuffer(const gl::Context *context,
1582                                          EGLenum target,
1583                                          EGLClientBuffer clientBuffer,
1584                                          const egl::AttributeMap &attribs) const
1585 {
1586     return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
1587 }
1588 
isValidDisplay(const egl::Display * display)1589 bool Display::isValidDisplay(const egl::Display *display)
1590 {
1591     const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
1592     for (const auto &displayPair : *anglePlatformDisplayMap)
1593     {
1594         if (displayPair.second == display)
1595         {
1596             return true;
1597         }
1598     }
1599 
1600     const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
1601     for (const auto &displayPair : *devicePlatformDisplayMap)
1602     {
1603         if (displayPair.second == display)
1604         {
1605             return true;
1606         }
1607     }
1608 
1609     return false;
1610 }
1611 
isValidNativeDisplay(EGLNativeDisplayType display)1612 bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
1613 {
1614     // TODO(jmadill): handle this properly
1615     if (display == EGL_DEFAULT_DISPLAY)
1616     {
1617         return true;
1618     }
1619 
1620 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
1621     if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
1622         display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
1623     {
1624         return true;
1625     }
1626     return (WindowFromDC(display) != nullptr);
1627 #else
1628     return true;
1629 #endif
1630 }
1631 
initVendorString()1632 void Display::initVendorString()
1633 {
1634     mVendorString = mImplementation->getVendorString();
1635 }
1636 
initializeFrontendFeatures()1637 void Display::initializeFrontendFeatures()
1638 {
1639     // Enable on all Impls
1640     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), loseContextOnOutOfMemory, true);
1641     ANGLE_FEATURE_CONDITION((&mFrontendFeatures), scalarizeVecAndMatConstructorArgs, true);
1642 
1643     mImplementation->initializeFrontendFeatures(&mFrontendFeatures);
1644 
1645     rx::ApplyFeatureOverrides(&mFrontendFeatures, mState);
1646 }
1647 
getExtensions() const1648 const DisplayExtensions &Display::getExtensions() const
1649 {
1650     return mDisplayExtensions;
1651 }
1652 
getExtensionString() const1653 const std::string &Display::getExtensionString() const
1654 {
1655     return mDisplayExtensionString;
1656 }
1657 
getVendorString() const1658 const std::string &Display::getVendorString() const
1659 {
1660     return mVendorString;
1661 }
1662 
getDevice() const1663 Device *Display::getDevice() const
1664 {
1665     return mDevice;
1666 }
1667 
getWGLSurface() const1668 Surface *Display::getWGLSurface() const
1669 {
1670     return mSurface;
1671 }
1672 
getMaxSupportedESVersion() const1673 gl::Version Display::getMaxSupportedESVersion() const
1674 {
1675     return mImplementation->getMaxSupportedESVersion();
1676 }
1677 
programCacheGetAttrib(EGLenum attrib) const1678 EGLint Display::programCacheGetAttrib(EGLenum attrib) const
1679 {
1680     switch (attrib)
1681     {
1682         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
1683             return static_cast<EGLint>(BlobCache::kKeyLength);
1684 
1685         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
1686             return static_cast<EGLint>(mMemoryProgramCache.entryCount());
1687 
1688         default:
1689             UNREACHABLE();
1690             return 0;
1691     }
1692 }
1693 
programCacheQuery(EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)1694 Error Display::programCacheQuery(EGLint index,
1695                                  void *key,
1696                                  EGLint *keysize,
1697                                  void *binary,
1698                                  EGLint *binarysize)
1699 {
1700     ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
1701 
1702     const BlobCache::Key *programHash = nullptr;
1703     BlobCache::Value programBinary;
1704     // TODO(jmadill): Make this thread-safe.
1705     bool result =
1706         mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
1707     if (!result)
1708     {
1709         return EglBadAccess() << "Program binary not accessible.";
1710     }
1711 
1712     ASSERT(keysize && binarysize);
1713 
1714     if (key)
1715     {
1716         ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength));
1717         memcpy(key, programHash->data(), BlobCache::kKeyLength);
1718     }
1719 
1720     if (binary)
1721     {
1722         // Note: we check the size here instead of in the validation code, since we need to
1723         // access the cache as atomically as possible. It's possible that the cache contents
1724         // could change between the validation size check and the retrieval.
1725         if (programBinary.size() > static_cast<size_t>(*binarysize))
1726         {
1727             return EglBadAccess() << "Program binary too large or changed during access.";
1728         }
1729 
1730         memcpy(binary, programBinary.data(), programBinary.size());
1731     }
1732 
1733     *binarysize = static_cast<EGLint>(programBinary.size());
1734     *keysize    = static_cast<EGLint>(BlobCache::kKeyLength);
1735 
1736     return NoError();
1737 }
1738 
programCachePopulate(const void * key,EGLint keysize,const void * binary,EGLint binarysize)1739 Error Display::programCachePopulate(const void *key,
1740                                     EGLint keysize,
1741                                     const void *binary,
1742                                     EGLint binarysize)
1743 {
1744     ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength));
1745 
1746     BlobCache::Key programHash;
1747     memcpy(programHash.data(), key, BlobCache::kKeyLength);
1748 
1749     if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
1750                                        static_cast<size_t>(binarysize)))
1751     {
1752         return EglBadAccess() << "Failed to copy program binary into the cache.";
1753     }
1754 
1755     return NoError();
1756 }
1757 
programCacheResize(EGLint limit,EGLenum mode)1758 EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
1759 {
1760     switch (mode)
1761     {
1762         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
1763         {
1764             size_t initialSize = mMemoryProgramCache.size();
1765             mMemoryProgramCache.resize(static_cast<size_t>(limit));
1766             return static_cast<EGLint>(initialSize);
1767         }
1768 
1769         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
1770             return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
1771 
1772         default:
1773             UNREACHABLE();
1774             return 0;
1775     }
1776 }
1777 
queryStringi(const EGLint name,const EGLint index)1778 const char *Display::queryStringi(const EGLint name, const EGLint index)
1779 {
1780     const char *result = nullptr;
1781     switch (name)
1782     {
1783         case EGL_FEATURE_NAME_ANGLE:
1784             result = mFeatures[index]->name;
1785             break;
1786         case EGL_FEATURE_CATEGORY_ANGLE:
1787             result = angle::FeatureCategoryToString(mFeatures[index]->category);
1788             break;
1789         case EGL_FEATURE_DESCRIPTION_ANGLE:
1790             result = mFeatures[index]->description;
1791             break;
1792         case EGL_FEATURE_BUG_ANGLE:
1793             result = mFeatures[index]->bug;
1794             break;
1795         case EGL_FEATURE_STATUS_ANGLE:
1796             result = angle::FeatureStatusToString(mFeatures[index]->enabled);
1797             break;
1798         case EGL_FEATURE_CONDITION_ANGLE:
1799             result = mFeatures[index]->condition;
1800             break;
1801         default:
1802             UNREACHABLE();
1803             return nullptr;
1804     }
1805     return result;
1806 }
1807 
queryAttrib(const EGLint attribute)1808 EGLAttrib Display::queryAttrib(const EGLint attribute)
1809 {
1810     EGLAttrib value = 0;
1811     switch (attribute)
1812     {
1813         case EGL_DEVICE_EXT:
1814             value = reinterpret_cast<EGLAttrib>(mDevice);
1815             break;
1816 
1817         case EGL_FEATURE_COUNT_ANGLE:
1818             value = mFeatures.size();
1819             break;
1820 
1821         default:
1822             UNREACHABLE();
1823     }
1824     return value;
1825 }
1826 
requestScratchBuffer()1827 angle::ScratchBuffer Display::requestScratchBuffer()
1828 {
1829     return requestScratchBufferImpl(&mScratchBuffers);
1830 }
1831 
returnScratchBuffer(angle::ScratchBuffer scratchBuffer)1832 void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer)
1833 {
1834     returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers);
1835 }
1836 
requestZeroFilledBuffer()1837 angle::ScratchBuffer Display::requestZeroFilledBuffer()
1838 {
1839     return requestScratchBufferImpl(&mZeroFilledBuffers);
1840 }
1841 
returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)1842 void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)
1843 {
1844     returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers);
1845 }
1846 
requestScratchBufferImpl(std::vector<angle::ScratchBuffer> * bufferVector)1847 angle::ScratchBuffer Display::requestScratchBufferImpl(
1848     std::vector<angle::ScratchBuffer> *bufferVector)
1849 {
1850     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
1851     if (!bufferVector->empty())
1852     {
1853         angle::ScratchBuffer buffer = std::move(bufferVector->back());
1854         bufferVector->pop_back();
1855         return buffer;
1856     }
1857 
1858     return angle::ScratchBuffer(kScratchBufferLifetime);
1859 }
1860 
returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,std::vector<angle::ScratchBuffer> * bufferVector)1861 void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
1862                                       std::vector<angle::ScratchBuffer> *bufferVector)
1863 {
1864     std::lock_guard<std::mutex> lock(mScratchBufferMutex);
1865     bufferVector->push_back(std::move(scratchBuffer));
1866 }
1867 
1868 }  // namespace egl
1869