/*
 * 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/gpu/graphite/PaintParamsKey.h"

#include "include/private/base/SkLog.h"
#include "src/base/SkArenaAlloc.h"
#include "src/base/SkAutoMalloc.h"
#include "src/base/SkBase64.h"
#include "src/base/SkStringView.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/KeyHelpers.h"
#include "src/gpu/graphite/ShaderCodeDictionary.h"

using namespace skia_private;

namespace skgpu::graphite {

// We don't want keys to get that large, so this limit is quite strict.
static constexpr int kEmbeddedDataSizeLimit = 16;

//--------------------------------------------------------------------------------------------------
// PaintParamsKeyBuilder

#ifdef SK_DEBUG

void PaintParamsKeyBuilder::checkReset() {
    SkASSERT(!fLocked);
    SkASSERT(fData.empty());
    SkASSERT(fStack.empty());
    SkASSERT(!fHasError);
}

void PaintParamsKeyBuilder::pushStack(int32_t codeSnippetID) {
    SkASSERT(!fLocked);
    SkASSERT(fDict->isValidID(codeSnippetID));
    // If the kError ID is pushed, fHasError must have been set already.
    SkASSERT(codeSnippetID != (int) BuiltInCodeSnippetID::kError || fHasError);

    if (!fStack.empty()) {
        fStack.back().fNumActualChildren++;
        SkASSERT(fStack.back().fNumActualChildren <= fStack.back().fNumExpectedChildren);
    }

    const ShaderSnippet* snippet = fDict->getEntry(codeSnippetID);
    fStack.push_back({codeSnippetID, snippet->fNumChildren});
}

void PaintParamsKeyBuilder::validateData(size_t dataSize) {
    // Check that the size of the embedded data fits our self-imposed limit.
    SkASSERT(dataSize <= kEmbeddedDataSizeLimit);

    SkASSERT(!fLocked);
    SkASSERT(!fStack.empty()); // addData() called within code snippet block
    // Check that addData() is only called for snippets that support it and is only called once
    const ShaderSnippet* snippet = fDict->getEntry(fStack.back().fCodeSnippetID);
    SkASSERT(snippet->storesSamplerDescData());
    SkASSERT(fStack.back().fDataSize < 0);

    fStack.back().fDataSize = SkTo<int>(dataSize);
}

void PaintParamsKeyBuilder::popStack() {
    SkASSERT(!fLocked);
    SkASSERT(!fStack.empty());
    SkASSERT(fStack.back().fNumActualChildren == fStack.back().fNumExpectedChildren);
    const bool expectsData = fDict->getEntry(fStack.back().fCodeSnippetID)->storesSamplerDescData();
    const bool hasData = fStack.back().fDataSize >= 0;
    SkASSERT(expectsData == hasData);
    fStack.pop_back();
}

#endif // SK_DEBUG

//--------------------------------------------------------------------------------------------------
// PaintParamsKey

PaintParamsKey PaintParamsKey::clone(SkArenaAlloc* arena) const {
    int32_t* newData = arena->makeArrayDefault<int32_t>(fData.size());
    memcpy(newData, fData.data(), fData.size_bytes());
    return PaintParamsKey({newData, fData.size()});
}

ShaderNode* PaintParamsKey::createNode(const ShaderCodeDictionary* dict,
                                       int* currentIndex,
                                       SkArenaAlloc* arena) const {
    SkASSERT(*currentIndex < SkTo<int>(fData.size()));
    const int32_t index = (*currentIndex)++;
    const int32_t id = fData[index];
    SkASSERT(id >= 0); // Otherwise we're calling createNode on a data length somehow

    const ShaderSnippet* entry = dict->getEntry(id);
    if (!entry) {
        SKIA_LOG_E("Unknown snippet ID in key: %d", id);
        return nullptr;
    }

    SkSpan<const uint32_t> dataSpan = {};
    if (entry->storesSamplerDescData()) {
        // If a snippet stores data, then the subsequent paint key index signifies the length of
        // its data. Determine this data length and iterate currentIndex past it.
        const int storedDataLengthIdx = (*currentIndex)++;
        SkASSERT(storedDataLengthIdx < SkTo<int>(fData.size()));
        const int dataLength = EncodeDataSize(fData[storedDataLengthIdx]);
        // Building ShaderNodes is assumed to be done for keys built by PaintParamsKeyBuilder or
        // already validated for deserialization, so we consider them trusted.
        SkASSERT(dataLength >= 0 && dataLength <= kEmbeddedDataSizeLimit);
        SkASSERT(storedDataLengthIdx + dataLength < SkTo<int>(fData.size()));

        // Gather the data contents (length can now be inferred by the consumers of the data) to
        // pass into ShaderNode creation. Iterate the paint key index past the data indices.
        // For the embedded data, we re-interpret the values as uint32_t's since that was what was
        // written by addData().
        SkSpan<const int32_t> signedDataSpan = fData.subspan(storedDataLengthIdx + 1, dataLength);
        dataSpan = {reinterpret_cast<const uint32_t*>(signedDataSpan.data()), dataLength};
        *currentIndex += dataLength;
    }

    ShaderNode** childArray = arena->makeArray<ShaderNode*>(entry->fNumChildren);
    for (int i = 0; i < entry->fNumChildren; ++i) {
        ShaderNode* child = this->createNode(dict, currentIndex, arena);
        if (!child) {
            return nullptr;
        }
        childArray[i] = child;
    }

    return arena->make<ShaderNode>(entry,
                                   SkSpan(childArray, entry->fNumChildren),
                                   id,
                                   index,
                                   dataSpan);
}

// Traverse a ShaderNode tree, attempting to lift any coordinate modification expressions.
// Returns whether any of the given nodes need local coordinate inputs after lifting.
bool lift_coord_expressions(SkSpan<ShaderNode*> nodes, int* availableVaryings) {
    bool anyNeedLocalCoords = false;

    for (ShaderNode* node : nodes) {
        bool curNeedsLocalCoords =
                SkToBool(node->requiredFlags() & SnippetRequirementFlags::kLocalCoords);

        // Lift expressions from nodes whose liftable expressions are on coordinate inputs.
        if (*availableVaryings > 0 && curNeedsLocalCoords &&
            node->entry()->fLiftableExpressionType ==
                    ShaderSnippet::LiftableExpressionType::kLocalCoords) {
            --*availableVaryings;

#if !defined(SK_USE_LEGACY_UNIFORM_LIFTING_GRAPHITE)
            // We can potentially lift the nested expressions under here as well.
            const bool childNeedsOurCoords =
                    lift_coord_expressions(node->children(), availableVaryings);
            // If no child needs our lifted coords, we can omit them from the fragment shader
            // entirely, and only use them in the vertex shader for calculating other coords.
            if (!childNeedsOurCoords) {
                node->setOmitExpressionFlag();
            } else {
                node->setLiftExpressionFlag();
            }
#else
            node->setLiftExpressionFlag();
#endif
            // Since we lifted the coordinate expression here, this node no longer needs a local
            // coords argument.
            curNeedsLocalCoords = false;
            node->unsetLocalCoordsFlag();

#if !defined(SK_USE_LEGACY_UNIFORM_LIFTING_GRAPHITE)
        // If the node passes through its local coords to its children, we check if those perform
        // modifications that can be lifted.
        } else if (*availableVaryings > 0 &&
                   node->requiredFlags() & SnippetRequirementFlags::kPassthroughLocalCoords) {
            // Assume that this node doesn't need local coordinates unless its actual shader snippet
            // entry does, or one of its children does even after accounting for lifting.
            const bool entryNeedsLocalCoords = node->entry()->needsLocalCoords();
            const bool childNeedsLocalCoords = lift_coord_expressions(node->children(),
                                                                      availableVaryings);
            curNeedsLocalCoords = entryNeedsLocalCoords || childNeedsLocalCoords;
            if (!curNeedsLocalCoords) {
                node->unsetLocalCoordsFlag();
            }
#endif
        }

        anyNeedLocalCoords |= curNeedsLocalCoords;
    }

    return anyNeedLocalCoords;
}

// Traverse a list of ShaderNodes, attempting to lift any expressions that resolve to a color.
// For now, this does not recurse into ShaderNodes' lists of children. In practice we only lift
// solid color expressions, and we only care to lift such expressions if there is no other fragment
// shader work (i.e., if the solid color expression is a root node in a shader's ShaderNode tree).
// If there is other fragment shader work, we'll likely be accessing other fragment shader uniforms,
// the color value will likely be cached, and lifting may not be worth the extra varying.
void lift_color_expressions(SkSpan<ShaderNode*> nodes, int* availableVaryings) {
#if !defined(SK_USE_LEGACY_UNIFORM_LIFTING_GRAPHITE)
    for (ShaderNode* node : nodes) {
        if (*availableVaryings > 0 &&
            node->entry()->fLiftableExpressionType ==
                    ShaderSnippet::LiftableExpressionType::kPriorStageOutput) {
            --*availableVaryings;
            node->setLiftExpressionFlag();
        }
    }
#endif
}

SkSpan<const ShaderNode*> PaintParamsKey::getRootNodes(const Caps* caps,
                                                       const ShaderCodeDictionary* dict,
                                                       SkArenaAlloc* arena,
                                                       int availableVaryings) const {
    // TODO: Once the PaintParamsKey creation is organized to represent a single tree starting at
    // the final blend, there will only be a single root node and this can be simplified.
    // For now, we don't know how many roots there are, so collect them into a local array before
    // copying into the arena.
    const int keySize = SkTo<int>(fData.size());

    // Normal PaintParams creation will have up to 7 roots for the different stages.
    STArray<7, ShaderNode*> roots;
    int currentIndex = 0;
    while (currentIndex < keySize) {
        ShaderNode* root = this->createNode(dict, &currentIndex, arena);
        if (!root) {
            return {}; // a bad key
        }
        roots.push_back(root);
    }

    // See what expressions we can lift to the vertex shader.
    const bool hasClipNode = roots.size() > 2;
    SkSpan<ShaderNode*> liftableNodes(roots.data(), hasClipNode ? 2 : roots.size());
    lift_coord_expressions(liftableNodes, &availableVaryings);
    // Don't lift constant expressions if we're using regular UBOs, since lifting is likely only
    // beneficial if we're avoiding a storage buffer access.
    if (caps->storageBufferSupport()) {
        lift_color_expressions(liftableNodes, &availableVaryings);
    }

    // Copy the accumulated roots into a span stored in the arena
    const ShaderNode** rootSpan = arena->makeArray<const ShaderNode*>(roots.size());
    memcpy(rootSpan, roots.data(), roots.size_bytes());
    return SkSpan(rootSpan, roots.size());
}

static void append_as_base64(SkString* str, SkSpan<const int32_t> data) {
    str->append("(");
    str->appendU32(data.size());
    str->append(": ");
    // Encode data in base64 to shorten it
    const size_t srcDataSize = data.size() * sizeof(uint32_t); // size in bytes
    SkAutoMalloc encodedData{SkBase64::EncodedSize(srcDataSize)};
    char* dst = static_cast<char*>(encodedData.get());
    size_t encodedLen = SkBase64::Encode(data.data(), srcDataSize, dst);
    str->append(dst, encodedLen);
    str->append(")");
}

static int key_to_string(const Caps* caps,
                         SkString* str,
                         const ShaderCodeDictionary* dict,
                         SkSpan<const int32_t> keyData,
                         int currentIndex,
                         int indent) {
    SkASSERT(currentIndex < SkTo<int>(keyData.size()));

    const bool multiline = indent >= 0;
    if (multiline) {
        // Format for multi-line printing
        str->appendf("%*c", 2 * indent, ' ');
    }

    int32_t id = keyData[currentIndex++];
    auto entry = dict->getEntry(id);
    if (!entry) {
        str->append("UnknownCodeSnippetID:");
        str->appendS32(id);
        str->append(" ");
        return currentIndex;
    }

    str->append(entry->fName);

    if (entry->storesSamplerDescData()) {
        SkASSERT(currentIndex + 1 < SkTo<int>(keyData.size()));

        // If an entry stores data, then the next key value reports the quantity of key indices that
        // are used to house the data for this snippet. This way, we know how many indices to
        // iterate over in order to capture the snippet's data before we may encounter another
        // snippet ID.
        // For example:
        // [snippetId using 2 indices worth of data] [2] [dataValue0] [dataValue1] [next snippet ID]
        const int dataIndexCount = PaintParamsKey::EncodeDataSize(keyData[currentIndex++]);
        // Printing keys is assumed to be done for keys that were built by PaintParamsKeyBuilder or
        // already validated for deserialization, so we consider them trusted.
        SkASSERT(dataIndexCount >= 0 && dataIndexCount <= kEmbeddedDataSizeLimit);
        SkASSERT(currentIndex + dataIndexCount < SkTo<int>(keyData.size()));

        bool descriptiveFormAppended = false;
        if (dataIndexCount == 0) {
            // We shorten the string for the common case of no extra data.
            str->append("(0)");
            descriptiveFormAppended = true;
        } else {
            SkASSERTF(dataIndexCount == 2 || dataIndexCount == 3, "count %d", dataIndexCount);

            // Attempt to append the sampler data as human-readable YCbCr information
            SamplerDesc s(keyData[currentIndex],
                          keyData[currentIndex+1],
                          /* extFormatMSB= */ dataIndexCount == 3 ? keyData[currentIndex+2] : 0);

            if (s.isImmutable()) {
                std::string tmp = caps->toString(s.immutableSamplerInfo());
                if (!tmp.empty()) {
                    str->append("(");
                    str->append(tmp);
                    str->append(")");
                    descriptiveFormAppended = true;
                }
            }
        }

        if (!descriptiveFormAppended) {
            append_as_base64(str, { &keyData[currentIndex], dataIndexCount });
        }

        // Increment current index past the indices which contain data
        currentIndex += dataIndexCount;
    }

    if (entry->fNumChildren > 0) {
        if (multiline) {
            str->append(":\n");
            indent++;
        } else {
            str->append(" [ ");
        }

        for (int i = 0; i < entry->fNumChildren; ++i) {
            currentIndex = key_to_string(caps, str, dict, keyData, currentIndex, indent);
        }

        if (!multiline) {
            str->append("]");
        }
    }

    if (!multiline) {
        str->append(" ");
    } else if (entry->fNumChildren == 0) {
        str->append("\n");
    }
    return currentIndex;
}

