/*
 * 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 "gl/GrGLProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "GrTBackendProcessorFactory.h"
#include "GrTexturePriv.h"
#include "SkGr.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));
    }
}

#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkColorCubeFilter::SkColorCubeFilter(SkReadBuffer& buffer)
  : fCache(buffer.readInt()) {
    fCubeData.reset(buffer.readByteArrayAsData());
    buffer.validate(is_valid_3D_lut(fCubeData, fCache.cubeDimension()));
    fUniqueID = SkNextColorCubeUniqueID();
}
#endif

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

    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
    int colorCubeSize() const { return fColorCubeAccess.getTexture()->width(); }

    static const char* Name() { return "ColorCube"; }

    virtual void onComputeInvariantOutput(GrProcessor::InvariantOutput*) const SK_OVERRIDE;

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

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

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

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

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

        typedef GrGLFragmentProcessor INHERITED;
    };

private:
    virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;

    GrColorCubeEffect(GrTexture* colorCube);

    GrCoordTransform    fColorCubeTransform;
    GrTextureAccess     fColorCubeAccess;

    typedef GrFragmentProcessor INHERITED;
};

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

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

GrColorCubeEffect::~GrColorCubeEffect() {
}

bool GrColorCubeEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
    const GrColorCubeEffect& s = sBase.cast<GrColorCubeEffect>();
    return fColorCubeAccess.getTexture() == s.fColorCubeAccess.getTexture();
}

const GrBackendFragmentProcessorFactory& GrColorCubeEffect::getFactory() const {
    return GrTBackendFragmentProcessorFactory<GrColorCubeEffect>::getInstance();
}

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

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

GrColorCubeEffect::GLProcessor::GLProcessor(const GrBackendProcessorFactory& factory,
                                            const GrProcessor&)
    : INHERITED(factory) {
}

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

void GrColorCubeEffect::GLProcessor::emitCode(GrGLFPBuilder* builder,
                                              const GrFragmentProcessor&,
                                              const GrProcessorKey&,
                                              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, "Size");
    const char* colorCubeSizeUni = builder->getUniformCStr(fColorCubeSizeUni);
    fColorCubeInvSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                               kFloat_GrSLType, "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 GrCacheID::Domain gCubeDomain = GrCacheID::GenerateDomain();

    GrCacheID::Key key;
    key.fData32[0] = fUniqueID;
    key.fData32[1] = fCache.cubeDimension();
    key.fData64[1] = 0;
    GrCacheID cacheID(gCubeDomain, key);

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

    SkAutoTUnref<GrTexture> textureCube(
        static_cast<GrTexture*>(context->findAndRefCachedResource(
            GrTexturePriv::ComputeKey(context->getGpu(), NULL, desc, cacheID))));

    if (!textureCube) {
        textureCube.reset(context->createTexture(NULL, desc, cacheID, fCubeData->data(), 0));
    }

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