//
// Copyright 2015 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.
//

// DisplayWGL.h: WGL implementation of egl::Display

#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"

#include "common/debug.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
#include "libANGLE/renderer/gl/wgl/ContextWGL.h"
#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/RendererWGL.h"
#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"

#include "platform/Platform.h"

#include <EGL/eglext.h>
#include <sstream>
#include <string>

namespace rx
{

namespace
{

std::string GetErrorMessage()
{
    DWORD errorCode     = GetLastError();
    LPSTR messageBuffer = nullptr;
    size_t size         = FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
    std::string message(messageBuffer, size);
    if (size == 0)
    {
        std::ostringstream stream;
        stream << "Failed to get the error message for '" << errorCode << "' due to the error '"
               << GetLastError() << "'";
        message = stream.str();
    }
    if (messageBuffer != nullptr)
    {
        LocalFree(messageBuffer);
    }
    return message;
}

}  // anonymous namespace

class FunctionsGLWindows : public FunctionsGL
{
  public:
    FunctionsGLWindows(HMODULE openGLModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL)
        : mOpenGLModule(openGLModule), mGetProcAddressWGL(getProcAddressWGL)
    {
        ASSERT(mOpenGLModule);
        ASSERT(mGetProcAddressWGL);
    }

    ~FunctionsGLWindows() override {}

  private:
    void *loadProcAddress(const std::string &function) const override
    {
        void *proc = reinterpret_cast<void *>(mGetProcAddressWGL(function.c_str()));
        if (!proc)
        {
            proc = reinterpret_cast<void *>(GetProcAddress(mOpenGLModule, function.c_str()));
        }
        return proc;
    }

    HMODULE mOpenGLModule;
    PFNWGLGETPROCADDRESSPROC mGetProcAddressWGL;
};

DisplayWGL::DisplayWGL(const egl::DisplayState &state)
    : DisplayGL(state),
      mRenderer(nullptr),
      mCurrentData(),
      mOpenGLModule(nullptr),
      mFunctionsWGL(nullptr),
      mHasWGLCreateContextRobustness(false),
      mHasRobustness(false),
      mWindowClass(0),
      mWindow(nullptr),
      mDeviceContext(nullptr),
      mPixelFormat(0),
      mUseDXGISwapChains(false),
      mHasDXInterop(false),
      mDxgiModule(nullptr),
      mD3d11Module(nullptr),
      mD3D11DeviceHandle(nullptr),
      mD3D11Device(nullptr),
      mUseARBShare(true)
{}

DisplayWGL::~DisplayWGL() {}

egl::Error DisplayWGL::initialize(egl::Display *display)
{
    egl::Error error = initializeImpl(display);
    if (error.isError())
    {
        destroy();
        return error;
    }

    return DisplayGL::initialize(display);
}

egl::Error DisplayWGL::initializeImpl(egl::Display *display)
{
    mDisplayAttributes = display->getAttributeMap();

    mOpenGLModule = LoadLibraryExA("opengl32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    if (!mOpenGLModule)
    {
        return egl::EglNotInitialized() << "Failed to load OpenGL library.";
    }

    mFunctionsWGL = new FunctionsWGL();
    mFunctionsWGL->initialize(mOpenGLModule, nullptr);

    // WGL can't grab extensions until it creates a context because it needs to load the driver's
    // DLLs first. Create a dummy context to load the driver and determine which GL versions are
    // available.

    // Work around compile error from not defining "UNICODE" while Chromium does
    const LPSTR idcArrow = MAKEINTRESOURCEA(32512);

    std::ostringstream stream;
    stream << "ANGLE DisplayWGL " << gl::FmtHex(display) << " Intermediate Window Class";
    std::string className = stream.str();

    WNDCLASSA intermediateClassDesc     = {};
    intermediateClassDesc.style         = CS_OWNDC;
    intermediateClassDesc.lpfnWndProc   = DefWindowProcA;
    intermediateClassDesc.cbClsExtra    = 0;
    intermediateClassDesc.cbWndExtra    = 0;
    intermediateClassDesc.hInstance     = GetModuleHandle(nullptr);
    intermediateClassDesc.hIcon         = nullptr;
    intermediateClassDesc.hCursor       = LoadCursorA(nullptr, idcArrow);
    intermediateClassDesc.hbrBackground = 0;
    intermediateClassDesc.lpszMenuName  = nullptr;
    intermediateClassDesc.lpszClassName = className.c_str();
    mWindowClass                        = RegisterClassA(&intermediateClassDesc);
    if (!mWindowClass)
    {
        return egl::EglNotInitialized()
               << "Failed to register intermediate OpenGL window class \"" << className.c_str()
               << "\":" << gl::FmtErr(HRESULT_CODE(GetLastError()));
    }

    HWND dummyWindow =
        CreateWindowExA(0, reinterpret_cast<const char *>(mWindowClass), "ANGLE Dummy Window",
                        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, nullptr, nullptr, nullptr, nullptr);
    if (!dummyWindow)
    {
        return egl::EglNotInitialized() << "Failed to create dummy OpenGL window.";
    }

    HDC dummyDeviceContext = GetDC(dummyWindow);
    if (!dummyDeviceContext)
    {
        return egl::EglNotInitialized()
               << "Failed to get the device context of the dummy OpenGL window.";
    }

    const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();

    int dummyPixelFormat = ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor);
    if (dummyPixelFormat == 0)
    {
        return egl::EglNotInitialized()
               << "Could not find a compatible pixel format for the dummy OpenGL window.";
    }

    if (!SetPixelFormat(dummyDeviceContext, dummyPixelFormat, &pixelFormatDescriptor))
    {
        return egl::EglNotInitialized()
               << "Failed to set the pixel format on the intermediate OpenGL window.";
    }

    HGLRC dummyWGLContext = mFunctionsWGL->createContext(dummyDeviceContext);
    if (!dummyDeviceContext)
    {
        return egl::EglNotInitialized()
               << "Failed to create a WGL context for the dummy OpenGL window.";
    }

    if (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext))
    {
        return egl::EglNotInitialized() << "Failed to make the dummy WGL context current.";
    }

