Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/effects/SkColorMatrixFilter.cpp

Issue 967943002: impl colormatrix w/ floats (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/effects/SkColorMatrixFilter.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
2 /* 1 /*
3 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
4 * 3 *
5 * 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
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
7
8 #include "SkColorMatrixFilter.h" 8 #include "SkColorMatrixFilter.h"
9 #include "SkColorMatrix.h" 9 #include "SkColorMatrix.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkPMFloat.h"
11 #include "SkReadBuffer.h" 12 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
13 #include "SkUnPreMultiply.h" 14 #include "SkUnPreMultiply.h"
14 #include "SkString.h" 15 #include "SkString.h"
15 16
17 #define SK_PMORDER_INDEX_A (SK_A32_SHIFT / 8)
18 #define SK_PMORDER_INDEX_R (SK_R32_SHIFT / 8)
19 #define SK_PMORDER_INDEX_G (SK_G32_SHIFT / 8)
20 #define SK_PMORDER_INDEX_B (SK_B32_SHIFT / 8)
21
22 static void transpose_to_pmorder(float dst[20], const float src[20]) {
23 const float* srcR = src + 0;
24 const float* srcG = src + 5;
25 const float* srcB = src + 10;
26 const float* srcA = src + 15;
27
28 for (int i = 0; i < 20; i += 4) {
29 dst[i + SK_PMORDER_INDEX_A] = *srcA++;
30 dst[i + SK_PMORDER_INDEX_R] = *srcR++;
31 dst[i + SK_PMORDER_INDEX_G] = *srcG++;
32 dst[i + SK_PMORDER_INDEX_B] = *srcB++;
33 }
34 }
35
16 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g, 36 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
17 unsigned b, unsigned a) { 37 unsigned b, unsigned a) {
18 return array[0] * r + array[1] * g + array[2] * b + array[3] * a + array[4] ; 38 return array[0] * r + array[1] * g + array[2] * b + array[3] * a + array[4] ;
19 } 39 }
20 40
21 static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g, 41 static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g,
22 unsigned b) { 42 unsigned b) {
23 return array[0] * r + array[1] * g + array[2] * b + array[4]; 43 return array[0] * r + array[1] * g + array[2] * b + array[4];
24 } 44 }
25 45
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 result[2] = b + (array[SkColorMatrix::kB_Trans] >> 16); 136 result[2] = b + (array[SkColorMatrix::kB_Trans] >> 16);
117 result[3] = a; 137 result[3] = a;
118 } 138 }
119 139
120 #define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag | \ 140 #define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag | \
121 SkColorFilter::kHasFilter16_Flag) 141 SkColorFilter::kHasFilter16_Flag)
122 142
123 // src is [20] but some compilers won't accept __restrict__ on anything 143 // src is [20] but some compilers won't accept __restrict__ on anything
124 // but an raw pointer or reference 144 // but an raw pointer or reference
125 void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) { 145 void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
146 transpose_to_pmorder(fTranspose, src);
147
126 int32_t* array = fState.fArray; 148 int32_t* array = fState.fArray;
127 SkFixed max = 0; 149 SkFixed max = 0;
128 for (int i = 0; i < 20; i++) { 150 for (int i = 0; i < 20; i++) {
129 SkFixed value = SkScalarToFixed(src[i]); 151 SkFixed value = SkScalarToFixed(src[i]);
130 array[i] = value; 152 array[i] = value;
131 value = SkAbs32(value); 153 value = SkAbs32(value);
132 max = SkMax32(max, value); 154 max = SkMax32(max, value);
133 } 155 }
134 156
135 /* All of fArray[] values must fit in 23 bits, to safely allow me to 157 /* All of fArray[] values must fit in 23 bits, to safely allow me to
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 235
214 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) { 236 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
215 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar)); 237 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar));
216 this->initState(array); 238 this->initState(array);
217 } 239 }
218 240
219 uint32_t SkColorMatrixFilter::getFlags() const { 241 uint32_t SkColorMatrixFilter::getFlags() const {
220 return this->INHERITED::getFlags() | fFlags; 242 return this->INHERITED::getFlags() | fFlags;
221 } 243 }
222 244
223 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, 245 /**
224 SkPMColor dst[]) const { 246 * Need inv255 = 1 / 255 as a constant, so when we premul a SkPMFloat, we can d o this
247 *
248 * new_red = old_red * alpha * inv255
249 *
250 * instead of (much slower)
251 *
252 * new_red = old_red * alpha / 255
253 *
254 * However, 1.0f/255 comes to (in hex) 0x3B808081, which is slightly bigger tha n the "actual"
255 * value of 0x3B808080(repeat 80)... This slightly too-big value can cause us t o compute
256 * new_red > alpha, which is a problem (for valid premul). To fix this, we use a
257 * hand-computed value of 0x3B808080, 1 ULP smaller. This keeps our colors vali d.
258 */
259 static const float gInv255 = 0.0039215683f; // (1.0f / 255) - ULP == SkBits2Flo at(0x3B808080)
260
261 static Sk4f premul(const Sk4f& x) {
262 float scale = SkPMFloat(x).a() * gInv255;
263 Sk4f pm = x * Sk4f(scale, scale, scale, 1);
264
265 #ifdef SK_DEBUG
266 SkPMFloat pmf(pm);
267 SkASSERT(pmf.isValid());
268 #endif
269
270 return pm;
271 }
272
273 static Sk4f unpremul(const SkPMFloat& pm) {
274 float scale = 255 / pm.a(); // candidate for fast/approx invert?
275 return Sk4f(pm) * Sk4f(scale, scale, scale, 1);
276 }
277
278 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
225 Proc proc = fProc; 279 Proc proc = fProc;
226 const State& state = fState;
227 int32_t result[4];
228
229 if (NULL == proc) { 280 if (NULL == proc) {
230 if (src != dst) { 281 if (src != dst) {
231 memcpy(dst, src, count * sizeof(SkPMColor)); 282 memcpy(dst, src, count * sizeof(SkPMColor));
232 } 283 }
233 return; 284 return;
234 } 285 }
235 286
236 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 287 #ifdef SK_SUPPORT_LEGACY_INT_COLORMATRIX
288 const bool use_floats = false;
289 #else
290 const bool use_floats = true;
291 #endif
237 292
238 for (int i = 0; i < count; i++) { 293 if (use_floats) {
239 SkPMColor c = src[i]; 294 const Sk4f c0 = Sk4f::Load(fTranspose + 0);
295 const Sk4f c1 = Sk4f::Load(fTranspose + 4);
296 const Sk4f c2 = Sk4f::Load(fTranspose + 8);
297 const Sk4f c3 = Sk4f::Load(fTranspose + 12);
298 const Sk4f c4 = Sk4f::Load(fTranspose + 16); // translates
240 299
241 unsigned r = SkGetPackedR32(c); 300 SkPMColor matrix_translate_pmcolor = SkPMFloat(premul(c4)).clamped();
242 unsigned g = SkGetPackedG32(c);
243 unsigned b = SkGetPackedB32(c);
244 unsigned a = SkGetPackedA32(c);
245 301
246 // need our components to be un-premultiplied 302 for (int i = 0; i < count; i++) {
247 if (255 != a) { 303 const SkPMColor src_c = src[i];
248 SkUnPreMultiply::Scale scale = table[a]; 304 if (0 == src_c) {
249 r = SkUnPreMultiply::ApplyScale(scale, r); 305 dst[i] = matrix_translate_pmcolor;
250 g = SkUnPreMultiply::ApplyScale(scale, g); 306 continue;
251 b = SkUnPreMultiply::ApplyScale(scale, b); 307 }
252 308
253 SkASSERT(r <= 255); 309 SkPMFloat srcf(src_c);
254 SkASSERT(g <= 255); 310
255 SkASSERT(b <= 255); 311 if (0xFF != SkGetPackedA32(src_c)) {
312 srcf = unpremul(srcf);
313 }
314
315 Sk4f r4 = Sk4f(srcf.r());
316 Sk4f g4 = Sk4f(srcf.g());
317 Sk4f b4 = Sk4f(srcf.b());
318 Sk4f a4 = Sk4f(srcf.a());
319
320 // apply matrix
321 Sk4f dst4 = c0 * r4 + c1 * g4 + c2 * b4 + c3 * a4 + c4;
322
323 // pin before re-premul (convention for color-matrix???)
324 dst4 = Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), dst4));
325
326 // re-premul and write
327 dst[i] = SkPMFloat(premul(dst4)).get();
256 } 328 }
329 } else {
330 const State& state = fState;
331 int32_t result[4];
332 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
257 333
258 proc(state, r, g, b, a, result); 334 for (int i = 0; i < count; i++) {
335 SkPMColor c = src[i];
259 336
260 r = pin(result[0], SK_R32_MASK); 337 unsigned r = SkGetPackedR32(c);
261 g = pin(result[1], SK_G32_MASK); 338 unsigned g = SkGetPackedG32(c);
262 b = pin(result[2], SK_B32_MASK); 339 unsigned b = SkGetPackedB32(c);
263 a = pin(result[3], SK_A32_MASK); 340 unsigned a = SkGetPackedA32(c);
264 // re-prepremultiply if needed 341
265 dst[i] = SkPremultiplyARGBInline(a, r, g, b); 342 // need our components to be un-premultiplied
343 if (255 != a) {
344 SkUnPreMultiply::Scale scale = table[a];
345 r = SkUnPreMultiply::ApplyScale(scale, r);
346 g = SkUnPreMultiply::ApplyScale(scale, g);
347 b = SkUnPreMultiply::ApplyScale(scale, b);
348
349 SkASSERT(r <= 255);
350 SkASSERT(g <= 255);
351 SkASSERT(b <= 255);
352 }
353
354 proc(state, r, g, b, a, result);
355
356 r = pin(result[0], SK_R32_MASK);
357 g = pin(result[1], SK_G32_MASK);
358 b = pin(result[2], SK_B32_MASK);
359 a = pin(result[3], SK_A32_MASK);
360 // re-prepremultiply if needed
361 dst[i] = SkPremultiplyARGBInline(a, r, g, b);
362 }
266 } 363 }
267 } 364 }
268 365
269 void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count, 366 void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
270 uint16_t dst[]) const { 367 uint16_t dst[]) const {
271 SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag); 368 SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);
272 369
273 Proc proc = fProc; 370 Proc proc = fProc;
274 const State& state = fState; 371 const State& state = fState;
275 int32_t result[4]; 372 int32_t result[4];
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 str->append("matrix: ("); 612 str->append("matrix: (");
516 for (int i = 0; i < 20; ++i) { 613 for (int i = 0; i < 20; ++i) {
517 str->appendScalar(fMatrix.fMat[i]); 614 str->appendScalar(fMatrix.fMat[i]);
518 if (i < 19) { 615 if (i < 19) {
519 str->append(", "); 616 str->append(", ");
520 } 617 }
521 } 618 }
522 str->append(")"); 619 str->append(")");
523 } 620 }
524 #endif 621 #endif
OLDNEW
« no previous file with comments | « include/effects/SkColorMatrixFilter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698