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