SkTableColorFilter.cpp revision 7c157a988845fb00f9024d6db6dda142c3458033
1/* 2* Copyright 2015 Google Inc. 3* 4* Use of this source code is governed by a BSD-style license that can be 5* found in the LICENSE file. 6*/ 7 8#include "SkBitmap.h" 9#include "SkTableColorFilter.h" 10#include "SkColorPriv.h" 11#include "SkReadBuffer.h" 12#include "SkWriteBuffer.h" 13#include "SkUnPreMultiply.h" 14#include "SkString.h" 15 16class SkTable_ColorFilter : public SkColorFilter { 17public: 18 SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[], 19 const uint8_t tableG[], const uint8_t tableB[]) { 20 fBitmap = NULL; 21 fFlags = 0; 22 23 uint8_t* dst = fStorage; 24 if (tableA) { 25 memcpy(dst, tableA, 256); 26 dst += 256; 27 fFlags |= kA_Flag; 28 } 29 if (tableR) { 30 memcpy(dst, tableR, 256); 31 dst += 256; 32 fFlags |= kR_Flag; 33 } 34 if (tableG) { 35 memcpy(dst, tableG, 256); 36 dst += 256; 37 fFlags |= kG_Flag; 38 } 39 if (tableB) { 40 memcpy(dst, tableB, 256); 41 fFlags |= kB_Flag; 42 } 43 } 44 45 virtual ~SkTable_ColorFilter() { 46 SkDELETE(fBitmap); 47 } 48 49 bool asComponentTable(SkBitmap* table) const override; 50 SkColorFilter* newComposed(const SkColorFilter* inner) const override; 51 52#if SK_SUPPORT_GPU 53 bool asFragmentProcessors(GrContext*, GrProcessorDataManager*, 54 SkTDArray<GrFragmentProcessor*>*) const override; 55#endif 56 57 void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override; 58 59 SK_TO_STRING_OVERRIDE() 60 61 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter) 62 63 enum { 64 kA_Flag = 1 << 0, 65 kR_Flag = 1 << 1, 66 kG_Flag = 1 << 2, 67 kB_Flag = 1 << 3, 68 }; 69 70protected: 71 void flatten(SkWriteBuffer&) const override; 72 73private: 74 mutable const SkBitmap* fBitmap; // lazily allocated 75 76 uint8_t fStorage[256 * 4]; 77 unsigned fFlags; 78 79 friend class SkTableColorFilter; 80 81 typedef SkColorFilter INHERITED; 82}; 83 84static const uint8_t gIdentityTable[] = { 85 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 86 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 87 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 88 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 89 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 90 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 91 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 92 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 93 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 94 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 95 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 96 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 97 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 98 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 99 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 100 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 101 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 102 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 103 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 104 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 105 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 106 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 107 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 108 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 109 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 110 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 111 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 112 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 113 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 114 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 115 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 116 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF 117}; 118 119void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const { 120 const uint8_t* table = fStorage; 121 const uint8_t* tableA = gIdentityTable; 122 const uint8_t* tableR = gIdentityTable; 123 const uint8_t* tableG = gIdentityTable; 124 const uint8_t* tableB = gIdentityTable; 125 if (fFlags & kA_Flag) { 126 tableA = table; table += 256; 127 } 128 if (fFlags & kR_Flag) { 129 tableR = table; table += 256; 130 } 131 if (fFlags & kG_Flag) { 132 tableG = table; table += 256; 133 } 134 if (fFlags & kB_Flag) { 135 tableB = table; 136 } 137 138 const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable(); 139 for (int i = 0; i < count; ++i) { 140 SkPMColor c = src[i]; 141 unsigned a, r, g, b; 142 if (0 == c) { 143 a = r = g = b = 0; 144 } else { 145 a = SkGetPackedA32(c); 146 r = SkGetPackedR32(c); 147 g = SkGetPackedG32(c); 148 b = SkGetPackedB32(c); 149 150 if (a < 255) { 151 SkUnPreMultiply::Scale scale = scaleTable[a]; 152 r = SkUnPreMultiply::ApplyScale(scale, r); 153 g = SkUnPreMultiply::ApplyScale(scale, g); 154 b = SkUnPreMultiply::ApplyScale(scale, b); 155 } 156 } 157 dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r], 158 tableG[g], tableB[b]); 159 } 160} 161 162#ifndef SK_IGNORE_TO_STRING 163void SkTable_ColorFilter::toString(SkString* str) const { 164 const uint8_t* table = fStorage; 165 const uint8_t* tableA = gIdentityTable; 166 const uint8_t* tableR = gIdentityTable; 167 const uint8_t* tableG = gIdentityTable; 168 const uint8_t* tableB = gIdentityTable; 169 if (fFlags & kA_Flag) { 170 tableA = table; table += 256; 171 } 172 if (fFlags & kR_Flag) { 173 tableR = table; table += 256; 174 } 175 if (fFlags & kG_Flag) { 176 tableG = table; table += 256; 177 } 178 if (fFlags & kB_Flag) { 179 tableB = table; 180 } 181 182 str->append("SkTable_ColorFilter ("); 183 184 for (int i = 0; i < 256; ++i) { 185 str->appendf("%d: %d,%d,%d,%d\n", 186 i, tableR[i], tableG[i], tableB[i], tableA[i]); 187 } 188 189 str->append(")"); 190} 191#endif 192 193static const uint8_t gCountNibBits[] = { 194 0, 1, 1, 2, 195 1, 2, 2, 3, 196 1, 2, 2, 3, 197 2, 3, 3, 4 198}; 199 200#include "SkPackBits.h" 201 202void SkTable_ColorFilter::flatten(SkWriteBuffer& buffer) const { 203 uint8_t storage[5*256]; 204 int count = gCountNibBits[fFlags & 0xF]; 205 size_t size = SkPackBits::Pack8(fStorage, count * 256, storage, 206 sizeof(storage)); 207 208 buffer.write32(fFlags); 209 buffer.writeByteArray(storage, size); 210} 211 212SkFlattenable* SkTable_ColorFilter::CreateProc(SkReadBuffer& buffer) { 213 const int flags = buffer.read32(); 214 const size_t count = gCountNibBits[flags & 0xF]; 215 SkASSERT(count <= 4); 216 217 uint8_t packedStorage[5*256]; 218 size_t packedSize = buffer.getArrayCount(); 219 if (!buffer.validate(packedSize <= sizeof(packedStorage))) { 220 return NULL; 221 } 222 if (!buffer.readByteArray(packedStorage, packedSize)) { 223 return NULL; 224 } 225 226 uint8_t unpackedStorage[4*256]; 227 size_t unpackedSize = SkPackBits::Unpack8(packedStorage, packedSize, 228 unpackedStorage, sizeof(unpackedStorage)); 229 // now check that we got the size we expected 230 if (!buffer.validate(unpackedSize == count*256)) { 231 return NULL; 232 } 233 234 const uint8_t* a = NULL; 235 const uint8_t* r = NULL; 236 const uint8_t* g = NULL; 237 const uint8_t* b = NULL; 238 const uint8_t* ptr = unpackedStorage; 239 240 if (flags & kA_Flag) { 241 a = ptr; 242 ptr += 256; 243 } 244 if (flags & kR_Flag) { 245 r = ptr; 246 ptr += 256; 247 } 248 if (flags & kG_Flag) { 249 g = ptr; 250 ptr += 256; 251 } 252 if (flags & kB_Flag) { 253 b = ptr; 254 ptr += 256; 255 } 256 return SkTableColorFilter::CreateARGB(a, r, g, b); 257} 258 259bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const { 260 if (table) { 261 if (NULL == fBitmap) { 262 SkBitmap* bmp = SkNEW(SkBitmap); 263 bmp->allocPixels(SkImageInfo::MakeA8(256, 4)); 264 uint8_t* bitmapPixels = bmp->getAddr8(0, 0); 265 int offset = 0; 266 static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag }; 267 268 for (int x = 0; x < 4; ++x) { 269 if (!(fFlags & kFlags[x])) { 270 memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable)); 271 } else { 272 memcpy(bitmapPixels, fStorage + offset, 256); 273 offset += 256; 274 } 275 bitmapPixels += 256; 276 } 277 fBitmap = bmp; 278 } 279 *table = *fBitmap; 280 } 281 return true; 282} 283 284// Combines the two lookup tables so that making a lookup using res[] has 285// the same effect as making a lookup through inner[] then outer[]. 286static void combine_tables(uint8_t res[256], const uint8_t outer[256], const uint8_t inner[256]) { 287 for (int i = 0; i < 256; i++) { 288 res[i] = outer[inner[i]]; 289 } 290} 291 292SkColorFilter* SkTable_ColorFilter::newComposed(const SkColorFilter* innerFilter) const { 293 SkBitmap innerBM; 294 if (!innerFilter->asComponentTable(&innerBM)) { 295 return NULL; 296 } 297 298 innerBM.lockPixels(); 299 if (NULL == innerBM.getPixels()) { 300 return NULL; 301 } 302 303 const uint8_t* table = fStorage; 304 const uint8_t* tableA = gIdentityTable; 305 const uint8_t* tableR = gIdentityTable; 306 const uint8_t* tableG = gIdentityTable; 307 const uint8_t* tableB = gIdentityTable; 308 if (fFlags & kA_Flag) { 309 tableA = table; table += 256; 310 } 311 if (fFlags & kR_Flag) { 312 tableR = table; table += 256; 313 } 314 if (fFlags & kG_Flag) { 315 tableG = table; table += 256; 316 } 317 if (fFlags & kB_Flag) { 318 tableB = table; 319 } 320 321 uint8_t concatA[256]; 322 uint8_t concatR[256]; 323 uint8_t concatG[256]; 324 uint8_t concatB[256]; 325 326 combine_tables(concatA, tableA, innerBM.getAddr8(0, 0)); 327 combine_tables(concatR, tableR, innerBM.getAddr8(0, 1)); 328 combine_tables(concatG, tableG, innerBM.getAddr8(0, 2)); 329 combine_tables(concatB, tableB, innerBM.getAddr8(0, 3)); 330 331 return SkTableColorFilter::CreateARGB(concatA, concatR, concatG, concatB); 332} 333 334#if SK_SUPPORT_GPU 335 336#include "GrFragmentProcessor.h" 337#include "GrInvariantOutput.h" 338#include "SkGr.h" 339#include "effects/GrTextureStripAtlas.h" 340#include "gl/GrGLFragmentProcessor.h" 341#include "gl/builders/GrGLProgramBuilder.h" 342 343class ColorTableEffect : public GrFragmentProcessor { 344public: 345 static GrFragmentProcessor* Create(GrContext* context, SkBitmap bitmap, unsigned flags); 346 347 virtual ~ColorTableEffect(); 348 349 const char* name() const override { return "ColorTable"; } 350 351 void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 352 353 GrGLFragmentProcessor* createGLInstance() const override; 354 355 const GrTextureStripAtlas* atlas() const { return fAtlas; } 356 int atlasRow() const { return fRow; } 357 358private: 359 bool onIsEqual(const GrFragmentProcessor&) const override; 360 361 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 362 363 ColorTableEffect(GrTexture* texture, GrTextureStripAtlas* atlas, int row, unsigned flags); 364 365 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 366 367 GrTextureAccess fTextureAccess; 368 369 // currently not used in shader code, just to assist onComputeInvariantOutput(). 370 unsigned fFlags; 371 372 GrTextureStripAtlas* fAtlas; 373 int fRow; 374 375 typedef GrFragmentProcessor INHERITED; 376}; 377 378class GLColorTableEffect : public GrGLFragmentProcessor { 379public: 380 GLColorTableEffect(const GrProcessor&); 381 382 virtual void emitCode(EmitArgs&) override; 383 384 void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 385 386 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {} 387 388private: 389 UniformHandle fRGBAYValuesUni; 390 typedef GrGLFragmentProcessor INHERITED; 391}; 392 393GLColorTableEffect::GLColorTableEffect(const GrProcessor&) { 394} 395 396void GLColorTableEffect::setData(const GrGLProgramDataManager& pdm, const GrProcessor& proc) { 397 // The textures are organized in a strip where the rows are ordered a, r, g, b. 398 float rgbaYValues[4]; 399 const ColorTableEffect& cte = proc.cast<ColorTableEffect>(); 400 if (cte.atlas()) { 401 SkScalar yDelta = cte.atlas()->getNormalizedTexelHeight(); 402 rgbaYValues[3] = cte.atlas()->getYOffset(cte.atlasRow()) + SK_ScalarHalf * yDelta; 403 rgbaYValues[0] = rgbaYValues[3] + yDelta; 404 rgbaYValues[1] = rgbaYValues[0] + yDelta; 405 rgbaYValues[2] = rgbaYValues[1] + yDelta; 406 } else { 407 rgbaYValues[3] = 0.125; 408 rgbaYValues[0] = 0.375; 409 rgbaYValues[1] = 0.625; 410 rgbaYValues[2] = 0.875; 411 } 412 pdm.set4fv(fRGBAYValuesUni, 1, rgbaYValues); 413} 414 415void GLColorTableEffect::emitCode(EmitArgs& args) { 416 const char* yoffsets; 417 fRGBAYValuesUni = args.fBuilder->addUniform(GrGLFPBuilder::kFragment_Visibility, 418 kVec4f_GrSLType, kDefault_GrSLPrecision, 419 "yoffsets", &yoffsets); 420 static const float kColorScaleFactor = 255.0f / 256.0f; 421 static const float kColorOffsetFactor = 1.0f / 512.0f; 422 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); 423 if (NULL == args.fInputColor) { 424 // the input color is solid white (all ones). 425 static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor; 426 fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n", 427 kMaxValue, kMaxValue, kMaxValue, kMaxValue); 428 429 } else { 430 fsBuilder->codeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor); 431 fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", 432 args.fInputColor); 433 fsBuilder->codeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n", 434 kColorScaleFactor, 435 kColorOffsetFactor, kColorOffsetFactor, 436 kColorOffsetFactor, kColorOffsetFactor); 437 } 438 439 SkString coord; 440 441 fsBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor); 442 coord.printf("vec2(coord.a, %s.a)", yoffsets); 443 fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str()); 444 fsBuilder->codeAppend(";\n"); 445 446 fsBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor); 447 coord.printf("vec2(coord.r, %s.r)", yoffsets); 448 fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str()); 449 fsBuilder->codeAppend(";\n"); 450 451 fsBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor); 452 coord.printf("vec2(coord.g, %s.g)", yoffsets); 453 fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str()); 454 fsBuilder->codeAppend(";\n"); 455 456 fsBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor); 457 coord.printf("vec2(coord.b, %s.b)", yoffsets); 458 fsBuilder->appendTextureLookup(args.fSamplers[0], coord.c_str()); 459 fsBuilder->codeAppend(";\n"); 460 461 fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", args.fOutputColor, args.fOutputColor); 462} 463 464/////////////////////////////////////////////////////////////////////////////// 465GrFragmentProcessor* ColorTableEffect::Create(GrContext* context, SkBitmap bitmap, unsigned flags) { 466 467 GrTextureStripAtlas::Desc desc; 468 desc.fWidth = bitmap.width(); 469 desc.fHeight = 128; 470 desc.fRowHeight = bitmap.height(); 471 desc.fContext = context; 472 desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); 473 GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(desc); 474 int row = atlas->lockRow(bitmap); 475 SkAutoTUnref<GrTexture> texture; 476 if (-1 == row) { 477 atlas = NULL; 478 // Passing params=NULL because this effect does no tiling or filtering. 479 texture.reset(GrRefCachedBitmapTexture(context, bitmap, NULL)); 480 } else { 481 texture.reset(SkRef(atlas->getTexture())); 482 } 483 484 return SkNEW_ARGS(ColorTableEffect, (texture, atlas, row, flags)); 485} 486 487ColorTableEffect::ColorTableEffect(GrTexture* texture, GrTextureStripAtlas* atlas, int row, 488 unsigned flags) 489 : fTextureAccess(texture, "a") 490 , fFlags(flags) 491 , fAtlas(atlas) 492 , fRow(row) { 493 this->initClassID<ColorTableEffect>(); 494 this->addTextureAccess(&fTextureAccess); 495} 496 497ColorTableEffect::~ColorTableEffect() { 498 if (fAtlas) { 499 fAtlas->unlockRow(fRow); 500 } 501} 502 503void ColorTableEffect::getGLProcessorKey(const GrGLSLCaps& caps, 504 GrProcessorKeyBuilder* b) const { 505 GLColorTableEffect::GenKey(*this, caps, b); 506} 507 508GrGLFragmentProcessor* ColorTableEffect::createGLInstance() const { 509 return SkNEW_ARGS(GLColorTableEffect, (*this)); 510} 511 512bool ColorTableEffect::onIsEqual(const GrFragmentProcessor& other) const { 513 // For non-atlased instances, the texture (compared by base class) is sufficient to 514 // differentiate different tables. For atlased instances we ensure they are using the 515 // same row. 516 const ColorTableEffect& that = other.cast<ColorTableEffect>(); 517 SkASSERT(SkToBool(fAtlas) == SkToBool(that.fAtlas)); 518 // Ok to always do this comparison since both would be -1 if non-atlased. 519 return fRow == that.fRow; 520} 521 522void ColorTableEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 523 // If we kept the table in the effect then we could actually run known inputs through the 524 // table. 525 uint8_t invalidateFlags = 0; 526 if (fFlags & SkTable_ColorFilter::kR_Flag) { 527 invalidateFlags |= kR_GrColorComponentFlag; 528 } 529 if (fFlags & SkTable_ColorFilter::kG_Flag) { 530 invalidateFlags |= kG_GrColorComponentFlag; 531 } 532 if (fFlags & SkTable_ColorFilter::kB_Flag) { 533 invalidateFlags |= kB_GrColorComponentFlag; 534 } 535 if (fFlags & SkTable_ColorFilter::kA_Flag) { 536 invalidateFlags |= kA_GrColorComponentFlag; 537 } 538 inout->invalidateComponents(invalidateFlags, GrInvariantOutput::kWill_ReadInput); 539} 540 541/////////////////////////////////////////////////////////////////////////////// 542 543GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorTableEffect); 544 545GrFragmentProcessor* ColorTableEffect::TestCreate(GrProcessorTestData* d) { 546 int flags = 0; 547 uint8_t luts[256][4]; 548 do { 549 for (int i = 0; i < 4; ++i) { 550 flags |= d->fRandom->nextBool() ? (1 << i): 0; 551 } 552 } while (!flags); 553 for (int i = 0; i < 4; ++i) { 554 if (flags & (1 << i)) { 555 for (int j = 0; j < 256; ++j) { 556 luts[j][i] = SkToU8(d->fRandom->nextBits(8)); 557 } 558 } 559 } 560 SkAutoTUnref<SkColorFilter> filter(SkTableColorFilter::CreateARGB( 561 (flags & (1 << 0)) ? luts[0] : NULL, 562 (flags & (1 << 1)) ? luts[1] : NULL, 563 (flags & (1 << 2)) ? luts[2] : NULL, 564 (flags & (1 << 3)) ? luts[3] : NULL 565 )); 566 567 SkTDArray<GrFragmentProcessor*> array; 568 if (filter->asFragmentProcessors(d->fContext, d->fProcDataManager, &array)) { 569 SkASSERT(1 == array.count()); // TableColorFilter only returns 1 570 return array[0]; 571 } 572 return NULL; 573} 574 575bool SkTable_ColorFilter::asFragmentProcessors(GrContext* context, 576 GrProcessorDataManager*, 577 SkTDArray<GrFragmentProcessor*>* array) const { 578 SkBitmap bitmap; 579 this->asComponentTable(&bitmap); 580 581 GrFragmentProcessor* frag = ColorTableEffect::Create(context, bitmap, fFlags); 582 if (frag) { 583 if (array) { 584 *array->append() = frag; 585 } else { 586 frag->unref(); 587 SkDEBUGCODE(frag = NULL;) 588 } 589 return true; 590 } 591 return false; 592} 593 594#endif // SK_SUPPORT_GPU 595 596/////////////////////////////////////////////////////////////////////////////// 597 598#ifdef SK_CPU_BENDIAN 599#else 600 #define SK_A32_INDEX (3 - (SK_A32_SHIFT >> 3)) 601 #define SK_R32_INDEX (3 - (SK_R32_SHIFT >> 3)) 602 #define SK_G32_INDEX (3 - (SK_G32_SHIFT >> 3)) 603 #define SK_B32_INDEX (3 - (SK_B32_SHIFT >> 3)) 604#endif 605 606/////////////////////////////////////////////////////////////////////////////// 607 608SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) { 609 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table)); 610} 611 612SkColorFilter* SkTableColorFilter::CreateARGB(const uint8_t tableA[256], 613 const uint8_t tableR[256], 614 const uint8_t tableG[256], 615 const uint8_t tableB[256]) { 616 return SkNEW_ARGS(SkTable_ColorFilter, (tableA, tableR, tableG, tableB)); 617} 618 619SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter) 620 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter) 621SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 622