3 #include "SkTableColorFilter.h"
4 #include "SkColorPriv.h"
5 #include "SkFlattenableBuffers.h"
6 #include "SkUnPreMultiply.h"
9 class SkTable_ColorFilter : public SkColorFilter {
11 SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
12 const uint8_t tableG[], const uint8_t tableB[]) {
16 uint8_t* dst = fStorage;
18 memcpy(dst, tableA, 256);
23 memcpy(dst, tableR, 256);
28 memcpy(dst, tableG, 256);
33 memcpy(dst, tableB, 256);
38 virtual ~SkTable_ColorFilter() {
42 virtual bool asComponentTable(SkBitmap* table) const SK_OVERRIDE;
45 virtual GrEffectRef* asNewEffect(GrContext* context) const SK_OVERRIDE;
48 virtual void filterSpan(const SkPMColor src[], int count,
49 SkPMColor dst[]) const SK_OVERRIDE;
51 SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
53 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
63 SkTable_ColorFilter(SkFlattenableReadBuffer& buffer);
64 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
67 mutable const SkBitmap* fBitmap; // lazily allocated
69 uint8_t fStorage[256 * 4];
72 typedef SkColorFilter INHERITED;
75 static const uint8_t gIdentityTable[] = {
76 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
77 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
78 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
79 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
80 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
81 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
82 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
83 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
84 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
85 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
86 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
87 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
88 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
89 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
90 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
91 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
92 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
93 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
94 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
95 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
96 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
97 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
98 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
99 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
100 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
101 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
102 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
103 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
104 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
105 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
106 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
107 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
110 void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count,
111 SkPMColor dst[]) const {
112 const uint8_t* table = fStorage;
113 const uint8_t* tableA = gIdentityTable;
114 const uint8_t* tableR = gIdentityTable;
115 const uint8_t* tableG = gIdentityTable;
116 const uint8_t* tableB = gIdentityTable;
117 if (fFlags & kA_Flag) {
118 tableA = table; table += 256;
120 if (fFlags & kR_Flag) {
121 tableR = table; table += 256;
123 if (fFlags & kG_Flag) {
124 tableG = table; table += 256;
126 if (fFlags & kB_Flag) {
130 const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
131 for (int i = 0; i < count; ++i) {
132 SkPMColor c = src[i];
137 a = SkGetPackedA32(c);
138 r = SkGetPackedR32(c);
139 g = SkGetPackedG32(c);
140 b = SkGetPackedB32(c);
143 SkUnPreMultiply::Scale scale = scaleTable[a];
144 r = SkUnPreMultiply::ApplyScale(scale, r);
145 g = SkUnPreMultiply::ApplyScale(scale, g);
146 b = SkUnPreMultiply::ApplyScale(scale, b);
149 dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r],
150 tableG[g], tableB[b]);
155 void SkTable_ColorFilter::toString(SkString* str) const {
156 str->append("SkTable_ColorFilter");
160 static const uint8_t gCountNibBits[] = {
167 #include "SkPackBits.h"
169 void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
170 this->INHERITED::flatten(buffer);
172 uint8_t storage[5*256];
173 int count = gCountNibBits[fFlags & 0xF];
174 size_t size = SkPackBits::Pack8(fStorage, count * 256, storage);
175 SkASSERT(size <= sizeof(storage));
177 // SkDebugf("raw %d packed %d\n", count * 256, size);
179 buffer.writeInt(fFlags);
180 buffer.writeByteArray(storage, size);
183 SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
186 uint8_t storage[5*256];
188 fFlags = buffer.readInt();
190 size_t size = buffer.getArrayCount();
191 SkASSERT(size <= sizeof(storage));
192 buffer.readByteArray(storage, size);
194 SkDEBUGCODE(size_t raw = ) SkPackBits::Unpack8(storage, size, fStorage);
196 SkASSERT(raw <= sizeof(fStorage));
197 SkDEBUGCODE(size_t count = gCountNibBits[fFlags & 0xF]);
198 SkASSERT(raw == count * 256);
201 bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
203 if (NULL == fBitmap) {
204 SkBitmap* bmp = SkNEW(SkBitmap);
205 bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
207 uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
209 static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
211 for (int x = 0; x < 4; ++x) {
212 if (!(fFlags & kFlags[x])) {
213 memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable));
215 memcpy(bitmapPixels, fStorage + offset, 256);
229 #include "GrEffect.h"
230 #include "GrTBackendEffectFactory.h"
231 #include "gl/GrGLEffect.h"
234 class GLColorTableEffect;
236 class ColorTableEffect : public GrEffect {
238 static GrEffectRef* Create(GrTexture* texture, unsigned flags) {
239 AutoEffectUnref effect(SkNEW_ARGS(ColorTableEffect, (texture, flags)));
240 return CreateEffectRef(effect);
243 virtual ~ColorTableEffect();
245 static const char* Name() { return "ColorTable"; }
246 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
248 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
250 typedef GLColorTableEffect GLEffect;
253 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
255 explicit ColorTableEffect(GrTexture* texture, unsigned flags);
257 GR_DECLARE_EFFECT_TEST;
259 GrTextureAccess fTextureAccess;
260 unsigned fFlags; // currently not used in shader code, just to assist
261 // getConstantColorComponents().
263 typedef GrEffect INHERITED;
266 class GLColorTableEffect : public GrGLEffect {
268 GLColorTableEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
270 virtual void emitCode(GrGLShaderBuilder*,
273 const char* outputColor,
274 const char* inputColor,
275 const TransformedCoordsArray&,
276 const TextureSamplerArray&) SK_OVERRIDE;
278 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
280 static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
284 typedef GrGLEffect INHERITED;
287 GLColorTableEffect::GLColorTableEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
288 : INHERITED(factory) {
291 void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder,
294 const char* outputColor,
295 const char* inputColor,
296 const TransformedCoordsArray&,
297 const TextureSamplerArray& samplers) {
299 static const float kColorScaleFactor = 255.0f / 256.0f;
300 static const float kColorOffsetFactor = 1.0f / 512.0f;
301 if (NULL == inputColor) {
302 // the input color is solid white (all ones).
303 static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
304 builder->fsCodeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n",
305 kMaxValue, kMaxValue, kMaxValue, kMaxValue);
308 builder->fsCodeAppendf("\t\tfloat nonZeroAlpha = max(%s.a, .0001);\n", inputColor);
309 builder->fsCodeAppendf("\t\tvec4 coord = vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n", inputColor);
310 builder->fsCodeAppendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
312 kColorOffsetFactor, kColorOffsetFactor,
313 kColorOffsetFactor, kColorOffsetFactor);
316 builder->fsCodeAppendf("\t\t%s.a = ", outputColor);
317 builder->fsAppendTextureLookup(samplers[0], "vec2(coord.a, 0.125)");
318 builder->fsCodeAppend(";\n");
320 builder->fsCodeAppendf("\t\t%s.r = ", outputColor);
321 builder->fsAppendTextureLookup(samplers[0], "vec2(coord.r, 0.375)");
322 builder->fsCodeAppend(";\n");
324 builder->fsCodeAppendf("\t\t%s.g = ", outputColor);
325 builder->fsAppendTextureLookup(samplers[0], "vec2(coord.g, 0.625)");
326 builder->fsCodeAppend(";\n");
328 builder->fsCodeAppendf("\t\t%s.b = ", outputColor);
329 builder->fsAppendTextureLookup(samplers[0], "vec2(coord.b, 0.875)");
330 builder->fsCodeAppend(";\n");
332 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
335 GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrDrawEffect&, const GrGLCaps&) {
339 ///////////////////////////////////////////////////////////////////////////////
341 ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags)
342 : fTextureAccess(texture, "a")
344 this->addTextureAccess(&fTextureAccess);
347 ColorTableEffect::~ColorTableEffect() {
350 const GrBackendEffectFactory& ColorTableEffect::getFactory() const {
351 return GrTBackendEffectFactory<ColorTableEffect>::getInstance();
354 bool ColorTableEffect::onIsEqual(const GrEffect& sBase) const {
355 return this->texture(0) == sBase.texture(0);
358 void ColorTableEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
359 // If we kept the table in the effect then we could actually run known inputs through the
361 if (fFlags & SkTable_ColorFilter::kR_Flag) {
362 *validFlags &= ~kR_GrColorComponentFlag;
364 if (fFlags & SkTable_ColorFilter::kG_Flag) {
365 *validFlags &= ~kG_GrColorComponentFlag;
367 if (fFlags & SkTable_ColorFilter::kB_Flag) {
368 *validFlags &= ~kB_GrColorComponentFlag;
370 if (fFlags & SkTable_ColorFilter::kA_Flag) {
371 *validFlags &= ~kA_GrColorComponentFlag;
376 ///////////////////////////////////////////////////////////////////////////////
378 GR_DEFINE_EFFECT_TEST(ColorTableEffect);
380 GrEffectRef* ColorTableEffect::TestCreate(SkRandom* random,
382 const GrDrawTargetCaps&,
383 GrTexture* textures[]) {
384 static unsigned kAllFlags = SkTable_ColorFilter::kR_Flag | SkTable_ColorFilter::kG_Flag |
385 SkTable_ColorFilter::kB_Flag | SkTable_ColorFilter::kA_Flag;
386 return ColorTableEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], kAllFlags);
389 GrEffectRef* SkTable_ColorFilter::asNewEffect(GrContext* context) const {
391 GrEffectRef* effect = NULL;
392 this->asComponentTable(&bitmap);
393 // passing NULL because this effect does no tiling or filtering.
394 GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, bitmap, NULL);
395 if (NULL != texture) {
396 effect = ColorTableEffect::Create(texture, fFlags);
398 // Unlock immediately, this is not great, but we don't have a way of
399 // knowing when else to unlock it currently. TODO: Remove this when
400 // unref becomes the unlock replacement for all types of textures.
401 GrUnlockAndUnrefCachedBitmapTexture(texture);
406 #endif // SK_SUPPORT_GPU
408 ///////////////////////////////////////////////////////////////////////////////
410 #ifdef SK_CPU_BENDIAN
412 #define SK_A32_INDEX (3 - (SK_A32_SHIFT >> 3))
413 #define SK_R32_INDEX (3 - (SK_R32_SHIFT >> 3))
414 #define SK_G32_INDEX (3 - (SK_G32_SHIFT >> 3))
415 #define SK_B32_INDEX (3 - (SK_B32_SHIFT >> 3))
418 ///////////////////////////////////////////////////////////////////////////////
420 SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) {
421 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table));
424 SkColorFilter* SkTableColorFilter::CreateARGB(const uint8_t tableA[256],
425 const uint8_t tableR[256],
426 const uint8_t tableG[256],
427 const uint8_t tableB[256]) {
428 return SkNEW_ARGS(SkTable_ColorFilter, (tableA, tableR, tableG, tableB));
431 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter)
432 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter)
433 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END