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

// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
// D3D9 texture.

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

#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"

namespace rx
{
TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage)
    : mTopLevel(0),
      mMipLevels(0),
      mTextureWidth(0),
      mTextureHeight(0),
      mInternalFormat(GL_NONE),
      mTextureFormat(D3DFMT_UNKNOWN),
      mRenderer(renderer),
      mD3DUsage(usage),
      mD3DPool(mRenderer->getTexturePool(usage))
{}

TextureStorage9::~TextureStorage9() {}

DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
{
    DWORD d3dusage = 0;

    const gl::InternalFormat &formatInfo     = gl::GetSizedInternalFormatInfo(internalformat);
    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
    if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
    {
        d3dusage |= D3DUSAGE_DEPTHSTENCIL;
    }
    else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
    {
        d3dusage |= D3DUSAGE_RENDERTARGET;
    }

    return d3dusage;
}

bool TextureStorage9::isRenderTarget() const
{
    return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
}

bool TextureStorage9::isManaged() const
{
    return (mD3DPool == D3DPOOL_MANAGED);
}

bool TextureStorage9::supportsNativeMipmapFunction() const
{
    return false;
}

D3DPOOL TextureStorage9::getPool() const
{
    return mD3DPool;
}

DWORD TextureStorage9::getUsage() const
{
    return mD3DUsage;
}

int TextureStorage9::getTopLevel() const
{
    return mTopLevel;
}

int TextureStorage9::getLevelCount() const
{
    return static_cast<int>(mMipLevels) - mTopLevel;
}

angle::Result TextureStorage9::setData(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       ImageD3D *image,
                                       const gl::Box *destBox,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
                                       const uint8_t *pixelData)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
    : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
{
    IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
    mTexture                          = surfaceTexture;
    mMipLevels                        = surfaceTexture->GetLevelCount();

    mInternalFormat = swapchain->getRenderTargetInternalFormat();

    D3DSURFACE_DESC surfaceDesc;
    surfaceTexture->GetLevelDesc(0, &surfaceDesc);
    mTextureWidth  = surfaceDesc.Width;
    mTextureHeight = surfaceDesc.Height;
    mTextureFormat = surfaceDesc.Format;

    mRenderTargets.resize(mMipLevels, nullptr);
}

TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer,
                                       GLenum internalformat,
                                       bool renderTarget,
                                       GLsizei width,
                                       GLsizei height,
                                       int levels)
    : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
    mTexture = nullptr;

    mInternalFormat = internalformat;

    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
    mTextureFormat                           = d3dFormatInfo.texFormat;

    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
    mTextureWidth  = width;
    mTextureHeight = height;
    mMipLevels     = mTopLevel + levels;

    mRenderTargets.resize(levels, nullptr);
}

TextureStorage9_2D::~TextureStorage9_2D()
{
    SafeRelease(mTexture);
    for (RenderTargetD3D *renderTarget : mRenderTargets)
    {
        SafeDelete(renderTarget);
    }
}

// Increments refcount on surface.
// caller must Release() the returned surface
angle::Result TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
                                                  gl::TextureTarget target,
                                                  int level,
                                                  bool dirty,
                                                  IDirect3DSurface9 **outSurface)
{
    ASSERT(target == gl::TextureTarget::_2D);

    IDirect3DBaseTexture9 *baseTexture = nullptr;
    ANGLE_TRY(getBaseTexture(context, &baseTexture));

    IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9 *>(baseTexture);

    HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");

    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
    if (level + mTopLevel != 0 && isManaged() && dirty)
    {
        texture->AddDirtyRect(nullptr);
    }

    return angle::Result::Continue;
}

angle::Result TextureStorage9_2D::getRenderTarget(const gl::Context *context,
                                                  const gl::ImageIndex &index,
                                                  GLsizei samples,
                                                  RenderTargetD3D **outRT)
{
    ASSERT(index.getLevelIndex() < getLevelCount());

    if (!mRenderTargets[index.getLevelIndex()] && isRenderTarget())
    {
        IDirect3DBaseTexture9 *baseTexture = nullptr;
        ANGLE_TRY(getBaseTexture(context, &baseTexture));

        IDirect3DSurface9 *surface = nullptr;
        ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, index.getLevelIndex(), false,
                                  &surface));

        size_t textureMipLevel = mTopLevel + index.getLevelIndex();
        size_t mipWidth        = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
        size_t mipHeight       = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);

        baseTexture->AddRef();
        mRenderTargets[index.getLevelIndex()] = new TextureRenderTarget9(
            baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
            static_cast<GLsizei>(mipHeight), 1, 0);
    }

    ASSERT(outRT);
    *outRT = mRenderTargets[index.getLevelIndex()];
    return angle::Result::Continue;
}

