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