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 10class SkTable_ColorFilter : public SkColorFilter { 11public: 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 63protected: 64#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 65 SkTable_ColorFilter(SkReadBuffer& buffer); 66#endif 67 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; 68 69private: 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 80static 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 115void 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 160void SkTable_ColorFilter::toString(SkString* str) const { 161 str->append("SkTable_ColorFilter"); 162} 163#endif 164 165static 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 174void 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 184SkFlattenable* 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 231SkTable_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 251bool 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 284class GLColorTableEffect; 285 286class ColorTableEffect : public GrFragmentProcessor { 287public: 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 301private: 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 315class GLColorTableEffect : public GrGLFragmentProcessor { 316public: 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 331private: 332 333 typedef GrGLFragmentProcessor INHERITED; 334}; 335 336GLColorTableEffect::GLColorTableEffect(const GrBackendProcessorFactory& factory, const GrProcessor&) 337 : INHERITED(factory) { 338 } 339 340void 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 387ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags) 388 : fTextureAccess(texture, "a") 389 , fFlags(flags) { 390 this->addTextureAccess(&fTextureAccess); 391} 392 393ColorTableEffect::~ColorTableEffect() { 394} 395 396const GrBackendFragmentProcessorFactory& ColorTableEffect::getFactory() const { 397 return GrTBackendFragmentProcessorFactory<ColorTableEffect>::getInstance(); 398} 399 400bool ColorTableEffect::onIsEqual(const GrProcessor& sBase) const { 401 return this->texture(0) == sBase.texture(0); 402} 403 404void 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 424GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorTableEffect); 425 426GrFragmentProcessor* 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 435GrFragmentProcessor* 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 466SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) { 467 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table)); 468} 469 470SkColorFilter* 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 477SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter) 478 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter) 479SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 480