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