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