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

#include "SkColorCubeFilter.h"
#include "SkColorPriv.h"
#include "SkOnce.h"
#include "SkReadBuffer.h"
#include "SkUnPreMultiply.h"
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrInvariantOutput.h"
#include "GrTexturePriv.h"
#include "SkGr.h"
#include "gl/GrGLProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
#endif

///////////////////////////////////////////////////////////////////////////////
namespace {

int32_t SkNextColorCubeUniqueID() {
    static int32_t gColorCubeUniqueID;
    // do a loop in case our global wraps around, as we never want to return a 0
    int32_t genID;
    do {
        genID = sk_atomic_inc(&gColorCubeUniqueID) + 1;
    } while (0 == genID);
    return genID;
}

} // end namespace

static const int MIN_CUBE_SIZE = 4;
static const int MAX_CUBE_SIZE = 64;

static bool is_valid_3D_lut(SkData* cubeData, int cubeDimension) {
    size_t minMemorySize = sizeof(uint8_t) * 4 * cubeDimension * cubeDimension * cubeDimension;
    return (cubeDimension >= MIN_CUBE_SIZE) && (cubeDimension <= MAX_CUBE_SIZE) &&
           (NULL != cubeData) && (cubeData->size() >= minMemorySize);
}

SkColorFilter* SkColorCubeFilter::Create(SkData* cubeData, int cubeDimension) {
    if (!is_valid_3D_lut(cubeData, cubeDimension)) {
        return NULL;
    }

    return SkNEW_ARGS(SkColorCubeFilter, (cubeData, cubeDimension));
}

SkColorCubeFilter::SkColorCubeFilter(SkData* cubeData, int cubeDimension)
  : fCubeData(SkRef(cubeData))
  , fUniqueID(SkNextColorCubeUniqueID())
  , fCache(cubeDimension) {
}

uint32_t SkColorCubeFilter::getFlags() const {
    return this->INHERITED::getFlags() | kAlphaUnchanged_Flag;
}

SkColorCubeFilter::ColorCubeProcesingCache::ColorCubeProcesingCache(int cubeDimension)
  : fCubeDimension(cubeDimension)
  , fLutsInited(false) {
    fColorToIndex[0] = fColorToIndex[1] = NULL;
    fColorToFactors[0] = fColorToFactors[1] = NULL;
    fColorToScalar = NULL;
}

void SkColorCubeFilter::ColorCubeProcesingCache::getProcessingLuts(
    const int* (*colorToIndex)[2], const SkScalar* (*colorToFactors)[2],
    const SkScalar** colorToScalar) {
    SkOnce(&fLutsInited, &fLutsMutex,
           SkColorCubeFilter::ColorCubeProcesingCache::initProcessingLuts, this);
    SkASSERT((fColorToIndex[0] != NULL) &&
             (fColorToIndex[1] != NULL) &&
             (fColorToFactors[0] != NULL) &&
             (fColorToFactors[1] != NULL) &&
             (fColorToScalar != NULL));
    (*colorToIndex)[0] = fColorToIndex[0];
    (*colorToIndex)[1] = fColorToIndex[1];
    (*colorToFactors)[0] = fColorToFactors[0];
    (*colorToFactors)[1] = fColorToFactors[1];
    (*colorToScalar) = fColorToScalar;
}

void SkColorCubeFilter::ColorCubeProcesingCache::initProcessingLuts(
    SkColorCubeFilter::ColorCubeProcesingCache* cache) {
    static const SkScalar inv8bit = SkScalarInvert(SkIntToScalar(255));

    // We need 256 int * 2 for fColorToIndex, so a total of 512 int.
    // We need 256 SkScalar * 2 for fColorToFactors and 256 SkScalar
    // for fColorToScalar, so a total of 768 SkScalar.
    cache->fLutStorage.reset(512 * sizeof(int) + 768 * sizeof(SkScalar));
    uint8_t* storage = (uint8_t*)cache->fLutStorage.get();
    cache->fColorToIndex[0] = (int*)storage;
    cache->fColorToIndex[1] = cache->fColorToIndex[0] + 256;
    cache->fColorToFactors[0] = (SkScalar*)(storage + (512 * sizeof(int)));
    cache->fColorToFactors[1] = cache->fColorToFactors[0] + 256;
    cache->fColorToScalar = cache->fColorToFactors[1] + 256;

    SkScalar size = SkIntToScalar(cache->fCubeDimension);
    SkScalar scale = (size - SK_Scalar1) * inv8bit;

    for (int i = 0; i < 256; ++i) {
        SkScalar index = scale * i;
        cache->fColorToIndex[0][i] = SkScalarFloorToInt(index);
        cache->fColorToIndex[1][i] = cache->fColorToIndex[0][i] + 1;
        cache->fColorToScalar[i] = inv8bit * i;
        if (cache->fColorToIndex[1][i] < cache->fCubeDimension) {
            cache->fColorToFactors[1][i] = index - SkIntToScalar(cache->fColorToIndex[0][i]);
            cache->fColorToFactors[0][i] = SK_Scalar1 - cache->fColorToFactors[1][i];
        } else {
            cache->fColorToIndex[1][i] = cache->fColorToIndex[0][i];
            cache->fColorToFactors[0][i] = SK_Scalar1;
            cache->fColorToFactors[1][i] = 0;
        }
    }
}

void SkColorCubeFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
    const int* colorToIndex[2];
    const SkScalar* colorToFactors[2];
    const SkScalar* colorToScalar;
    fCache.getProcessingLuts(&colorToIndex, &colorToFactors, &colorToScalar);

    const int dim = fCache.cubeDimension();
    SkColor* colorCube = (SkColor*)fCubeData->data();
    for (int i = 0; i < count; ++i) {
        SkColor inputColor = SkUnPreMultiply::PMColorToColor(src[i]);
        uint8_t r = SkColorGetR(inputColor);
        uint8_t g = SkColorGetG(inputColor);
        uint8_t b = SkColorGetB(inputColor);
        uint8_t a = SkColorGetA(inputColor);
        SkScalar rOut(0), gOut(0), bOut(0);
        for (int x = 0; x < 2; ++x) {
            for (int y = 0; y < 2; ++y) {
                for (int z = 0; z < 2; ++z) {
                    SkColor lutColor = colorCube[colorToIndex[x][r] +
                                                (colorToIndex[y][g] +
                                                 colorToIndex[z][b] * dim) * dim];
                    SkScalar factor = colorToFactors[x][r] *
                                      colorToFactors[y][g] *
                                      colorToFactors[z][b];
                    rOut += colorToScalar[SkColorGetR(lutColor)] * factor;
                    gOut += colorToScalar[SkColorGetG(lutColor)] * factor;
                    bOut += colorToScalar[SkColorGetB(lutColor)] * factor;
                }
            }
        }
        const SkScalar aOut = SkIntToScalar(a);
        dst[i] = SkPackARGB32(a,
            SkScalarRoundToInt(rOut * aOut),
            SkScalarRoundToInt(gOut * aOut),
            SkScalarRoundToInt(bOut * aOut));
    }
}

SkFlattenable* SkColorCubeFilter::CreateProc(SkReadBuffer& buffer) {
    int cubeDimension = buffer.readInt();
    SkAutoDataUnref cubeData(buffer.readByteArrayAsData());
    if (!buffer.validate(is_valid_3D_lut(cubeData, cubeDimension))) {
        return NULL;
    }
    return Create(cubeData, cubeDimension);
}

void SkColorCubeFilter::flatten(SkWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);
    buffer.writeInt(fCache.cubeDimension());
    buffer.writeDataAsByteArray(fCubeData);
}

#ifndef SK_IGNORE_TO_STRING
void SkColorCubeFilter::toString(SkString* str) const {
    str->append("SkColorCubeFilter ");
}
#endif

///////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU

class GrColorCubeEffect : public GrFragmentProcessor {
public:
    static GrFragmentProcessor* Create(GrTexture* colorCube) {
        return (NULL != colorCube) ? SkNEW_ARGS(GrColorCubeEffect, (colorCube)) : NULL;
    }

    virtual ~GrColorCubeEffect();

    const char* name() const SK_OVERRIDE { return "ColorCube"; }

    virtual void getGLProcessorKey(const GrGLCaps& caps,
                                   GrProcessorKeyBuilder* b) const SK_OVERRIDE;

    GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
    int colorCubeSize() const { return fColorCubeAccess.getTexture()->width(); }


    void onComputeInvariantOutput(GrInvariantOutput*) const SK_OVERRIDE;

    class GLProcessor : public GrGLFragmentProcessor {
    public:
        GLProcessor(const GrProcessor&);
        virtual ~GLProcessor();

        virtual void emitCode(GrGLFPBuilder*,
                              const GrFragmentProcessor&,
                              const char* outputColor,
                              const char* inputColor,
                              const TransformedCoordsArray&,
                              const TextureSamplerArray&) SK_OVERRIDE;

        static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);

        void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;

    private:
        GrGLProgramDataManager::UniformHandle fColorCubeSizeUni;
        GrGLProgramDataManager::UniformHandle fColorCubeInvSizeUni;

        typedef GrGLFragmentProcessor INHERITED;
    };

private:
    bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { return true; }

    GrColorCubeEffect(GrTexture* colorCube);

    GrCoordTransform    fColorCubeTransform;
    GrTextureAccess     fColorCubeAccess;

    typedef GrFragmentProcessor INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

GrColorCubeEffect::GrColorCubeEffect(GrTexture* colorCube)
    : fColorCubeTransform(kLocal_GrCoordSet, colorCube, GrTextureParams::kBilerp_FilterMode)
    , fColorCubeAccess(colorCube, "bgra", GrTextureParams::kBilerp_FilterMode) {
    this->initClassID<GrColorCubeEffect>();
    this->addCoordTransform(&fColorCubeTransform);
    this->addTextureAccess(&fColorCubeAccess);
}

GrColorCubeEffect::~GrColorCubeEffect() {
}

