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

// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.

#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"

#include "libANGLE/features.h"
#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"

namespace rx
{

SwapChain9::SwapChain9(Renderer9 *renderer,
                       NativeWindow9 *nativeWindow,
                       HANDLE shareHandle,
                       IUnknown *d3dTexture,
                       GLenum backBufferFormat,
                       GLenum depthBufferFormat,
                       EGLint orientation)
    : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
      mRenderer(renderer),
      mWidth(-1),
      mHeight(-1),
      mSwapInterval(-1),
      mNativeWindow(nativeWindow),
      mSwapChain(nullptr),
      mBackBuffer(nullptr),
      mRenderTarget(nullptr),
      mDepthStencil(nullptr),
      mOffscreenTexture(nullptr),
      mColorRenderTarget(this, false),
      mDepthStencilRenderTarget(this, true)
{
    ASSERT(orientation == 0);
}

SwapChain9::~SwapChain9()
{
    release();
}

void SwapChain9::release()
{
    SafeRelease(mSwapChain);
    SafeRelease(mBackBuffer);
    SafeRelease(mDepthStencil);
    SafeRelease(mRenderTarget);
    SafeRelease(mOffscreenTexture);

    if (mNativeWindow->getNativeWindow())
    {
        mShareHandle = nullptr;
    }
}

static DWORD convertInterval(EGLint interval)
{
#if ANGLE_VSYNC == ANGLE_DISABLED
    return D3DPRESENT_INTERVAL_IMMEDIATE;
#else
    switch (interval)
    {
        case 0:
            return D3DPRESENT_INTERVAL_IMMEDIATE;
        case 1:
            return D3DPRESENT_INTERVAL_ONE;
        case 2:
            return D3DPRESENT_INTERVAL_TWO;
        case 3:
            return D3DPRESENT_INTERVAL_THREE;
        case 4:
            return D3DPRESENT_INTERVAL_FOUR;
        default:
            UNREACHABLE();
    }

    return D3DPRESENT_INTERVAL_DEFAULT;
#endif
}

EGLint SwapChain9::resize(DisplayD3D *displayD3D, int backbufferWidth, int backbufferHeight)
{
    // D3D9 does not support resizing swap chains without recreating them
    return reset(displayD3D, backbufferWidth, backbufferHeight, mSwapInterval);
}

EGLint SwapChain9::reset(DisplayD3D *displayD3D,
                         int backbufferWidth,
                         int backbufferHeight,
                         EGLint swapInterval)
{
    IDirect3DDevice9 *device = mRenderer->getDevice();

    if (device == nullptr)
    {
        return EGL_BAD_ACCESS;
    }

    // Evict all non-render target textures to system memory and release all resources
    // before reallocating them to free up as much video memory as possible.
    device->EvictManagedResources();

    HRESULT result;

    // Release specific resources to free up memory for the new render target, while the
    // old render target still exists for the purpose of preserving its contents.
    SafeRelease(mSwapChain);
    SafeRelease(mBackBuffer);
    SafeRelease(mOffscreenTexture);
    SafeRelease(mDepthStencil);

    const d3d9::TextureFormat &backBufferd3dFormatInfo =
        d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
    if (mD3DTexture != nullptr)
    {
        result = mD3DTexture->QueryInterface(&mOffscreenTexture);
        ASSERT(SUCCEEDED(result));
    }
    else
    {
        HANDLE *pShareHandle = nullptr;
        if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
        {
            pShareHandle = &mShareHandle;
        }

        result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
                                       backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
                                       &mOffscreenTexture, pShareHandle);
        if (FAILED(result))
        {
            ERR() << "Could not create offscreen texture, " << gl::FmtHR(result);
            release();

            if (d3d9::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }
    }

    IDirect3DSurface9 *oldRenderTarget = mRenderTarget;

    result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
    ASSERT(SUCCEEDED(result));

    if (oldRenderTarget)
    {
        RECT rect = {0, 0, mWidth, mHeight};

        if (rect.right > static_cast<LONG>(backbufferWidth))
        {
            rect.right = backbufferWidth;
        }

        if (rect.bottom > static_cast<LONG>(backbufferHeight))
        {
            rect.bottom = backbufferHeight;
        }

        mRenderer->endScene();

        result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
        ASSERT(SUCCEEDED(result));

        SafeRelease(oldRenderTarget);
    }

    const d3d9::TextureFormat &depthBufferd3dFormatInfo =
        d3d9::GetTextureFormatInfo(mDepthBufferFormat);

    // Don't create a swapchain for NULLREF devices
    D3DDEVTYPE deviceType      = mRenderer->getD3D9DeviceType();
    EGLNativeWindowType window = mNativeWindow->getNativeWindow();
    if (window && deviceType != D3DDEVTYPE_NULLREF)
    {
        D3DPRESENT_PARAMETERS presentParameters  = {};
        presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
        presentParameters.BackBufferCount        = 1;
        presentParameters.BackBufferFormat       = backBufferd3dFormatInfo.renderFormat;
        presentParameters.EnableAutoDepthStencil = FALSE;
        presentParameters.Flags                  = 0;
        presentParameters.hDeviceWindow          = window;
        presentParameters.MultiSampleQuality     = 0;                    // FIXME: Unimplemented
        presentParameters.MultiSampleType        = D3DMULTISAMPLE_NONE;  // FIXME: Unimplemented
        presentParameters.PresentationInterval   = convertInterval(swapInterval);
        presentParameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
        presentParameters.Windowed               = TRUE;
        presentParameters.BackBufferWidth        = backbufferWidth;
        presentParameters.BackBufferHeight       = backbufferHeight;

        // http://crbug.com/140239
        // http://crbug.com/143434
        //
        // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a
        // multiple of 64 pixels in width when using the integrated Intel. This rounds the width up
        // rather than down.
        //
        // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present.
        // Therefore, when the vendor ID is not Intel, the back buffer width must be exactly the
        // same width as the window or horizontal scaling will occur.
        if (IsIntel(mRenderer->getVendorId()))
        {
            presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
        }

        result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);

        if (FAILED(result))
        {
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
                   result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);

            ERR() << "Could not create additional swap chains or offscreen surfaces, "
                  << gl::FmtHR(result);
            release();

            if (d3d9::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }

        result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
        ASSERT(SUCCEEDED(result));
        InvalidateRect(window, nullptr, FALSE);
    }

