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

// DisplayD3D.cpp: D3D implementation of egl::Display

#include "libANGLE/renderer/d3d/DisplayD3D.h"

#include <EGL/eglext.h>

#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Thread.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"

#if defined(ANGLE_ENABLE_D3D9)
#    include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#endif  // ANGLE_ENABLE_D3D9

#if defined(ANGLE_ENABLE_D3D11)
#    include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#endif  // ANGLE_ENABLE_D3D11

#if !defined(ANGLE_DEFAULT_D3D11)
// Enables use of the Direct3D 11 API for a default display, when available
#    define ANGLE_DEFAULT_D3D11 1
#endif

namespace rx
{

typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display *);

template <typename RendererType>
static RendererD3D *CreateTypedRendererD3D(egl::Display *display)
{
    return new RendererType(display);
}

egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
{
    ASSERT(outRenderer != nullptr);

    std::vector<CreateRendererD3DFunction> rendererCreationFunctions;

    if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
    {
        const auto &attribMap              = display->getAttributeMap();
        EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();

        EGLint requestedDisplayType = static_cast<EGLint>(
            attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));

#if defined(ANGLE_ENABLE_D3D11)
        if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
            nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
        {
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
        }
#endif

#if defined(ANGLE_ENABLE_D3D9)
        if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
        {
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
        }
#endif

        if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
            nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
        {
            // The default display is requested, try the D3D9 and D3D11 renderers, order them using
            // the definition of ANGLE_DEFAULT_D3D11
#if ANGLE_DEFAULT_D3D11
#    if defined(ANGLE_ENABLE_D3D11)
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
#    endif
#    if defined(ANGLE_ENABLE_D3D9)
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
#    endif
#else
#    if defined(ANGLE_ENABLE_D3D9)
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
#    endif
#    if defined(ANGLE_ENABLE_D3D11)
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
#    endif
#endif
        }
    }
    else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
    {
#if defined(ANGLE_ENABLE_D3D11)
        if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
        {
            rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
        }
#endif
    }
    else
    {
        UNIMPLEMENTED();
    }

    for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
    {
        RendererD3D *renderer = rendererCreationFunctions[i](display);
        egl::Error result     = renderer->initialize();

#if defined(ANGLE_ENABLE_D3D11)
        if (renderer->getRendererClass() == RENDERER_D3D11)
        {
            ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS);
            ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", result.getID(),
                                        NUM_D3D11_INIT_ERRORS);
        }
#endif

#if defined(ANGLE_ENABLE_D3D9)
        if (renderer->getRendererClass() == RENDERER_D3D9)
        {
            ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS);
            ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", result.getID(),
                                        NUM_D3D9_INIT_ERRORS);
        }
#endif

        if (!result.isError())
        {
            *outRenderer = renderer;
            return result;
        }

        // Failed to create the renderer, try the next
        SafeDelete(renderer);
    }

    return egl::EglNotInitialized() << "No available renderers.";
}

DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr) {}

SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
                                             EGLNativeWindowType window,
                                             const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs);
}

SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
                                              const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs);
}

SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
                                                       EGLenum buftype,
                                                       EGLClientBuffer clientBuffer,
                                                       const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs);
}

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

ImageImpl *DisplayD3D::createImage(const egl::ImageState &state,
                                   const gl::Context *context,
                                   EGLenum target,
                                   const egl::AttributeMap &attribs)
{
    return new EGLImageD3D(state, target, attribs, mRenderer);
}

DeviceImpl *DisplayD3D::createDevice()
{
    return mRenderer->createEGLDevice();
}

rx::ContextImpl *DisplayD3D::createContext(const gl::State &state,
                                           gl::ErrorSet *errorSet,
                                           const egl::Config *configuration,
                                           const gl::Context *shareContext,
                                           const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return mRenderer->createContext(state, errorSet);
}

StreamProducerImpl *DisplayD3D::createStreamProducerD3DTexture(
    egl::Stream::ConsumerType consumerType,
    const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return mRenderer->createStreamProducerD3DTexture(consumerType, attribs);
}

ExternalImageSiblingImpl *DisplayD3D::createExternalImageSibling(const gl::Context *context,
                                                                 EGLenum target,
                                                                 EGLClientBuffer buffer,
                                                                 const egl::AttributeMap &attribs)
{
    ASSERT(mRenderer != nullptr);
    return mRenderer->createExternalImageSibling(context, target, buffer, attribs);
}

egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface,
                                   egl::Surface *readSurface,
                                   gl::Context *context)
{
    return egl::NoError();
}

egl::Error DisplayD3D::initialize(egl::Display *display)
{
    ASSERT(mRenderer == nullptr && display != nullptr);
    mDisplay = display;
    ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
    return egl::NoError();
}

void DisplayD3D::terminate()
{
    SafeDelete(mRenderer);
}

egl::ConfigSet DisplayD3D::generateConfigs()
{
    ASSERT(mRenderer != nullptr);
    return mRenderer->generateConfigs();
}

bool DisplayD3D::testDeviceLost()
{
    ASSERT(mRenderer != nullptr);
    return mRenderer->testDeviceLost();
}

egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display)
{
    // Release surface resources to make the Reset() succeed
    for (egl::Surface *surface : mState.surfaceSet)
    {
        ASSERT(!surface->getBoundTexture());
        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
        surfaceD3D->releaseSwapChain();
    }

    if (!mRenderer->resetDevice())
    {
        return egl::EglBadAlloc();
    }

    // Restore any surfaces that may have been lost
    for (const egl::Surface *surface : mState.surfaceSet)
    {
        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);

        ANGLE_TRY(surfaceD3D->resetSwapChain(display));
    }

    return egl::NoError();
}

bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
{
    return mRenderer->isValidNativeWindow(window);
}

egl::Error DisplayD3D::validateClientBuffer(const egl::Config *config,
                                            EGLenum buftype,
                                            EGLClientBuffer clientBuffer,
                                            const egl::AttributeMap &attribs) const
{
    switch (buftype)
    {
        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
            return mRenderer->validateShareHandle(config, static_cast<HANDLE>(clientBuffer),
                                                  attribs);

        case EGL_D3D_TEXTURE_ANGLE:
            return mRenderer->getD3DTextureInfo(config, static_cast<IUnknown *>(clientBuffer),
                                                attribs, nullptr, nullptr, nullptr, nullptr,
                                                nullptr);

        default:
            return DisplayImpl::validateClientBuffer(config, buftype, clientBuffer, attribs);
    }
}

egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
                                                 EGLenum target,
                                                 EGLClientBuffer clientBuffer,
                                                 const egl::AttributeMap &attribs) const
{
    switch (target)
    {
        case EGL_D3D11_TEXTURE_ANGLE:
        {
            return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
                                                attribs, nullptr, nullptr, nullptr, nullptr,
                                                nullptr);
        }

        default:
            return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
    }
}

void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
    mRenderer->generateDisplayExtensions(outExtensions);
}

std::string DisplayD3D::getVendorString() const
{
    std::string vendorString = "Google Inc.";
    if (mRenderer)
    {
        vendorString += " " + mRenderer->getVendorString();
    }

    return vendorString;
}

void DisplayD3D::generateCaps(egl::Caps *outCaps) const
{
    // Display must be initialized to generate caps
    ASSERT(mRenderer != nullptr);

    outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT;
}

egl::Error DisplayD3D::waitClient(const gl::Context *context)
{
    for (egl::Surface *surface : mState.surfaceSet)
    {
        SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
        ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(this));
    }

    return egl::NoError();
}

egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine)
{
    egl::Surface *drawSurface = context->getCurrentDrawSurface();
    egl::Surface *readSurface = context->getCurrentReadSurface();

    if (drawSurface != nullptr)
    {
        SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
        ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(this));
    }

    if (readSurface != nullptr)
    {
        SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
        ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(this));
    }

    return egl::NoError();
}

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

gl::Version DisplayD3D::getMaxConformantESVersion() const
{
    return mRenderer->getMaxConformantESVersion();
}

void DisplayD3D::handleResult(HRESULT hr,
                              const char *message,
                              const char *file,
                              const char *function,
                              unsigned int line)
{
    ASSERT(FAILED(hr));

    std::stringstream errorStream;
    errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ", in " << file << ", " << function
                << ":" << line << ". " << message;

    mStoredErrorString = errorStream.str();
}

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

}  // namespace rx