void GrColorCubeEffect::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
    GLProcessor::GenKey(*this, caps, b);
}

GrGLFragmentProcessor* GrColorCubeEffect::createGLInstance() const {
    return SkNEW_ARGS(GLProcessor, (*this));
}

void GrColorCubeEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
    inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
}

///////////////////////////////////////////////////////////////////////////////

GrColorCubeEffect::GLProcessor::GLProcessor(const GrProcessor&) {
}

GrColorCubeEffect::GLProcessor::~GLProcessor() {
}

void GrColorCubeEffect::GLProcessor::emitCode(GrGLFPBuilder* builder,
                                              const GrFragmentProcessor&,
                                              const char* outputColor,
                                              const char* inputColor,
                                              const TransformedCoordsArray& coords,
                                              const TextureSamplerArray& samplers) {
    if (NULL == inputColor) {
        inputColor = "vec4(1)";
    }

    fColorCubeSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kFloat_GrSLType, kDefault_GrSLPrecision,
                                            "Size");
    const char* colorCubeSizeUni = builder->getUniformCStr(fColorCubeSizeUni);
    fColorCubeInvSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                               kFloat_GrSLType, kDefault_GrSLPrecision,
                                               "InvSize");
    const char* colorCubeInvSizeUni = builder->getUniformCStr(fColorCubeInvSizeUni);

    const char* nonZeroAlpha = "nonZeroAlpha";
    const char* unPMColor = "unPMColor";
    const char* cubeIdx = "cubeIdx";
    const char* cCoords1 = "cCoords1";
    const char* cCoords2 = "cCoords2";

    // Note: if implemented using texture3D in OpenGL ES older than OpenGL ES 3.0,
    //       the shader might need "#extension GL_OES_texture_3D : enable".

    GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();

    // Unpremultiply color
    fsBuilder->codeAppendf("\tfloat %s = max(%s.a, 0.00001);\n", nonZeroAlpha, inputColor);
    fsBuilder->codeAppendf("\tvec4 %s = vec4(%s.rgb / %s, %s);\n",
                           unPMColor, inputColor, nonZeroAlpha, nonZeroAlpha);

    // Fit input color into the cube.
    fsBuilder->codeAppendf(
        "vec3 %s = vec3(%s.rg * vec2((%s - 1.0) * %s) + vec2(0.5 * %s), %s.b * (%s - 1.0));\n",
        cubeIdx, unPMColor, colorCubeSizeUni, colorCubeInvSizeUni, colorCubeInvSizeUni,
        unPMColor, colorCubeSizeUni);

    // Compute y coord for for texture fetches.
    fsBuilder->codeAppendf("vec2 %s = vec2(%s.r, (floor(%s.b) + %s.g) * %s);\n",
                           cCoords1, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);
    fsBuilder->codeAppendf("vec2 %s = vec2(%s.r, (ceil(%s.b) + %s.g) * %s);\n",
                           cCoords2, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);

    // Apply the cube.
    fsBuilder->codeAppendf("%s = vec4(mix(", outputColor);
    fsBuilder->appendTextureLookup(samplers[0], cCoords1, coords[0].getType());
    fsBuilder->codeAppend(".rgb, ");
    fsBuilder->appendTextureLookup(samplers[0], cCoords2, coords[0].getType());

    // Premultiply color by alpha. Note that the input alpha is not modified by this shader.
    fsBuilder->codeAppendf(".rgb, fract(%s.b)) * vec3(%s), %s.a);\n",
                           cubeIdx, nonZeroAlpha, inputColor);
}

void GrColorCubeEffect::GLProcessor::setData(const GrGLProgramDataManager& pdman,
                                             const GrProcessor& proc) {
    const GrColorCubeEffect& colorCube = proc.cast<GrColorCubeEffect>();
    SkScalar size = SkIntToScalar(colorCube.colorCubeSize());
    pdman.set1f(fColorCubeSizeUni, SkScalarToFloat(size));
    pdman.set1f(fColorCubeInvSizeUni, SkScalarToFloat(SkScalarInvert(size)));
}

void GrColorCubeEffect::GLProcessor::GenKey(const GrProcessor& proc,
                                            const GrGLCaps&, GrProcessorKeyBuilder* b) {
    b->add32(1); // Always same shader for now
}

GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context) const {
    static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
    GrContentKey key;
    GrContentKey::Builder builder(&key, kDomain, 2);
    builder[0] = fUniqueID;
    builder[1] = fCache.cubeDimension();
    builder.finish();

    GrSurfaceDesc desc;
    desc.fWidth = fCache.cubeDimension();
    desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension();
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    SkAutoTUnref<GrTexture> textureCube(context->findAndRefCachedTexture(key));
    if (!textureCube) {
        textureCube.reset(context->createTexture(desc, fCubeData->data(), 0));
        if (textureCube) {
            SkAssertResult(context->addResourceToCache(key, textureCube));
        }
    }

    return textureCube ? GrColorCubeEffect::Create(textureCube) : NULL;
}
#endif
