/*
 * 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/gpu/ganesh/GrBackendSurface.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkTo.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/Swizzle.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/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrXferProcessor.h"
#include "src/gpu/ganesh/effects/GrTextureEffect.h"

enum GrSurfaceOrigin : int;

// Currently we allow 8 bits for the class id
static constexpr uint32_t kClassIDBits = 8;
static constexpr uint32_t 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");
    }
    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);
    }
}

/**
 * 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);
}

// This corresponds to GrGLSLProgramBuilder::emitAndInstallXferProc
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");

    xp.addToKey(*caps.shaderCaps(), b);
}

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");
        }
    }
}

// This corresponds to GrGLSLProgramBuilder::emitAndInstallDstTexture
static void gen_dstTexture_key(const GrCaps& caps,
                               const GrPipeline& pipeline,
                               skgpu::KeyBuilder* b) {

    const GrSurfaceProxyView& dstView = pipeline.dstProxyView();
    if (dstView.proxy()) {
        uint32_t samplerKey = sampler_key(dstView.proxy()->backendFormat().textureType(),
                                          dstView.swizzle(), caps);
        b->add32(samplerKey);

        b->addBool(kTopLeft_GrSurfaceOrigin == dstView.origin(), "surfaceOrigin");
        b->addBool(pipeline.usesDstInputAttachment(), "usesDstInputAttachment");
    }
}

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

    gen_dstTexture_key(caps, pipeline, b);

    // This corresponds to GrGLSLProgramBuilder::emitAndInstallFragProcs
    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();
}
