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

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

Issue 1030743003: Revert of 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
1 /* 2 /*
2 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
3 * 4 *
4 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 6 * found in the LICENSE file.
6 */ 7 */
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"
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)
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
36 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g, 16 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
37 unsigned b, unsigned a) { 17 unsigned b, unsigned a) {
38 return array[0] * r + array[1] * g + array[2] * b + array[3] * a + array[4] ; 18 return array[0] * r + array[1] * g + array[2] * b + array[3] * a + array[4] ;
39 } 19 }
40 20
41 static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g, 21 static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g,
42 unsigned b) { 22 unsigned b) {
43 return array[0] * r + array[1] * g + array[2] * b + array[4]; 23 return array[0] * r + array[1] * g + array[2] * b + array[4];
44 } 24 }
45 25
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 result[2] = b + (array[SkColorMatrix::kB_Trans] >> 16); 116 result[2] = b + (array[SkColorMatrix::kB_Trans] >> 16);
137 result[3] = a; 117 result[3] = a;
138 } 118 }
139 119
140 #define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag | \ 120 #define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag | \
141 SkColorFilter::kHasFilter16_Flag) 121 SkColorFilter::kHasFilter16_Flag)
142 122
143 // src is [20] but some compilers won't accept __restrict__ on anything 123 // src is [20] but some compilers won't accept __restrict__ on anything
144 // but an raw pointer or reference 124 // but an raw pointer or reference
145 void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) { 125 void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
146 transpose_to_pmorder(fTranspose, src);
147
148 int32_t* array = fState.fArray; 126 int32_t* array = fState.fArray;
149 SkFixed max = 0; 127 SkFixed max = 0;
150 for (int i = 0; i < 20; i++) { 128 for (int i = 0; i < 20; i++) {
151 SkFixed value = SkScalarToFixed(src[i]); 129 SkFixed value = SkScalarToFixed(src[i]);
152 array[i] = value; 130 array[i] = value;
153 value = SkAbs32(value); 131 value = SkAbs32(value);
154 max = SkMax32(max, value); 132 max = SkMax32(max, value);
155 } 133 }
156 134
157 /* All of fArray[] values must fit in 23 bits, to safely allow me to 135 /* 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
235 213
236 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) { 214 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
237 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar)); 215 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar));
238 this->initState(array); 216 this->initState(array);
239 } 217 }
240 218
241 uint32_t SkColorMatrixFilter::getFlags() const { 219 uint32_t SkColorMatrixFilter::getFlags() const {
242 return this->INHERITED::getFlags() | fFlags; 220 return this->INHERITED::getFlags() | fFlags;
243 } 221 }
244 222
245 /** 223 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count,
246 * Need inv255 = 1 / 255 as a constant, so when we premul a SkPMFloat, we can d o this 224 SkPMColor dst[]) const {
247 * 225 Proc proc = fProc;
248 * new_red = old_red * alpha * inv255 226 const State& state = fState;
249 * 227 int32_t result[4];
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 228
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 {
279 Proc proc = fProc;
280 if (NULL == proc) { 229 if (NULL == proc) {
281 if (src != dst) { 230 if (src != dst) {
282 memcpy(dst, src, count * sizeof(SkPMColor)); 231 memcpy(dst, src, count * sizeof(SkPMColor));
283 } 232 }
284 return; 233 return;
285 } 234 }
286 235
287 #ifdef SK_SUPPORT_LEGACY_INT_COLORMATRIX 236 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
288 const bool use_floats = false;
289 #else
290 const bool use_floats = true;
291 #endif
292 237
293 if (use_floats) { 238 for (int i = 0; i < count; i++) {
294 const Sk4f c0 = Sk4f::Load(fTranspose + 0); 239 SkPMColor c = src[i];
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
299 240
300 SkPMColor matrix_translate_pmcolor = SkPMFloat(premul(c4)).clamped(); 241 unsigned r = SkGetPackedR32(c);
242 unsigned g = SkGetPackedG32(c);
243 unsigned b = SkGetPackedB32(c);
244 unsigned a = SkGetPackedA32(c);
301 245
302 for (int i = 0; i < count; i++) { 246 // need our components to be un-premultiplied
303 const SkPMColor src_c = src[i]; 247 if (255 != a) {
304 if (0 == src_c) { 248 SkUnPreMultiply::Scale scale = table[a];
305 dst[i] = matrix_translate_pmcolor; 249 r = SkUnPreMultiply::ApplyScale(scale, r);
306 continue; 250 g = SkUnPreMultiply::ApplyScale(scale, g);
307 } 251 b = SkUnPreMultiply::ApplyScale(scale, b);
308 252
309 SkPMFloat srcf(src_c); 253 SkASSERT(r <= 255);
254 SkASSERT(g <= 255);
255 SkASSERT(b <= 255);
256 }
310 257
311 if (0xFF != SkGetPackedA32(src_c)) { 258 proc(state, r, g, b, a, result);
312 srcf = unpremul(srcf);
313 }
314 259
315 Sk4f r4 = Sk4f(srcf.r()); 260 r = pin(result[0], SK_R32_MASK);
316 Sk4f g4 = Sk4f(srcf.g()); 261 g = pin(result[1], SK_G32_MASK);
317 Sk4f b4 = Sk4f(srcf.b()); 262 b = pin(result[2], SK_B32_MASK);
318 Sk4f a4 = Sk4f(srcf.a()); 263 a = pin(result[3], SK_A32_MASK);
319 264 // re-prepremultiply if needed
320 // apply matrix 265 dst[i] = SkPremultiplyARGBInline(a, r, g, b);
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();
328 }
329 } else {
330 const State& state = fState;
331 int32_t result[4];
332 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
333
334 for (int i = 0; i < count; i++) {
335 SkPMColor c = src[i];
336
337 unsigned r = SkGetPackedR32(c);
338 unsigned g = SkGetPackedG32(c);
339 unsigned b = SkGetPackedB32(c);
340 unsigned a = SkGetPackedA32(c);
341
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 }
363 } 266 }
364 } 267 }
365 268
366 void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count, 269 void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
367 uint16_t dst[]) const { 270 uint16_t dst[]) const {
368 SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag); 271 SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);
369 272
370 Proc proc = fProc; 273 Proc proc = fProc;
371 const State& state = fState; 274 const State& state = fState;
372 int32_t result[4]; 275 int32_t result[4];
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 str->append("matrix: ("); 515 str->append("matrix: (");
613 for (int i = 0; i < 20; ++i) { 516 for (int i = 0; i < 20; ++i) {
614 str->appendScalar(fMatrix.fMat[i]); 517 str->appendScalar(fMatrix.fMat[i]);
615 if (i < 19) { 518 if (i < 19) {
616 str->append(", "); 519 str->append(", ");
617 } 520 }
618 } 521 }
619 str->append(")"); 522 str->append(")");
620 } 523 }
621 #endif 524 #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