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

// renderer11_utils.h: Conversion functions and other utility routines
// specific to the D3D11 renderer.

#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_

#include <array>
#include <functional>
#include <vector>

#include "common/Color.h"

#include "libANGLE/Caps.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"

namespace gl
{
class FramebufferAttachment;
}

namespace rx
{
class Context11;
class Renderer11;
class RenderTarget11;
struct Renderer11DeviceCaps;

using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;

namespace gl_d3d11
{

D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);

D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode);

D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
UINT8 ConvertStencilMask(GLuint stencilmask);
D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);

D3D11_FILTER ConvertFilter(GLenum minFilter,
                           GLenum magFilter,
                           float maxAnisotropy,
                           GLenum comparisonMode);
D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);

D3D11_QUERY ConvertQueryType(gl::QueryType type);

UINT8 GetColorMask(const gl::InternalFormat &formatInfo);

}  // namespace gl_d3d11

namespace d3d11_gl
{

unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);

unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);

gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
void GenerateCaps(ID3D11Device *device,
                  ID3D11DeviceContext *deviceContext,
                  const Renderer11DeviceCaps &renderer11DeviceCaps,
                  const angle::FeaturesD3D &features,
                  const char *description,
                  gl::Caps *caps,
                  gl::TextureCapsMap *textureCapsMap,
                  gl::Extensions *extensions,
                  gl::Limitations *limitations);

void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);

D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();

}  // namespace d3d11_gl

namespace d3d11
{

enum ANGLED3D11DeviceType
{
    ANGLE_D3D11_DEVICE_TYPE_UNKNOWN,
    ANGLE_D3D11_DEVICE_TYPE_HARDWARE,
    ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL,
    ANGLE_D3D11_DEVICE_TYPE_WARP,
};

ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device);

void MakeValidSize(bool isImage,
                   DXGI_FORMAT format,
                   GLsizei *requestWidth,
                   GLsizei *requestHeight,
                   int *levelOffset);

angle::Result GenerateInitialTextureData(
    const gl::Context *context,
    GLint internalFormat,
    const Renderer11DeviceCaps &renderer11DeviceCaps,
    GLuint width,
    GLuint height,
    GLuint depth,
    GLuint mipLevels,
    gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData);

UINT GetPrimitiveRestartIndex();

struct PositionTexCoordVertex
{
    float x, y;
    float u, v;
};
void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v);

struct PositionLayerTexCoord3DVertex
{
    float x, y;
    unsigned int l;
    float u, v, s;
};
void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
                                      float x,
                                      float y,
                                      unsigned int layer,
                                      float u,
                                      float v,
                                      float s);

struct PositionVertex
{
    float x, y, z, w;
};

struct BlendStateKey final
{
    // This will zero-initialize the struct, including padding.
    BlendStateKey();

    gl::BlendState blendState;

    // An int so struct size rounds nicely.
    uint32_t rtvMax;

    uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
};

bool operator==(const BlendStateKey &a, const BlendStateKey &b);
bool operator!=(const BlendStateKey &a, const BlendStateKey &b);

struct RasterizerStateKey final
{
    // This will zero-initialize the struct, including padding.
    RasterizerStateKey();

    gl::RasterizerState rasterizerState;

    // Use a 32-bit int to round the struct nicely.
    uint32_t scissorEnabled;
};

bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b);

template <typename outType>
outType *DynamicCastComObject(IUnknown *object)
{
    outType *outObject = nullptr;
    HRESULT result =
        object->QueryInterface(__uuidof(outType), reinterpret_cast<void **>(&outObject));
    if (SUCCEEDED(result))
    {
        return outObject;
    }
    else
    {
        SafeRelease(outObject);
        return nullptr;
    }
}

template <typename outType>
angle::ComPtr<outType> DynamicCastComObjectToComPtr(IUnknown *object)
{
    angle::ComPtr<outType> outObject;
    const HRESULT hr = object->QueryInterface(IID_PPV_ARGS(&outObject));
    if (SUCCEEDED(hr))
    {
        return outObject;
    }
    else
    {
        return nullptr;
    }
}

inline bool isDeviceLostError(HRESULT errorCode)
{
    switch (errorCode)
    {
        case DXGI_ERROR_DEVICE_HUNG:
        case DXGI_ERROR_DEVICE_REMOVED:
        case DXGI_ERROR_DEVICE_RESET:
        case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
        case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
            return true;
        default:
            return false;
    }
}

template <ResourceType ResourceT>
class LazyResource : angle::NonCopyable
{
  public:
    constexpr LazyResource() : mResource() {}
    virtual ~LazyResource() {}

    virtual angle::Result resolve(d3d::Context *context, Renderer11 *renderer) = 0;
    void reset() { mResource.reset(); }
    GetD3D11Type<ResourceT> *get() const
    {
        ASSERT(mResource.valid());
        return mResource.get();
    }

    const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }

  protected:
    LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {}

    // Specialized in the cpp file to avoid MSVS/Clang specific code.
    angle::Result resolveImpl(d3d::Context *context,
                              Renderer11 *renderer,
                              const GetDescType<ResourceT> &desc,
                              GetInitDataType<ResourceT> *initData,
                              const char *name);

    Resource11<GetD3D11Type<ResourceT>> mResource;
};

