//
// Copyright 2019 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.
//
// EGLNoConfigContectTest.cpp:
//   EGL extension EGL_KHR_no_config_context allows a context to be created
//   without a config specified. This means all surfaces are compatible.
//   As a result compatibility checks are circumvented.
//   This test suite creates and verifies creating a configless context
//   and then verifies simple rendering to ensure compatibility.
//

#include <gtest/gtest.h>

#include "test_utils/ANGLETest.h"

using namespace angle;

class EGLNoConfigContextTest : public ANGLETest
{
  public:
    EGLNoConfigContextTest() : mDisplay(EGL_NO_DISPLAY), mContext(EGL_NO_CONTEXT) {}

    void testSetUp() override
    {
        int clientVersion = GetParam().majorVersion;

        EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
        mDisplay           = eglGetPlatformDisplayEXT(
            EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
        EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
        EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));

        mExtensionSupported = IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_no_config_context");
        if (!mExtensionSupported)
        {
            return;  // Not supported, don't create context
        }

        EGLint ctxattrs[] = {EGL_CONTEXT_CLIENT_VERSION, clientVersion, EGL_NONE};
        mContext          = eglCreateContext(mDisplay, EGL_NO_CONFIG_KHR, nullptr, ctxattrs);
        EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
    }

    void testTearDown() override
    {
        if (mDisplay != EGL_NO_DISPLAY)
        {
            if (mContext != EGL_NO_CONTEXT)
            {
                eglDestroyContext(mDisplay, mContext);
                mContext = EGL_NO_CONTEXT;
            }
            eglTerminate(mDisplay);
            eglReleaseThread();
        }
        ASSERT_EGL_SUCCESS() << "Error during test TearDown";
    }

    EGLDisplay mDisplay      = EGL_NO_DISPLAY;
    EGLContext mContext      = EGL_NO_CONTEXT;
    bool mExtensionSupported = false;
};

// Check that context has no config.
TEST_P(EGLNoConfigContextTest, QueryConfigID)
{
    ANGLE_SKIP_TEST_IF(!mExtensionSupported);
    EXPECT_TRUE(mDisplay);
    EXPECT_TRUE(mContext);

    EGLint configId = -1;
    EXPECT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONFIG_ID, &configId));
    EXPECT_TRUE(configId == 0);
    ASSERT_EGL_SUCCESS();
}

// Any surface should be eglMakeCurrent compatible with no-config context.
// Do a glClear and glReadPixel to verify rendering.
TEST_P(EGLNoConfigContextTest, RenderCheck)
{
    ANGLE_SKIP_TEST_IF(!mExtensionSupported);

    // Get all the configs
    EGLint count;
    EXPECT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &count));
    EXPECT_TRUE(count > 0);
    std::vector<EGLConfig> configs(count);
    EXPECT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), count, &count));

    // For each config, create PbufferSurface and do a render check
    EGLSurface surface = EGL_NO_SURFACE;
    for (auto config : configs)
    {
        const uint32_t kWidth  = 1;
        const uint32_t kHeight = 1;

        EGLint configId;
        EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_CONFIG_ID, &configId));
        EGLint surfattrs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE};
        surface            = eglCreatePbufferSurface(mDisplay, config, surfattrs);
        EXPECT_TRUE(surface != EGL_NO_SURFACE);

        EGLint bufferSize = 0;
        EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_BUFFER_SIZE, &bufferSize));

        EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, mContext));
        ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed with Config: " << configId << '\n';

        // ClearColor RED
        glClearColor(1.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        ASSERT_GL_NO_ERROR() << "glClear failed";

        if (bufferSize > 32)
        {  // GL_FLOAT configs
            EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
        }
        else
        {  // GL_UNSIGNED_BYTE configs
            EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
        }

        eglDestroySurface(mDisplay, surface);
        surface = EGL_NO_SURFACE;
    }
}

ANGLE_INSTANTIATE_TEST(EGLNoConfigContextTest,
                       WithNoFixture(ES2_OPENGL()),
                       WithNoFixture(ES2_VULKAN()),
                       WithNoFixture(ES3_OPENGL()),
                       WithNoFixture(ES3_VULKAN()));
