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