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