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