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

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

Issue 1201343004: Convert SkPMFloat to [0,1] range and prune its API. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweaks Created 5 years, 6 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 | « src/core/SkPMFloat.h ('k') | src/opts/SkPMFloat_SSE2.h » ('j') | 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 * 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 "SkColorMatrixFilter.h"
9 #include "SkColorMatrix.h" 9 #include "SkColorMatrix.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 232
233 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) { 233 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
234 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar)); 234 memcpy(fMatrix.fMat, array, 20 * sizeof(SkScalar));
235 this->initState(array); 235 this->initState(array);
236 } 236 }
237 237
238 uint32_t SkColorMatrixFilter::getFlags() const { 238 uint32_t SkColorMatrixFilter::getFlags() const {
239 return this->INHERITED::getFlags() | fFlags; 239 return this->INHERITED::getFlags() | fFlags;
240 } 240 }
241 241
242 /**
243 * Need inv255 = 1 / 255 as a constant, so when we premul a SkPMFloat, we can d o this
244 *
245 * new_red = old_red * alpha * inv255
246 *
247 * instead of (much slower)
248 *
249 * new_red = old_red * alpha / 255
250 *
251 * However, 1.0f/255 comes to (in hex) 0x3B808081, which is slightly bigger tha n the "actual"
252 * value of 0x3B808080(repeat 80)... This slightly too-big value can cause us t o compute
253 * new_red > alpha, which is a problem (for valid premul). To fix this, we use a
254 * hand-computed value of 0x3B808080, 1 ULP smaller. This keeps our colors vali d.
255 */
256 static const float gInv255 = 0.0039215683f; // (1.0f / 255) - ULP == SkBits2Flo at(0x3B808080)
257
258 static Sk4f premul(const Sk4f& x) { 242 static Sk4f premul(const Sk4f& x) {
259 float scale = SkPMFloat(x).a() * gInv255; 243 float scale = SkPMFloat(x).a();
260 Sk4f pm = x * Sk4f(scale, scale, scale, 1); 244 Sk4f pm = x * SkPMFloat(1, scale, scale, scale);
261 245
262 #ifdef SK_DEBUG 246 #ifdef SK_DEBUG
263 SkPMFloat pmf(pm); 247 SkPMFloat pmf(pm);
264 SkASSERT(pmf.isValid()); 248 SkASSERT(pmf.isValid());
265 #endif 249 #endif
266 250
267 return pm; 251 return pm;
268 } 252 }
269 253
270 static Sk4f unpremul(const SkPMFloat& pm) { 254 static Sk4f unpremul(const SkPMFloat& pm) {
271 float scale = 255 / pm.a(); // candidate for fast/approx invert? 255 float scale = 1 / pm.a(); // candidate for fast/approx invert?
272 return pm * Sk4f(scale, scale, scale, 1); 256 return pm * SkPMFloat(1, scale, scale, scale);
273 } 257 }
274 258
275 static Sk4f clamp_0_255(const Sk4f& value) { 259 static Sk4f clamp_0_1(const Sk4f& value) {
276 return Sk4f::Max(Sk4f::Min(value, Sk4f(255)), Sk4f(0)); 260 return Sk4f::Max(Sk4f::Min(value, Sk4f(1)), Sk4f(0));
277 } 261 }
278 262
279 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const { 263 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
280 Proc proc = fProc; 264 Proc proc = fProc;
281 if (NULL == proc) { 265 if (NULL == proc) {
282 if (src != dst) { 266 if (src != dst) {
283 memcpy(dst, src, count * sizeof(SkPMColor)); 267 memcpy(dst, src, count * sizeof(SkPMColor));
284 } 268 }
285 return; 269 return;
286 } 270 }
287 271
288 #ifdef SK_SUPPORT_LEGACY_INT_COLORMATRIX 272 #ifdef SK_SUPPORT_LEGACY_INT_COLORMATRIX
289 const bool use_floats = false; 273 const bool use_floats = false;
290 #else 274 #else
291 const bool use_floats = true; 275 const bool use_floats = true;
292 #endif 276 #endif
293 277
294 if (use_floats) { 278 if (use_floats) {
279 // c0-c3 are already in [0,1].
295 const Sk4f c0 = Sk4f::Load(fTranspose + 0); 280 const Sk4f c0 = Sk4f::Load(fTranspose + 0);
296 const Sk4f c1 = Sk4f::Load(fTranspose + 4); 281 const Sk4f c1 = Sk4f::Load(fTranspose + 4);
297 const Sk4f c2 = Sk4f::Load(fTranspose + 8); 282 const Sk4f c2 = Sk4f::Load(fTranspose + 8);
298 const Sk4f c3 = Sk4f::Load(fTranspose + 12); 283 const Sk4f c3 = Sk4f::Load(fTranspose + 12);
299 const Sk4f c4 = Sk4f::Load(fTranspose + 16); // translates 284 // c4 (the translate vector) is in [0, 255]. Bring it back to [0,1].
285 const Sk4f c4 = Sk4f::Load(fTranspose + 16)*Sk4f(1.0f/255);
300 286
301 // todo: we could cache this in the constructor... 287 // todo: we could cache this in the constructor...
302 SkPMColor matrix_translate_pmcolor = SkPMFloat(premul(clamp_0_255(c4))). roundClamp(); 288 SkPMColor matrix_translate_pmcolor = SkPMFloat(premul(clamp_0_1(c4))).ro und();
303 289
304 for (int i = 0; i < count; i++) { 290 for (int i = 0; i < count; i++) {
305 const SkPMColor src_c = src[i]; 291 const SkPMColor src_c = src[i];
306 if (0 == src_c) { 292 if (0 == src_c) {
307 dst[i] = matrix_translate_pmcolor; 293 dst[i] = matrix_translate_pmcolor;
308 continue; 294 continue;
309 } 295 }
310 296
311 SkPMFloat srcf(src_c); 297 SkPMFloat srcf(src_c);
312 298
313 if (0xFF != SkGetPackedA32(src_c)) { 299 if (0xFF != SkGetPackedA32(src_c)) {
314 srcf = unpremul(srcf); 300 srcf = unpremul(srcf);
315 } 301 }
316 302
317 Sk4f r4 = Sk4f(srcf.r()); 303 Sk4f r4 = Sk4f(srcf.r());
318 Sk4f g4 = Sk4f(srcf.g()); 304 Sk4f g4 = Sk4f(srcf.g());
319 Sk4f b4 = Sk4f(srcf.b()); 305 Sk4f b4 = Sk4f(srcf.b());
320 Sk4f a4 = Sk4f(srcf.a()); 306 Sk4f a4 = Sk4f(srcf.a());
321 307
322 // apply matrix 308 // apply matrix
323 Sk4f dst4 = c0 * r4 + c1 * g4 + c2 * b4 + c3 * a4 + c4; 309 Sk4f dst4 = c0 * r4 + c1 * g4 + c2 * b4 + c3 * a4 + c4;
324 310
325 // clamp, re-premul, and write 311 // clamp, re-premul, and write
326 dst[i] = SkPMFloat(premul(clamp_0_255(dst4))).round(); 312 dst[i] = SkPMFloat(premul(clamp_0_1(dst4))).round();
327 } 313 }
328 } else { 314 } else {
329 const State& state = fState; 315 const State& state = fState;
330 int32_t result[4]; 316 int32_t result[4];
331 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 317 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
332 318
333 for (int i = 0; i < count; i++) { 319 for (int i = 0; i < count; i++) {
334 SkPMColor c = src[i]; 320 SkPMColor c = src[i];
335 321
336 unsigned r = SkGetPackedR32(c); 322 unsigned r = SkGetPackedR32(c);
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 str->append("matrix: ("); 566 str->append("matrix: (");
581 for (int i = 0; i < 20; ++i) { 567 for (int i = 0; i < 20; ++i) {
582 str->appendScalar(fMatrix.fMat[i]); 568 str->appendScalar(fMatrix.fMat[i]);
583 if (i < 19) { 569 if (i < 19) {
584 str->append(", "); 570 str->append(", ");
585 } 571 }
586 } 572 }
587 str->append(")"); 573 str->append(")");
588 } 574 }
589 #endif 575 #endif
OLDNEW
« no previous file with comments | « src/core/SkPMFloat.h ('k') | src/opts/SkPMFloat_SSE2.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698