Home | History | Annotate | Download | only in effects
      1 
      2 #include "SkBitmap.h"
      3 #include "SkTableColorFilter.h"
      4 #include "SkColorPriv.h"
      5 #include "SkFlattenableBuffers.h"
      6 #include "SkUnPreMultiply.h"
      7 #include "SkString.h"
      8 
      9 class SkTable_ColorFilter : public SkColorFilter {
     10 public:
     11     SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
     12                         const uint8_t tableG[], const uint8_t tableB[]) {
     13         fBitmap = NULL;
     14         fFlags = 0;
     15 
     16         uint8_t* dst = fStorage;
     17         if (tableA) {
     18             memcpy(dst, tableA, 256);
     19             dst += 256;
     20             fFlags |= kA_Flag;
     21         }
     22         if (tableR) {
     23             memcpy(dst, tableR, 256);
     24             dst += 256;
     25             fFlags |= kR_Flag;
     26         }
     27         if (tableG) {
     28             memcpy(dst, tableG, 256);
     29             dst += 256;
     30             fFlags |= kG_Flag;
     31         }
     32         if (tableB) {
     33             memcpy(dst, tableB, 256);
     34             fFlags |= kB_Flag;
     35         }
     36     }
     37 
     38     virtual ~SkTable_ColorFilter() {
     39         SkDELETE(fBitmap);
     40     }
     41 
     42     virtual bool asComponentTable(SkBitmap* table) const SK_OVERRIDE;
     43 
     44 #if SK_SUPPORT_GPU
     45     virtual GrEffectRef* asNewEffect(GrContext* context) const SK_OVERRIDE;
     46 #endif
     47 
     48     virtual void filterSpan(const SkPMColor src[], int count,
     49                             SkPMColor dst[]) const SK_OVERRIDE;
     50 
     51     SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
     52 
     53     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
     54 
     55     enum {
     56         kA_Flag = 1 << 0,
     57         kR_Flag = 1 << 1,
     58         kG_Flag = 1 << 2,
     59         kB_Flag = 1 << 3,
     60     };
     61 
     62 protected:
     63     SkTable_ColorFilter(SkFlattenableReadBuffer& buffer);
     64     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
     65 
     66 private:
     67     mutable const SkBitmap* fBitmap; // lazily allocated
     68 
     69     uint8_t fStorage[256 * 4];
     70     unsigned fFlags;
     71 
     72     typedef SkColorFilter INHERITED;
     73 };
     74 
     75 static const uint8_t gIdentityTable[] = {
     76     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     77     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
     78     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     79     0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
     80     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
     81     0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
     82     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
     83     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
     84     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
     85     0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
     86     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
     87     0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
     88     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
     89     0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
     90     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
     91     0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
     92     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
     93     0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
     94     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
     95     0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
     96     0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
     97     0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
     98     0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
     99     0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
    100     0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
    101     0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
    102     0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
    103     0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
    104     0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
    105     0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
    106     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
    107     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
    108 };
    109 
    110 void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count,
    111                                      SkPMColor dst[]) const {
    112     const uint8_t* table = fStorage;
    113     const uint8_t* tableA = gIdentityTable;
    114     const uint8_t* tableR = gIdentityTable;
    115     const uint8_t* tableG = gIdentityTable;
    116     const uint8_t* tableB = gIdentityTable;
    117     if (fFlags & kA_Flag) {
    118         tableA = table; table += 256;
    119     }
    120     if (fFlags & kR_Flag) {
    121         tableR = table; table += 256;
    122     }
    123     if (fFlags & kG_Flag) {
    124         tableG = table; table += 256;
    125     }
    126     if (fFlags & kB_Flag) {
    127         tableB = table;
    128     }
    129 
    130     const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
    131     for (int i = 0; i < count; ++i) {
    132         SkPMColor c = src[i];
    133         unsigned a, r, g, b;
    134         if (0 == c) {
    135             a = r = g = b = 0;
    136         } else {
    137             a = SkGetPackedA32(c);
    138             r = SkGetPackedR32(c);
    139             g = SkGetPackedG32(c);
    140             b = SkGetPackedB32(c);
    141 
    142             if (a < 255) {
    143                 SkUnPreMultiply::Scale scale = scaleTable[a];
    144                 r = SkUnPreMultiply::ApplyScale(scale, r);
    145                 g = SkUnPreMultiply::ApplyScale(scale, g);
    146                 b = SkUnPreMultiply::ApplyScale(scale, b);
    147             }
    148         }
    149         dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r],
    150                                          tableG[g], tableB[b]);
    151     }
    152 }
    153 
    154 #ifdef SK_DEVELOPER
    155 void SkTable_ColorFilter::toString(SkString* str) const {
    156     str->append("SkTable_ColorFilter");
    157 }
    158 #endif
    159 
    160 static const uint8_t gCountNibBits[] = {
    161     0, 1, 1, 2,
    162     1, 2, 2, 3,
    163     1, 2, 2, 3,
    164     2, 3, 3, 4
    165 };
    166 
    167 #include "SkPackBits.h"
    168 
    169 void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
    170     this->INHERITED::flatten(buffer);
    171 
    172     uint8_t storage[5*256];
    173     int count = gCountNibBits[fFlags & 0xF];
    174     size_t size = SkPackBits::Pack8(fStorage, count * 256, storage);
    175     SkASSERT(size <= sizeof(storage));
    176 
    177 //    SkDebugf("raw %d packed %d\n", count * 256, size);
    178 
    179     buffer.writeInt(fFlags);
    180     buffer.writeByteArray(storage, size);
    181 }
    182 
    183 SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
    184     fBitmap = NULL;
    185 
    186     uint8_t storage[5*256];
    187 
    188     fFlags = buffer.readInt();
    189 
    190     size_t size = buffer.getArrayCount();
    191     SkASSERT(size <= sizeof(storage));
    192     buffer.readByteArray(storage);
    193 
    194     SkDEBUGCODE(size_t raw = ) SkPackBits::Unpack8(storage, size, fStorage);
    195 
    196     SkASSERT(raw <= sizeof(fStorage));
    197     SkDEBUGCODE(size_t count = gCountNibBits[fFlags & 0xF]);
    198     SkASSERT(raw == count * 256);
    199 }
    200 
    201 bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
    202     if (table) {
    203         if (NULL == fBitmap) {
    204             SkBitmap* bmp = SkNEW(SkBitmap);
    205             bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
    206             bmp->allocPixels();
    207             uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
    208             int offset = 0;
    209             static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
    210 
    211             for (int x = 0; x < 4; ++x) {
    212                 if (!(fFlags & kFlags[x])) {
    213                     memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable));
    214                 } else {
    215                     memcpy(bitmapPixels, fStorage + offset, 256);
    216                     offset += 256;
    217                 }
    218                 bitmapPixels += 256;
    219             }
    220             fBitmap = bmp;
    221         }
    222         *table = *fBitmap;
    223     }
    224     return true;
    225 }
    226 
    227 #if SK_SUPPORT_GPU
    228 
    229 #include "GrEffect.h"
    230 #include "GrTBackendEffectFactory.h"
    231 #include "gl/GrGLEffect.h"
    232 #include "SkGr.h"
    233 
    234 class GLColorTableEffect;
    235 
    236 class ColorTableEffect : public GrEffect {
    237 public:
    238     static GrEffectRef* Create(GrTexture* texture, unsigned flags) {
    239         AutoEffectUnref effect(SkNEW_ARGS(ColorTableEffect, (texture, flags)));
    240         return CreateEffectRef(effect);
    241     }
    242 
    243     virtual ~ColorTableEffect();
    244 
    245     static const char* Name() { return "ColorTable"; }
    246     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
    247 
    248     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
    249 
    250     typedef GLColorTableEffect GLEffect;
    251 
    252 private:
    253     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
    254 
    255     explicit ColorTableEffect(GrTexture* texture, unsigned flags);
    256 
    257     GR_DECLARE_EFFECT_TEST;
    258 
    259     GrTextureAccess fTextureAccess;
    260     unsigned        fFlags; // currently not used in shader code, just to assist
    261                             // getConstantColorComponents().
    262 
    263     typedef GrEffect INHERITED;
    264 };
    265 
    266 class GLColorTableEffect : public GrGLEffect {
    267 public:
    268     GLColorTableEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
    269 
    270     virtual void emitCode(GrGLShaderBuilder*,
    271                           const GrDrawEffect&,
    272                           EffectKey,
    273                           const char* outputColor,
    274                           const char* inputColor,
    275                           const TextureSamplerArray&) SK_OVERRIDE;
    276 
    277     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
    278 
    279     static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
    280 
    281 private:
    282 
    283     typedef GrGLEffect INHERITED;
    284 };
    285 
    286 GLColorTableEffect::GLColorTableEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    287     : INHERITED(factory) {
    288  }
    289 
    290 void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder,
    291                                   const GrDrawEffect&,
    292                                   EffectKey,
    293                                   const char* outputColor,
    294                                   const char* inputColor,
    295                                   const TextureSamplerArray& samplers) {
    296 
    297     static const float kColorScaleFactor = 255.0f / 256.0f;
    298     static const float kColorOffsetFactor = 1.0f / 512.0f;
    299     if (NULL == inputColor) {
    300         // the input color is solid white (all ones).
    301         static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
    302         builder->fsCodeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n",
    303                                kMaxValue, kMaxValue, kMaxValue, kMaxValue);
    304 
    305     } else {
    306         builder->fsCodeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor);
    307         builder->fsCodeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor);
    308         builder->fsCodeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
    309                               kColorScaleFactor,
    310                               kColorOffsetFactor, kColorOffsetFactor,
    311                               kColorOffsetFactor, kColorOffsetFactor);
    312     }
    313 
    314     builder->fsCodeAppendf("\t\t%s.a = ", outputColor);
    315     builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "vec2(coord.a, 0.125)");
    316     builder->fsCodeAppend(";\n");
    317 
    318     builder->fsCodeAppendf("\t\t%s.r = ", outputColor);
    319     builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "vec2(coord.r, 0.375)");
    320     builder->fsCodeAppend(";\n");
    321 
    322     builder->fsCodeAppendf("\t\t%s.g = ", outputColor);
    323     builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "vec2(coord.g, 0.625)");
    324     builder->fsCodeAppend(";\n");
    325 
    326     builder->fsCodeAppendf("\t\t%s.b = ", outputColor);
    327     builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "vec2(coord.b, 0.875)");
    328     builder->fsCodeAppend(";\n");
    329 
    330     builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
    331 }
    332 
    333 GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrDrawEffect&, const GrGLCaps&) {
    334     return 0;
    335 }
    336 
    337 ///////////////////////////////////////////////////////////////////////////////
    338 
    339 ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags)
    340     : fTextureAccess(texture, "a")
    341     , fFlags(flags) {
    342     this->addTextureAccess(&fTextureAccess);
    343 }
    344 
    345 ColorTableEffect::~ColorTableEffect() {
    346 }
    347 
    348 const GrBackendEffectFactory&  ColorTableEffect::getFactory() const {
    349     return GrTBackendEffectFactory<ColorTableEffect>::getInstance();
    350 }
    351 
    352 bool ColorTableEffect::onIsEqual(const GrEffect& sBase) const {
    353     return this->texture(0) == sBase.texture(0);
    354 }
    355 
    356 void ColorTableEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
    357     // If we kept the table in the effect then we could actually run known inputs through the
    358     // table.
    359     if (fFlags & SkTable_ColorFilter::kR_Flag) {
    360         *validFlags &= ~kR_GrColorComponentFlag;
    361     }
    362     if (fFlags & SkTable_ColorFilter::kG_Flag) {
    363         *validFlags &= ~kG_GrColorComponentFlag;
    364     }
    365     if (fFlags & SkTable_ColorFilter::kB_Flag) {
    366         *validFlags &= ~kB_GrColorComponentFlag;
    367     }
    368     if (fFlags & SkTable_ColorFilter::kA_Flag) {
    369         *validFlags &= ~kA_GrColorComponentFlag;
    370     }
    371 }
    372 
    373 
    374 ///////////////////////////////////////////////////////////////////////////////
    375 
    376 GR_DEFINE_EFFECT_TEST(ColorTableEffect);
    377 
    378 GrEffectRef* ColorTableEffect::TestCreate(SkMWCRandom* random,
    379                                           GrContext* context,
    380                                           const GrDrawTargetCaps&,
    381                                           GrTexture* textures[]) {
    382     static unsigned kAllFlags = SkTable_ColorFilter::kR_Flag | SkTable_ColorFilter::kG_Flag |
    383                                 SkTable_ColorFilter::kB_Flag | SkTable_ColorFilter::kA_Flag;
    384     return ColorTableEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], kAllFlags);
    385 }
    386 
    387 GrEffectRef* SkTable_ColorFilter::asNewEffect(GrContext* context) const {
    388     SkBitmap bitmap;
    389     GrEffectRef* effect = NULL;
    390     this->asComponentTable(&bitmap);
    391     // passing NULL because this effect does no tiling or filtering.
    392     GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, bitmap, NULL);
    393     if (NULL != texture) {
    394         effect = ColorTableEffect::Create(texture, fFlags);
    395 
    396         // Unlock immediately, this is not great, but we don't have a way of
    397         // knowing when else to unlock it currently. TODO: Remove this when
    398         // unref becomes the unlock replacement for all types of textures.
    399         GrUnlockAndUnrefCachedBitmapTexture(texture);
    400     }
    401     return effect;
    402 }
    403 
    404 #endif // SK_SUPPORT_GPU
    405 
    406 ///////////////////////////////////////////////////////////////////////////////
    407 
    408 #ifdef SK_CPU_BENDIAN
    409 #else
    410     #define SK_A32_INDEX    (3 - (SK_A32_SHIFT >> 3))
    411     #define SK_R32_INDEX    (3 - (SK_R32_SHIFT >> 3))
    412     #define SK_G32_INDEX    (3 - (SK_G32_SHIFT >> 3))
    413     #define SK_B32_INDEX    (3 - (SK_B32_SHIFT >> 3))
    414 #endif
    415 
    416 ///////////////////////////////////////////////////////////////////////////////
    417 
    418 SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) {
    419     return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table));
    420 }
    421 
    422 SkColorFilter* SkTableColorFilter::CreateARGB(const uint8_t tableA[256],
    423                                               const uint8_t tableR[256],
    424                                               const uint8_t tableG[256],
    425                                               const uint8_t tableB[256]) {
    426     return SkNEW_ARGS(SkTable_ColorFilter, (tableA, tableR, tableG, tableB));
    427 }
    428 
    429 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter)
    430     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter)
    431 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
    432