    // Reinitialize the wgl functions to grab the extensions
    mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext);

    mHasWGLCreateContextRobustness =
        mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness");

    // Destroy the dummy window and context
    mFunctionsWGL->makeCurrent(dummyDeviceContext, nullptr);
    mFunctionsWGL->deleteContext(dummyWGLContext);
    ReleaseDC(dummyWindow, dummyDeviceContext);
    DestroyWindow(dummyWindow);

    const egl::AttributeMap &displayAttributes = display->getAttributeMap();
    EGLint requestedDisplayType                = static_cast<EGLint>(displayAttributes.get(
        EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
    if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
        !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es2_profile") &&
        !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es_profile"))
    {
        return egl::EglNotInitialized() << "Cannot create an OpenGL ES platform on Windows without "
                                           "the WGL_EXT_create_context_es(2)_profile extension.";
    }

    // Create the real intermediate context and windows
    mWindow = CreateWindowExA(0, reinterpret_cast<const char *>(mWindowClass),
                              "ANGLE Intermediate Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr,
                              nullptr, nullptr);
    if (!mWindow)
    {
        return egl::EglNotInitialized() << "Failed to create intermediate OpenGL window.";
    }

    mDeviceContext = GetDC(mWindow);
    if (!mDeviceContext)
    {
        return egl::EglNotInitialized()
               << "Failed to get the device context of the intermediate OpenGL window.";
    }

    if (mFunctionsWGL->choosePixelFormatARB)
    {
        std::vector<int> attribs = wgl::GetDefaultPixelFormatAttributes(false);

        UINT matchingFormats = 0;
        mFunctionsWGL->choosePixelFormatARB(mDeviceContext, &attribs[0], nullptr, 1u, &mPixelFormat,
                                            &matchingFormats);
    }

    if (mPixelFormat == 0)
    {
        mPixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
    }

    if (mPixelFormat == 0)
    {
        return egl::EglNotInitialized()
               << "Could not find a compatible pixel format for the intermediate OpenGL window.";
    }

    if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
    {
        return egl::EglNotInitialized()
               << "Failed to set the pixel format on the intermediate OpenGL window.";
    }

    ANGLE_TRY(createRenderer(&mRenderer));
    const FunctionsGL *functionsGL = mRenderer->getFunctions();

    mHasRobustness = functionsGL->getGraphicsResetStatus != nullptr;
    if (mHasWGLCreateContextRobustness != mHasRobustness)
    {
        WARN() << "WGL_ARB_create_context_robustness exists but unable to create a context with "
                  "robustness.";
    }

    // Intel OpenGL ES drivers are not currently supported due to bugs in the driver and ANGLE
    VendorID vendor = GetVendorID(functionsGL);
    if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && IsIntel(vendor))
    {
        return egl::EglNotInitialized() << "Intel OpenGL ES drivers are not supported.";
    }

    // Create DXGI swap chains for windows that come from other processes.  Windows is unable to
    // SetPixelFormat on windows from other processes when a sandbox is enabled.
    HDC nativeDisplay = display->getNativeDisplayId();
    HWND nativeWindow = WindowFromDC(nativeDisplay);
    if (nativeWindow != nullptr)
    {
        DWORD currentProcessId = GetCurrentProcessId();
        DWORD windowProcessId;
        GetWindowThreadProcessId(nativeWindow, &windowProcessId);

        // AMD drivers advertise the WGL_NV_DX_interop and WGL_NV_DX_interop2 extensions but fail
        mUseDXGISwapChains = !IsAMD(vendor) && (currentProcessId != windowProcessId);
    }
    else
    {
        mUseDXGISwapChains = false;
    }

    mHasDXInterop = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");

    if (mUseDXGISwapChains)
    {
        if (mHasDXInterop)
        {
            ANGLE_TRY(initializeD3DDevice());
        }
        else
        {
            // Want to use DXGI swap chains but WGL_NV_DX_interop2 is not present, fail
            // initialization
            return egl::EglNotInitialized() << "WGL_NV_DX_interop2 is required but not present.";
        }
    }

    const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
    if (maxVersion < gl::Version(2, 0))
    {
        return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
    }

    return egl::NoError();
}