    if (mDepthBufferFormat != GL_NONE)
    {
        result = device->CreateDepthStencilSurface(
            backbufferWidth, backbufferHeight, depthBufferd3dFormatInfo.renderFormat,
            D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, nullptr);

        if (FAILED(result))
        {
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
                   result == D3DERR_INVALIDCALL);

            ERR() << "Could not create depthstencil surface for new swap chain, "
                  << gl::FmtHR(result);
            release();

            if (d3d9::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }
    }

    mWidth        = backbufferWidth;
    mHeight       = backbufferHeight;
    mSwapInterval = swapInterval;

    return EGL_SUCCESS;
}

// parameters should be validated/clamped by caller
EGLint SwapChain9::swapRect(DisplayD3D *displayD3D, EGLint x, EGLint y, EGLint width, EGLint height)
{
    if (!mSwapChain)
    {
        return EGL_SUCCESS;
    }

    IDirect3DDevice9 *device = mRenderer->getDevice();

    // Disable all pipeline operations
    device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
    device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
    device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
    device->SetRenderState(D3DRS_COLORWRITEENABLE,
                           D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE |
                               D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
    device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
    device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
    device->SetPixelShader(nullptr);
    device->SetVertexShader(nullptr);

    device->SetRenderTarget(0, mBackBuffer);
    device->SetDepthStencilSurface(nullptr);

    device->SetTexture(0, mOffscreenTexture);
    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
    device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);

    for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++)
    {
        device->SetStreamSourceFreq(streamIndex, 1);
    }

    D3DVIEWPORT9 viewport = {0,    0,   static_cast<DWORD>(mWidth), static_cast<DWORD>(mHeight),
                             0.0f, 1.0f};
    device->SetViewport(&viewport);

    float x1 = x - 0.5f;
    float y1 = (mHeight - y - height) - 0.5f;
    float x2 = (x + width) - 0.5f;
    float y2 = (mHeight - y) - 0.5f;

    float u1 = x / float(mWidth);
    float v1 = y / float(mHeight);
    float u2 = (x + width) / float(mWidth);
    float v2 = (y + height) / float(mHeight);

    float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
                        {x2, y1, 0.0f, 1.0f, u2, v2},
                        {x2, y2, 0.0f, 1.0f, u2, v1},
                        {x1, y2, 0.0f, 1.0f, u1, v1}};  // x, y, z, rhw, u, v

    mRenderer->startScene();
    device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
    mRenderer->endScene();

    device->SetTexture(0, nullptr);

    RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
                 static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};

    HRESULT result = mSwapChain->Present(&rect, &rect, nullptr, nullptr, 0);

    mRenderer->markAllStateDirty();

    if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
        result == D3DERR_DRIVERINTERNALERROR)
    {
        return EGL_BAD_ALLOC;
    }

    // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the
    // windows is in the process of entering/exiting fullscreen. This code doesn't seem to have any
    // documentation.  The device appears to be ok after emitting this error so simply return a
    // failure to swap.
    if (result == static_cast<HRESULT>(0x88760873) || result == static_cast<HRESULT>(0x88760872))
    {
        return EGL_BAD_MATCH;
    }

    // http://crbug.com/313210
    // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific
    // device removed bug with lost contexts when reinstalling drivers.
    if (FAILED(result))
    {
        mRenderer->notifyDeviceLost();
        return EGL_CONTEXT_LOST;
    }

    return EGL_SUCCESS;
}

