tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Display.cpp (78477B)


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