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

#include "src/core/SkOpts.h"
#include "src/core/SkPipelineData.h"
#include "src/core/SkShaderCodeDictionary.h"

#ifdef SK_GRAPHITE_ENABLED
SkPipelineDataGatherer::SkPipelineDataGatherer(skgpu::graphite::Layout layout)
        : fUniformManager(layout)
        , fSnippetRequirementFlags(SnippetRequirementFlags::kNone) {
}
#endif

void SkPipelineDataGatherer::reset() {
#ifdef SK_GRAPHITE_ENABLED
    fTextureDataBlock.reset();
    fBlendInfo = BlendInfo();
    fUniformManager.reset();
#endif
    fSnippetRequirementFlags = SnippetRequirementFlags::kNone;
}

#ifdef SK_DEBUG
void SkPipelineDataGatherer::checkReset() {
#ifdef SK_GRAPHITE_ENABLED
    SkASSERT(fTextureDataBlock.empty());
    SkASSERT(fBlendInfo == BlendInfo());
    SkDEBUGCODE(fUniformManager.checkReset());
#endif
    SkASSERT(fSnippetRequirementFlags == SnippetRequirementFlags::kNone);
}
#endif // SK_DEBUG

void SkPipelineDataGatherer::addFlags(SnippetRequirementFlags flags) {
    fSnippetRequirementFlags |= flags;
}

bool SkPipelineDataGatherer::needsLocalCoords() const {
    return fSnippetRequirementFlags & SnippetRequirementFlags::kLocalCoords;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
SkUniformDataBlock* SkUniformDataBlock::Make(const SkUniformDataBlock& other,
                                             SkArenaAlloc* arena) {
    static constexpr size_t kUniformAlignment = alignof(void*);
    char* mem = static_cast<char*>(arena->makeBytesAlignedTo(other.size(), kUniformAlignment));
    memcpy(mem, other.data(), other.size());

    return arena->make([&](void* ptr) {
        return new (ptr) SkUniformDataBlock(SkSpan<const char>(mem, other.size()));
    });
}

uint32_t SkUniformDataBlock::hash() const {
    return SkOpts::hash_fn(fData.data(), fData.size(), 0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SK_GRAPHITE_ENABLED
static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1;

std::unique_ptr<SkTextureDataBlock> SkTextureDataBlock::Make(const SkTextureDataBlock& other,
                                                             SkArenaAlloc* /* arena */) {
    return std::make_unique<SkTextureDataBlock>(other);
}

bool SkTextureDataBlock::TextureInfo::operator==(const TextureInfo& other) const {
    return fProxy == other.fProxy &&
           fSamplingOptions == other.fSamplingOptions &&
           fTileModes[0] == other.fTileModes[0] &&
           fTileModes[1] == other.fTileModes[1];
}

uint32_t SkTextureDataBlock::TextureInfo::samplerKey() const {
    static_assert(kSkTileModeCount <= 4 && kSkFilterModeCount <= 2);
    return (static_cast<int>(fTileModes[0])           << 0) |
           (static_cast<int>(fTileModes[1])           << 2) |
           (static_cast<int>(fSamplingOptions.filter) << 4) |
           (static_cast<int>(fSamplingOptions.mipmap) << 5);
}

bool SkTextureDataBlock::operator==(const SkTextureDataBlock& other) const {
    if (fTextureData.size() != other.fTextureData.size()) {
        return false;
    }

    for (size_t i = 0; i < fTextureData.size(); ++i) {
        if (fTextureData[i] != other.fTextureData[i]) {
            return false;
        }
    }

    return true;
}

uint32_t SkTextureDataBlock::hash() const {
    uint32_t hash = 0;

    for (auto& d : fTextureData) {
        uint32_t samplerKey = d.samplerKey();
        hash = SkOpts::hash_fn(&samplerKey, sizeof(samplerKey), hash);

        // Because the lifetime of the TextureDataCache is for just one Recording and the
        // TextureDataBlocks hold refs on their proxies, we can just use the proxy's pointer
        // for the hash here. This is a bit sloppy though in that it would be nice if proxies backed
        // by the same scratch texture hashed the same (it is tough to see how we could do that
        // at DrawPass creation time though).
        hash = SkOpts::hash_fn(d.fProxy.get(), sizeof(skgpu::graphite::TextureProxy*), hash);
    }

    return hash;
}

#endif
