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

#include "src/gpu/ganesh/GrProgramDesc.h"

#include "include/private/SkChecksum.h"
#include "include/private/base/SkTo.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrGeometryProcessor.h"
#include "src/gpu/ganesh/GrPipeline.h"
#include "src/gpu/ganesh/GrProcessor.h"
#include "src/gpu/ganesh/GrProgramInfo.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrTexture.h"
#include "src/gpu/ganesh/effects/GrTextureEffect.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"

enum {
    kSamplerOrImageTypeKeyBits = 4
};

static inline uint16_t texture_type_key(GrTextureType type) {
    int value = UINT16_MAX;
    switch (type) {
        case GrTextureType::k2D:
            value = 0;
            break;
        case GrTextureType::kExternal:
            value = 1;
            break;
        case GrTextureType::kRectangle:
            value = 2;
            break;
        default:
            SK_ABORT("Unexpected texture type");
            value = 3;
            break;
    }
    SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
    return SkToU16(value);
}

static uint32_t sampler_key(GrTextureType textureType, const skgpu::Swizzle& swizzle,
                            const GrCaps& caps) {
    int samplerTypeKey = texture_type_key(textureType);

    static_assert(2 == sizeof(swizzle.asKey()));
    uint16_t swizzleKey = swizzle.asKey();
    return SkToU32(samplerTypeKey | swizzleKey << kSamplerOrImageTypeKeyBits);
}

static void add_geomproc_sampler_keys(skgpu::KeyBuilder* b,
                                      const GrGeometryProcessor& geomProc,
                                      const GrCaps& caps) {
    int numTextureSamplers = geomProc.numTextureSamplers();
    b->add32(numTextureSamplers, "ppNumSamplers");
    for (int i = 0; i < numTextureSamplers; ++i) {
        const GrGeometryProcessor::TextureSampler& sampler = geomProc.textureSampler(i);
        const GrBackendFormat& backendFormat = sampler.backendFormat();

        uint32_t samplerKey = sampler_key(backendFormat.textureType(), sampler.swizzle(), caps);
        b->add32(samplerKey);

        caps.addExtraSamplerKey(b, sampler.samplerState(), backendFormat);
    }
}

// Currently we allow 8 bits for the class id
static constexpr uint32_t kClassIDBits = 8;

/**
 * Functions which emit processor key info into the key builder.
 * For every effect, we include the effect's class ID (different for every GrProcessor subclass),
 * any information generated by the effect itself (addToKey), and some meta-information.
 * Shader code may be dependent on properties of the effect not placed in the key by the effect
 * (e.g. pixel format of textures used).
 */
static void gen_geomproc_key(const GrGeometryProcessor& geomProc,
                             const GrCaps& caps,
                             skgpu::KeyBuilder* b) {
    b->appendComment(geomProc.name());
    b->addBits(kClassIDBits, geomProc.classID(), "geomProcClassID");

    geomProc.addToKey(*caps.shaderCaps(), b);
    geomProc.getAttributeKey(b);

    add_geomproc_sampler_keys(b, geomProc, caps);
}

static void gen_xp_key(const GrXferProcessor& xp,
                       const GrCaps& caps,
                       const GrPipeline& pipeline,
                       skgpu::KeyBuilder* b) {
    b->appendComment(xp.name());
    b->addBits(kClassIDBits, xp.classID(), "xpClassID");

    const GrSurfaceOrigin* originIfDstTexture = nullptr;
    GrSurfaceOrigin origin;
    const GrSurfaceProxyView& dstView = pipeline.dstProxyView();
    if (dstView.proxy()) {
        origin = dstView.origin();
        originIfDstTexture = &origin;

        uint32_t samplerKey = sampler_key(dstView.proxy()->backendFormat().textureType(),
                                          dstView.swizzle(), caps);
        b->add32(samplerKey);
    }

    xp.addToKey(*caps.shaderCaps(),
                b,
                originIfDstTexture,
                pipeline.dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment);
}

static void gen_fp_key(const GrFragmentProcessor& fp,
                       const GrCaps& caps,
                       skgpu::KeyBuilder* b) {
    b->appendComment(fp.name());
    b->addBits(kClassIDBits, fp.classID(), "fpClassID");
    b->addBits(GrGeometryProcessor::kCoordTransformKeyBits,
               GrGeometryProcessor::ComputeCoordTransformsKey(fp), "fpTransforms");

    if (auto* te = fp.asTextureEffect()) {
        const GrBackendFormat& backendFormat = te->view().proxy()->backendFormat();
        uint32_t samplerKey = sampler_key(backendFormat.textureType(), te->view().swizzle(), caps);
        b->add32(samplerKey, "fpSamplerKey");
        caps.addExtraSamplerKey(b, te->samplerState(), backendFormat);
    }

    fp.addToKey(*caps.shaderCaps(), b);
    b->add32(fp.numChildProcessors(), "fpNumChildren");

    for (int i = 0; i < fp.numChildProcessors(); ++i) {
        if (auto child = fp.childProcessor(i)) {
            gen_fp_key(*child, caps, b);
        } else {
            // Fold in a sentinel value as the "class ID" for any null children
            b->appendComment("Null");
            b->addBits(kClassIDBits, GrProcessor::ClassID::kNull_ClassID, "fpClassID");
        }
    }
}

static void gen_key(skgpu::KeyBuilder* b,
                    const GrProgramInfo& programInfo,
                    const GrCaps& caps) {
    gen_geomproc_key(programInfo.geomProc(), caps, b);

    const GrPipeline& pipeline = programInfo.pipeline();
    b->addBits(2, pipeline.numFragmentProcessors(),      "numFPs");
    b->addBits(1, pipeline.numColorFragmentProcessors(), "numColorFPs");
    for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
        gen_fp_key(pipeline.getFragmentProcessor(i), caps, b);
    }

    gen_xp_key(pipeline.getXferProcessor(), caps, pipeline, b);

    b->addBits(16, pipeline.writeSwizzle().asKey(), "writeSwizzle");
    b->addBool(pipeline.snapVerticesToPixelCenters(), "snapVertices");
    // The base descriptor only stores whether or not the primitiveType is kPoints. Backend-
    // specific versions (e.g., Vulkan) require more detail
    b->addBool((programInfo.primitiveType() == GrPrimitiveType::kPoints), "isPoints");

    // Put a clean break between the "common" data written by this function, and any backend data
    // appended later. The initial key length will just be this portion (rounded to 4 bytes).
    b->flush();
}

void GrProgramDesc::Build(GrProgramDesc* desc,
                          const GrProgramInfo& programInfo,
                          const GrCaps& caps) {
    desc->reset();
    skgpu::KeyBuilder b(desc->key());
    gen_key(&b, programInfo, caps);
    desc->fInitialKeyLength = desc->keyLength();
}

SkString GrProgramDesc::Describe(const GrProgramInfo& programInfo,
                                 const GrCaps& caps) {
    GrProgramDesc desc;
    skgpu::StringKeyBuilder b(desc.key());
    gen_key(&b, programInfo, caps);
    b.flush();
    return b.description();
}
