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