template <typename D3D11ShaderType>
class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>
{
  public:
    // All parameters must be constexpr. Not supported in VS2013.
    constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name)
        : mByteCode(byteCode, byteCodeSize), mName(name)
    {}

    constexpr LazyShader(LazyShader &&shader)
        : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)),
          mByteCode(std::move(shader.mByteCode)),
          mName(shader.mName)
    {}

    angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override
    {
        return this->resolveImpl(context, renderer, mByteCode, nullptr, mName);
    }

  private:
    ShaderData mByteCode;
    const char *mName;
};

class LazyInputLayout final : public LazyResource<ResourceType::InputLayout>
{
  public:
    LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
                    size_t inputDescLen,
                    const BYTE *byteCode,
                    size_t byteCodeLen,
                    const char *debugName);
    ~LazyInputLayout() override;

    angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;

  private:
    InputElementArray mInputDesc;
    ShaderData mByteCode;
    const char *mDebugName;
};

class LazyBlendState final : public LazyResource<ResourceType::BlendState>
{
  public:
    LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);

    angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;

  private:
    D3D11_BLEND_DESC mDesc;
    const char *mDebugName;
};

// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
// represent an entire buffer.
template <class T>
void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
{
    D3D11_MAPPED_SUBRESOURCE mappedResource = {};
    HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    ASSERT(SUCCEEDED(result));
    if (SUCCEEDED(result))
    {
        memcpy(mappedResource.pData, &value, sizeof(T));
        context->Unmap(constantBuffer, 0);
    }
}

void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
                        const DXGI_ADAPTER_DESC &adapterDesc,
                        angle::FeaturesD3D *features);

enum ReservedConstantBufferSlot
{
    RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
    RESERVED_CONSTANT_BUFFER_SLOT_DRIVER                = 1,

    RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
};

void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);

// Helper class for RAII patterning.
template <typename T>
class ScopedUnmapper final : angle::NonCopyable
{
  public:
    ScopedUnmapper(T *object) : mObject(object) {}
    ~ScopedUnmapper() { mObject->unmap(); }

  private:
    T *mObject;
};
}  // namespace d3d11

struct GenericData
{
    GenericData() {}
    ~GenericData()
    {
        if (object)
        {
            // We can have a nullptr factory when holding passed-in resources.
            if (manager)
            {
                manager->onReleaseGeneric(resourceType, object);
                manager = nullptr;
            }
            object->Release();
            object = nullptr;
        }
    }

    ResourceType resourceType  = ResourceType::Last;
    ID3D11Resource *object     = nullptr;
    ResourceManager11 *manager = nullptr;
};

// A helper class which wraps a 2D or 3D texture.
class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData>
{
  public:
    TextureHelper11();
    TextureHelper11(TextureHelper11 &&other);
    TextureHelper11(const TextureHelper11 &other);
    ~TextureHelper11() override;
    TextureHelper11 &operator=(TextureHelper11 &&other);
    TextureHelper11 &operator=(const TextureHelper11 &other);

    bool is2D() const { return mData->resourceType == ResourceType::Texture2D; }
    bool is3D() const { return mData->resourceType == ResourceType::Texture3D; }
    ResourceType getTextureType() const { return mData->resourceType; }
    gl::Extents getExtents() const { return mExtents; }
    DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; }
    const d3d11::Format &getFormatSet() const { return *mFormatSet; }
    int getSampleCount() const { return mSampleCount; }

    template <typename DescT, typename ResourceT>
    void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format)
    {
        std::swap(mData->manager, texture.mData->manager);

        // Can't use std::swap because texture is typed, and here we use ID3D11Resource.
        ID3D11Resource *temp  = mData->object;
        mData->object         = texture.mData->object;
        texture.mData->object = static_cast<ResourceT *>(temp);

        mFormatSet = &format;
        initDesc(desc);
    }

    template <typename ResourceT>
    void set(ResourceT *object, const d3d11::Format &format)
    {
        ASSERT(!valid());

        mFormatSet     = &format;
        mData->object  = object;
        mData->manager = nullptr;

        GetDescFromD3D11<ResourceT> desc;
        getDesc(&desc);
        initDesc(desc);
    }

    bool operator==(const TextureHelper11 &other) const;
    bool operator!=(const TextureHelper11 &other) const;

    void getDesc(D3D11_TEXTURE2D_DESC *desc) const;
    void getDesc(D3D11_TEXTURE3D_DESC *desc) const;

  private:
    void initDesc(const D3D11_TEXTURE2D_DESC &desc2D);
    void initDesc(const D3D11_TEXTURE3D_DESC &desc3D);

    const d3d11::Format *mFormatSet;
    gl::Extents mExtents;
    int mSampleCount;
};

enum class StagingAccess
{
    READ,
    READ_WRITE,
};

bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
                                   gl::DrawElementsType type);

enum class IndexStorageType
{
    // Dynamic indexes are re-streamed every frame. They come from a client data pointer or
    // from buffers that are updated frequently.
    Dynamic,

    // Static indexes are translated from the original storage once, and re-used multiple times.
    Static,

    // Direct indexes are never transated and are used directly from the source buffer. They are
    // the fastest available path.
    Direct,

    // Not a real storage type.
    Invalid,
};

IndexStorageType ClassifyIndexStorage(const gl::State &glState,
                                      const gl::Buffer *elementArrayBuffer,
                                      gl::DrawElementsType elementType,
                                      gl::DrawElementsType destElementType,
                                      unsigned int offset);

}  // namespace rx

#endif  // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
