//
// 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