void DisplayWGL::terminate()
{
    DisplayGL::terminate();
    destroy();
}

void DisplayWGL::destroy()
{
    releaseD3DDevice(mD3D11DeviceHandle);

    mRenderer.reset();

    if (mFunctionsWGL)
    {
        if (mDeviceContext)
        {
            mFunctionsWGL->makeCurrent(mDeviceContext, nullptr);
        }
    }
    mCurrentData.clear();

    SafeDelete(mFunctionsWGL);

    if (mDeviceContext)
    {
        ReleaseDC(mWindow, mDeviceContext);
        mDeviceContext = nullptr;
    }

    if (mWindow)
    {
        DestroyWindow(mWindow);
        mWindow = nullptr;
    }

    if (mWindowClass)
    {
        if (!UnregisterClassA(reinterpret_cast<const char *>(mWindowClass),
                              GetModuleHandle(nullptr)))
        {
            WARN() << "Failed to unregister OpenGL window class: " << gl::FmtHex(mWindowClass);
        }
        mWindowClass = NULL;
    }

    if (mOpenGLModule)
    {
        FreeLibrary(mOpenGLModule);
        mOpenGLModule = nullptr;
    }

    SafeRelease(mD3D11Device);

    if (mDxgiModule)
    {
        FreeLibrary(mDxgiModule);
        mDxgiModule = nullptr;
    }

    if (mD3d11Module)
    {
        FreeLibrary(mD3d11Module);
        mD3d11Module = nullptr;
    }

    ASSERT(mRegisteredD3DDevices.empty());
}

