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