//
// Copyright (c) 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.
//

// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.

#include "libGLESv2/renderer/TextureStorage11.h"

#include "libGLESv2/renderer/Renderer11.h"
#include "libGLESv2/renderer/RenderTarget11.h"
#include "libGLESv2/renderer/SwapChain11.h"
#include "libGLESv2/renderer/renderer11_utils.h"

#include "libGLESv2/main.h"

namespace rx
{

TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
    : mBindFlags(bindFlags),
      mLodOffset(0),
      mMipLevels(0)
{
    mRenderer = Renderer11::makeRenderer11(renderer);
}

TextureStorage11::~TextureStorage11()
{
}

TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
{
    ASSERT(dynamic_cast<TextureStorage11*>(storage) != NULL);
    return static_cast<TextureStorage11*>(storage);
}

DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
{
    UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
    
    if (format == DXGI_FORMAT_D24_UNORM_S8_UINT)
    {
        bindFlags |= D3D11_BIND_DEPTH_STENCIL;
    }
    else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
    {
        bindFlags |= D3D11_BIND_RENDER_TARGET;
    }
    return bindFlags;
}

bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
{
    switch(format)
    {
      case DXGI_FORMAT_R8G8B8A8_UNORM:
      case DXGI_FORMAT_A8_UNORM:
      case DXGI_FORMAT_R32G32B32A32_FLOAT:
      case DXGI_FORMAT_R32G32B32_FLOAT:
      case DXGI_FORMAT_R16G16B16A16_FLOAT:
      case DXGI_FORMAT_B8G8R8A8_UNORM:
      case DXGI_FORMAT_R8_UNORM:
      case DXGI_FORMAT_R8G8_UNORM:
      case DXGI_FORMAT_R16_FLOAT:
      case DXGI_FORMAT_R16G16_FLOAT:
        return true;
      case DXGI_FORMAT_BC1_UNORM:
      case DXGI_FORMAT_BC2_UNORM: 
      case DXGI_FORMAT_BC3_UNORM:
        return false;
      default:
        UNREACHABLE();
        return false;
    }
}

UINT TextureStorage11::getBindFlags() const
{
    return mBindFlags;
}

int TextureStorage11::getLodOffset() const
{
    return mLodOffset;
}

bool TextureStorage11::isRenderTarget() const
{
    return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
}
    
bool TextureStorage11::isManaged() const
{
    return false;
}

int TextureStorage11::levelCount()
{
    int levels = 0;
    if (getBaseTexture())
    {
        levels = mMipLevels - getLodOffset();
    }
    return levels;
}

UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
{
    UINT index = 0;
    if (getBaseTexture())
    {
        index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
    }
    return index;
}

bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, int level, int face, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
    if (srcTexture)
    {
        D3D11_BOX srcBox;
        srcBox.left = xoffset;
        srcBox.top = yoffset;
        srcBox.right = xoffset + width;
        srcBox.bottom = yoffset + height;
        srcBox.front = 0;
        srcBox.back = 1;

        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
        
        ASSERT(getBaseTexture());
        context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level, face), xoffset, yoffset, 0, srcTexture, 0, &srcBox);
        return true;
    }

    return false;
}

TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
    : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
{
    ID3D11Texture2D *surfaceTexture = swapchain->getOffscreenTexture();
    mTexture = surfaceTexture;
    mSRV = NULL;

    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        mRenderTarget[i] = NULL;
    }

    D3D11_TEXTURE2D_DESC desc;
    surfaceTexture->GetDesc(&desc);

    mMipLevels = desc.MipLevels;
    mTextureFormat = desc.Format;
    mTextureWidth = desc.Width;
    mTextureHeight = desc.Height;
}

TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
{
    mTexture = NULL;
    mSRV = NULL;
    mTextureWidth = 0;
    mTextureHeight = 0;
    DXGI_FORMAT format = gl_d3d11::ConvertTextureFormat(internalformat);

    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        mRenderTarget[i] = NULL;
    }

    // if the width or height is not positive this should be treated as an incomplete texture
    // we handle that here by skipping the d3d texture creation
    if (width > 0 && height > 0)
    {
        // adjust size if needed for compressed textures
        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);

        ID3D11Device *device = mRenderer->getDevice();

        D3D11_TEXTURE2D_DESC desc;
        desc.Width = width;      // Compressed texture size constraints?
        desc.Height = height;
        desc.MipLevels = levels + mLodOffset;
        desc.ArraySize = 1;
        desc.Format = format;
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.BindFlags = getBindFlags();
        desc.CPUAccessFlags = 0;
        desc.MiscFlags = 0;

        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);

        if (FAILED(result))
        {
            ASSERT(result == E_OUTOFMEMORY);
            ERR("Creating image failed.");
            error(GL_OUT_OF_MEMORY);
        }
        else
        {
            mTexture->GetDesc(&desc);
            mMipLevels = desc.MipLevels;
            mTextureFormat = desc.Format;
            mTextureWidth = desc.Width;
            mTextureHeight = desc.Height;
        }
    }
}

TextureStorage11_2D::~TextureStorage11_2D()
{
    if (mTexture)
    {
        mTexture->Release();
        mTexture = NULL;
    }

    if (mSRV)
    {
        mSRV->Release();
        mSRV = NULL;
    }

    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        delete mRenderTarget[i];
        mRenderTarget[i] = NULL;
    }
}

TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
{
    ASSERT(dynamic_cast<TextureStorage11_2D*>(storage) != NULL);
    return static_cast<TextureStorage11_2D*>(storage);
}

RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
{
    if (level >= 0 && level < static_cast<int>(mMipLevels))
    {
        if (!mRenderTarget[level])
        {
            ID3D11Device *device = mRenderer->getDevice();
            HRESULT result;

            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
            rtvDesc.Format = mTextureFormat;
            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
            rtvDesc.Texture2D.MipSlice = level;

            ID3D11RenderTargetView *rtv;
            result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);

            if (result == E_OUTOFMEMORY)
            {
                return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
            }
            ASSERT(SUCCEEDED(result));

            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
            srvDesc.Format = mTextureFormat;
            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
            srvDesc.Texture2D.MostDetailedMip = level;
            srvDesc.Texture2D.MipLevels = 1;

            ID3D11ShaderResourceView *srv;
            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);

            if (result == E_OUTOFMEMORY)
            {
                rtv->Release();
                return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
            }
            ASSERT(SUCCEEDED(result));

            mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, srv,
                                                      std::max(mTextureWidth >> level, 1U),
                                                      std::max(mTextureHeight >> level, 1U));
        }

        return mRenderTarget[level];
    }
    else
    {
        return NULL;
    }
}

ID3D11Texture2D *TextureStorage11_2D::getBaseTexture() const
{
    return mTexture;
}

ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
{
    if (!mSRV)
    {
        ID3D11Device *device = mRenderer->getDevice();

        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
        srvDesc.Format = mTextureFormat;
        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
        srvDesc.Texture2D.MostDetailedMip = 0;

        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);

        if (result == E_OUTOFMEMORY)
        {
            return error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
        }
        ASSERT(SUCCEEDED(result));
    }

    return mSRV;
}

void TextureStorage11_2D::generateMipmap(int level)
{
    // TODO
    UNIMPLEMENTED();
}

TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
    : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
{
    mTexture = NULL;
    mSRV = NULL;
    mTextureWidth = 0;
    mTextureHeight = 0;

    for (unsigned int i = 0; i < 6; i++)
    {
        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
        {
            mRenderTarget[i][j] = NULL;
        }
    }

    DXGI_FORMAT format = gl_d3d11::ConvertTextureFormat(internalformat);
    // if the size is not positive this should be treated as an incomplete texture
    // we handle that here by skipping the d3d texture creation
    if (size > 0)
    {
        // adjust size if needed for compressed textures
        int height = size;
        gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);

        ID3D11Device *device = mRenderer->getDevice();

        D3D11_TEXTURE2D_DESC desc;
        desc.Width = size;
        desc.Height = size;
        desc.MipLevels = levels + mLodOffset;
        desc.ArraySize = 6;
        desc.Format = format;
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.BindFlags = getBindFlags();
        desc.CPUAccessFlags = 0;
        desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;

        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);

        if (FAILED(result))
        {
            ASSERT(result == E_OUTOFMEMORY);
            ERR("Creating image failed.");
            error(GL_OUT_OF_MEMORY);
        }
        else
        {
            mTexture->GetDesc(&desc);
            mMipLevels = desc.MipLevels;
            mTextureFormat = desc.Format;
            mTextureWidth = desc.Width;
            mTextureHeight = desc.Height;
        }
    }
}

TextureStorage11_Cube::~TextureStorage11_Cube()
{
    if (mTexture)
    {
        mTexture->Release();
        mTexture = NULL;
    }

    if (mSRV)
    {
        mSRV->Release();
        mSRV = NULL;
    }

    for (unsigned int i = 0; i < 6; i++)
    {
        for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
        {
            delete mRenderTarget[i][j];
            mRenderTarget[i][j] = NULL;
        }
    }
}

TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
{
    ASSERT(dynamic_cast<TextureStorage11_Cube*>(storage) != NULL);
    return static_cast<TextureStorage11_Cube*>(storage);
}

RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
{
    unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
    if (level >= 0 && level < static_cast<int>(mMipLevels))
    {
        if (!mRenderTarget[faceIdx][level])
        {
            ID3D11Device *device = mRenderer->getDevice();
            HRESULT result;

            if (getBindFlags() & D3D11_BIND_RENDER_TARGET)
            {
                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
                rtvDesc.Format = mTextureFormat;
                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
                rtvDesc.Texture2DArray.MipSlice = level;
                rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
                rtvDesc.Texture2DArray.ArraySize = 1;

                ID3D11RenderTargetView *rtv;
                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);

                if (result == E_OUTOFMEMORY)
                {
                    return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
                }
                ASSERT(SUCCEEDED(result));

                D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
                srvDesc.Format = mTextureFormat;
                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
                srvDesc.Texture2DArray.MostDetailedMip = level;
                srvDesc.Texture2DArray.MipLevels = 1;
                srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
                srvDesc.Texture2DArray.ArraySize = 1;

                ID3D11ShaderResourceView *srv;
                result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);

                if (result == E_OUTOFMEMORY)
                {
                    rtv->Release();
                    return error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
                }
                ASSERT(SUCCEEDED(result));

                mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, srv,
                                                                   std::max(mTextureWidth >> level, 1U),
                                                                   std::max(mTextureHeight >> level, 1U));
            }
            else if (getBindFlags() & D3D11_BIND_DEPTH_STENCIL)
            {
                // TODO
                UNIMPLEMENTED();
            }
            else UNREACHABLE();
        }

        return mRenderTarget[faceIdx][level];
    }
    else
    {
        return NULL;
    }
}

ID3D11Texture2D *TextureStorage11_Cube::getBaseTexture() const
{
    return mTexture;
}

ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
{
    if (!mSRV)
    {
        ID3D11Device *device = mRenderer->getDevice();

        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
        srvDesc.Format = mTextureFormat;
        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
        srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
        srvDesc.TextureCube.MostDetailedMip = 0;

        HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);

        if (result == E_OUTOFMEMORY)
        {
            return error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
        }
        ASSERT(SUCCEEDED(result));
    }

    return mSRV;
}

void TextureStorage11_Cube::generateMipmap(int face, int level)
{
    // TODO
    UNIMPLEMENTED();
}

}
