/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef skgpu_graphite_DrawPassCommands_DEFINED
#define skgpu_graphite_DrawPassCommands_DEFINED

#include "include/core/SkRect.h"
#include "src/base/SkArenaAlloc.h"
#include "src/base/SkTBlockList.h"
#include "src/gpu/graphite/DrawTypes.h"

namespace skgpu::graphite {

namespace DrawPassCommands {

// A list of all the commands types used by a DrawPass.
// Each of these is reified into a struct below.
//
// The design of this systems is based on SkRecords.

// (We're using the macro-of-macro trick here to do several different things with the same list.)
//
// We leave this SKGPU_DRAW_COMMAND_TYPES macro defined for use by code that wants to operate on
// DrawPassCommands types polymorphically.
#define SKGPU_DRAW_PASS_COMMAND_TYPES(M) \
    M(BindGraphicsPipeline)              \
    M(SetBlendConstants)                 \
    M(BindUniformBuffer)                 \
    M(BindDrawBuffers)                   \
    M(BindTexturesAndSamplers)           \
    M(SetScissor)                        \
    M(Draw)                              \
    M(DrawIndexed)                       \
    M(DrawInstanced)                     \
    M(DrawIndexedInstanced)              \
    M(DrawIndirect)                      \
    M(DrawIndexedIndirect)

// Defines DrawPassCommands::Type, an enum of all draw command types.
#define ENUM(T) k##T,
enum class Type { SKGPU_DRAW_PASS_COMMAND_TYPES(ENUM) };
#undef ENUM

#define ACT_AS_PTR(ptr)                 \
    operator T*() const { return ptr; } \
    T* operator->() const { return ptr; }

// PODArray doesn't own the pointer's memory, and we assume the data is POD.
template <typename T>
class PODArray {
public:
    PODArray() {}
    PODArray(T* ptr) : fPtr(ptr) {}
    // Default copy and assign.

    ACT_AS_PTR(fPtr)
private:
    T* fPtr;
};

#undef ACT_AS_PTR

// A macro to make it a little easier to define a struct that can be stored in DrawPass.
#define COMMAND(T, ...)                    \
struct T {                                 \
static constexpr Type kType = Type::k##T;  \
    __VA_ARGS__;                           \
};

COMMAND(BindGraphicsPipeline,
            uint32_t fPipelineIndex);
COMMAND(SetBlendConstants,
            PODArray<float> fBlendConstants);
COMMAND(BindUniformBuffer,
            BindBufferInfo fInfo;
            UniformSlot fSlot);
COMMAND(BindDrawBuffers,
            BindBufferInfo fVertices;
            BindBufferInfo fInstances;
            BindBufferInfo fIndices;
            BindBufferInfo fIndirect);
COMMAND(BindTexturesAndSamplers,
            int fNumTexSamplers;
            PODArray<int> fTextureIndices;
            PODArray<int> fSamplerIndices);
COMMAND(SetScissor,
            SkIRect fScissor);
COMMAND(Draw,
            PrimitiveType fType;
            uint32_t fBaseVertex;
            uint32_t fVertexCount);
COMMAND(DrawIndexed,
            PrimitiveType fType;
            uint32_t fBaseIndex;
            uint32_t fIndexCount;
            uint32_t fBaseVertex);
COMMAND(DrawInstanced,
            PrimitiveType fType;
            uint32_t fBaseVertex;
            uint32_t fVertexCount;
            uint32_t fBaseInstance;
            uint32_t fInstanceCount);
COMMAND(DrawIndexedInstanced,
            PrimitiveType fType;
            uint32_t fBaseIndex;
            uint32_t fIndexCount;
            uint32_t fBaseVertex;
            uint32_t fBaseInstance;
            uint32_t fInstanceCount);
COMMAND(DrawIndirect,
            PrimitiveType fType);
COMMAND(DrawIndexedIndirect,
            PrimitiveType fType);

#undef COMMAND

#define ASSERT_TRIV_DES(T) static_assert(std::is_trivially_destructible<T>::value);
SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_DES)
#undef ASSERT_TRIV_DES
#define ASSERT_TRIV_CPY(T) static_assert(std::is_trivially_copyable<T>::value);
SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_CPY)
#undef ASSERT_TRIV_CPY