SurfaceImpl *DisplayWGL::createWindowSurface(const egl::SurfaceState &state,
                                             EGLNativeWindowType window,
                                             const egl::AttributeMap &attribs)
{
    EGLint orientation = static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
    if (mUseDXGISwapChains)
    {
        egl::Error error = initializeD3DDevice();
        if (error.isError())
        {
            return nullptr;
        }

        return new DXGISwapChainWindowSurfaceWGL(
            state, mRenderer->getStateManager(), window, mD3D11Device, mD3D11DeviceHandle,
            mDeviceContext, mRenderer->getFunctions(), mFunctionsWGL, orientation);
    }
    else
    {
        return new WindowSurfaceWGL(state, window, mPixelFormat, mFunctionsWGL, orientation);
    }
}

SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state,
                                              const egl::AttributeMap &attribs)
{
    EGLint width          = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
    EGLint height         = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
    bool largest          = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
    EGLenum textureFormat = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
    EGLenum textureTarget = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));

    return new PbufferSurfaceWGL(state, width, height, textureFormat, textureTarget, largest,
                                 mPixelFormat, mDeviceContext, mFunctionsWGL);
}

SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
                                                       EGLenum buftype,
                                                       EGLClientBuffer clientBuffer,
                                                       const egl::AttributeMap &attribs)
{
    egl::Error error = initializeD3DDevice();
    if (error.isError())
    {
        return nullptr;
    }

    return new D3DTextureSurfaceWGL(state, mRenderer->getStateManager(), buftype, clientBuffer,
                                    this, mDeviceContext, mD3D11Device, mRenderer->getFunctions(),
                                    mFunctionsWGL);
}

SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
                                             NativePixmapType nativePixmap,
                                             const egl::AttributeMap &attribs)
{
    UNIMPLEMENTED();
    return nullptr;
}

rx::ContextImpl *DisplayWGL::createContext(const gl::State &state,
                                           gl::ErrorSet *errorSet,
                                           const egl::Config *configuration,
                                           const gl::Context *shareContext,
                                           const egl::AttributeMap &attribs)
{
    return new ContextWGL(state, errorSet, mRenderer);
}

DeviceImpl *DisplayWGL::createDevice()
{
    UNREACHABLE();
    return nullptr;
}

egl::ConfigSet DisplayWGL::generateConfigs()
{
    egl::ConfigSet configs;

    int minSwapInterval = 1;
    int maxSwapInterval = 1;
    if (mFunctionsWGL->swapIntervalEXT)
    {
        // No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number
        minSwapInterval = 0;
        maxSwapInterval = 8;
    }

    const gl::Version &maxVersion = getMaxSupportedESVersion();
    ASSERT(maxVersion >= gl::Version(2, 0));
    bool supportsES3 = maxVersion >= gl::Version(3, 0);

    PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
    DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor),
                        &pixelFormatDescriptor);

    auto getAttrib = [this](int attrib) {
        return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL);
    };

    const EGLint optimalSurfaceOrientation =
        mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0;

    egl::Config config;
    config.renderTargetFormat = GL_RGBA8;  // TODO: use the bit counts to determine the format
    config.depthStencilFormat =
        GL_DEPTH24_STENCIL8;  // TODO: use the bit counts to determine the format
    config.bufferSize        = pixelFormatDescriptor.cColorBits;
    config.redSize           = pixelFormatDescriptor.cRedBits;
    config.greenSize         = pixelFormatDescriptor.cGreenBits;
    config.blueSize          = pixelFormatDescriptor.cBlueBits;
    config.luminanceSize     = 0;
    config.alphaSize         = pixelFormatDescriptor.cAlphaBits;
    config.alphaMaskSize     = 0;
    config.bindToTextureRGB  = (getAttrib(WGL_BIND_TO_TEXTURE_RGB_ARB) == TRUE);
    config.bindToTextureRGBA = (getAttrib(WGL_BIND_TO_TEXTURE_RGBA_ARB) == TRUE);
    config.colorBufferType   = EGL_RGB_BUFFER;
    config.configCaveat      = EGL_NONE;
    config.conformant        = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
    config.depthSize         = pixelFormatDescriptor.cDepthBits;
    config.level             = 0;
    config.matchNativePixmap = EGL_NONE;
    config.maxPBufferWidth   = getAttrib(WGL_MAX_PBUFFER_WIDTH_ARB);
    config.maxPBufferHeight  = getAttrib(WGL_MAX_PBUFFER_HEIGHT_ARB);
    config.maxPBufferPixels  = getAttrib(WGL_MAX_PBUFFER_PIXELS_ARB);
    config.maxSwapInterval   = maxSwapInterval;
    config.minSwapInterval   = minSwapInterval;
    config.nativeRenderable  = EGL_TRUE;  // Direct rendering
    config.nativeVisualID    = 0;
    config.nativeVisualType  = EGL_NONE;
    config.renderableType    = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
    config.sampleBuffers     = 0;  // FIXME: enumerate multi-sampling
    config.samples           = 0;
    config.stencilSize       = pixelFormatDescriptor.cStencilBits;
    config.surfaceType =
        ((pixelFormatDescriptor.dwFlags & PFD_DRAW_TO_WINDOW) ? EGL_WINDOW_BIT : 0) |
        ((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_BIT : 0) |
        ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT
                                                               : 0);
    config.optimalOrientation = optimalSurfaceOrientation;
    config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;

    config.transparentType       = EGL_NONE;
    config.transparentRedValue   = 0;
    config.transparentGreenValue = 0;
    config.transparentBlueValue  = 0;

    configs.add(config);

    return configs;
}

