- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkTableColorFilter.cpp
1
2 #include "SkBitmap.h"
3 #include "SkTableColorFilter.h"
4 #include "SkColorPriv.h"
5 #include "SkFlattenableBuffers.h"
6 #include "SkUnPreMultiply.h"
7 #include "SkString.h"
8
9 class SkTable_ColorFilter : public SkColorFilter {
10 public:
11     SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
12                         const uint8_t tableG[], const uint8_t tableB[]) {
13         fBitmap = NULL;
14         fFlags = 0;
15
16         uint8_t* dst = fStorage;
17         if (tableA) {
18             memcpy(dst, tableA, 256);
19             dst += 256;
20             fFlags |= kA_Flag;
21         }
22         if (tableR) {
23             memcpy(dst, tableR, 256);
24             dst += 256;
25             fFlags |= kR_Flag;
26         }
27         if (tableG) {
28             memcpy(dst, tableG, 256);
29             dst += 256;
30             fFlags |= kG_Flag;
31         }
32         if (tableB) {
33             memcpy(dst, tableB, 256);
34             fFlags |= kB_Flag;
35         }
36     }
37
38     virtual ~SkTable_ColorFilter() {
39         SkDELETE(fBitmap);
40     }
41
42     virtual bool asComponentTable(SkBitmap* table) const SK_OVERRIDE;
43
44 #if SK_SUPPORT_GPU
45     virtual GrEffectRef* asNewEffect(GrContext* context) const SK_OVERRIDE;
46 #endif
47
48     virtual void filterSpan(const SkPMColor src[], int count,
49                             SkPMColor dst[]) const SK_OVERRIDE;
50
51     SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
52
53     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
54
55     enum {
56         kA_Flag = 1 << 0,
57         kR_Flag = 1 << 1,
58         kG_Flag = 1 << 2,
59         kB_Flag = 1 << 3,
60     };
61
62 protected:
63     SkTable_ColorFilter(SkFlattenableReadBuffer& buffer);
64     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
65
66 private:
67     mutable const SkBitmap* fBitmap; // lazily allocated
68
69     uint8_t fStorage[256 * 4];
70     unsigned fFlags;
71
72     typedef SkColorFilter INHERITED;
73 };
74
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
108 };
109
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;
119     }
120     if (fFlags & kR_Flag) {
121         tableR = table; table += 256;
122     }
123     if (fFlags & kG_Flag) {
124         tableG = table; table += 256;
125     }
126     if (fFlags & kB_Flag) {
127         tableB = table;
128     }
129
130     const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
131     for (int i = 0; i < count; ++i) {
132         SkPMColor c = src[i];
133         unsigned a, r, g, b;
134         if (0 == c) {
135             a = r = g = b = 0;
136         } else {
137             a = SkGetPackedA32(c);
138             r = SkGetPackedR32(c);
139             g = SkGetPackedG32(c);
140             b = SkGetPackedB32(c);
141
142             if (a < 255) {
143                 SkUnPreMultiply::Scale scale = scaleTable[a];
144                 r = SkUnPreMultiply::ApplyScale(scale, r);
145                 g = SkUnPreMultiply::ApplyScale(scale, g);
146                 b = SkUnPreMultiply::ApplyScale(scale, b);
147             }
148         }
149         dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r],
150                                          tableG[g], tableB[b]);
151     }
152 }
153
154 #ifdef SK_DEVELOPER
155 void SkTable_ColorFilter::toString(SkString* str) const {
156     str->append("SkTable_ColorFilter");
157 }
158 #endif
159
160 static const uint8_t gCountNibBits[] = {
161     0, 1, 1, 2,
162     1, 2, 2, 3,
163     1, 2, 2, 3,
164     2, 3, 3, 4
165 };
166
167 #include "SkPackBits.h"
168
169 void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
170     this->INHERITED::flatten(buffer);
171
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));
176
177 //    SkDebugf("raw %d packed %d\n", count * 256, size);
178
179     buffer.writeInt(fFlags);
180     buffer.writeByteArray(storage, size);
181 }
182
183 SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
184     fBitmap = NULL;
185
186     uint8_t storage[5*256];
187
188     fFlags = buffer.readInt();
189
190     size_t size = buffer.getArrayCount();
191     SkASSERT(size <= sizeof(storage));
192     buffer.readByteArray(storage, size);
193
194     SkDEBUGCODE(size_t raw = ) SkPackBits::Unpack8(storage, size, fStorage);
195
196     SkASSERT(raw <= sizeof(fStorage));
197     SkDEBUGCODE(size_t count = gCountNibBits[fFlags & 0xF]);
198     SkASSERT(raw == count * 256);
199 }
200
201 bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
202     if (table) {
203         if (NULL == fBitmap) {
204             SkBitmap* bmp = SkNEW(SkBitmap);
205             bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
206             bmp->allocPixels();
207             uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
208             int offset = 0;
209             static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
210
211             for (int x = 0; x < 4; ++x) {
212                 if (!(fFlags & kFlags[x])) {
213                     memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable));
214                 } else {
215                     memcpy(bitmapPixels, fStorage + offset, 256);
216                     offset += 256;
217                 }
218                 bitmapPixels += 256;
219             }
220             fBitmap = bmp;
221         }
222         *table = *fBitmap;
223     }
224     return true;
225 }
226
227 #if SK_SUPPORT_GPU
228
229 #include "GrEffect.h"
230 #include "GrTBackendEffectFactory.h"
231 #include "gl/GrGLEffect.h"
232 #include "SkGr.h"
233
234 class GLColorTableEffect;
235
236 class ColorTableEffect : public GrEffect {
237 public:
238     static GrEffectRef* Create(GrTexture* texture, unsigned flags) {
239         AutoEffectUnref effect(SkNEW_ARGS(ColorTableEffect, (texture, flags)));
240         return CreateEffectRef(effect);
241     }
242
243     virtual ~ColorTableEffect();
244
245     static const char* Name() { return "ColorTable"; }
246     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
247
248     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
249
250     typedef GLColorTableEffect GLEffect;
251
252 private:
253     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
254
255     explicit ColorTableEffect(GrTexture* texture, unsigned flags);
256
257     GR_DECLARE_EFFECT_TEST;
258
259     GrTextureAccess fTextureAccess;
260     unsigned        fFlags; // currently not used in shader code, just to assist
261                             // getConstantColorComponents().
262
263     typedef GrEffect INHERITED;
264 };
265
266 class GLColorTableEffect : public GrGLEffect {
267 public:
268     GLColorTableEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
269
270     virtual void emitCode(GrGLShaderBuilder*,
271                           const GrDrawEffect&,
272                           EffectKey,
273                           const char* outputColor,
274                           const char* inputColor,
275                           const TransformedCoordsArray&,
276                           const TextureSamplerArray&) SK_OVERRIDE;
277
278     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
279
280     static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
281
282 private:
283
284     typedef GrGLEffect INHERITED;
285 };
286
287 GLColorTableEffect::GLColorTableEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
288     : INHERITED(factory) {
289  }
290
291 void GLColorTableEffect::emitCode(GrGLShaderBuilder* builder,
292                                   const GrDrawEffect&,
293                                   EffectKey,
294                                   const char* outputColor,
295                                   const char* inputColor,
296                                   const TransformedCoordsArray&,
297                                   const TextureSamplerArray& samplers) {
298
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);
306
307     } else {
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",
311                               kColorScaleFactor,
312                               kColorOffsetFactor, kColorOffsetFactor,
313                               kColorOffsetFactor, kColorOffsetFactor);
314     }
315
316     builder->fsCodeAppendf("\t\t%s.a = ", outputColor);
317     builder->fsAppendTextureLookup(samplers[0], "vec2(coord.a, 0.125)");
318     builder->fsCodeAppend(";\n");
319
320     builder->fsCodeAppendf("\t\t%s.r = ", outputColor);
321     builder->fsAppendTextureLookup(samplers[0], "vec2(coord.r, 0.375)");
322     builder->fsCodeAppend(";\n");
323
324     builder->fsCodeAppendf("\t\t%s.g = ", outputColor);
325     builder->fsAppendTextureLookup(samplers[0], "vec2(coord.g, 0.625)");
326     builder->fsCodeAppend(";\n");
327
328     builder->fsCodeAppendf("\t\t%s.b = ", outputColor);
329     builder->fsAppendTextureLookup(samplers[0], "vec2(coord.b, 0.875)");
330     builder->fsCodeAppend(";\n");
331
332     builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
333 }
334
335 GrGLEffect::EffectKey GLColorTableEffect::GenKey(const GrDrawEffect&, const GrGLCaps&) {
336     return 0;
337 }
338
339 ///////////////////////////////////////////////////////////////////////////////
340
341 ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags)
342     : fTextureAccess(texture, "a")
343     , fFlags(flags) {
344     this->addTextureAccess(&fTextureAccess);
345 }
346
347 ColorTableEffect::~ColorTableEffect() {
348 }
349
350 const GrBackendEffectFactory&  ColorTableEffect::getFactory() const {
351     return GrTBackendEffectFactory<ColorTableEffect>::getInstance();
352 }
353
354 bool ColorTableEffect::onIsEqual(const GrEffect& sBase) const {
355     return this->texture(0) == sBase.texture(0);
356 }
357
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
360     // table.
361     if (fFlags & SkTable_ColorFilter::kR_Flag) {
362         *validFlags &= ~kR_GrColorComponentFlag;
363     }
364     if (fFlags & SkTable_ColorFilter::kG_Flag) {
365         *validFlags &= ~kG_GrColorComponentFlag;
366     }
367     if (fFlags & SkTable_ColorFilter::kB_Flag) {
368         *validFlags &= ~kB_GrColorComponentFlag;
369     }
370     if (fFlags & SkTable_ColorFilter::kA_Flag) {
371         *validFlags &= ~kA_GrColorComponentFlag;
372     }
373 }
374
375
376 ///////////////////////////////////////////////////////////////////////////////
377
378 GR_DEFINE_EFFECT_TEST(ColorTableEffect);
379
380 GrEffectRef* ColorTableEffect::TestCreate(SkRandom* random,
381                                           GrContext* context,
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);
387 }
388
389 GrEffectRef* SkTable_ColorFilter::asNewEffect(GrContext* context) const {
390     SkBitmap bitmap;
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);
397
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);
402     }
403     return effect;
404 }
405
406 #endif // SK_SUPPORT_GPU
407
408 ///////////////////////////////////////////////////////////////////////////////
409
410 #ifdef SK_CPU_BENDIAN
411 #else
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))
416 #endif
417
418 ///////////////////////////////////////////////////////////////////////////////
419
420 SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) {
421     return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table));
422 }
423
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));
429 }
430
431 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter)
432     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter)
433 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END