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