• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Display.cpp: Implements the egl::Display class, representing the abstract
8 // display on which graphics are drawn. Implements EGLDisplay.
9 // [EGL 1.4] section 2.1.2 page 3.
10 
11 #include "libANGLE/Display.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <map>
16 #include <sstream>
17 #include <vector>
18 
19 #include <EGL/eglext.h>
20 #include <platform/Platform.h>
21 
22 #include "anglebase/no_destructor.h"
23 #include "common/android_util.h"
24 #include "common/debug.h"
25 #include "common/mathutil.h"
26 #include "common/platform.h"
27 #include "common/string_utils.h"
28 #include "common/system_utils.h"
29 #include "common/utilities.h"
30 #include "libANGLE/Context.h"
31 #include "libANGLE/Device.h"
32 #include "libANGLE/EGLSync.h"
33 #include "libANGLE/Image.h"
34 #include "libANGLE/ResourceManager.h"
35 #include "libANGLE/Stream.h"
36 #include "libANGLE/Surface.h"
37 #include "libANGLE/Thread.h"
38 #include "libANGLE/histogram_macros.h"
39 #include "libANGLE/renderer/DeviceImpl.h"
40 #include "libANGLE/renderer/DisplayImpl.h"
41 #include "libANGLE/renderer/ImageImpl.h"
42 #include "libANGLE/trace.h"
43 
44 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
45 #    include "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