/*
 * 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,
                                           const RuntimeEffectDictionary* rteDict,
                                           SkArenaAlloc* arena,
                                           int availableVaryings,
                                           bool canLiftCoords) 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 4 roots for the different stages.
    STArray<4, ShaderNode*> roots;
    STArray<2, ShaderNode*> liftableRoots;
    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;
                liftableRoots.push_back(root);
                break;
            case RootBlockType::kFinalBlend:
                SkASSERT(!rootsInfo.fFinalBlend);
                rootsInfo.fFinalBlend = root;
                liftableRoots.push_back(root);
                break;
            case RootBlockType::kClip:
                SkASSERT(!rootsInfo.fClip);
                rootsInfo.fClip = root;
                break;
            case RootBlockType::kMeshShader:
                SkASSERT(!rootsInfo.fMeshShader);
                rootsInfo.fMeshShader = root;
                break;
            default:
                SkUNREACHABLE;
        }
    }

    if (rootsInfo.fMeshShader) {
        rootsInfo.fMeshSpec = rteDict->findMeshSpec(rootsInfo.fMeshShader->codeSnippetId());
        if (!rootsInfo.fMeshSpec) {
            // Couldn't find the SkMeshSpecification for the mesh shader snippet so the key is bad.
            return {};
        }
    }

    // See what expressions we can lift to the vertex shader.
    if (canLiftCoords) {
        lift_coord_expressions(liftableRoots, &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(liftableRoots, &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;
                case RootBlockType::kMeshShader:
                    str->append("[RootMeshShader] ");
                    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
