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

// SurfaceD3D.cpp: D3D implementation of an EGL surface
#include <Mfobjects.h>

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

#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"

#include <EGL/eglext.h>
#include <tchar.h>
#include <algorithm>

// A key for ID3D11DeviceChild. The value should be a bool.
// When set and true, indicates that the NV12 texture passed
// in eglCreatePbufferFromClientBuffer EGL_D3D_TEXTURE_ANGLE should
// draw it's chroma component when a ShaderResourceView is created for it.
// If absent or false, the luma component is drawn.
//
// The value is fetched from ID3D11DeviceChild and stored before
// eglCreatePbufferFromClientBuffer returns.
//
// {3C3A43AB-C69B-46C9-AA8D-B0CFFCD4596D}
static const GUID kCobaltNv12BindChroma = {0x3c3a43ab,
                                           0xc69b,
                                           0x46c9,
                                           {0xaa, 0x8d, 0xb0, 0xcf, 0xfc, 0xd4, 0x59, 0x6d}};

namespace rx
{

SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
                       RendererD3D *renderer,
                       egl::Display *display,
                       EGLNativeWindowType window,
                       EGLenum buftype,
                       EGLClientBuffer clientBuffer,
                       const egl::AttributeMap &attribs)
    : SurfaceImpl(state),
      mRenderer(renderer),
      mDisplay(display),
      mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
      mFixedWidth(0),
      mFixedHeight(0),
      mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
      mRenderTargetFormat(state.config->renderTargetFormat),
      mDepthStencilFormat(state.config->depthStencilFormat),
      mColorFormat(nullptr),
      mSwapChain(nullptr),
      mSwapIntervalDirty(true),
      mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
      mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
      mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
      mSwapInterval(1),
      mShareHandle(0),
      mD3DTexture(nullptr),
      mBuftype(buftype),
      mBindChroma(false)
{
    if (window != nullptr && !mFixedSize)
    {
        mWidth  = -1;
        mHeight = -1;
    }

    if (mFixedSize)
    {
        mFixedWidth  = mWidth;
        mFixedHeight = mHeight;
    }

    switch (buftype)
    {
        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
            mShareHandle = static_cast<HANDLE>(clientBuffer);
            break;

        case EGL_D3D_TEXTURE_ANGLE:
        {
            mD3DTexture = static_cast<IUnknown *>(clientBuffer);
            ASSERT(mD3DTexture != nullptr);
            mD3DTexture->AddRef();
            break;
        }

        default:
            break;
    }
}

SurfaceD3D::~SurfaceD3D()
{
    releaseSwapChain();
    SafeDelete(mNativeWindow);
    SafeRelease(mD3DTexture);
}

void SurfaceD3D::releaseSwapChain()
{
    SafeDelete(mSwapChain);
}

egl::Error SurfaceD3D::initialize(const egl::Display *display)
{
    if (mNativeWindow->getNativeWindow())
    {
        if (!mNativeWindow->initialize())
        {
            return egl::EglBadSurface();
        }
    }

    if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
    {
        UINT out;
        HRESULT hr = static_cast<ID3D11DeviceChild *>(mD3DTexture)
                         ->GetPrivateData(kCobaltNv12BindChroma, &out, nullptr);
        mBindChroma = (SUCCEEDED(hr)) && (out != 0);

        ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, mState.attributes,
                                               &mFixedWidth, &mFixedHeight, nullptr, nullptr,
                                               &mColorFormat));
        if (mState.attributes.contains(EGL_GL_COLORSPACE))
        {
            if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
                mColorFormat->id != angle::FormatID::B8G8R8A8_TYPELESS)
            {
                return egl::EglBadMatch()
                       << "EGL_GL_COLORSPACE may only be specified for TYPELESS textures";
            }
        }
        if (mColorFormat->id == angle::FormatID::R8G8B8A8_TYPELESS)
        {
            EGLAttrib colorspace =
                mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
            if (colorspace == EGL_GL_COLORSPACE_SRGB)
            {
                mColorFormat = &angle::Format::Get(angle::FormatID::R8G8B8A8_TYPELESS_SRGB);
            }
        }
        if (mColorFormat->id == angle::FormatID::B8G8R8A8_TYPELESS)
        {
            EGLAttrib colorspace =
                mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
            if (colorspace == EGL_GL_COLORSPACE_SRGB)
            {
                mColorFormat = &angle::Format::Get(angle::FormatID::B8G8R8A8_TYPELESS_SRGB);
            }
        }
        mRenderTargetFormat = mColorFormat->fboImplementationInternalFormat;

        ID3D11Texture2D *d3Texture = static_cast<ID3D11Texture2D *>(mD3DTexture);
        D3D11_TEXTURE2D_DESC texture_desc;
        d3Texture->GetDesc(&texture_desc);
        if (texture_desc.Format == DXGI_FORMAT_NV12)
        {
            // NV12 textures cannot be rendered to,
            // so don't proceed to making a swap chain.
            mWidth  = mFixedWidth;
            mHeight = mFixedHeight;
            return egl::NoError();
        }
    }

    ANGLE_TRY(resetSwapChain(display));
    return egl::NoError();
}

FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Context *context,
                                                      const gl::FramebufferState &data)
{
    return mRenderer->createDefaultFramebuffer(data);
}

egl::Error SurfaceD3D::bindTexImage(const gl::Context *, gl::Texture *, EGLint)
{
    return egl::NoError();
}

egl::Error SurfaceD3D::releaseTexImage(const gl::Context *, EGLint)
{
    return egl::NoError();
}

egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
{
    if (!mState.directComposition)
    {
        return egl::EglBadSurface()
               << "getSyncValues: surface requires Direct Composition to be enabled";
    }

    return mSwapChain->getSyncValues(ust, msc, sbc);
}

egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
{
    ASSERT(!mSwapChain);

    int width;
    int height;

    if (!mFixedSize)
    {
        RECT windowRect;
        if (!mNativeWindow->getClientRect(&windowRect))
        {
            ASSERT(false);

            return egl::EglBadSurface() << "Could not retrieve the window dimensions";
        }

        width  = windowRect.right - windowRect.left;
        height = windowRect.bottom - windowRect.top;
    }
    else
    {
        // non-window surface - size is determined at creation
        width  = mFixedWidth;
        height = mFixedHeight;
    }

    mSwapChain =
        mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat,
                                   mDepthStencilFormat, mOrientation, mState.config->samples);
    if (!mSwapChain)
    {
        return egl::EglBadAlloc();
    }

    // This is a bit risky to pass the proxy context here, but it can happen at almost any time.
    DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(display);
    egl::Error error       = resetSwapChain(displayD3D, width, height);
    if (error.isError())
    {
        SafeDelete(mSwapChain);
        return error;
    }

    return egl::NoError();
}

egl::Error SurfaceD3D::resizeSwapChain(DisplayD3D *displayD3D,
                                       int backbufferWidth,
                                       int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status =
        mSwapChain->resize(displayD3D, std::max(1, backbufferWidth), std::max(1, backbufferHeight));

    if (status == EGL_CONTEXT_LOST)
    {
        mDisplay->notifyDeviceLost();
        return egl::Error(status);
    }
    else if (status != EGL_SUCCESS)
    {
        return egl::Error(status);
    }

    mWidth  = backbufferWidth;
    mHeight = backbufferHeight;

    return egl::NoError();
}

egl::Error SurfaceD3D::resetSwapChain(DisplayD3D *displayD3D,
                                      int backbufferWidth,
                                      int backbufferHeight)
{
    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
    ASSERT(mSwapChain);

    EGLint status = mSwapChain->reset(displayD3D, std::max(1, backbufferWidth),
                                      std::max(1, backbufferHeight), mSwapInterval);

    if (status == EGL_CONTEXT_LOST)
    {
        mRenderer->notifyDeviceLost();
        return egl::Error(status);
    }
    else if (status != EGL_SUCCESS)
    {
        return egl::Error(status);
    }

    mWidth             = backbufferWidth;
    mHeight            = backbufferHeight;
    mSwapIntervalDirty = false;

    return egl::NoError();
}

egl::Error SurfaceD3D::swapRect(DisplayD3D *displayD3D,
                                EGLint x,
                                EGLint y,
                                EGLint width,
                                EGLint height)
{
    if (!mSwapChain)
    {
        return egl::NoError();
    }

    if (x + width > mWidth)
    {
        width = mWidth - x;
    }

    if (y + height > mHeight)
    {
        height = mHeight - y;
    }

    if (width != 0 && height != 0)
    {
        EGLint status = mSwapChain->swapRect(displayD3D, x, y, width, height);

        if (status == EGL_CONTEXT_LOST)
        {
            mRenderer->notifyDeviceLost();
            return egl::Error(status);
        }
        else if (status != EGL_SUCCESS)
        {
            return egl::Error(status);
        }
    }

    ANGLE_TRY(checkForOutOfDateSwapChain(displayD3D));

    return egl::NoError();
}

egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D)
{
    RECT client;
    int clientWidth  = getWidth();
    int clientHeight = getHeight();
    bool sizeDirty   = false;
    if (!mFixedSize && !mNativeWindow->isIconic())
    {
        // The window is automatically resized to 150x22 when it's minimized, but the swapchain
        // shouldn't be resized because that's not a useful size to render to.
        if (!mNativeWindow->getClientRect(&client))
        {
            UNREACHABLE();
            return egl::NoError();
        }

        // Grow the buffer now, if the window has grown. We need to grow now to avoid losing
        // information.
        clientWidth  = client.right - client.left;
        clientHeight = client.bottom - client.top;
        sizeDirty    = clientWidth != getWidth() || clientHeight != getHeight();
    }
    else if (mFixedSize)
    {
        clientWidth  = mFixedWidth;
        clientHeight = mFixedHeight;
        sizeDirty    = mFixedWidth != getWidth() || mFixedHeight != getHeight();
    }

    if (mSwapIntervalDirty)
    {
        ANGLE_TRY(resetSwapChain(displayD3D, clientWidth, clientHeight));
    }
    else if (sizeDirty)
    {
        ANGLE_TRY(resizeSwapChain(displayD3D, clientWidth, clientHeight));
    }

    return egl::NoError();
}

egl::Error SurfaceD3D::swap(const gl::Context *context)
{
    DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
    return swapRect(displayD3D, 0, 0, mWidth, mHeight);
}

egl::Error SurfaceD3D::postSubBuffer(const gl::Context *context,
                                     EGLint x,
                                     EGLint y,
                                     EGLint width,
                                     EGLint height)
{
    DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
    return swapRect(displayD3D, x, y, width, height);
}

rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
{
    return mSwapChain;
}

void SurfaceD3D::setSwapInterval(EGLint interval)
{
    if (mSwapInterval == interval)
    {
        return;
    }

    mSwapInterval      = interval;
    mSwapIntervalDirty = true;
}

void SurfaceD3D::setFixedWidth(EGLint width)
{
    mFixedWidth = width;
}

void SurfaceD3D::setFixedHeight(EGLint height)
{
    mFixedHeight = height;
}

EGLint SurfaceD3D::getWidth() const
{
    return mWidth;
}

EGLint SurfaceD3D::getHeight() const
{
    return mHeight;
}

EGLint SurfaceD3D::isPostSubBufferSupported() const
{
    // post sub buffer is always possible on D3D surfaces
    return EGL_TRUE;
}

EGLint SurfaceD3D::getSwapBehavior() const
{
    return EGL_BUFFER_PRESERVED;
}

egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
{
    if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
    {
        *value = mSwapChain->getShareHandle();
    }
    else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE)
    {
        *value = mSwapChain->getKeyedMutex();
    }
    else
        UNREACHABLE();

    return egl::NoError();
}

const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const
{
    return mColorFormat;
}

angle::Result SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
                                                    GLenum binding,
                                                    const gl::ImageIndex &imageIndex,
                                                    GLsizei samples,
                                                    FramebufferAttachmentRenderTarget **rtOut)
{
    if (binding == GL_BACK)
    {
        *rtOut = mSwapChain->getColorRenderTarget();
    }
    else
    {
        *rtOut = mSwapChain->getDepthStencilRenderTarget();
    }
    return angle::Result::Continue;
}

angle::Result SurfaceD3D::initializeContents(const gl::Context *context,
                                             const gl::ImageIndex &imageIndex)
{
    if (mState.config->renderTargetFormat != GL_NONE)
    {
        ANGLE_TRY(mRenderer->initRenderTarget(context, mSwapChain->getColorRenderTarget()));
    }
    if (mState.config->depthStencilFormat != GL_NONE)
    {
        ANGLE_TRY(mRenderer->initRenderTarget(context, mSwapChain->getDepthStencilRenderTarget()));
    }
    return angle::Result::Continue;
}

WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
                                   RendererD3D *renderer,
                                   egl::Display *display,
                                   EGLNativeWindowType window,
                                   const egl::AttributeMap &attribs)
    : SurfaceD3D(state, renderer, display, window, 0, static_cast<EGLClientBuffer>(0), attribs)
{}

WindowSurfaceD3D::~WindowSurfaceD3D() {}

PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
                                     RendererD3D *renderer,
                                     egl::Display *display,
                                     EGLenum buftype,
                                     EGLClientBuffer clientBuffer,
                                     const egl::AttributeMap &attribs)
    : SurfaceD3D(state,
                 renderer,
                 display,
                 static_cast<EGLNativeWindowType>(0),
                 buftype,
                 clientBuffer,
                 attribs)
{}

PbufferSurfaceD3D::~PbufferSurfaceD3D() {}

}  // namespace rx
