//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EGLDisplaySelectionTest.cpp:
//   Checks display selection and caching with EGL extensions EGL_ANGLE_display_power_preference,
//   EGL_ANGLE_platform_angle, and EGL_ANGLE_device_id
//

#include <gtest/gtest.h>

#include <array>
#include <set>

#include "common/debug.h"
#include "common/string_utils.h"
#include "gpu_info_util/SystemInfo.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/system_info_util.h"
#include "util/OSWindow.h"

using namespace angle;

class EGLDisplaySelectionTest : public ANGLETest<>
{
  public:
    void testSetUp() override { (void)GetSystemInfo(&mSystemInfo); }

  protected:
    // Returns the index of the low or high power GPU in SystemInfo depending on the argument.
    int findGPU(bool lowPower) const
    {
        if (lowPower)
        {
            return FindLowPowerGPU(mSystemInfo);
        }
        return FindHighPowerGPU(mSystemInfo);
    }

    // Returns the index of the active GPU in SystemInfo based on the renderer string.
    int findActiveGPU() const { return FindActiveOpenGLGPU(mSystemInfo); }

    SystemInfo mSystemInfo;
};

class EGLDisplaySelectionTestNoFixture : public EGLDisplaySelectionTest
{
  protected:
    void terminateWindow()
    {
        if (mOSWindow)
        {
            OSWindow::Delete(&mOSWindow);
        }
    }

    void terminateDisplay(EGLDisplay display)
    {
        EXPECT_EGL_TRUE(eglTerminate(display));
        EXPECT_EGL_SUCCESS();
    }

    void terminateContext(EGLDisplay display, EGLContext context)
    {
        if (context != EGL_NO_CONTEXT)
        {
            eglDestroyContext(display, context);
            ASSERT_EGL_SUCCESS();
        }
    }

    void initializeWindow()
    {
        mOSWindow = OSWindow::New();
        mOSWindow->initialize("EGLDisplaySelectionTestMultiDisplay", kWindowWidth, kWindowHeight);
        setWindowVisible(mOSWindow, true);
    }

    void initializeContextForDisplay(EGLDisplay display, EGLContext *context)
    {
        // Find a default config.
        const EGLint configAttributes[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE,     EGL_DONT_CARE,  EGL_GREEN_SIZE,
            EGL_DONT_CARE,    EGL_BLUE_SIZE,  EGL_DONT_CARE,    EGL_ALPHA_SIZE, EGL_DONT_CARE,
            EGL_DEPTH_SIZE,   EGL_DONT_CARE,  EGL_STENCIL_SIZE, EGL_DONT_CARE,  EGL_NONE};

        EGLint configCount;
        EGLConfig config;
        EGLint ret = eglChooseConfig(display, configAttributes, &config, 1, &configCount);

        if (!ret || configCount == 0)
        {
            return;
        }

        EGLint contextAttributes[] = {
            EGL_CONTEXT_MAJOR_VERSION_KHR,
            GetParam().majorVersion,
            EGL_CONTEXT_MINOR_VERSION_KHR,
            GetParam().minorVersion,
            EGL_NONE,
        };

        *context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
        ASSERT_TRUE(*context != EGL_NO_CONTEXT);
    }

    static constexpr int kWindowWidth  = 16;
    static constexpr int kWindowHeight = 8;

    OSWindow *mOSWindow = nullptr;
};

class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixture
{

  protected:
    void initializeDisplayWithPowerPreference(EGLDisplay *display, EGLAttrib powerPreference)
    {
        GLenum platformType = GetParam().getRenderer();
        GLenum deviceType   = GetParam().getDeviceType();

        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(platformType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(deviceType);
        displayAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
        displayAttributes.push_back(powerPreference);
        displayAttributes.push_back(EGL_NONE);

        *display = eglGetPlatformDisplay(GetEglPlatform(),
                                         reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                                         displayAttributes.data());
        ASSERT_TRUE(*display != EGL_NO_DISPLAY);

        EGLint majorVersion, minorVersion;
        ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);

        eglBindAPI(EGL_OPENGL_ES_API);
        ASSERT_EGL_SUCCESS();
    }

