Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkTableColorFilter.cpp
index 4853f73..e4daf20 100644 (file)
@@ -275,39 +275,46 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
 
 #if SK_SUPPORT_GPU
 
-#include "GrProcessor.h"
+#include "GrFragmentProcessor.h"
 #include "GrTBackendProcessorFactory.h"
+#include "SkGr.h"
+#include "effects/GrTextureStripAtlas.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/builders/GrGLProgramBuilder.h"
-#include "SkGr.h"
+
 
 class GLColorTableEffect;
 
 class ColorTableEffect : public GrFragmentProcessor {
 public:
-    static GrFragmentProcessor* Create(GrTexture* texture, unsigned flags) {
-        return SkNEW_ARGS(ColorTableEffect, (texture, flags));
-    }
+    static GrFragmentProcessor* Create(GrContext* context, SkBitmap bitmap, unsigned flags);
 
     virtual ~ColorTableEffect();
 
     static const char* Name() { return "ColorTable"; }
     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
 
-    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
-
     typedef GLColorTableEffect GLProcessor;
 
+    const GrTextureStripAtlas* atlas() const { return fAtlas; }
+    int atlasRow() const { return fRow; }
+
 private:
-    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
+    virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
 
-    explicit ColorTableEffect(GrTexture* texture, unsigned flags);
+    virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE;
+
+    ColorTableEffect(GrTexture* texture, GrTextureStripAtlas* atlas, int row, unsigned flags);
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
 
-    GrTextureAccess fTextureAccess;
-    unsigned        fFlags; // currently not used in shader code, just to assist
-                            // getConstantColorComponents().
+    GrTextureAccess         fTextureAccess;
+
+    // currently not used in shader code, just to assist onComputeInvariantOutput().
+    unsigned                fFlags; 
+
+    GrTextureStripAtlas*    fAtlas;
+    int                     fRow;
 
     typedef GrFragmentProcessor INHERITED;
 };
@@ -316,7 +323,7 @@ class GLColorTableEffect : public GrGLFragmentProcessor {
 public:
     GLColorTableEffect(const GrBackendProcessorFactory&, const GrProcessor&);
 
-    virtual void emitCode(GrGLProgramBuilder*,
+    virtual void emitCode(GrGLFPBuilder*,
                           const GrFragmentProcessor&,
                           const GrProcessorKey&,
                           const char* outputColor,
@@ -324,12 +331,12 @@ public:
                           const TransformedCoordsArray&,
                           const TextureSamplerArray&) SK_OVERRIDE;
 
-    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}
+    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
 
     static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b) {}
 
 private:
-
+    UniformHandle fRGBAYValuesUni;
     typedef GrGLFragmentProcessor INHERITED;
 };
 
