SkTableColorFilter.cpp revision 2eaaefd7e6a58339b3f93333f1e9cc92252cc303
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 "GrTBackendEffectFactory.h" 221#include "gl/GrGLEffect.h" 222#include "SkGr.h" 223 224class GLColorTableEffect; 225 226class ColorTableEffect : public GrEffect { 227public: 228 229 explicit ColorTableEffect(GrTexture* texture); 230 virtual ~ColorTableEffect(); 231 232 static const char* Name() { return "ColorTable"; } 233 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 234 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE; 235 236 virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE; 237 238 typedef GLColorTableEffect GLEffect; 239 240private: 241 GR_DECLARE_EFFECT_TEST; 242 243 GrTextureAccess fTextureAccess; 244 245 typedef GrEffect INHERITED; 246}; 247 248class GLColorTableEffect : public GrGLEffect { 249public: 250 GLColorTableEffect(const GrBackendEffectFactory& factory, 251 const GrEffect& effect); 252 253 virtual void emitCode(GrGLShaderBuilder*, 254 const GrEffectStage&, 255 EffectKey, 256 const char* vertexCoords, 257 const char* outputColor, 258 const char* inputColor, 259 const TextureSamplerArray&) SK_OVERRIDE; 260 261 virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE {} 262 263 static EffectKey GenKey(const GrEffectStage&, const GrGLCaps&); 264 265private: 266 267 typedef GrGLEffect INHERITED; 268}; 269 270GLColorTableEffect::GLColorTableEffect( 271 const GrBackendEffectFactory& factory, const GrEffect& effect) 272 : INHERITED(factory) { 273 } 274 275void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder, 276 const GrEffectStage&, 277 EffectKey, 278 const char* vertexCoords, 279 const char* outputColor, 280 const char* inputColor, 281 const TextureSamplerArray& samplers) { 282 283 static const float kColorScaleFactor = 255.0f / 256.0f; 284 static const float kColorOffsetFactor = 1.0f / 512.0f; 285 SkString* code = &builder->fFSCode; 286 if (NULL == inputColor) { 287 // the input color is solid white (all ones). 288 static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor; 289 code->appendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n", 290 kMaxValue, kMaxValue, kMaxValue, kMaxValue); 291 292 } else { 293 code->appendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor); 294 code->appendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor); 295 code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n", 296 kColorScaleFactor, 297 kColorOffsetFactor, kColorOffsetFactor, 298 kColorOffsetFactor, kColorOffsetFactor); 299 } 300 301 code->appendf("\t\t%s.a = ", outputColor); 302 builder->appendTextureLookup(code, samplers[0], "vec2(coord.a, 0.125)"); 303 code->append(";\n"); 304 305 code->appendf("\t\t%s.r = ", outputColor); 306 builder->appendTextureLookup(code, samplers[0], "vec2(coord.r, 0.375)"); 307 code->append(";\n"); 308 309 code->appendf("\t\t%s.g = ", outputColor); 310 builder->appendTextureLookup(code, samplers[0], "vec2(coord.g, 0.625)"); 311 code->append(";\n"); 312 313 code->appendf("\t\t%s.b = ", outputColor); 314 builder->appendTextureLookup(code, samplers[0], "vec2(coord.b, 0.875)"); 315 code->append(";\n"); 316 317 code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor); 318} 319 320GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrEffectStage&, const GrGLCaps&) { 321 return 0; 322} 323 324/////////////////////////////////////////////////////////////////////////////// 325 326ColorTableEffect::ColorTableEffect(GrTexture* texture) 327 : INHERITED(1) 328 , fTextureAccess(texture, "a") { 329} 330 331ColorTableEffect::~ColorTableEffect() { 332} 333 334const GrBackendEffectFactory& ColorTableEffect::getFactory() const { 335 return GrTBackendEffectFactory<ColorTableEffect>::getInstance(); 336} 337 338bool ColorTableEffect::isEqual(const GrEffect& sBase) const { 339 return INHERITED::isEqual(sBase); 340} 341 342const GrTextureAccess& ColorTableEffect::textureAccess(int index) const { 343 GrAssert(0 == index); 344 return fTextureAccess; 345} 346 347/////////////////////////////////////////////////////////////////////////////// 348 349GR_DEFINE_EFFECT_TEST(ColorTableEffect); 350 351GrEffect* ColorTableEffect::TestCreate(SkRandom* random, 352 GrContext* context, 353 GrTexture* textures[]) { 354 return SkNEW_ARGS(ColorTableEffect, (textures[GrEffectUnitTest::kAlphaTextureIdx])); 355} 356 357GrEffect* SkTable_ColorFilter::asNewEffect(GrContext* context) const { 358 SkBitmap bitmap; 359 this->asComponentTable(&bitmap); 360 // passing NULL because this effect does no tiling or filtering. 361 GrTexture* texture = GrLockCachedBitmapTexture(context, bitmap, NULL); 362 GrEffect* effect = SkNEW_ARGS(ColorTableEffect, (texture)); 363 364 // Unlock immediately, this is not great, but we don't have a way of 365 // knowing when else to unlock it currently. TODO: Remove this when 366 // unref becomes the unlock replacement for all types of textures. 367 GrUnlockCachedBitmapTexture(texture); 368 return effect; 369} 370 371#endif // SK_SUPPORT_GPU 372 373/////////////////////////////////////////////////////////////////////////////// 374 375#ifdef SK_CPU_BENDIAN 376#else 377 #define SK_A32_INDEX (3 - (SK_A32_SHIFT >> 3)) 378 #define SK_R32_INDEX (3 - (SK_R32_SHIFT >> 3)) 379 #define SK_G32_INDEX (3 - (SK_G32_SHIFT >> 3)) 380 #define SK_B32_INDEX (3 - (SK_B32_SHIFT >> 3)) 381#endif 382 383/////////////////////////////////////////////////////////////////////////////// 384 385SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) { 386 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table)); 387} 388 389SkColorFilter* SkTableColorFilter::CreateARGB(const uint8_t tableA[256], 390 const uint8_t tableR[256], 391 const uint8_t tableG[256], 392 const uint8_t tableB[256]) { 393 return SkNEW_ARGS(SkTable_ColorFilter, (tableA, tableR, tableG, tableB)); 394} 395 396SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter) 397 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter) 398SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 399