    void initializeDisplayWithBackend(EGLDisplay *display, EGLAttrib platformType)
    {
        GLenum deviceType = GetParam().getDeviceType();

        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(platformType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(deviceType);
        displayAttributes.push_back(EGL_NONE);

        *display = eglGetPlatformDisplay(GetEglPlatform(),
                                         reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                                         displayAttributes.data());
        ASSERT_TRUE(*display != EGL_NO_DISPLAY);

        EGLint majorVersion, minorVersion;
        ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);

        eglBindAPI(EGL_OPENGL_ES_API);
        ASSERT_EGL_SUCCESS();
    }

    void runReinitializeDisplayPowerPreference(EGLAttrib powerPreference)
    {
        initializeWindow();

        // Initialize the display with the selected power preference
        EGLDisplay display;
        EGLContext context;
        initializeDisplayWithPowerPreference(&display, powerPreference);
        initializeContextForDisplay(display, &context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);

        bool lowPower = (powerPreference == EGL_LOW_POWER_ANGLE);
        ASSERT_EQ(findGPU(lowPower), findActiveGPU());

        // Terminate the display
        terminateContext(display, context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display);

        // Change the power preference
        if (powerPreference == EGL_LOW_POWER_ANGLE)
        {
            powerPreference = EGL_HIGH_POWER_ANGLE;
        }
        else
        {
            powerPreference = EGL_LOW_POWER_ANGLE;
        }

        // Reinitialize the display with a new power preference
        initializeDisplayWithPowerPreference(&display, powerPreference);
        initializeContextForDisplay(display, &context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);

        // Expect that the power preference has changed
        lowPower = (powerPreference == EGL_LOW_POWER_ANGLE);
        ASSERT_EQ(findGPU(lowPower), findActiveGPU());

        // Terminate the display
        terminateContext(display, context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display);

        terminateWindow();
    }

    void runMultiDisplayBackend(EGLAttrib backend1,
                                bool(checkFunc1)(void),
                                EGLAttrib backend2,
                                bool(checkFunc2)(void))
    {
        initializeWindow();

        // Initialize the display with the selected backend
        EGLDisplay display1;
        EGLContext context1;
        initializeDisplayWithBackend(&display1, backend1);
        initializeContextForDisplay(display1, &context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);

        // Check that the correct backend is chosen
        ASSERT_TRUE(checkFunc1());

        // Initialize the second display with the second backend
        EGLDisplay display2;
        EGLContext context2;
        initializeDisplayWithBackend(&display2, backend2);
        initializeContextForDisplay(display2, &context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);

        // Check that the correct backend is chosen
        ASSERT_TRUE(checkFunc2());

        // Switch back to the first display to verify
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
        ASSERT_TRUE(checkFunc1());

        // Terminate the displays
        terminateContext(display1, context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display1);
        terminateContext(display2, context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display2);

        terminateWindow();
    }

