/*
 * 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_PipelineData_DEFINED
#define skgpu_graphite_PipelineData_DEFINED

#include <vector>
#include "include/core/SkM44.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTileMode.h"
#include "include/private/SkColorData.h"
#include "src/core/SkEnumBitMask.h"
#include "src/gpu/graphite/DrawTypes.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/UniformManager.h"

class SkArenaAlloc;

namespace skgpu::graphite {

enum class SnippetRequirementFlags : uint32_t;
class Uniform;

class UniformDataBlock {
public:
    static UniformDataBlock* Make(const UniformDataBlock&, SkArenaAlloc*);

    UniformDataBlock(SkSpan<const char> data) : fData(data) {}
    UniformDataBlock() = default;

    const char* data() const { return fData.data(); }
    size_t size() const { return fData.size(); }

    uint32_t hash() const;

    bool operator==(const UniformDataBlock& that) const {
        return fData.size() == that.fData.size() &&
               !memcmp(fData.data(), that.fData.data(), fData.size());
    }
    bool operator!=(const UniformDataBlock& that) const { return !(*this == that); }

private:
    SkSpan<const char> fData;
};

class TextureDataBlock {
public:
    using SampledTexture = std::pair<sk_sp<TextureProxy>, SamplerDesc>;

    static TextureDataBlock* Make(const TextureDataBlock&, SkArenaAlloc*);
    TextureDataBlock() = default;

    bool empty() const { return fTextureData.empty(); }
    int numTextures() const { return SkTo<int>(fTextureData.size()); }
    const SampledTexture& texture(int index) const { return fTextureData[index]; }

    bool operator==(const TextureDataBlock&) const;
    bool operator!=(const TextureDataBlock& other) const { return !(*this == other);  }
    uint32_t hash() const;

    void add(const SkSamplingOptions& sampling,
             const SkTileMode tileModes[2],
             sk_sp<TextureProxy> proxy) {
        fTextureData.push_back({std::move(proxy), {sampling, {tileModes[0], tileModes[1]}}});
    }

    void reset() {
        fTextureData.clear();
    }

private:
    // TODO: Move this into a SkSpan that's managed by the gatherer or copied into the arena.
    std::vector<SampledTexture> fTextureData;
};

// The PipelineDataGatherer is just used to collect information for a given PaintParams object.
//   The UniformData is added to a cache and uniquified. Only that unique ID is passed around.
//   The TextureData is also added to a cache and uniquified. Only that ID is passed around.

// TODO: The current plan for fixing uniform padding is for the PipelineDataGatherer to hold a
// persistent uniformManager. A stretch goal for this system would be for this combination
// to accumulate all the uniforms and then rearrange them to minimize padding. This would,
// obviously, vastly complicate uniform accumulation.
class PipelineDataGatherer {
public:
    PipelineDataGatherer(Layout layout);

    void resetWithNewLayout(Layout layout);

    // Check that the gatherer has been reset to its initial state prior to collecting new data.
    SkDEBUGCODE(void checkReset();)

    void add(const SkSamplingOptions& sampling,
             const SkTileMode tileModes[2],
             sk_sp<TextureProxy> proxy) {
        fTextureDataBlock.add(sampling, tileModes, std::move(proxy));
    }
    bool hasTextures() const { return !fTextureDataBlock.empty(); }

    void addFlags(SkEnumBitMask<SnippetRequirementFlags> flags);
    bool needsLocalCoords() const;

    const TextureDataBlock& textureDataBlock() { return fTextureDataBlock; }

    void write(const SkM44& mat) { fUniformManager.write(mat); }
    void write(const SkPMColor4f& premulColor) { fUniformManager.write(premulColor); }
    void write(const SkRect& rect) { fUniformManager.write(rect); }
    void write(const SkV2& v) { fUniformManager.write(v); }
    void write(const SkV4& v) { fUniformManager.write(v); }
    void write(const SkPoint& point) { fUniformManager.write(point); }
    void write(float f) { fUniformManager.write(f); }
    void write(int i) { fUniformManager.write(i); }


    void write(SkSLType t, const void* data) { fUniformManager.write(t, data); }
    void write(const Uniform& u, const uint8_t* data) { fUniformManager.write(u, data); }

    void writeArray(SkSpan<const SkColor4f> colors) { fUniformManager.writeArray(colors); }
    void writeArray(SkSpan<const SkPMColor4f> colors) { fUniformManager.writeArray(colors); }
    void writeArray(SkSpan<const float> floats) { fUniformManager.writeArray(floats); }

    void writeHalf(const SkMatrix& mat) { fUniformManager.writeHalf(mat); }
    void writeHalfArray(SkSpan<const float> floats) { fUniformManager.writeHalfArray(floats); }

    bool hasUniforms() const { return fUniformManager.size(); }

    // Returns the uniform data written so far. Will automatically pad the end of the data as needed
    // to the overall required alignment, and so should only be called when all writing is done.
    UniformDataBlock finishUniformDataBlock() { return fUniformManager.finishUniformDataBlock(); }

private:
#ifdef SK_DEBUG
    friend class UniformExpectationsValidator;

    void setExpectedUniforms(SkSpan<const Uniform> expectedUniforms);
    void doneWithExpectedUniforms() { fUniformManager.doneWithExpectedUniforms(); }
#endif // SK_DEBUG

    TextureDataBlock                       fTextureDataBlock;
    UniformManager                         fUniformManager;
    SkEnumBitMask<SnippetRequirementFlags> fSnippetRequirementFlags;
};

#ifdef SK_DEBUG
class UniformExpectationsValidator {
public:
    UniformExpectationsValidator(PipelineDataGatherer *gatherer,
                                 SkSpan<const Uniform> expectedUniforms);

    ~UniformExpectationsValidator() {
        fGatherer->doneWithExpectedUniforms();
    }

private:
    PipelineDataGatherer *fGatherer;

    UniformExpectationsValidator(UniformExpectationsValidator &&) = delete;
    UniformExpectationsValidator(const UniformExpectationsValidator &) = delete;
    UniformExpectationsValidator &operator=(UniformExpectationsValidator &&) = delete;
    UniformExpectationsValidator &operator=(const UniformExpectationsValidator &) = delete;
};
#endif // SK_DEBUG

} // namespace skgpu::graphite

#endif // skgpu_graphite_PipelineData_DEFINED