class List {
public:
    List() = default;
    ~List() = default;

    void bindGraphicsPipeline(uint32_t pipelineIndex) {
        this->add<BindGraphicsPipeline>(pipelineIndex);
    }

    void setBlendConstants(std::array<float, 4>  blendConstants) {
        this->add<SetBlendConstants>(this->copy(blendConstants.data(), 4));
    }

    void bindUniformBuffer(BindBufferInfo info, UniformSlot slot) {
        this->add<BindUniformBuffer>(info, slot);
    }

    // Caller must write 'numTexSamplers' texture and sampler indices into the two returned arrays.
    std::pair<int*, int*>
    bindDeferredTexturesAndSamplers(int numTexSamplers) {
        int* textureIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
        int* samplerIndices = fAlloc.makeArrayDefault<int>(numTexSamplers);
        this->add<BindTexturesAndSamplers>(numTexSamplers, textureIndices, samplerIndices);
        return {textureIndices, samplerIndices};
    }

    void setScissor(SkIRect scissor) {
        this->add<SetScissor>(scissor);
    }

    void bindDrawBuffers(BindBufferInfo vertexAttribs,
                         BindBufferInfo instanceAttribs,
                         BindBufferInfo indices,
                         BindBufferInfo indirect) {
        this->add<BindDrawBuffers>(vertexAttribs, instanceAttribs, indices, indirect);
    }

    void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) {
        this->add<Draw>(type, baseVertex, vertexCount);
    }

    void drawIndexed(PrimitiveType type, unsigned int baseIndex,
                     unsigned int indexCount, unsigned int baseVertex) {
        this->add<DrawIndexed>(type, baseIndex, indexCount, baseVertex);
    }

    void drawInstanced(PrimitiveType type,
                       unsigned int baseVertex, unsigned int vertexCount,
                       unsigned int baseInstance, unsigned int instanceCount) {
        this->add<DrawInstanced>(type, baseVertex, vertexCount, baseInstance, instanceCount);
    }

    void drawIndexedInstanced(PrimitiveType type,
                              unsigned int baseIndex, unsigned int indexCount,
                              unsigned int baseVertex, unsigned int baseInstance,
                              unsigned int instanceCount) {
        this->add<DrawIndexedInstanced>(type,
                                        baseIndex,
                                        indexCount,
                                        baseVertex,
                                        baseInstance,
                                        instanceCount);
    }

    void drawIndirect(PrimitiveType type) {
        this->add<DrawIndirect>(type);
    }

    void drawIndexedIndirect(PrimitiveType type) {
        this->add<DrawIndexedIndirect>(type);
    }

    using Command = std::pair<Type, void*>;
    using Iter = SkTBlockList<Command>::CIter;
    Iter commands() const { return fCommands.items(); }

private:
    template <typename T, typename... Args>
    void add(Args&&... args) {
        T* cmd = fAlloc.make<T>(T{std::forward<Args>(args)...});
        fCommands.push_back(std::make_pair(T::kType, cmd));
    }

    // This copy() is for arrays.
    // It will work with POD only arrays.
    template <typename T>
    T* copy(const T src[], size_t count) {
        static_assert(std::is_trivially_copyable<T>::value);
        T* dst = fAlloc.makeArrayDefault<T>(count);
        memcpy(dst, src, count*sizeof(T));
        return dst;
    }

    SkTBlockList<Command> fCommands;

    // fAlloc needs to be a data structure which can append variable length data in contiguous
    // chunks, returning a stable handle to that data for later retrieval.
    SkArenaAlloc fAlloc{256};
};

} // namespace DrawPassCommands

} // namespace skgpu::graphite

#endif // skgpu_graphite_DrawPassCommands_DEFINED
