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