// Increments refcount on surface.
// caller must Release() the returned surface
// TODO: remove the AddRef to match SwapChain11
IDirect3DSurface9 *SwapChain9::getRenderTarget()
{
    if (mRenderTarget)
    {
        mRenderTarget->AddRef();
    }

    return mRenderTarget;
}

// Increments refcount on surface.
// caller must Release() the returned surface
// TODO: remove the AddRef to match SwapChain11
IDirect3DSurface9 *SwapChain9::getDepthStencil()
{
    if (mDepthStencil)
    {
        mDepthStencil->AddRef();
    }

    return mDepthStencil;
}

// Increments refcount on texture.
// caller must Release() the returned texture
// TODO: remove the AddRef to match SwapChain11
IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
{
    if (mOffscreenTexture)
    {
        mOffscreenTexture->AddRef();
    }

    return mOffscreenTexture;
}

void *SwapChain9::getKeyedMutex()
{
    UNREACHABLE();
    return nullptr;
}

egl::Error SwapChain9::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
{
    UNREACHABLE();
    return egl::EglBadSurface();
}

void SwapChain9::recreate()
{
    if (!mSwapChain)
    {
        return;
    }

    IDirect3DDevice9 *device = mRenderer->getDevice();
    if (device == nullptr)
    {
        return;
    }

    D3DPRESENT_PARAMETERS presentParameters;
    HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
    ASSERT(SUCCEEDED(result));

    IDirect3DSwapChain9 *newSwapChain = nullptr;
    result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
    if (FAILED(result))
    {
        return;
    }

    SafeRelease(mSwapChain);
    mSwapChain = newSwapChain;

    SafeRelease(mBackBuffer);
    result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
    ASSERT(SUCCEEDED(result));
}

RenderTargetD3D *SwapChain9::getColorRenderTarget()
{
    return &mColorRenderTarget;
}

RenderTargetD3D *SwapChain9::getDepthStencilRenderTarget()
{
    return &mDepthStencilRenderTarget;
}
}  // namespace rx
