/*
 * 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/SkLog.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkBase64.h"
#include "src/core/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 {

//--------------------------------------------------------------------------------------------------
// 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 <= PaintParamsKey::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();
}

void PaintParamsKeyBuilder::validateReplacement(int32_t oldCodeSnippetID,
                                                int32_t newCodeSnippetID) {
    // Rules for allowed replacements:
    // 1. BuiltInCodeSnippetIDs only
    // 2. Have the same number of children (and 0 if allowChildren is false)
    // 3. Have the same uniform and texture signature
    // 4. No extra data
    //
    // This ensures that replacing on a block by block basis produces a valid ShaderNode tree
    // after modification, and that extracted uniforms and textures for the original key can be
    // used with the new key.
    SkASSERT(oldCodeSnippetID >= 0 && oldCodeSnippetID < kBuiltInCodeSnippetIDCount);
    SkASSERT(newCodeSnippetID >= 0 && newCodeSnippetID < kBuiltInCodeSnippetIDCount);

    const ShaderSnippet* oldSnippet = fDict->getEntry(oldCodeSnippetID);
    const ShaderSnippet* newSnippet = fDict->getEntry(newCodeSnippetID);

    SkASSERT(oldSnippet->fNumChildren == newSnippet->fNumChildren);

    // Same signature, not caring about the actual variable names.
    SkASSERT(oldSnippet->fUniforms.size() == newSnippet->fUniforms.size());
    for (int u = 0; u < oldSnippet->fUniforms.size(); ++u) {
        const Uniform& oldU = oldSnippet->fUniforms[u];
        const Uniform& newU = newSnippet->fUniforms[u];
        SkASSERT(oldU.type() == newU.type());
        SkASSERT(oldU.count() == newU.count());
        SkASSERT(oldU.isPaintColor() == newU.isPaintColor());
    }

    SkASSERT(oldSnippet->fTexturesAndSamplers.size() == newSnippet->fTexturesAndSamplers.size());

    SkASSERT(!oldSnippet->storesSamplerDescData());
    SkASSERT(!newSnippet->storesSamplerDescData());
}

#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
}

RootNodesInfo 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());

    RootNodesInfo rootsInfo;
    // Normal PaintParams creation will have up to 3 roots for the different stages.
    STArray<3, ShaderNode*> roots;
    int currentIndex = 0;
    while (currentIndex < keySize) {
        int32_t blockMarker = fData[currentIndex++];
        if (blockMarker >= 0) {
            return {}; // a bad key
        }
        RootBlockType type = static_cast<RootBlockType>(blockMarker);
        ShaderNode* root = this->createNode(dict, &currentIndex, arena);
        if (!root) {
            return {}; // a bad key
        }
        roots.push_back(root);
        switch (type) {
            case RootBlockType::kSrcColor:
                SkASSERT(!rootsInfo.fSrcColor);
                rootsInfo.fSrcColor = root;
                break;
            case RootBlockType::kFinalBlend:
                SkASSERT(!rootsInfo.fFinalBlend);
                rootsInfo.fFinalBlend = root;
                break;
            case RootBlockType::kClip:
                SkASSERT(!rootsInfo.fClip);
                rootsInfo.fClip = root;
                break;
            default:
                SkUNREACHABLE;
        }
    }

    // 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());
    rootsInfo.fRoots = SkSpan(rootSpan, roots.size());
    return rootsInfo;
}

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++];
    // Skip the root block headers.
    if (id < 0) {
        if (multiline) {
            switch (static_cast<RootBlockType>(id)) {
                case RootBlockType::kSrcColor:
                    str->append("[RootSrcColor] ");
                    break;
                case RootBlockType::kFinalBlend:
                    str->append("[RootFinalBlend] ");
                    break;
                case RootBlockType::kClip:
                    str->append("[RootClip] ");
                    break;
                default:
                    SkUNREACHABLE;
            }
        }
        id = keyData[currentIndex++];
    }

    auto entry = dict->getEntry(id);
    if (!entry) {
        str->append("Unknown(");
        str->appendS32(id);
        str->append(")");
        return currentIndex;
    }

    // Single lined Composes get shortened to just a plus between its two children, e.g. Compose [ A
    // B ] becomes A+B. We don't do a similar prettification for Blend [ A B C ] to (A B)+C because
    // that's not quite as readable and they aren't nearly as common within keys. To make sure
    // chains of Composes are not ambiguous, we only consolidate cases where the inner node is not
    // Compose, e.g. Compose [ A Compose [ B C ]] => A+B+C but [ Compose [ Compose [ A B ] C ] does
    // not become A+B+C
    static constexpr int32_t kComposeID = (int32_t) BuiltInCodeSnippetID::kCompose;
    SkASSERT(dict->getEntry(kComposeID)->fNumChildren == 2);
    const bool prettyCompose =
            // single-lined Compose block
            id == kComposeID && !multiline &&
            // that doesn't have an inner Compose child
            currentIndex < SkTo<int>(keyData.size()) && keyData[currentIndex] != kComposeID;

    if (prettyCompose) {
        SkASSERT(entry->fNumChildren == 2); // ordered [inner, outer]
        currentIndex = key_to_string(caps, str, dict, keyData, currentIndex, indent);
        str->append("+");
        return key_to_string(caps, str, dict, keyData, currentIndex, indent);
    }

    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 <= PaintParamsKey::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) {
            if (i > 0) {
                str->append(", ");
            }
            currentIndex = key_to_string(caps, str, dict, keyData, currentIndex, indent);
        }

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

    if (multiline && 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);
        str.append(" ");
    }
    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;
    }

    int32_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(PaintParamsKey::kEmbeddedDataSizeLimit)) {
            // Would not produce a valid size after decoding
            return false;
        }
        dataLength = PaintParamsKey::EncodeDataSize(dataLength);
        SkASSERT(dataLength >= 0 && dataLength <= PaintParamsKey::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) {
        // Ensure root nodes have their headers set properly, if not the key is malformed.
        if (fData[currentIndex++] >= 0) {
            return false;
        }
        if (!is_block_valid(dict, fData, &currentIndex)) {
            return false;
        }
    }

    return true;
}

} // namespace skgpu::graphite
