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