//
// Copyright 2018 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.
//
// EGLMakeCurrentPerfTest:
//   Performance test for eglMakeCurrent.
//

#include "ANGLEPerfTest.h"
#include "platform/Platform.h"
#include "test_utils/angle_test_configs.h"
#include "test_utils/angle_test_instantiate.h"
#include "util/system_utils.h"

#define ITERATIONS 20

using namespace testing;

namespace
{
class EGLMakeCurrentPerfTest : public ANGLEPerfTest,
                               public WithParamInterface<angle::PlatformParameters>
{
  public:
    EGLMakeCurrentPerfTest();

    void step() override;
    void SetUp() override;
    void TearDown() override;

  private:
    OSWindow *mOSWindow;
    EGLDisplay mDisplay;
    EGLSurface mSurface;
    EGLConfig mConfig;
    std::array<EGLContext, 2> mContexts;
    std::unique_ptr<angle::Library> mEGLLibrary;
};

EGLMakeCurrentPerfTest::EGLMakeCurrentPerfTest()
    : ANGLEPerfTest("EGLMakeCurrent", "_run", ITERATIONS),
      mOSWindow(nullptr),
      mDisplay(EGL_NO_DISPLAY),
      mSurface(EGL_NO_SURFACE),
      mConfig(nullptr),
      mContexts({})
{
    auto platform = GetParam().eglParameters;

    std::vector<EGLint> displayAttributes;
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
    displayAttributes.push_back(platform.renderer);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
    displayAttributes.push_back(platform.majorVersion);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
    displayAttributes.push_back(platform.minorVersion);
    displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
    displayAttributes.push_back(platform.deviceType);
    displayAttributes.push_back(EGL_NONE);

    mOSWindow = OSWindow::New();
    mOSWindow->initialize("EGLMakeCurrent Test", 64, 64);

    mEGLLibrary.reset(angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME));

    angle::LoadProc getProc =
        reinterpret_cast<angle::LoadProc>(mEGLLibrary->getSymbol("eglGetProcAddress"));

    if (!getProc)
    {
        abortTest();
    }
    else
    {
        angle::LoadEGL(getProc);

        if (!eglGetPlatformDisplayEXT)
        {
            abortTest();
        }
        else
        {
            mDisplay = eglGetPlatformDisplayEXT(
                EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
                &displayAttributes[0]);
        }
    }
}

void EGLMakeCurrentPerfTest::SetUp()
{
    ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
    EGLint majorVersion, minorVersion;
    ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion));

    EGLint numConfigs;
    EGLint configAttrs[] = {EGL_RED_SIZE,
                            8,
                            EGL_GREEN_SIZE,
                            8,
                            EGL_BLUE_SIZE,
                            8,
                            EGL_RENDERABLE_TYPE,
                            GetParam().majorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
                            EGL_SURFACE_TYPE,
                            EGL_PBUFFER_BIT,
                            EGL_NONE};

    ASSERT_TRUE(eglChooseConfig(mDisplay, configAttrs, &mConfig, 1, &numConfigs));

    mContexts[0] = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, nullptr);
    ASSERT_NE(EGL_NO_CONTEXT, mContexts[0]);
    mContexts[1] = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, nullptr);
    ASSERT_NE(EGL_NO_CONTEXT, mContexts[1]);

    mSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), nullptr);
    ASSERT_NE(EGL_NO_SURFACE, mSurface);
    ASSERT_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContexts[0]));
}

void EGLMakeCurrentPerfTest::TearDown()
{
    ANGLEPerfTest::TearDown();
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroySurface(mDisplay, mSurface);
    eglDestroyContext(mDisplay, mContexts[0]);
    eglDestroyContext(mDisplay, mContexts[1]);
}

void EGLMakeCurrentPerfTest::step()
{
    int mCurrContext = 0;
    for (int x = 0; x < ITERATIONS; x++)
    {
        mCurrContext = (mCurrContext + 1) % mContexts.size();
        eglMakeCurrent(mDisplay, mSurface, mSurface, mContexts[mCurrContext]);
    }
}

TEST_P(EGLMakeCurrentPerfTest, Run)
{
    run();
}

#if !defined(ANGLE_PLATFORM_ANDROID)
ANGLE_INSTANTIATE_TEST(EGLMakeCurrentPerfTest,
                       angle::ES2_D3D9(),
                       angle::ES2_D3D11(),
                       angle::ES2_OPENGL(),
                       angle::ES2_OPENGLES(),
                       angle::ES2_VULKAN());
#else
ANGLE_INSTANTIATE_TEST(EGLMakeCurrentPerfTest, angle::ES2_D3D9(), angle::ES2_D3D11());
#endif

}  // namespace