    void runMultiDisplayBackendDefault(EGLAttrib backend, bool(checkFunc)(void))
    {
        initializeWindow();

        // Initialize the display with the selected backend
        EGLDisplay display1;
        EGLContext context1;
        initializeDisplayWithBackend(&display1, backend);
        initializeContextForDisplay(display1, &context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);

        // Check that the correct backend is chosen
        ASSERT_TRUE(checkFunc());

        // Initialize the second display with the second backend
        EGLDisplay display2;
        EGLContext context2;
        initializeDisplayWithBackend(&display2, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
        initializeContextForDisplay(display2, &context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);

        bool sameDisplay = false;
        // If this backend is the same as the first display, check that the display is cached
        if (checkFunc())
        {
            ASSERT_EQ(display1, display2);
            sameDisplay = true;
        }
        // If this backend is not the same, check that this is a different display
        else
        {
            ASSERT_NE(display1, display2);
        }

        // Switch back to the first display to verify
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
        ASSERT_TRUE(checkFunc());

        // Terminate the displays
        terminateContext(display1, context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        if (!sameDisplay)
        {
            terminateDisplay(display1);
        }
        terminateContext(display2, context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display2);

        terminateWindow();
    }

    void runMultiDisplayPowerPreference()
    {
        initializeWindow();

        // Initialize the first display with low power
        EGLDisplay display1;
        EGLContext context1;
        initializeDisplayWithPowerPreference(&display1, EGL_LOW_POWER_ANGLE);
        initializeContextForDisplay(display1, &context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);

        ASSERT_EQ(findGPU(true), findActiveGPU());

        // Initialize the second display with high power
        EGLDisplay display2;
        EGLContext context2;
        initializeDisplayWithPowerPreference(&display2, EGL_HIGH_POWER_ANGLE);
        initializeContextForDisplay(display2, &context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);

        ASSERT_EQ(findGPU(false), findActiveGPU());

        // Switch back to the first display to verify
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
        ASSERT_EQ(findGPU(true), findActiveGPU());

        // Terminate the displays
        terminateContext(display1, context1);
        eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display1);
        terminateContext(display2, context2);
        eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display2);

        terminateWindow();
    }
};

TEST_P(EGLDisplaySelectionTest, SelectGPU)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));
    ASSERT_NE(GetParam().eglParameters.displayPowerPreference, EGL_DONT_CARE);

    bool lowPower = (GetParam().eglParameters.displayPowerPreference == EGL_LOW_POWER_ANGLE);
    ASSERT_EQ(findGPU(lowPower), findActiveGPU());
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, ReInitializePowerPreferenceLowToHigh)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));

    runReinitializeDisplayPowerPreference(EGL_LOW_POWER_ANGLE);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, ReInitializePowerPreferenceHighToLow)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));

    runReinitializeDisplayPowerPreference(EGL_HIGH_POWER_ANGLE);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendMetalOpenGL)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_METAL) && defined(ANGLE_ENABLE_OPENGL)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal,
                           EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendOpenGLMetal)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_METAL) && defined(ANGLE_ENABLE_OPENGL)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL,
                           EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendVulkanD3D11)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_ENABLE_D3D11)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan,
                           EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendD3D11Vulkan)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_ENABLE_D3D11)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11,
                           EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultMetal)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_METAL)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultOpenGL)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_OPENGL)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultD3D11)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_D3D11)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultVulkan)
{
    bool missingBackends = true;
#if defined(ANGLE_ENABLE_VULKAN)
    missingBackends = false;
#endif
    ANGLE_SKIP_TEST_IF(missingBackends);

    // http://anglebug.com/42265471
    ANGLE_SKIP_TEST_IF(IsMac());

    runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan);
}

TEST_P(EGLDisplaySelectionTestMultiDisplay, PowerPreference)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));

    runMultiDisplayPowerPreference();
}

class EGLDisplaySelectionTestDeviceId : public EGLDisplaySelectionTestNoFixture
{

  protected:
    void initializeDisplayWithDeviceId(EGLDisplay *display, uint64_t deviceId)
    {
        GLenum platformType          = GetParam().getRenderer();
        GLenum deviceType            = GetParam().getDeviceType();
        GLint displayPowerPreference = GetParam().eglParameters.displayPowerPreference;

        EGLAttrib high = ((deviceId >> 32) & 0xFFFFFFFF);
        EGLAttrib low  = (deviceId & 0xFFFFFFFF);

        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(platformType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(deviceType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE);
        displayAttributes.push_back(high);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE);
        displayAttributes.push_back(low);
        if (displayPowerPreference != EGL_DONT_CARE)
        {
            displayAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
            displayAttributes.push_back(displayPowerPreference);
        }
        displayAttributes.push_back(EGL_NONE);

        *display = eglGetPlatformDisplay(GetEglPlatform(),
                                         reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                                         displayAttributes.data());
        ASSERT_TRUE(*display != EGL_NO_DISPLAY);

        EGLint majorVersion, minorVersion;
        ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);

