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