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