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