        eglBindAPI(EGL_OPENGL_ES_API);
        ASSERT_EGL_SUCCESS();
    }
};

TEST_P(EGLDisplaySelectionTestDeviceId, DeviceId)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_device_id"));
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference") &&
                       GetParam().eglParameters.displayPowerPreference != EGL_DONT_CARE);

    initializeWindow();

    for (size_t i = 0; i < mSystemInfo.gpus.size(); i++)
    {
        // Initialize the display with device id for each GPU
        EGLDisplay display;
        EGLContext context;
        initializeDisplayWithDeviceId(&display, mSystemInfo.gpus[i].systemDeviceId);
        initializeContextForDisplay(display, &context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);

        ASSERT_EQ(static_cast<int>(i), findActiveGPU());

        // Terminate the displays
        terminateContext(display, context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(display);
    }

    terminateWindow();
}

TEST_P(EGLDisplaySelectionTestDeviceId, DeviceIdConcurrently)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_device_id"));
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference") &&
                       GetParam().eglParameters.displayPowerPreference != EGL_DONT_CARE);

    initializeWindow();
    struct ContextForDevice
    {
        EGLDisplay display{};
        EGLContext context{};
    };
    std::vector<ContextForDevice> contexts(mSystemInfo.gpus.size());

    for (size_t i = 0; i < contexts.size(); i++)
    {
        auto &display = contexts[i].display;
        auto &context = contexts[i].context;
        initializeDisplayWithDeviceId(&display, mSystemInfo.gpus[i].systemDeviceId);
        initializeContextForDisplay(display, &context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
        ASSERT_EQ(static_cast<int>(i), findActiveGPU());
    }
    for (auto &context : contexts)
    {
        // Terminate the displays
        terminateContext(context.display, context.context);
        eglMakeCurrent(context.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(context.display);
    }

    terminateWindow();
}

class EGLDisplaySelectionTestDisplayKey : public EGLDisplaySelectionTestNoFixture
{

  protected:
    void initializeDisplayWithKey(EGLDisplay *display, EGLAttrib displayKey)
    {
        GLenum platformType          = GetParam().getRenderer();
        GLenum deviceType            = GetParam().getDeviceType();
        GLint displayPowerPreference = GetParam().eglParameters.displayPowerPreference;

        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(platformType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
        displayAttributes.push_back(EGL_DONT_CARE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
        displayAttributes.push_back(deviceType);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_DISPLAY_KEY_ANGLE);
        displayAttributes.push_back(displayKey);
        if (displayPowerPreference != EGL_DONT_CARE)
        {
            displayAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
            displayAttributes.push_back(displayPowerPreference);
        }
        displayAttributes.push_back(EGL_NONE);

        *display = eglGetPlatformDisplay(GetEglPlatform(),
                                         reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                                         displayAttributes.data());
        ASSERT_TRUE(*display != EGL_NO_DISPLAY);

        EGLint majorVersion, minorVersion;
        ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);

        eglBindAPI(EGL_OPENGL_ES_API);
        ASSERT_EGL_SUCCESS();
    }
};

// Test creating multiple displays with different display keys and verifying they are unique.
TEST_P(EGLDisplaySelectionTestDisplayKey, ConcurentDisplayKey)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_display_key"));

    initializeWindow();
    struct ContextForKey
    {
        EGLDisplay display{};
        EGLContext context{};
    };
    std::vector<ContextForKey> contexts;
    constexpr size_t kDisplayCount = 10;

    for (size_t i = 0; i < kDisplayCount; i++)
    {
        ContextForKey contextForKey;
        auto &display = contextForKey.display;
        auto &context = contextForKey.context;
        initializeDisplayWithKey(&display, i);
        initializeContextForDisplay(display, &context);
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);

        // Test that this display is unique
        for (auto &otherContext : contexts)
        {
            EXPECT_NE(display, otherContext.display);
        }

        contexts.push_back(contextForKey);
    }

    // Test that requesting using the same display key returns the same display
    for (size_t i = 0; i < kDisplayCount; i++)
    {
        EGLDisplay display = EGL_NO_DISPLAY;
        initializeDisplayWithKey(&display, i);
        EXPECT_EQ(contexts[i].display, display);
    }

    for (auto &context : contexts)
    {
        // Terminate the displays
        terminateContext(context.display, context.context);
        eglMakeCurrent(context.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        terminateDisplay(context.display);
    }

    terminateWindow();
}