SkString PaintParamsKey::toString(const Caps* caps,
                                  const ShaderCodeDictionary* dict) const {
    SkString str;
    const int keySize = SkTo<int>(fData.size());
    for (int currentIndex = 0; currentIndex < keySize;) {
        currentIndex = key_to_string(caps, &str, dict, fData, currentIndex, /*indent=*/-1);
    }
    return str.isEmpty() ? SkString("(empty)") : str;
}

#ifdef SK_DEBUG

void PaintParamsKey::dump(const Caps* caps,
                          const ShaderCodeDictionary* dict,
                          UniquePaintParamsID id) const {
    const int keySize = SkTo<int>(fData.size());

    SkDebugf("--------------------------------------\n");
    SkDebugf("PaintParamsKey %u (keySize: %d): ", id.asUInt(), keySize);
    const int32_t* data = fData.data();
    for (int i = 0; i < keySize; ++i) {
        SkDebugf("%x ", (uint32_t) data[i]);
    }
    SkDebugf("\n");

    int currentIndex = 0;
    while (currentIndex < keySize) {
        SkString nodeStr;
        currentIndex = key_to_string(caps, &nodeStr, dict, fData, currentIndex, /*indent=*/1);
        SkDebugf("%s", nodeStr.c_str());
    }
}

#endif // SK_DEBUG