angle::Result TextureStorage9_2D::generateMipmap(const gl::Context *context,
                                                 const gl::ImageIndex &sourceIndex,
                                                 const gl::ImageIndex &destIndex)
{
    angle::ComPtr<IDirect3DSurface9> upper = nullptr;
    ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, sourceIndex.getLevelIndex(), false,
                              &upper));

    angle::ComPtr<IDirect3DSurface9> lower = nullptr;
    ANGLE_TRY(
        getSurfaceLevel(context, gl::TextureTarget::_2D, destIndex.getLevelIndex(), true, &lower));

    ASSERT(upper && lower);
    return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
}

angle::Result TextureStorage9_2D::getBaseTexture(const gl::Context *context,
                                                 IDirect3DBaseTexture9 **outTexture)
{
    // 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 (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
    {
        ASSERT(mMipLevels > 0);

        IDirect3DDevice9 *device = mRenderer->getDevice();
        HRESULT result           = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
                                               static_cast<unsigned int>(mTextureHeight),
                                               static_cast<unsigned int>(mMipLevels), getUsage(),
                                               mTextureFormat, getPool(), &mTexture, nullptr);
        ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create 2D storage texture");
    }

    *outTexture = mTexture;
    return angle::Result::Continue;
}

angle::Result TextureStorage9_2D::copyToStorage(const gl::Context *context,
                                                TextureStorage *destStorage)
{
    ASSERT(destStorage);

    TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);

    int levels = getLevelCount();
    for (int i = 0; i < levels; ++i)
    {
        angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
        ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, i, false, &srcSurf));

        angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
        ANGLE_TRY(dest9->getSurfaceLevel(context, gl::TextureTarget::_2D, i, true, &dstSurf));

        ANGLE_TRY(
            mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
    }

    return angle::Result::Continue;
}

TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
                                                   EGLImageD3D *image,
                                                   RenderTarget9 *renderTarget9)
    : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image)
{
    mInternalFormat = renderTarget9->getInternalFormat();
    mTextureFormat  = renderTarget9->getD3DFormat();
    mTextureWidth   = renderTarget9->getWidth();
    mTextureHeight  = renderTarget9->getHeight();
    mTopLevel       = static_cast<int>(renderTarget9->getTextureLevel());
    mMipLevels      = mTopLevel + 1;
}

TextureStorage9_EGLImage::~TextureStorage9_EGLImage() {}

angle::Result TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
                                                        gl::TextureTarget target,
                                                        int level,
                                                        bool,
                                                        IDirect3DSurface9 **outSurface)
{
    ASSERT(target == gl::TextureTarget::_2D);
    ASSERT(level == 0);

    RenderTargetD3D *renderTargetD3D = nullptr;
    ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));

    RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);

    *outSurface = renderTarget9->getSurface();
    return angle::Result::Continue;
}

angle::Result TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
                                                        const gl::ImageIndex &index,
                                                        GLsizei samples,
                                                        RenderTargetD3D **outRT)
{
    ASSERT(!index.hasLayer());
    ASSERT(index.getLevelIndex() == 0);
    ASSERT(samples == 0);

    return mImage->getRenderTarget(context, outRT);
}

angle::Result TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
                                                       IDirect3DBaseTexture9 **outTexture)
{
    RenderTargetD3D *renderTargetD3D = nullptr;
    ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));

    RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
    *outTexture                  = renderTarget9->getTexture();
    ASSERT(*outTexture != nullptr);

    return angle::Result::Continue;
}

angle::Result TextureStorage9_EGLImage::generateMipmap(const gl::Context *context,
                                                       const gl::ImageIndex &,
                                                       const gl::ImageIndex &)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

angle::Result TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
                                                      TextureStorage *destStorage)
{
    ASSERT(destStorage);
    ASSERT(getLevelCount() == 1);

    TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);

    IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
    ANGLE_TRY(dest9->getBaseTexture(context, &destBaseTexture9));

    IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);

    angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
    HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");

    RenderTargetD3D *sourceRenderTarget = nullptr;
    ANGLE_TRY(mImage->getRenderTarget(context, &sourceRenderTarget));

    RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
    ANGLE_TRY(mRenderer->copyToRenderTarget(context, destSurface.Get(),
                                            sourceRenderTarget9->getSurface(), isManaged()));

    if (destStorage->getTopLevel() != 0)
    {
        destTexture9->AddDirtyRect(nullptr);
    }

    return angle::Result::Continue;
}

TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer,
                                           GLenum internalformat,
                                           bool renderTarget,
                                           int size,
                                           int levels,
                                           bool hintLevelZeroOnly)
    : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
    mTexture = nullptr;
    for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
    {
        mRenderTarget[i] = nullptr;
    }

    mInternalFormat = internalformat;

    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
    mTextureFormat                           = d3dFormatInfo.texFormat;

    int height = size;
    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
    mTextureWidth  = size;
    mTextureHeight = size;
    mMipLevels     = mTopLevel + levels;
}

TextureStorage9_Cube::~TextureStorage9_Cube()
{
    SafeRelease(mTexture);

    for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
    {
        SafeDelete(mRenderTarget[i]);
    }
}

// Increments refcount on surface.
// caller must Release() the returned surface
angle::Result TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
                                                    gl::TextureTarget target,
                                                    int level,
                                                    bool dirty,
                                                    IDirect3DSurface9 **outSurface)
{
    IDirect3DBaseTexture9 *baseTexture = nullptr;
    ANGLE_TRY(getBaseTexture(context, &baseTexture));

    IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9 *>(baseTexture);

    D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
    HRESULT result        = texture->GetCubeMapSurface(face, level, outSurface);
    ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");

    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
    if (level != 0 && isManaged() && dirty)
    {
        texture->AddDirtyRect(face, nullptr);
    }

    return angle::Result::Continue;
}

angle::Result TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
                                                    const gl::ImageIndex &index,
                                                    GLsizei samples,
                                                    RenderTargetD3D **outRT)
{
    ASSERT(outRT);
    ASSERT(index.getLevelIndex() == 0);
    ASSERT(samples == 0);

    ASSERT(index.getType() == gl::TextureType::CubeMap &&
           gl::IsCubeMapFaceTarget(index.getTarget()));
    const size_t renderTargetIndex = index.cubeMapFaceIndex();

    if (mRenderTarget[renderTargetIndex] == nullptr && isRenderTarget())
    {
        IDirect3DBaseTexture9 *baseTexture = nullptr;
        ANGLE_TRY(getBaseTexture(context, &baseTexture));

        IDirect3DSurface9 *surface = nullptr;
        ANGLE_TRY(getSurfaceLevel(context, index.getTarget(), mTopLevel + index.getLevelIndex(),
                                  false, &surface));

        baseTexture->AddRef();
        mRenderTarget[renderTargetIndex] = new TextureRenderTarget9(
            baseTexture, mTopLevel + index.getLevelIndex(), surface, mInternalFormat,
            static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
    }

    *outRT = mRenderTarget[renderTargetIndex];
    return angle::Result::Continue;
}

angle::Result TextureStorage9_Cube::generateMipmap(const gl::Context *context,
                                                   const gl::ImageIndex &sourceIndex,
                                                   const gl::ImageIndex &destIndex)
{
    angle::ComPtr<IDirect3DSurface9> upper = nullptr;
    ANGLE_TRY(getSurfaceLevel(context, sourceIndex.getTarget(), sourceIndex.getLevelIndex(), false,
                              &upper));

    angle::ComPtr<IDirect3DSurface9> lower = nullptr;
    ANGLE_TRY(
        getSurfaceLevel(context, destIndex.getTarget(), destIndex.getLevelIndex(), true, &lower));

    ASSERT(upper && lower);
    return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
}

angle::Result TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
                                                   IDirect3DBaseTexture9 **outTexture)
{
    // 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 (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
    {
        ASSERT(mMipLevels > 0);
        ASSERT(mTextureWidth == mTextureHeight);

        IDirect3DDevice9 *device = mRenderer->getDevice();
        HRESULT result           = device->CreateCubeTexture(
            static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
            getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
        ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create cube storage texture");
    }

    *outTexture = mTexture;
    return angle::Result::Continue;
}

angle::Result TextureStorage9_Cube::copyToStorage(const gl::Context *context,
                                                  TextureStorage *destStorage)
{
    ASSERT(destStorage);

    TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);

    int levels = getLevelCount();
    for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
    {
        for (int i = 0; i < levels; i++)
        {
            angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
            ANGLE_TRY(getSurfaceLevel(context, face, i, false, &srcSurf));

            angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
            ANGLE_TRY(dest9->getSurfaceLevel(context, face, i, true, &dstSurf));

            ANGLE_TRY(
                mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
        }
    }

    return angle::Result::Continue;
}
}  // namespace rx