class EGLDisplaySelectionTestVulkanDeviceUuid : public EGLDisplaySelectionTestNoFixture
{

  protected:
    static constexpr size_t kVulkanUuidSize = 16;
    using VulkanUuid                        = std::array<uint8_t, kVulkanUuidSize>;

    static VulkanUuid MakeUuid(uint8_t seed)
    {
        VulkanUuid uuid;
        uuid.fill(seed);
        return uuid;
    }

    // Deliberately does not call eglInitialize.  Display creation is lazy, so no
    // physical device is selected here and the test does not depend on the
    // running system having a device that matches |deviceUuid|.  The cache key
    // is built by eglGetPlatformDisplay alone, which is exactly what is under
    // test.
    EGLDisplay getDisplayWithDeviceUuid(const VulkanUuid &deviceUuid)
    {
        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_VULKAN_DEVICE_UUID_ANGLE);
        displayAttributes.push_back(reinterpret_cast<EGLAttrib>(deviceUuid.data()));
        displayAttributes.push_back(EGL_NONE);

        EGLDisplay display = eglGetPlatformDisplay(
            GetEglPlatform(), reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
            displayAttributes.data());
        EXPECT_EGL_SUCCESS();
        return display;
    }
};

// Test that displays requesting different Vulkan device UUIDs are distinct, and
// that a UUID supplied through a different buffer still maps to the display
// already cached for those bytes.
TEST_P(EGLDisplaySelectionTestVulkanDeviceUuid, DistinctDeviceUuidsAreNotShared)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_vulkan_device_uuid"));

    initializeWindow();

    constexpr size_t kDisplayCount = 4;

    // Built up front so that no reallocation can move the bytes a display was
    // keyed on: the UUID must outlive the display that references it.
    std::vector<VulkanUuid> uuids;
    uuids.reserve(kDisplayCount);
    for (size_t i = 0; i < kDisplayCount; i++)
    {
        uuids.push_back(MakeUuid(static_cast<uint8_t>(i + 1)));
    }

    std::set<EGLDisplay> uniqueDisplays;
    std::vector<EGLDisplay> displays;
    for (const VulkanUuid &uuid : uuids)
    {
        EGLDisplay display = getDisplayWithDeviceUuid(uuid);
        ASSERT_TRUE(display != EGL_NO_DISPLAY);

        // Test that this display is unique
        EXPECT_TRUE(uniqueDisplays.insert(display).second);

        displays.push_back(display);
    }

    // Test that the key holds the UUID bytes rather than the caller's pointer,
    // by requesting the same UUIDs again through a separate buffer.
    for (size_t i = 0; i < kDisplayCount; i++)
    {
        const VulkanUuid sameBytesOtherBuffer = uuids[i];
        EXPECT_EQ(displays[i], getDisplayWithDeviceUuid(sameBytesOtherBuffer));
    }

    // Test mutating UUID contents in-place with the same buffer address:
    // the mutated contents must produce a new unique display.
    VulkanUuid mutableUuid           = MakeUuid(0xFE);
    EGLDisplay displayBeforeMutation = getDisplayWithDeviceUuid(mutableUuid);
    ASSERT_TRUE(displayBeforeMutation != EGL_NO_DISPLAY);
    EXPECT_TRUE(uniqueDisplays.insert(displayBeforeMutation).second);

    mutableUuid[0] += 1;
    EGLDisplay displayAfterMutation = getDisplayWithDeviceUuid(mutableUuid);
    ASSERT_TRUE(displayAfterMutation != EGL_NO_DISPLAY);
    EXPECT_TRUE(uniqueDisplays.insert(displayAfterMutation).second);

    for (EGLDisplay display : uniqueDisplays)
    {
        terminateDisplay(display);
    }

    terminateWindow();
}