namespace {

// check a single block and, recursively, all its children
[[nodiscard]] bool is_block_valid(const ShaderCodeDictionary* dict,
                                  SkSpan<const int32_t> keyData,
                                  int* currentIndex) {
    if (*currentIndex >= SkTo<int>(keyData.size())) {
        return false;
    }

    uint32_t id = keyData[(*currentIndex)++];
    if (id >= kBuiltInCodeSnippetIDCount &&
        !SkKnownRuntimeEffects::IsSkiaKnownRuntimeEffect(id) &&
        !dict->isUserDefinedKnownRuntimeEffect(id)) {
        return false;
    }

    auto entry = dict->getEntry(id);
    if (!entry) {
        return false;
    }

    if (entry->storesSamplerDescData()) {
        if (*currentIndex >= SkTo<int>(keyData.size())) {
            return false;
        }

        int dataLength = keyData[(*currentIndex)++];
        // This `dataLength` is untrusted, so check that it doesn't overflow EncodeDataSize
        // and that matches expectations of a valid length (i.e. it started out negative and is
        // now positive and less than the key data limit).
        if (dataLength >= 0 ||
            dataLength < PaintParamsKey::EncodeDataSize(kEmbeddedDataSizeLimit)) {
            // Would not produce a valid size after decoding
            return false;
        }
        dataLength = PaintParamsKey::EncodeDataSize(dataLength);
        SkASSERT(dataLength >= 0 && dataLength <= kEmbeddedDataSizeLimit);
        if (*currentIndex + dataLength > SkTo<int>(keyData.size())) {
            return false;
        }

        *currentIndex += dataLength;
    }

    if (entry->fNumChildren > 0) {
        for (int i = 0; i < entry->fNumChildren; ++i) {
            if (!is_block_valid(dict, keyData, currentIndex)) {
                return false;
            }
        }
    }

    return true;
}

} // anonymous namespace


bool PaintParamsKey::isSerializable(const ShaderCodeDictionary* dict) const {
    const int keySize = SkTo<int>(fData.size());

    int currentIndex = 0;
    while (currentIndex < keySize) {
        if (!is_block_valid(dict, fData, &currentIndex)) {
            return false;
        }
    }

    return true;
}

} // namespace skgpu::graphite