bool DisplayWGL::testDeviceLost()
{
    if (mHasRobustness)
    {
        return mRenderer->getResetStatus() != gl::GraphicsResetStatus::NoError;
    }

    return false;
}

egl::Error DisplayWGL::restoreLostDevice(const egl::Display *display)
{
    return egl::EglBadDisplay();
}

bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const
{
    return (IsWindow(window) == TRUE);
}

egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
                                            EGLenum buftype,
                                            EGLClientBuffer clientBuffer,
                                            const egl::AttributeMap &attribs) const
{
    switch (buftype)
    {
        case EGL_D3D_TEXTURE_ANGLE:
        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
            ANGLE_TRY(const_cast<DisplayWGL *>(this)->initializeD3DDevice());
            return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(buftype, clientBuffer,
                                                                        mD3D11Device);

        default:
            return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
    }
}

std::string DisplayWGL::getVendorString() const
{
    // UNIMPLEMENTED();
    return "";
}

egl::Error DisplayWGL::initializeD3DDevice()
{
    if (mD3D11Device != nullptr)
    {
        return egl::NoError();
    }

    mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
    if (!mDxgiModule)
    {
        return egl::EglNotInitialized() << "Failed to load DXGI library.";
    }

    mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
    if (!mD3d11Module)
    {
        return egl::EglNotInitialized() << "Failed to load d3d11 library.";
    }

    PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr;
    d3d11CreateDevice                         = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
        GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
    if (d3d11CreateDevice == nullptr)
    {
        return egl::EglNotInitialized() << "Could not retrieve D3D11CreateDevice address.";
    }

    HRESULT result = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
                                       D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr);
    if (FAILED(result))
    {
        return egl::EglNotInitialized() << "Could not create D3D11 device, " << gl::FmtHR(result);
    }

    return registerD3DDevice(mD3D11Device, &mD3D11DeviceHandle);
}

void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
    // Only enable the surface orientation  and post sub buffer for DXGI swap chain surfaces, they
    // prefer to swap with inverted Y.
    outExtensions->postSubBuffer      = mUseDXGISwapChains;
    outExtensions->surfaceOrientation = mUseDXGISwapChains;

    outExtensions->createContextRobustness = mHasRobustness;

    outExtensions->d3dTextureClientBuffer         = mHasDXInterop;
    outExtensions->d3dShareHandleClientBuffer     = mHasDXInterop;
    outExtensions->surfaceD3DTexture2DShareHandle = true;
    outExtensions->querySurfacePointer            = true;
    outExtensions->keyedMutex                     = true;

    // Contexts are virtualized so textures can be shared globally
    outExtensions->displayTextureShareGroup = true;

    outExtensions->surfacelessContext = true;

    DisplayGL::generateExtensions(outExtensions);
}