@@ -337,17 +344,38 @@ GLColorTableEffect::GLColorTableEffect(const GrBackendProcessorFactory& factory,
     : INHERITED(factory) {
  }
 
-void GLColorTableEffect::emitCode(GrGLProgramBuilder* builder,
+void GLColorTableEffect::setData(const GrGLProgramDataManager& pdm, const GrProcessor& proc) {
+    // The textures are organized in a strip where the rows are ordered a, r, g, b.
+    float rgbaYValues[4];
+    const ColorTableEffect& cte = proc.cast<ColorTableEffect>();
+    if (cte.atlas()) {
+        SkScalar yDelta = cte.atlas()->getNormalizedTexelHeight();
+        rgbaYValues[3] = cte.atlas()->getYOffset(cte.atlasRow()) + SK_ScalarHalf * yDelta;
+        rgbaYValues[0] = rgbaYValues[3] + yDelta;
+        rgbaYValues[1] = rgbaYValues[0] + yDelta;
+        rgbaYValues[2] = rgbaYValues[1] + yDelta;
+    } else {
+        rgbaYValues[3] = 0.125;
+        rgbaYValues[0] = 0.375;
+        rgbaYValues[1] = 0.625;
+        rgbaYValues[2] = 0.875;        
+    }
+    pdm.set4fv(fRGBAYValuesUni, 1, rgbaYValues);
+}
+
+void GLColorTableEffect::emitCode(GrGLFPBuilder* builder,
                                   const GrFragmentProcessor&,
                                   const GrProcessorKey&,
                                   const char* outputColor,
                                   const char* inputColor,
                                   const TransformedCoordsArray&,
                                   const TextureSamplerArray& samplers) {
-
+    const char* yoffsets;
+    fRGBAYValuesUni = builder->addUniform(GrGLFPBuilder::kFragment_Visibility,
+                                          kVec4f_GrSLType, "yoffsets", &yoffsets);
     static const float kColorScaleFactor = 255.0f / 256.0f;
     static const float kColorOffsetFactor = 1.0f / 512.0f;
-    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+    GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     if (NULL == inputColor) {
         // the input color is solid white (all ones).
         static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
@@ -363,62 +391,103 @@ void GLColorTableEffect::emitCode(GrGLProgramBuilder* builder,
                               kColorOffsetFactor, kColorOffsetFactor);
     }
 
+    SkString coord;
+
     fsBuilder->codeAppendf("\t\t%s.a = ", outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.a, 0.125)");
+    coord.printf("vec2(coord.a, %s.a)", yoffsets);
+    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
     fsBuilder->codeAppendf("\t\t%s.r = ", outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.r, 0.375)");
+    coord.printf("vec2(coord.r, %s.r)", yoffsets);
+    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
     fsBuilder->codeAppendf("\t\t%s.g = ", outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.g, 0.625)");
+    coord.printf("vec2(coord.g, %s.g)", yoffsets);
+    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
     fsBuilder->codeAppendf("\t\t%s.b = ", outputColor);
-    fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.b, 0.875)");
+    coord.printf("vec2(coord.b, %s.b)", yoffsets);
+    fsBuilder->appendTextureLookup(samplers[0], coord.c_str());
     fsBuilder->codeAppend(";\n");
 
     fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+GrFragmentProcessor* ColorTableEffect::Create(GrContext* context, SkBitmap bitmap, unsigned flags) {
+
+    GrTextureStripAtlas::Desc desc;
+    desc.fWidth  = bitmap.width();
+    desc.fHeight = 128;
+    desc.fRowHeight = bitmap.height();
+    desc.fContext = context;
+    desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
+    GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(desc);
+    int row = atlas->lockRow(bitmap);
+    SkAutoTUnref<GrTexture> texture;
+    if (-1 == row) {
+        atlas = NULL;
+        // Passing params=NULL because this effect does no tiling or filtering.
+        texture.reset(GrRefCachedBitmapTexture(context, bitmap, NULL));
+    } else {
+        texture.reset(SkRef(atlas->getTexture()));
+    }
 
-ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags)
+    return SkNEW_ARGS(ColorTableEffect, (texture, atlas, row, flags));
+}
+
+ColorTableEffect::ColorTableEffect(GrTexture* texture, GrTextureStripAtlas* atlas, int row,
+                                   unsigned flags)
     : fTextureAccess(texture, "a")
-    , fFlags(flags) {
+    , fFlags(flags)
+    , fAtlas(atlas)
+    , fRow(row) {
+
     this->addTextureAccess(&fTextureAccess);
 }
 
 ColorTableEffect::~ColorTableEffect() {
+    if (fAtlas) {
+        fAtlas->unlockRow(fRow);
+    }
 }
 
 const GrBackendFragmentProcessorFactory&  ColorTableEffect::getFactory() const {
     return GrTBackendFragmentProcessorFactory<ColorTableEffect>::getInstance();
 }
 
-bool ColorTableEffect::onIsEqual(const GrProcessor& sBase) const {
-    return this->texture(0) == sBase.texture(0);
+bool ColorTableEffect::onIsEqual(const GrFragmentProcessor& other) const {
+    // For non-atlased instances, the texture (compared by base class) is sufficient to
+    // differentiate different tables. For atlased instances we ensure they are using the
+    // same row.
+    const ColorTableEffect& that = other.cast<ColorTableEffect>();
+    SkASSERT(SkToBool(fAtlas) == SkToBool(that.fAtlas));
+    // Ok to always do this comparison since both would be -1 if non-atlased.
+    return fRow == that.fRow;
 }
 
-void ColorTableEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+void ColorTableEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
     // If we kept the table in the effect then we could actually run known inputs through the
     // table.
+    uint8_t invalidateFlags = 0;
     if (fFlags & SkTable_ColorFilter::kR_Flag) {
-        *validFlags &= ~kR_GrColorComponentFlag;
+        invalidateFlags |= kR_GrColorComponentFlag;
     }
     if (fFlags & SkTable_ColorFilter::kG_Flag) {
-        *validFlags &= ~kG_GrColorComponentFlag;
+        invalidateFlags |= kG_GrColorComponentFlag;
     }
     if (fFlags & SkTable_ColorFilter::kB_Flag) {
-        *validFlags &= ~kB_GrColorComponentFlag;
+        invalidateFlags |= kB_GrColorComponentFlag;
     }
     if (fFlags & SkTable_ColorFilter::kA_Flag) {
-        *validFlags &= ~kA_GrColorComponentFlag;
+        invalidateFlags |= kA_GrColorComponentFlag;
     }
+    inout->invalidateComponents(invalidateFlags, InvariantOutput::kWill_ReadInput);
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 
 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorTableEffect);
@@ -427,26 +496,34 @@ GrFragmentProcessor* ColorTableEffect::TestCreate(SkRandom* random,
                                                   GrContext* context,
                                                   const GrDrawTargetCaps&,
                                                   GrTexture* textures[]) {
-    static unsigned kAllFlags = SkTable_ColorFilter::kR_Flag | SkTable_ColorFilter::kG_Flag |
-                                SkTable_ColorFilter::kB_Flag | SkTable_ColorFilter::kA_Flag;
-    return ColorTableEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], kAllFlags);
+    int flags = 0;
+    uint8_t luts[256][4];
+    do {
+        for (int i = 0; i < 4; ++i) {
+            flags |= random->nextBool() ? (1  << i): 0;
+        }
+    } while (!flags);
+    for (int i = 0; i < 4; ++i) {
+        if (flags & (1 << i)) {
+            for (int j = 0; j < 256; ++j) {
+                luts[j][i] = SkToU8(random->nextBits(8));
+            }
+        }
+    }
+    SkAutoTUnref<SkColorFilter> filter(SkTableColorFilter::CreateARGB(
+        (flags & (1 << 0)) ? luts[0] : NULL,
+        (flags & (1 << 1)) ? luts[1] : NULL,
+        (flags & (1 << 2)) ? luts[2] : NULL,
+        (flags & (1 << 3)) ? luts[3] : NULL
+    ));
+    return filter->asFragmentProcessor(context);
 }
 
 GrFragmentProcessor* SkTable_ColorFilter::asFragmentProcessor(GrContext* context) const {
     SkBitmap bitmap;
-    GrFragmentProcessor* fp = NULL;
     this->asComponentTable(&bitmap);
-    // passing NULL because this effect does no tiling or filtering.
-    GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, bitmap, NULL);
-    if (texture) {
-        fp = ColorTableEffect::Create(texture, fFlags);
-
-        // Unlock immediately, this is not great, but we don't have a way of
-        // knowing when else to unlock it currently. TODO: Remove this when
-        // unref becomes the unlock replacement for all types of textures.
-        GrUnlockAndUnrefCachedBitmapTexture(texture);
-    }
-    return fp;
+
+    return ColorTableEffect::Create(context, bitmap, fFlags);
 }
 
 #endif // SK_SUPPORT_GPU