OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorMatrixFilter.h" | 8 #include "SkColorMatrixFilterRowMajor255.h" |
9 #include "SkColorMatrix.h" | |
10 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
11 #include "SkNx.h" | 10 #include "SkNx.h" |
12 #include "SkReadBuffer.h" | 11 #include "SkReadBuffer.h" |
13 #include "SkWriteBuffer.h" | 12 #include "SkWriteBuffer.h" |
14 #include "SkUnPreMultiply.h" | 13 #include "SkUnPreMultiply.h" |
15 #include "SkString.h" | 14 #include "SkString.h" |
16 | 15 |
17 #define SK_PMORDER_INDEX_A (SK_A32_SHIFT / 8) | 16 #define SK_PMORDER_INDEX_A (SK_A32_SHIFT / 8) |
18 #define SK_PMORDER_INDEX_R (SK_R32_SHIFT / 8) | 17 #define SK_PMORDER_INDEX_R (SK_R32_SHIFT / 8) |
19 #define SK_PMORDER_INDEX_G (SK_G32_SHIFT / 8) | 18 #define SK_PMORDER_INDEX_G (SK_G32_SHIFT / 8) |
20 #define SK_PMORDER_INDEX_B (SK_B32_SHIFT / 8) | 19 #define SK_PMORDER_INDEX_B (SK_B32_SHIFT / 8) |
21 | 20 |
22 static void transpose_to_pmorder(float dst[20], const float src[20]) { | 21 static void transpose_to_pmorder(float dst[20], const float src[20]) { |
23 const float* srcR = src + 0; | 22 const float* srcR = src + 0; |
24 const float* srcG = src + 5; | 23 const float* srcG = src + 5; |
25 const float* srcB = src + 10; | 24 const float* srcB = src + 10; |
26 const float* srcA = src + 15; | 25 const float* srcA = src + 15; |
27 | 26 |
28 for (int i = 0; i < 20; i += 4) { | 27 for (int i = 0; i < 20; i += 4) { |
29 dst[i + SK_PMORDER_INDEX_A] = *srcA++; | 28 dst[i + SK_PMORDER_INDEX_A] = *srcA++; |
30 dst[i + SK_PMORDER_INDEX_R] = *srcR++; | 29 dst[i + SK_PMORDER_INDEX_R] = *srcR++; |
31 dst[i + SK_PMORDER_INDEX_G] = *srcG++; | 30 dst[i + SK_PMORDER_INDEX_G] = *srcG++; |
32 dst[i + SK_PMORDER_INDEX_B] = *srcB++; | 31 dst[i + SK_PMORDER_INDEX_B] = *srcB++; |
33 } | 32 } |
34 } | 33 } |
35 | 34 |
36 // src is [20] but some compilers won't accept __restrict__ on anything | 35 // src is [20] but some compilers won't accept __restrict__ on anything |
37 // but an raw pointer or reference | 36 // but an raw pointer or reference |
38 void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) { | 37 void SkColorMatrixFilterRowMajor255::initState(const SkScalar* SK_RESTRICT src)
{ |
39 transpose_to_pmorder(fTranspose, src); | 38 transpose_to_pmorder(fTranspose, src); |
40 | 39 |
41 const float* array = fMatrix.fMat; | 40 const float* array = fMatrix; |
42 | 41 |
43 // check if we have to munge Alpha | 42 // check if we have to munge Alpha |
44 bool changesAlpha = (array[15] || array[16] || array[17] || (array[18] - 1)
|| array[19]); | 43 bool changesAlpha = (array[15] || array[16] || array[17] || (array[18] - 1)
|| array[19]); |
45 bool usesAlpha = (array[3] || array[8] || array[13]); | 44 bool usesAlpha = (array[3] || array[8] || array[13]); |
46 | 45 |
47 if (changesAlpha || usesAlpha) { | 46 if (changesAlpha || usesAlpha) { |
48 fFlags = changesAlpha ? 0 : kAlphaUnchanged_Flag; | 47 fFlags = changesAlpha ? 0 : kAlphaUnchanged_Flag; |
49 } else { | 48 } else { |
50 fFlags = kAlphaUnchanged_Flag; | 49 fFlags = kAlphaUnchanged_Flag; |
51 } | 50 } |
52 fFlags |= kSupports4f_Flag; | 51 fFlags |= kSupports4f_Flag; |
53 } | 52 } |
54 | 53 |
55 /////////////////////////////////////////////////////////////////////////////// | 54 /////////////////////////////////////////////////////////////////////////////// |
56 | 55 |
57 SkColorMatrixFilter::SkColorMatrixFilter(const SkColorMatrix& cm) : fMatrix(cm)
{ | 56 SkColorMatrixFilterRowMajor255::SkColorMatrixFilterRowMajor255(const SkScalar ar
ray[20]) { |
58 this->initState(cm.fMat); | 57 memcpy(fMatrix, array, 20 * sizeof(SkScalar)); |
59 } | |
60 | |
61 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) { | |
62 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar)); | |
63 this->initState(array); | 58 this->initState(array); |
64 } | 59 } |
65 | 60 |
66 uint32_t SkColorMatrixFilter::getFlags() const { | 61 uint32_t SkColorMatrixFilterRowMajor255::getFlags() const { |
67 return this->INHERITED::getFlags() | fFlags; | 62 return this->INHERITED::getFlags() | fFlags; |
68 } | 63 } |
69 | 64 |
70 static Sk4f scale_rgb(float scale) { | 65 static Sk4f scale_rgb(float scale) { |
71 static_assert(SkPM4f::A == 3, "Alpha is lane 3"); | 66 static_assert(SkPM4f::A == 3, "Alpha is lane 3"); |
72 return Sk4f(scale, scale, scale, 1); | 67 return Sk4f(scale, scale, scale, 1); |
73 } | 68 } |
74 | 69 |
75 static Sk4f premul(const Sk4f& x) { | 70 static Sk4f premul(const Sk4f& x) { |
76 return x * scale_rgb(x.kth<SkPM4f::A>()); | 71 return x * scale_rgb(x.kth<SkPM4f::A>()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 } | 123 } |
129 | 124 |
130 struct SkPMColorAdaptor { | 125 struct SkPMColorAdaptor { |
131 static SkPMColor From4f(const Sk4f& c4) { | 126 static SkPMColor From4f(const Sk4f& c4) { |
132 return round(c4); | 127 return round(c4); |
133 } | 128 } |
134 static Sk4f To4f(SkPMColor c) { | 129 static Sk4f To4f(SkPMColor c) { |
135 return SkNx_cast<float>(Sk4b::Load(&c)) * Sk4f(1.0f/255); | 130 return SkNx_cast<float>(Sk4b::Load(&c)) * Sk4f(1.0f/255); |
136 } | 131 } |
137 }; | 132 }; |
138 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, SkPMColor
dst[]) const { | 133 void SkColorMatrixFilterRowMajor255::filterSpan(const SkPMColor src[], int count
, SkPMColor dst[]) const { |
139 filter_span<SkPMColorAdaptor>(fTranspose, src, count, dst); | 134 filter_span<SkPMColorAdaptor>(fTranspose, src, count, dst); |
140 } | 135 } |
141 | 136 |
142 struct SkPM4fAdaptor { | 137 struct SkPM4fAdaptor { |
143 static SkPM4f From4f(const Sk4f& c4) { | 138 static SkPM4f From4f(const Sk4f& c4) { |
144 SkPM4f c; | 139 SkPM4f c; |
145 c4.store(&c); | 140 c4.store(&c); |
146 return c; | 141 return c; |
147 } | 142 } |
148 static Sk4f To4f(const SkPM4f& c) { | 143 static Sk4f To4f(const SkPM4f& c) { |
149 return Sk4f::Load(&c); | 144 return Sk4f::Load(&c); |
150 } | 145 } |
151 }; | 146 }; |
152 void SkColorMatrixFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst
[]) const { | 147 void SkColorMatrixFilterRowMajor255::filterSpan4f(const SkPM4f src[], int count,
SkPM4f dst[]) const { |
153 filter_span<SkPM4fAdaptor>(fTranspose, src, count, dst); | 148 filter_span<SkPM4fAdaptor>(fTranspose, src, count, dst); |
154 } | 149 } |
155 | 150 |
156 /////////////////////////////////////////////////////////////////////////////// | 151 /////////////////////////////////////////////////////////////////////////////// |
157 | 152 |
158 void SkColorMatrixFilter::flatten(SkWriteBuffer& buffer) const { | 153 void SkColorMatrixFilterRowMajor255::flatten(SkWriteBuffer& buffer) const { |
159 SkASSERT(sizeof(fMatrix.fMat)/sizeof(SkScalar) == 20); | 154 SkASSERT(sizeof(fMatrix)/sizeof(SkScalar) == 20); |
160 buffer.writeScalarArray(fMatrix.fMat, 20); | 155 buffer.writeScalarArray(fMatrix, 20); |
161 } | 156 } |
162 | 157 |
163 SkFlattenable* SkColorMatrixFilter::CreateProc(SkReadBuffer& buffer) { | 158 SkFlattenable* SkColorMatrixFilterRowMajor255::CreateProc(SkReadBuffer& buffer)
{ |
164 SkColorMatrix matrix; | 159 SkScalar matrix[20]; |
165 if (buffer.readScalarArray(matrix.fMat, 20)) { | 160 if (buffer.readScalarArray(matrix, 20)) { |
166 return Create(matrix); | 161 return new SkColorMatrixFilterRowMajor255(matrix); |
167 } | 162 } |
168 return nullptr; | 163 return nullptr; |
169 } | 164 } |
170 | 165 |
171 bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) const { | 166 bool SkColorMatrixFilterRowMajor255::asColorMatrix(SkScalar matrix[20]) const { |
172 if (matrix) { | 167 if (matrix) { |
173 memcpy(matrix, fMatrix.fMat, 20 * sizeof(SkScalar)); | 168 memcpy(matrix, fMatrix, 20 * sizeof(SkScalar)); |
174 } | 169 } |
175 return true; | 170 return true; |
176 } | 171 } |
177 | 172 |
178 SkColorFilter* SkColorMatrixFilter::newComposed(const SkColorFilter* innerFilter
) const { | 173 /////////////////////////////////////////////////////////////////////////////// |
| 174 // This code was duplicated from src/effects/SkColorMatrixc.cpp in order to be
used in core. |
| 175 ////// |
| 176 |
| 177 // To detect if we need to apply clamping after applying a matrix, we check if |
| 178 // any output component might go outside of [0, 255] for any combination of |
| 179 // input components in [0..255]. |
| 180 // Each output component is an affine transformation of the input component, so |
| 181 // the minimum and maximum values are for any combination of minimum or maximum |
| 182 // values of input components (i.e. 0 or 255). |
| 183 // E.g. if R' = x*R + y*G + z*B + w*A + t |
| 184 // Then the maximum value will be for R=255 if x>0 or R=0 if x<0, and the |
| 185 // minimum value will be for R=0 if x>0 or R=255 if x<0. |
| 186 // Same goes for all components. |
| 187 static bool component_needs_clamping(const SkScalar row[5]) { |
| 188 SkScalar maxValue = row[4] / 255; |
| 189 SkScalar minValue = row[4] / 255; |
| 190 for (int i = 0; i < 4; ++i) { |
| 191 if (row[i] > 0) |
| 192 maxValue += row[i]; |
| 193 else |
| 194 minValue += row[i]; |
| 195 } |
| 196 return (maxValue > 1) || (minValue < 0); |
| 197 } |
| 198 |
| 199 static bool needs_clamping(const SkScalar matrix[20]) { |
| 200 return component_needs_clamping(matrix) |
| 201 || component_needs_clamping(matrix+5) |
| 202 || component_needs_clamping(matrix+10) |
| 203 || component_needs_clamping(matrix+15); |
| 204 } |
| 205 |
| 206 static void set_concat(SkScalar result[20], const SkScalar outer[20], const SkSc
alar inner[20]) { |
| 207 int index = 0; |
| 208 for (int j = 0; j < 20; j += 5) { |
| 209 for (int i = 0; i < 4; i++) { |
| 210 result[index++] = outer[j + 0] * inner[i + 0] + |
| 211 outer[j + 1] * inner[i + 5] + |
| 212 outer[j + 2] * inner[i + 10] + |
| 213 outer[j + 3] * inner[i + 15]; |
| 214 } |
| 215 result[index++] = outer[j + 0] * inner[4] + |
| 216 outer[j + 1] * inner[9] + |
| 217 outer[j + 2] * inner[14] + |
| 218 outer[j + 3] * inner[19] + |
| 219 outer[j + 4]; |
| 220 } |
| 221 } |
| 222 |
| 223 /////////////////////////////////////////////////////////////////////////////// |
| 224 // End duplication |
| 225 ////// |
| 226 |
| 227 SkColorFilter* SkColorMatrixFilterRowMajor255::newComposed(const SkColorFilter*
innerFilter) const { |
179 SkScalar innerMatrix[20]; | 228 SkScalar innerMatrix[20]; |
180 if (innerFilter->asColorMatrix(innerMatrix) && !SkColorMatrix::NeedsClamping
(innerMatrix)) { | 229 if (innerFilter->asColorMatrix(innerMatrix) && !needs_clamping(innerMatrix))
{ |
181 SkScalar concat[20]; | 230 SkScalar concat[20]; |
182 SkColorMatrix::SetConcat(concat, fMatrix.fMat, innerMatrix); | 231 set_concat(concat, fMatrix, innerMatrix); |
183 return SkColorMatrixFilter::Create(concat); | 232 return new SkColorMatrixFilterRowMajor255(concat); |
184 } | 233 } |
185 return nullptr; | 234 return nullptr; |
186 } | 235 } |
187 | 236 |
188 #if SK_SUPPORT_GPU | 237 #if SK_SUPPORT_GPU |
189 #include "GrFragmentProcessor.h" | 238 #include "GrFragmentProcessor.h" |
190 #include "GrInvariantOutput.h" | 239 #include "GrInvariantOutput.h" |
191 #include "glsl/GrGLSLFragmentProcessor.h" | 240 #include "glsl/GrGLSLFragmentProcessor.h" |
192 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 241 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
193 #include "glsl/GrGLSLProgramDataManager.h" | 242 #include "glsl/GrGLSLProgramDataManager.h" |
194 #include "glsl/GrGLSLUniformHandler.h" | 243 #include "glsl/GrGLSLUniformHandler.h" |
195 | 244 |
196 class ColorMatrixEffect : public GrFragmentProcessor { | 245 class ColorMatrixEffect : public GrFragmentProcessor { |
197 public: | 246 public: |
198 static const GrFragmentProcessor* Create(const SkColorMatrix& matrix) { | 247 static const GrFragmentProcessor* Create(const SkScalar matrix[20]) { |
199 return new ColorMatrixEffect(matrix); | 248 return new ColorMatrixEffect(matrix); |
200 } | 249 } |
201 | 250 |
202 const char* name() const override { return "Color Matrix"; } | 251 const char* name() const override { return "Color Matrix"; } |
203 | 252 |
204 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 253 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
205 | 254 |
206 class GLSLProcessor : public GrGLSLFragmentProcessor { | 255 class GLSLProcessor : public GrGLSLFragmentProcessor { |
207 public: | 256 public: |
208 // this class always generates the same code. | 257 // this class always generates the same code. |
(...skipping 26 matching lines...) Expand all Loading... |
235 uniformHandler->getUniformCStr(fVectorHandl
e)); | 284 uniformHandler->getUniformCStr(fVectorHandl
e)); |
236 fragBuilder->codeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", | 285 fragBuilder->codeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", |
237 args.fOutputColor, args.fOutputColor); | 286 args.fOutputColor, args.fOutputColor); |
238 fragBuilder->codeAppendf("\t%s.rgb *= %s.a;\n", args.fOutputColor, a
rgs.fOutputColor); | 287 fragBuilder->codeAppendf("\t%s.rgb *= %s.a;\n", args.fOutputColor, a
rgs.fOutputColor); |
239 } | 288 } |
240 | 289 |
241 protected: | 290 protected: |
242 virtual void onSetData(const GrGLSLProgramDataManager& uniManager, | 291 virtual void onSetData(const GrGLSLProgramDataManager& uniManager, |
243 const GrProcessor& proc) override { | 292 const GrProcessor& proc) override { |
244 const ColorMatrixEffect& cme = proc.cast<ColorMatrixEffect>(); | 293 const ColorMatrixEffect& cme = proc.cast<ColorMatrixEffect>(); |
245 const float* m = cme.fMatrix.fMat; | 294 const float* m = cme.fMatrix; |
246 // The GL matrix is transposed from SkColorMatrix. | 295 // The GL matrix is transposed from SkColorMatrix. |
247 float mt[] = { | 296 float mt[] = { |
248 m[0], m[5], m[10], m[15], | 297 m[0], m[5], m[10], m[15], |
249 m[1], m[6], m[11], m[16], | 298 m[1], m[6], m[11], m[16], |
250 m[2], m[7], m[12], m[17], | 299 m[2], m[7], m[12], m[17], |
251 m[3], m[8], m[13], m[18], | 300 m[3], m[8], m[13], m[18], |
252 }; | 301 }; |
253 static const float kScale = 1.0f / 255.0f; | 302 static const float kScale = 1.0f / 255.0f; |
254 float vec[] = { | 303 float vec[] = { |
255 m[4] * kScale, m[9] * kScale, m[14] * kScale, m[19] * kScale, | 304 m[4] * kScale, m[9] * kScale, m[14] * kScale, m[19] * kScale, |
256 }; | 305 }; |
257 uniManager.setMatrix4fv(fMatrixHandle, 1, mt); | 306 uniManager.setMatrix4fv(fMatrixHandle, 1, mt); |
258 uniManager.set4fv(fVectorHandle, 1, vec); | 307 uniManager.set4fv(fVectorHandle, 1, vec); |
259 } | 308 } |
260 | 309 |
261 private: | 310 private: |
262 GrGLSLProgramDataManager::UniformHandle fMatrixHandle; | 311 GrGLSLProgramDataManager::UniformHandle fMatrixHandle; |
263 GrGLSLProgramDataManager::UniformHandle fVectorHandle; | 312 GrGLSLProgramDataManager::UniformHandle fVectorHandle; |
264 | 313 |
265 typedef GrGLSLFragmentProcessor INHERITED; | 314 typedef GrGLSLFragmentProcessor INHERITED; |
266 }; | 315 }; |
267 | 316 |
268 private: | 317 private: |
269 ColorMatrixEffect(const SkColorMatrix& matrix) : fMatrix(matrix) { | 318 ColorMatrixEffect(const SkScalar matrix[20]) { |
| 319 memcpy(fMatrix, matrix, sizeof(SkScalar) * 20); |
270 this->initClassID<ColorMatrixEffect>(); | 320 this->initClassID<ColorMatrixEffect>(); |
271 } | 321 } |
272 | 322 |
273 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { | 323 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
274 return new GLSLProcessor(*this); | 324 return new GLSLProcessor(*this); |
275 } | 325 } |
276 | 326 |
277 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, | 327 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
278 GrProcessorKeyBuilder* b) const override
{ | 328 GrProcessorKeyBuilder* b) const override
{ |
279 GLSLProcessor::GenKey(*this, caps, b); | 329 GLSLProcessor::GenKey(*this, caps, b); |
280 } | 330 } |
281 | 331 |
282 bool onIsEqual(const GrFragmentProcessor& s) const override { | 332 bool onIsEqual(const GrFragmentProcessor& s) const override { |
283 const ColorMatrixEffect& cme = s.cast<ColorMatrixEffect>(); | 333 const ColorMatrixEffect& cme = s.cast<ColorMatrixEffect>(); |
284 return cme.fMatrix == fMatrix; | 334 return 0 == memcmp(fMatrix, cme.fMatrix, sizeof(fMatrix)); |
285 } | 335 } |
286 | 336 |
287 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 337 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
288 // We only bother to check whether the alpha channel will be constant. I
f SkColorMatrix had | 338 // We only bother to check whether the alpha channel will be constant. I
f SkColorMatrix had |
289 // type flags it might be worth checking the other components. | 339 // type flags it might be worth checking the other components. |
290 | 340 |
291 // The matrix is defined such the 4th row determines the output alpha. T
he first four | 341 // The matrix is defined such the 4th row determines the output alpha. T
he first four |
292 // columns of that row multiply the input r, g, b, and a, respectively,
and the last column | 342 // columns of that row multiply the input r, g, b, and a, respectively,
and the last column |
293 // is the "translation". | 343 // is the "translation". |
294 static const uint32_t kRGBAFlags[] = { | 344 static const uint32_t kRGBAFlags[] = { |
295 kR_GrColorComponentFlag, | 345 kR_GrColorComponentFlag, |
296 kG_GrColorComponentFlag, | 346 kG_GrColorComponentFlag, |
297 kB_GrColorComponentFlag, | 347 kB_GrColorComponentFlag, |
298 kA_GrColorComponentFlag | 348 kA_GrColorComponentFlag |
299 }; | 349 }; |
300 static const int kShifts[] = { | 350 static const int kShifts[] = { |
301 GrColor_SHIFT_R, GrColor_SHIFT_G, GrColor_SHIFT_B, GrColor_SHIFT_A, | 351 GrColor_SHIFT_R, GrColor_SHIFT_G, GrColor_SHIFT_B, GrColor_SHIFT_A, |
302 }; | 352 }; |
303 enum { | 353 enum { |
304 kAlphaRowStartIdx = 15, | 354 kAlphaRowStartIdx = 15, |
305 kAlphaRowTranslateIdx = 19, | 355 kAlphaRowTranslateIdx = 19, |
306 }; | 356 }; |
307 | 357 |
308 SkScalar outputA = 0; | 358 SkScalar outputA = 0; |
309 for (int i = 0; i < 4; ++i) { | 359 for (int i = 0; i < 4; ++i) { |
310 // If any relevant component of the color to be passed through the m
atrix is non-const | 360 // If any relevant component of the color to be passed through the m
atrix is non-const |
311 // then we can't know the final result. | 361 // then we can't know the final result. |
312 if (0 != fMatrix.fMat[kAlphaRowStartIdx + i]) { | 362 if (0 != fMatrix[kAlphaRowStartIdx + i]) { |
313 if (!(inout->validFlags() & kRGBAFlags[i])) { | 363 if (!(inout->validFlags() & kRGBAFlags[i])) { |
314 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 364 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
315 return; | 365 return; |
316 } else { | 366 } else { |
317 uint32_t component = (inout->color() >> kShifts[i]) & 0xFF; | 367 uint32_t component = (inout->color() >> kShifts[i]) & 0xFF; |
318 outputA += fMatrix.fMat[kAlphaRowStartIdx + i] * component; | 368 outputA += fMatrix[kAlphaRowStartIdx + i] * component; |
319 } | 369 } |
320 } | 370 } |
321 } | 371 } |
322 outputA += fMatrix.fMat[kAlphaRowTranslateIdx]; | 372 outputA += fMatrix[kAlphaRowTranslateIdx]; |
323 // We pin the color to [0,1]. This would happen to the *final* color out
put from the frag | 373 // We pin the color to [0,1]. This would happen to the *final* color out
put from the frag |
324 // shader but currently the effect does not pin its own output. So in th
e case of over/ | 374 // shader but currently the effect does not pin its own output. So in th
e case of over/ |
325 // underflow this may deviate from the actual result. Maybe the effect s
hould pin its | 375 // underflow this may deviate from the actual result. Maybe the effect s
hould pin its |
326 // result if the matrix could over/underflow for any component? | 376 // result if the matrix could over/underflow for any component? |
327 inout->setToOther(kA_GrColorComponentFlag, | 377 inout->setToOther(kA_GrColorComponentFlag, |
328 static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) <<
GrColor_SHIFT_A, | 378 static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) <<
GrColor_SHIFT_A, |
329 GrInvariantOutput::kWill_ReadInput); | 379 GrInvariantOutput::kWill_ReadInput); |
330 } | 380 } |
331 | 381 |
332 SkColorMatrix fMatrix; | 382 SkScalar fMatrix[20]; |
333 | 383 |
334 typedef GrFragmentProcessor INHERITED; | 384 typedef GrFragmentProcessor INHERITED; |
335 }; | 385 }; |
336 | 386 |
337 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorMatrixEffect); | 387 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorMatrixEffect); |
338 | 388 |
339 const GrFragmentProcessor* ColorMatrixEffect::TestCreate(GrProcessorTestData* d)
{ | 389 const GrFragmentProcessor* ColorMatrixEffect::TestCreate(GrProcessorTestData* d)
{ |
340 SkColorMatrix colorMatrix; | 390 SkScalar colorMatrix[20]; |
341 for (size_t i = 0; i < SK_ARRAY_COUNT(colorMatrix.fMat); ++i) { | 391 for (size_t i = 0; i < SK_ARRAY_COUNT(colorMatrix); ++i) { |
342 colorMatrix.fMat[i] = d->fRandom->nextSScalar1(); | 392 colorMatrix[i] = d->fRandom->nextSScalar1(); |
343 } | 393 } |
344 return ColorMatrixEffect::Create(colorMatrix); | 394 return ColorMatrixEffect::Create(colorMatrix); |
345 } | 395 } |
346 | 396 |
347 const GrFragmentProcessor* SkColorMatrixFilter::asFragmentProcessor(GrContext*)
const { | 397 const GrFragmentProcessor* SkColorMatrixFilterRowMajor255::asFragmentProcessor(G
rContext*) const { |
348 return ColorMatrixEffect::Create(fMatrix); | 398 return ColorMatrixEffect::Create(fMatrix); |
349 } | 399 } |
350 | 400 |
351 #endif | 401 #endif |
352 | 402 |
353 #ifndef SK_IGNORE_TO_STRING | 403 #ifndef SK_IGNORE_TO_STRING |
354 void SkColorMatrixFilter::toString(SkString* str) const { | 404 void SkColorMatrixFilterRowMajor255::toString(SkString* str) const { |
355 str->append("SkColorMatrixFilter: "); | 405 str->append("SkColorMatrixFilterRowMajor255: "); |
356 | 406 |
357 str->append("matrix: ("); | 407 str->append("matrix: ("); |
358 for (int i = 0; i < 20; ++i) { | 408 for (int i = 0; i < 20; ++i) { |
359 str->appendScalar(fMatrix.fMat[i]); | 409 str->appendScalar(fMatrix[i]); |
360 if (i < 19) { | 410 if (i < 19) { |
361 str->append(", "); | 411 str->append(", "); |
362 } | 412 } |
363 } | 413 } |
364 str->append(")"); | 414 str->append(")"); |
365 } | 415 } |
366 #endif | 416 #endif |
367 | 417 |
368 /////////////////////////////////////////////////////////////////////////////// | 418 /////////////////////////////////////////////////////////////////////////////// |
369 | 419 |
370 static SkScalar byte_to_scale(U8CPU byte) { | 420 SkColorFilter* SkColorFilter::CreateMatrixFilterRowMajor255(const SkScalar array
[20]) { |
371 if (0xFF == byte) { | 421 return new SkColorMatrixFilterRowMajor255(array); |
372 // want to get this exact | |
373 return 1; | |
374 } else { | |
375 return byte * 0.00392156862745f; | |
376 } | |
377 } | 422 } |
378 | |
379 SkColorFilter* SkColorMatrixFilter::CreateLightingFilter(SkColor mul, SkColor ad
d) { | |
380 SkColorMatrix matrix; | |
381 matrix.setScale(byte_to_scale(SkColorGetR(mul)), | |
382 byte_to_scale(SkColorGetG(mul)), | |
383 byte_to_scale(SkColorGetB(mul)), | |
384 1); | |
385 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), | |
386 SkIntToScalar(SkColorGetG(add)), | |
387 SkIntToScalar(SkColorGetB(add)), | |
388 0); | |
389 return SkColorMatrixFilter::Create(matrix); | |
390 } | |
OLD | NEW |