void DisplayWGL::generateCaps(egl::Caps *outCaps) const
{
    outCaps->textureNPOT = true;
}

egl::Error DisplayWGL::makeCurrentSurfaceless(gl::Context *context)
{
    // Nothing to do because WGL always uses the same context and the previous surface can be left
    // current.
    return egl::NoError();
}

egl::Error DisplayWGL::waitClient(const gl::Context *context)
{
    // Unimplemented as this is not needed for WGL
    return egl::NoError();
}

egl::Error DisplayWGL::waitNative(const gl::Context *context, EGLint engine)
{
    // Unimplemented as this is not needed for WGL
    return egl::NoError();
}

egl::Error DisplayWGL::makeCurrent(egl::Surface *drawSurface,
                                   egl::Surface *readSurface,
                                   gl::Context *context)
{
    CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];

    HDC newDC = currentContext.dc;
    if (drawSurface)
    {
        SurfaceWGL *drawSurfaceWGL = GetImplAs<SurfaceWGL>(drawSurface);
        newDC                      = drawSurfaceWGL->getDC();
    }
    else
    {
        newDC = mDeviceContext;
    }

    HGLRC newContext = currentContext.glrc;
    if (context)
    {
        ContextWGL *contextWGL = GetImplAs<ContextWGL>(context);
        newContext             = contextWGL->getContext();
    }
    else if (!mUseDXGISwapChains)
    {
        newContext = 0;
    }

    if (newDC != currentContext.dc || newContext != currentContext.glrc)
    {
        ASSERT(newDC != 0);

        if (!mFunctionsWGL->makeCurrent(newDC, newContext))
        {
            // TODO(geofflang): What error type here?
            return egl::EglContextLost() << "Failed to make the WGL context current.";
        }
        currentContext.dc   = newDC;
        currentContext.glrc = newContext;
    }

    return DisplayGL::makeCurrent(drawSurface, readSurface, context);
}

egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle)
{
    ASSERT(device != nullptr);
    ASSERT(outHandle != nullptr);

    auto iter = mRegisteredD3DDevices.find(device);
    if (iter != mRegisteredD3DDevices.end())
    {
        iter->second.refCount++;
        *outHandle = iter->second.handle;
        return egl::NoError();
    }

    HANDLE handle = mFunctionsWGL->dxOpenDeviceNV(device);
    if (!handle)
    {
        return egl::EglBadParameter() << "Failed to open D3D device.";
    }

    device->AddRef();

    D3DObjectHandle newDeviceInfo;
    newDeviceInfo.handle          = handle;
    newDeviceInfo.refCount        = 1;
    mRegisteredD3DDevices[device] = newDeviceInfo;

    *outHandle = handle;
    return egl::NoError();
}

void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle)
{
    for (auto iter = mRegisteredD3DDevices.begin(); iter != mRegisteredD3DDevices.end(); iter++)
    {
        if (iter->second.handle == deviceHandle)
        {
            iter->second.refCount--;
            if (iter->second.refCount == 0)
            {
                mFunctionsWGL->dxCloseDeviceNV(iter->second.handle);
                iter->first->Release();
                mRegisteredD3DDevices.erase(iter);
                break;
            }
        }
    }
}

gl::Version DisplayWGL::getMaxSupportedESVersion() const
{
    return mRenderer->getMaxSupportedESVersion();
}

void DisplayWGL::destroyNativeContext(HGLRC context)
{
    mFunctionsWGL->deleteContext(context);
}

HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttributes,
                                           HGLRC &sharedContext,
                                           bool &useARBShare,
                                           std::vector<int> &workerContextAttribs) const
{
    EGLint requestedDisplayType = static_cast<EGLint>(
        eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));

    // Create a context of the requested version, if any.
    gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get(
                                     EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)),
                                 static_cast<EGLint>(eglAttributes.get(
                                     EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)));
    if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
        static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
    {
        int profileMask = 0;
        if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
            requestedVersion >= gl::Version(3, 2))
        {
            profileMask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
        }
        return createContextAttribs(requestedVersion, profileMask, sharedContext, useARBShare,
                                    workerContextAttribs);
    }

    // Try all the GL version in order as a workaround for Mesa context creation where the driver
    // doesn't automatically return the highest version available.
    for (const auto &info : GenerateContextCreationToTry(requestedDisplayType, false))
    {
        int profileFlag = 0;
        if (info.type == ContextCreationTry::Type::DESKTOP_CORE)
        {
            profileFlag |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
        }
        else if (info.type == ContextCreationTry::Type::ES)
        {
            profileFlag |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
        }

        HGLRC context = createContextAttribs(info.version, profileFlag, sharedContext, useARBShare,
                                             workerContextAttribs);
        if (context != nullptr)
        {
            return context;
        }
    }

    return nullptr;
}

HGLRC DisplayWGL::createContextAttribs(const gl::Version &version,
                                       int profileMask,
                                       HGLRC &sharedContext,
                                       bool &useARBShare,
                                       std::vector<int> &workerContextAttribs) const
{
    std::vector<int> attribs;

    if (mHasWGLCreateContextRobustness)
    {
        attribs.push_back(WGL_CONTEXT_FLAGS_ARB);
        attribs.push_back(WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB);
        attribs.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
        attribs.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
    }

    attribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
    attribs.push_back(version.major);

    attribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
    attribs.push_back(version.minor);

    if (profileMask != 0)
    {
        attribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
        attribs.push_back(profileMask);
    }

    attribs.push_back(0);
    attribs.push_back(0);
    HGLRC context = mFunctionsWGL->createContextAttribsARB(mDeviceContext, nullptr, &attribs[0]);

    // This shared context is never made current. It is safer than the main context to be used as
    // a seed to create worker contexts from.
    // It seems a WGL restriction not mentioned in MSDN, but some posts revealed it.
    // https://www.opengl.org/discussion_boards/showthread.php/152648-wglShareLists-failing
    // https://github.com/glfw/glfw/issues/402
    sharedContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, context, &attribs[0]);
    workerContextAttribs = attribs;
    useARBShare          = true;
    return context;
}

egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
{
    HGLRC context       = nullptr;
    HGLRC sharedContext = nullptr;
    std::vector<int> workerContextAttribs;

    if (mFunctionsWGL->createContextAttribsARB)
    {
        context = initializeContextAttribs(mDisplayAttributes, sharedContext, mUseARBShare,
                                           workerContextAttribs);
    }

    // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
    if (!context)
    {
        // Don't have control over GL versions
        context = mFunctionsWGL->createContext(mDeviceContext);
    }

    if (!context)
    {
        return egl::EglNotInitialized()
               << "Failed to create a WGL context for the intermediate OpenGL window."
               << GetErrorMessage();
    }

    if (!sharedContext)
    {
        sharedContext = mFunctionsWGL->createContext(mDeviceContext);
        if (!mFunctionsWGL->shareLists(context, sharedContext))
        {
            mFunctionsWGL->deleteContext(sharedContext);
            sharedContext = nullptr;
        }
        mUseARBShare = false;
    }

    if (!mFunctionsWGL->makeCurrent(mDeviceContext, context))
    {
        return egl::EglNotInitialized() << "Failed to make the intermediate WGL context current.";
    }
    CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];
    currentContext.dc                    = mDeviceContext;
    currentContext.glrc                  = context;

    std::unique_ptr<FunctionsGL> functionsGL(
        new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress));
    functionsGL->initialize(mDisplayAttributes);

    outRenderer->reset(new RendererWGL(std::move(functionsGL), mDisplayAttributes, this, context,
                                       sharedContext, workerContextAttribs));

    return egl::NoError();
}

class WorkerContextWGL final : public WorkerContext
{
  public:
    WorkerContextWGL(FunctionsWGL *functions,
                     HPBUFFERARB pbuffer,
                     HDC deviceContext,
                     HGLRC context);
    ~WorkerContextWGL() override;

