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

#ifndef GrAtlasedShaderHelpers_DEFINED
#define GrAtlasedShaderHelpers_DEFINED

#include "src/gpu/ganesh/GrDrawOpAtlas.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"

static inline void append_index_uv_varyings(GrGeometryProcessor::ProgramImpl::EmitArgs& args,
                                            int numTextureSamplers,
                                            const char* inTexCoordsName,
                                            const char* atlasDimensionsInvName,
                                            GrGLSLVarying* uv,
                                            GrGLSLVarying* texIdx,
                                            GrGLSLVarying* st) {
    using Interpolation = GrGLSLVaryingHandler::Interpolation;
    // This extracts the texture index and texel coordinates from the same variable
    // Packing structure: texel coordinates have the 2-bit texture page encoded in bits 13 & 14 of
    // the x coordinate. It would be nice to use bits 14 and 15, but iphone6 has problem with those
    // bits when in gles. Iphone6 works fine with bits 14 and 15 in metal.
    if (args.fShaderCaps->fIntegerSupport) {
        if (numTextureSamplers <= 1) {
            args.fVertBuilder->codeAppendf(
                "int texIdx = 0;"
                "float2 unormTexCoords = float2(%s.x, %s.y);"
           , inTexCoordsName, inTexCoordsName);
        } else {
            args.fVertBuilder->codeAppendf(
                "int2 coords = int2(%s.x, %s.y);"
                "int texIdx = coords.x >> 13;"
                "float2 unormTexCoords = float2(coords.x & 0x1FFF, coords.y);"
            , inTexCoordsName, inTexCoordsName);
        }
    } else {
        if (numTextureSamplers <= 1) {
            args.fVertBuilder->codeAppendf(
                "float texIdx = 0;"
                "float2 unormTexCoords = float2(%s.x, %s.y);"
            , inTexCoordsName, inTexCoordsName);
        } else {
            args.fVertBuilder->codeAppendf(
                "float2 coord = float2(%s.x, %s.y);"
                "float texIdx = floor(coord.x * exp2(-13));"
                "float2 unormTexCoords = float2(coord.x - texIdx * exp2(13), coord.y);"
            , inTexCoordsName, inTexCoordsName);
        }
    }

    // Multiply by 1/atlasDimensions to get normalized texture coordinates
    uv->reset(SkSLType::kFloat2);
    args.fVaryingHandler->addVarying("TextureCoords", uv);
    args.fVertBuilder->codeAppendf(
            "%s = unormTexCoords * %s;", uv->vsOut(), atlasDimensionsInvName);

    // On ANGLE there is a significant cost to using an int varying. We don't know of any case where
    // it is worse to use a float so for now we always do.
    texIdx->reset(SkSLType::kFloat);
    // If we computed the local var "texIdx" as an int we will need to cast it to float
    const char* cast = args.fShaderCaps->fIntegerSupport ? "float" : "";
    args.fVaryingHandler->addVarying("TexIndex", texIdx, Interpolation::kCanBeFlat);
    args.fVertBuilder->codeAppendf("%s = %s(texIdx);", texIdx->vsOut(), cast);

    if (st) {
        st->reset(SkSLType::kFloat2);
        args.fVaryingHandler->addVarying("IntTextureCoords", st);
        args.fVertBuilder->codeAppendf("%s = unormTexCoords;", st->vsOut());
    }
}

static inline void append_multitexture_lookup(GrGeometryProcessor::ProgramImpl::EmitArgs& args,
                                              int numTextureSamplers,
                                              const GrGLSLVarying& texIdx,
                                              const char* coordName,
                                              const char* colorName) {
    SkASSERT(numTextureSamplers > 0);
    // This shouldn't happen, but will avoid a crash if it does
    if (numTextureSamplers <= 0) {
        args.fFragBuilder->codeAppendf("%s = float4(1, 1, 1, 1);", colorName);
        return;
    }

    // conditionally load from the indexed texture sampler
    for (int i = 0; i < numTextureSamplers-1; ++i) {
        args.fFragBuilder->codeAppendf("if (%s == %d) { %s = ", texIdx.fsIn(), i, colorName);
        args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i],
                                               coordName);
        args.fFragBuilder->codeAppend("; } else ");
    }
    args.fFragBuilder->codeAppendf("{ %s = ", colorName);
    args.fFragBuilder->appendTextureLookup(args.fTexSamplers[numTextureSamplers - 1],
                                           coordName);
    args.fFragBuilder->codeAppend("; }");
}

#endif
