blob: 88b4a4bf4bbfe9ea366cb46bdbe2b8ed64142c3c [file] [log] [blame]
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00001
reed@google.com02f65f22012-08-06 21:20:05 +00002#include "SkBitmap.h"
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +00003#include "SkTableColorFilter.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00004#include "SkColorPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +00005#include "SkReadBuffer.h"
6#include "SkWriteBuffer.h"
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +00007#include "SkUnPreMultiply.h"
robertphillips@google.com1202c2a2013-05-23 14:00:17 +00008#include "SkString.h"
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +00009
10class SkTable_ColorFilter : public SkColorFilter {
11public:
12 SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
13 const uint8_t tableG[], const uint8_t tableB[]) {
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000014 fBitmap = NULL;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000015 fFlags = 0;
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000016
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000017 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
tomhudson@google.com1bb4be22012-07-24 17:24:21 +000039 virtual ~SkTable_ColorFilter() {
40 SkDELETE(fBitmap);
41 }
42
bsalomon@google.comb2ad1012012-10-17 15:00:32 +000043 virtual bool asComponentTable(SkBitmap* table) const SK_OVERRIDE;
44
45#if SK_SUPPORT_GPU
joshualittb0a8a372014-09-23 09:50:21 -070046 virtual GrFragmentProcessor* asFragmentProcessor(GrContext* context) const SK_OVERRIDE;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +000047#endif
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000048
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000049 virtual void filterSpan(const SkPMColor src[], int count,
reed@google.combada6442012-12-17 20:21:44 +000050 SkPMColor dst[]) const SK_OVERRIDE;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000051
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +000052 SK_TO_STRING_OVERRIDE()
robertphillips@google.com1202c2a2013-05-23 14:00:17 +000053
djsollen@google.comba28d032012-03-26 17:57:35 +000054 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000055
bsalomon@google.com371e1052013-01-11 21:08:55 +000056 enum {
57 kA_Flag = 1 << 0,
58 kR_Flag = 1 << 1,
59 kG_Flag = 1 << 2,
60 kB_Flag = 1 << 3,
61 };
62
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000063protected:
reed9fa60da2014-08-21 07:59:51 -070064#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000065 SkTable_ColorFilter(SkReadBuffer& buffer);
reed9fa60da2014-08-21 07:59:51 -070066#endif
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000067 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000068
69private:
bsalomon@google.comb2ad1012012-10-17 15:00:32 +000070 mutable const SkBitmap* fBitmap; // lazily allocated
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000071
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000072 uint8_t fStorage[256 * 4];
73 unsigned fFlags;
74
reed9fa60da2014-08-21 07:59:51 -070075 friend class SkTableColorFilter;
76
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000077 typedef SkColorFilter INHERITED;
78};
79
80static const uint8_t gIdentityTable[] = {
rmistry@google.comfbfcd562012-08-23 18:09:54 +000081 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,
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000112 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
113};
114
115void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count,
reed@google.combada6442012-12-17 20:21:44 +0000116 SkPMColor dst[]) const {
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000117 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
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000159#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com1202c2a2013-05-23 14:00:17 +0000160void SkTable_ColorFilter::toString(SkString* str) const {
161 str->append("SkTable_ColorFilter");
162}
163#endif
164
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000165static 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
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000174void SkTable_ColorFilter::flatten(SkWriteBuffer& buffer) const {
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000175 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
reed9fa60da2014-08-21 07:59:51 -0700180 buffer.write32(fFlags);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000181 buffer.writeByteArray(storage, size);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000182}
183
reed9fa60da2014-08-21 07:59:51 -0700184SkFlattenable* 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
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000231SkTable_ColorFilter::SkTable_ColorFilter(SkReadBuffer& buffer) : INHERITED(buffer) {
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000232 fBitmap = NULL;
233
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000234 uint8_t storage[5*256];
235
236 fFlags = buffer.readInt();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000237
238 size_t size = buffer.getArrayCount();
239 SkASSERT(size <= sizeof(storage));
commit-bot@chromium.orgef74fa12013-12-17 20:49:46 +0000240 buffer.validate(size <= sizeof(storage));
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000241 buffer.readByteArray(storage, size);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000242
humper@google.com0e515772013-01-07 19:54:40 +0000243 SkDEBUGCODE(size_t raw = ) SkPackBits::Unpack8(storage, size, fStorage);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000244
245 SkASSERT(raw <= sizeof(fStorage));
humper@google.com0e515772013-01-07 19:54:40 +0000246 SkDEBUGCODE(size_t count = gCountNibBits[fFlags & 0xF]);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000247 SkASSERT(raw == count * 256);
248}
reed9fa60da2014-08-21 07:59:51 -0700249#endif
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000250
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000251bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000252 if (table) {
253 if (NULL == fBitmap) {
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000254 SkBitmap* bmp = SkNEW(SkBitmap);
reed@google.com9ebcac52014-01-24 18:53:42 +0000255 bmp->allocPixels(SkImageInfo::MakeA8(256, 4));
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000256 uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
twiz@google.com58071162012-07-18 21:41:50 +0000257 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 }
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000269 fBitmap = bmp;
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000270 }
271 *table = *fBitmap;
272 }
273 return true;
274}
275
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000276#if SK_SUPPORT_GPU
277
joshualittb0a8a372014-09-23 09:50:21 -0700278#include "GrProcessor.h"
279#include "GrTBackendProcessorFactory.h"
280#include "gl/GrGLProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -0700281#include "gl/builders/GrGLProgramBuilder.h"
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000282#include "SkGr.h"
283
284class GLColorTableEffect;
285
joshualittb0a8a372014-09-23 09:50:21 -0700286class ColorTableEffect : public GrFragmentProcessor {
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000287public:
joshualittb0a8a372014-09-23 09:50:21 -0700288 static GrFragmentProcessor* Create(GrTexture* texture, unsigned flags) {
bsalomon55fad7a2014-07-08 07:34:20 -0700289 return SkNEW_ARGS(ColorTableEffect, (texture, flags));
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000290 }
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000291
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000292 virtual ~ColorTableEffect();
293
294 static const char* Name() { return "ColorTable"; }
joshualittb0a8a372014-09-23 09:50:21 -0700295 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000296
bsalomon@google.com371e1052013-01-11 21:08:55 +0000297 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
298
joshualittb0a8a372014-09-23 09:50:21 -0700299 typedef GLColorTableEffect GLProcessor;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000300
301private:
joshualittb0a8a372014-09-23 09:50:21 -0700302 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000303
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000304 explicit ColorTableEffect(GrTexture* texture, unsigned flags);
305
joshualittb0a8a372014-09-23 09:50:21 -0700306 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000307
308 GrTextureAccess fTextureAccess;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000309 unsigned fFlags; // currently not used in shader code, just to assist
310 // getConstantColorComponents().
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000311
joshualittb0a8a372014-09-23 09:50:21 -0700312 typedef GrFragmentProcessor INHERITED;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000313};
314
joshualittb0a8a372014-09-23 09:50:21 -0700315class GLColorTableEffect : public GrGLFragmentProcessor {
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000316public:
joshualittb0a8a372014-09-23 09:50:21 -0700317 GLColorTableEffect(const GrBackendProcessorFactory&, const GrProcessor&);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000318
joshualitt30ba4362014-08-21 20:18:45 -0700319 virtual void emitCode(GrGLProgramBuilder*,
joshualittb0a8a372014-09-23 09:50:21 -0700320 const GrFragmentProcessor&,
321 const GrProcessorKey&,
bsalomon@google.com22a800a2012-10-26 19:16:46 +0000322 const char* outputColor,
323 const char* inputColor,
bsalomon@google.com77af6802013-10-02 13:04:56 +0000324 const TransformedCoordsArray&,
bsalomon@google.com22a800a2012-10-26 19:16:46 +0000325 const TextureSamplerArray&) SK_OVERRIDE;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000326
joshualittb0a8a372014-09-23 09:50:21 -0700327 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000328
joshualittb0a8a372014-09-23 09:50:21 -0700329 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b) {}
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000330
331private:
332
joshualittb0a8a372014-09-23 09:50:21 -0700333 typedef GrGLFragmentProcessor INHERITED;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000334};
335
joshualittb0a8a372014-09-23 09:50:21 -0700336GLColorTableEffect::GLColorTableEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000337 : INHERITED(factory) {
338 }
339
joshualitt30ba4362014-08-21 20:18:45 -0700340void GLColorTableEffect::emitCode(GrGLProgramBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700341 const GrFragmentProcessor&,
342 const GrProcessorKey&,
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000343 const char* outputColor,
344 const char* inputColor,
bsalomon@google.com77af6802013-10-02 13:04:56 +0000345 const TransformedCoordsArray&,
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000346 const TextureSamplerArray& samplers) {
bsalomon@google.com22a800a2012-10-26 19:16:46 +0000347
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000348 static const float kColorScaleFactor = 255.0f / 256.0f;
349 static const float kColorOffsetFactor = 1.0f / 512.0f;
joshualitt30ba4362014-08-21 20:18:45 -0700350 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000351 if (NULL == inputColor) {
352 // the input color is solid white (all ones).
353 static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
joshualitt30ba4362014-08-21 20:18:45 -0700354 fsBuilder->codeAppendf("\t\tvec4 coord = vec4(%f, %f, %f, %f);\n",
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000355 kMaxValue, kMaxValue, kMaxValue, kMaxValue);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000356
357 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700358 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",
bsalomon@google.comf910d3b2013-03-07 17:06:57 +0000361 kColorScaleFactor,
362 kColorOffsetFactor, kColorOffsetFactor,
363 kColorOffsetFactor, kColorOffsetFactor);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000364 }
365
joshualitt30ba4362014-08-21 20:18:45 -0700366 fsBuilder->codeAppendf("\t\t%s.a = ", outputColor);
367 fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.a, 0.125)");
368 fsBuilder->codeAppend(";\n");
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000369
joshualitt30ba4362014-08-21 20:18:45 -0700370 fsBuilder->codeAppendf("\t\t%s.r = ", outputColor);
371 fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.r, 0.375)");
372 fsBuilder->codeAppend(";\n");
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000373
joshualitt30ba4362014-08-21 20:18:45 -0700374 fsBuilder->codeAppendf("\t\t%s.g = ", outputColor);
375 fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.g, 0.625)");
376 fsBuilder->codeAppend(";\n");
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000377
joshualitt30ba4362014-08-21 20:18:45 -0700378 fsBuilder->codeAppendf("\t\t%s.b = ", outputColor);
379 fsBuilder->appendTextureLookup(samplers[0], "vec2(coord.b, 0.875)");
380 fsBuilder->codeAppend(";\n");
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000381
joshualitt30ba4362014-08-21 20:18:45 -0700382 fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000383}
384
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000385///////////////////////////////////////////////////////////////////////////////
386
bsalomon@google.com371e1052013-01-11 21:08:55 +0000387ColorTableEffect::ColorTableEffect(GrTexture* texture, unsigned flags)
388 : fTextureAccess(texture, "a")
389 , fFlags(flags) {
bsalomon@google.com50db75c2013-01-11 13:54:30 +0000390 this->addTextureAccess(&fTextureAccess);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000391}
392
393ColorTableEffect::~ColorTableEffect() {
394}
395
joshualittb0a8a372014-09-23 09:50:21 -0700396const GrBackendFragmentProcessorFactory& ColorTableEffect::getFactory() const {
397 return GrTBackendFragmentProcessorFactory<ColorTableEffect>::getInstance();
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000398}
399
joshualittb0a8a372014-09-23 09:50:21 -0700400bool ColorTableEffect::onIsEqual(const GrProcessor& sBase) const {
bsalomon@google.com8a252f72013-01-22 20:35:13 +0000401 return this->texture(0) == sBase.texture(0);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000402}
403
bsalomon@google.com371e1052013-01-11 21:08:55 +0000404void 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) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000408 *validFlags &= ~kR_GrColorComponentFlag;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000409 }
410 if (fFlags & SkTable_ColorFilter::kG_Flag) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000411 *validFlags &= ~kG_GrColorComponentFlag;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000412 }
413 if (fFlags & SkTable_ColorFilter::kB_Flag) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000414 *validFlags &= ~kB_GrColorComponentFlag;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000415 }
416 if (fFlags & SkTable_ColorFilter::kA_Flag) {
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +0000417 *validFlags &= ~kA_GrColorComponentFlag;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000418 }
419}
420
421
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000422///////////////////////////////////////////////////////////////////////////////
423
joshualittb0a8a372014-09-23 09:50:21 -0700424GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorTableEffect);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000425
joshualittb0a8a372014-09-23 09:50:21 -0700426GrFragmentProcessor* ColorTableEffect::TestCreate(SkRandom* random,
427 GrContext* context,
428 const GrDrawTargetCaps&,
429 GrTexture* textures[]) {
bsalomon@google.com371e1052013-01-11 21:08:55 +0000430 static unsigned kAllFlags = SkTable_ColorFilter::kR_Flag | SkTable_ColorFilter::kG_Flag |
431 SkTable_ColorFilter::kB_Flag | SkTable_ColorFilter::kA_Flag;
joshualittb0a8a372014-09-23 09:50:21 -0700432 return ColorTableEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], kAllFlags);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000433}
434
joshualittb0a8a372014-09-23 09:50:21 -0700435GrFragmentProcessor* SkTable_ColorFilter::asFragmentProcessor(GrContext* context) const {
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000436 SkBitmap bitmap;
joshualittb0a8a372014-09-23 09:50:21 -0700437 GrFragmentProcessor* fp = NULL;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000438 this->asComponentTable(&bitmap);
bsalomon@google.com8ea78d82012-10-24 20:11:30 +0000439 // passing NULL because this effect does no tiling or filtering.
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000440 GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, bitmap, NULL);
bsalomon49f085d2014-09-05 13:34:00 -0700441 if (texture) {
joshualittb0a8a372014-09-23 09:50:21 -0700442 fp = ColorTableEffect::Create(texture, fFlags);
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000443
commit-bot@chromium.orgc7d624e2013-05-28 13:13:56 +0000444 // 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 }
joshualittb0a8a372014-09-23 09:50:21 -0700449 return fp;
bsalomon@google.comb2ad1012012-10-17 15:00:32 +0000450}
451
452#endif // SK_SUPPORT_GPU
453
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000454///////////////////////////////////////////////////////////////////////////////
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
466SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) {
467 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table));
468}
469
470SkColorFilter* 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}
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000476
477SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter)
478 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter)
479SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END