    bool makeCurrent() override;
    void unmakeCurrent() override;

  private:
    FunctionsWGL *mFunctionsWGL;
    HPBUFFERARB mPbuffer;
    HDC mDeviceContext;
    HGLRC mContext;
};

WorkerContextWGL::WorkerContextWGL(FunctionsWGL *functions,
                                   HPBUFFERARB pbuffer,
                                   HDC deviceContext,
                                   HGLRC context)
    : mFunctionsWGL(functions), mPbuffer(pbuffer), mDeviceContext(deviceContext), mContext(context)
{}

WorkerContextWGL::~WorkerContextWGL()
{
    mFunctionsWGL->makeCurrent(mDeviceContext, nullptr);
    mFunctionsWGL->deleteContext(mContext);
    mFunctionsWGL->releasePbufferDCARB(mPbuffer, mDeviceContext);
    mFunctionsWGL->destroyPbufferARB(mPbuffer);
}

bool WorkerContextWGL::makeCurrent()
{
    bool result = mFunctionsWGL->makeCurrent(mDeviceContext, mContext);
    if (!result)
    {
        ERR() << GetErrorMessage();
    }
    return result;
}

void WorkerContextWGL::unmakeCurrent()
{
    mFunctionsWGL->makeCurrent(mDeviceContext, nullptr);
}

WorkerContext *DisplayWGL::createWorkerContext(std::string *infoLog,
                                               HGLRC sharedContext,
                                               const std::vector<int> &workerContextAttribs)
{
    if (!sharedContext)
    {
        *infoLog += "Unable to create the shared context.";
        return nullptr;
    }

    HPBUFFERARB workerPbuffer = nullptr;
    HDC workerDeviceContext   = nullptr;
    HGLRC workerContext       = nullptr;

#define CLEANUP_ON_ERROR()                                                          \
    do                                                                              \
    {                                                                               \
        if (workerContext)                                                          \
        {                                                                           \
            mFunctionsWGL->deleteContext(workerContext);                            \
        }                                                                           \
        if (workerDeviceContext)                                                    \
        {                                                                           \
            mFunctionsWGL->releasePbufferDCARB(workerPbuffer, workerDeviceContext); \
        }                                                                           \
        if (workerPbuffer)                                                          \
        {                                                                           \
            mFunctionsWGL->destroyPbufferARB(workerPbuffer);                        \
        }                                                                           \
    } while (0)

    const int attribs[] = {0, 0};
    workerPbuffer = mFunctionsWGL->createPbufferARB(mDeviceContext, mPixelFormat, 1, 1, attribs);
    if (!workerPbuffer)
    {
        *infoLog += GetErrorMessage();
        return nullptr;
    }

    workerDeviceContext = mFunctionsWGL->getPbufferDCARB(workerPbuffer);
    if (!workerDeviceContext)
    {
        *infoLog += GetErrorMessage();
        CLEANUP_ON_ERROR();
        return nullptr;
    }

    if (mUseARBShare)
    {
        workerContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, sharedContext,
                                                               &workerContextAttribs[0]);
    }
    else
    {
        workerContext = mFunctionsWGL->createContext(workerDeviceContext);
    }
    if (!workerContext)
    {
        GetErrorMessage();
        CLEANUP_ON_ERROR();
        return nullptr;
    }

    if (!mUseARBShare && !mFunctionsWGL->shareLists(sharedContext, workerContext))
    {
        GetErrorMessage();
        CLEANUP_ON_ERROR();
        return nullptr;
    }

#undef CLEANUP_ON_ERROR

    return new WorkerContextWGL(mFunctionsWGL, workerPbuffer, workerDeviceContext, workerContext);
}

void DisplayWGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
{
    mRenderer->initializeFrontendFeatures(features);
}

void DisplayWGL::populateFeatureList(angle::FeatureList *features)
{
    mRenderer->getFeatures().populateFeatureList(features);
}

}  // namespace rx