// Test that the caller's UUID buffer does not have to outlive
// eglGetPlatformDisplay.  The physical device is chosen later, during
// eglInitialize, and must be chosen from the display's own copy of the bytes.
// Reading the caller's buffer there is a use-after-free that only a sanitizer
// build reports, so this test guards the contract rather than demonstrating a
// visible failure.
TEST_P(EGLDisplaySelectionTestVulkanDeviceUuid, DeviceUuidNeedNotOutliveDisplayCreation)
{
    ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_vulkan_device_uuid"));

    initializeWindow();

    EGLDisplay display = EGL_NO_DISPLAY;
    {
        // Heap allocated so that a sanitizer poisons the bytes when the buffer
        // goes out of scope, the way a caller's stack array would be reused.
        std::vector<uint8_t> deviceUuid(kVulkanUuidSize, 0xAB);

        std::vector<EGLAttrib> displayAttributes;
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
        displayAttributes.push_back(EGL_PLATFORM_ANGLE_VULKAN_DEVICE_UUID_ANGLE);
        displayAttributes.push_back(reinterpret_cast<EGLAttrib>(deviceUuid.data()));
        displayAttributes.push_back(EGL_NONE);

        display = eglGetPlatformDisplay(GetEglPlatform(),
                                        reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                                        displayAttributes.data());
        ASSERT_EGL_SUCCESS();
    }
    ASSERT_TRUE(display != EGL_NO_DISPLAY);

    // No device carries this UUID, so the implementation falls back to another
    // device and initialization still succeeds.
    EXPECT_TRUE(eglInitialize(display, nullptr, nullptr) == EGL_TRUE);
    EXPECT_EGL_SUCCESS();

    terminateDisplay(display);
    terminateWindow();
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTest);
ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTest,
                       WithLowPowerGPU(ES2_METAL()),
                       WithLowPowerGPU(ES3_METAL()),
                       WithHighPowerGPU(ES2_METAL()),
                       WithHighPowerGPU(ES3_METAL()));

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestMultiDisplay);
ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestMultiDisplay,
                       WithNoFixture(ES2_METAL()),
                       WithNoFixture(ES3_METAL()));

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestDeviceId);
ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestDeviceId,
                       WithNoFixture(ES2_D3D11()),
                       WithNoFixture(ES3_D3D11()),
                       WithNoFixture(ES2_METAL()),
                       WithNoFixture(ES3_METAL()),
                       WithNoFixture(WithLowPowerGPU(ES2_METAL())),
                       WithNoFixture(WithLowPowerGPU(ES3_METAL())),
                       WithNoFixture(WithHighPowerGPU(ES2_METAL())),
                       WithNoFixture(WithHighPowerGPU(ES3_METAL())));

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestDisplayKey);
ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestDisplayKey,
                       WithNoFixture(ES2_D3D11()),
                       WithNoFixture(ES3_D3D11()),
                       WithNoFixture(ES2_METAL()),
                       WithNoFixture(ES3_METAL()),
                       WithNoFixture(ES2_WEBGPU()),
                       WithNoFixture(ES3_WEBGPU()),
                       WithNoFixture(WithLowPowerGPU(ES2_METAL())),
                       WithNoFixture(WithLowPowerGPU(ES3_METAL())),
                       WithNoFixture(WithHighPowerGPU(ES2_METAL())),
                       WithNoFixture(WithHighPowerGPU(ES3_METAL())));

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestVulkanDeviceUuid);
ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestVulkanDeviceUuid,
                       WithNoFixture(ES2_VULKAN()),
                       WithNoFixture(ES3_VULKAN()));
