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

Side by Side Diff: src/effects/gradients/Sk4fLinearGradient.cpp

Issue 1808963005: 4f linear gradient shader blitters (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 4 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
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 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 "Sk4fGradientPriv.h" 8 #include "Sk4fGradientPriv.h"
9 #include "Sk4fLinearGradient.h" 9 #include "Sk4fLinearGradient.h"
10 #include "SkXfermode.h"
10 11
11 namespace { 12 namespace {
12 13
13 template<typename DstType, bool do_premul> 14 template<typename DstType, SkColorProfileType, bool do_premul>
14 void fill(const Sk4f& c, DstType* dst, int n); 15 void fill(const Sk4f& c, DstType* dst, int n);
15 16
16 template<> 17 template<>
17 void fill<SkPM4f, false>(const Sk4f& c, SkPM4f* dst, int n) { 18 void fill<SkPM4f, kLinear_SkColorProfileType, false>(const Sk4f& c, SkPM4f* dst, int n) {
18 while (n > 0) { 19 while (n > 0) {
19 c.store(dst++); 20 c.store(dst++);
20 n--; 21 n--;
21 } 22 }
22 } 23 }
23 24
24 template<> 25 template<>
25 void fill<SkPM4f, true>(const Sk4f& c, SkPM4f* dst, int n) { 26 void fill<SkPM4f, kLinear_SkColorProfileType, true>(const Sk4f& c, SkPM4f* dst, int n) {
26 fill<SkPM4f, false>(premul_4f(c), dst, n); 27 fill<SkPM4f, kLinear_SkColorProfileType, false>(premul_4f(c), dst, n);
27 } 28 }
28 29
29 template<> 30 template<>
30 void fill<SkPMColor, false>(const Sk4f& c, SkPMColor* dst, int n) { 31 void fill<SkPMColor, kLinear_SkColorProfileType, false>(const Sk4f& c, SkPMColor * dst, int n) {
31 sk_memset32(dst, trunc_from_255<false>(c), n); 32 sk_memset32(dst, trunc_from_255<false>(c), n);
32 } 33 }
33 34
34 template<> 35 template<>
35 void fill<SkPMColor, true>(const Sk4f& c, SkPMColor* dst, int n) { 36 void fill<SkPMColor, kLinear_SkColorProfileType, true>(const Sk4f& c, SkPMColor* dst, int n) {
36 sk_memset32(dst, trunc_from_255<true>(c), n); 37 sk_memset32(dst, trunc_from_255<true>(c), n);
37 } 38 }
38 39
39 template<typename DstType, bool do_premul> 40 template<>
41 void fill<SkPMColor, kSRGB_SkColorProfileType, false>(const Sk4f& c, SkPMColor* dst, int n) {
42 // FIXME: this assumes opaque colors. Handle unpremultiplication.
43 const SkPMColor pmc = Sk4f_toS32(c);
44 sk_memset32(dst, pmc, n);
45 }
46
47 template<>
48 void fill<SkPMColor, kSRGB_SkColorProfileType, true>(const Sk4f& c, SkPMColor* d st, int n) {
49 const SkPMColor s32 = Sk4f_toS32(c);
50 const SkPMColor pmc = SkPreMultiplyARGB(SkGetPackedA32(s32), SkGetPackedR32( s32),
51 SkGetPackedG32(s32), SkGetPackedB32( s32));
52 sk_memset32(dst, pmc, n);
53 }
54
55 template<>
56 void fill<uint64_t, kLinear_SkColorProfileType, false>(const Sk4f& c, uint64_t* dst, int n) {
57 const uint64_t c64 = SkFloatToHalf_01(c);
58 while (n > 0) {
reed1 2016/03/18 14:28:59 sk_memset64() ?
f(malita) 2016/03/18 16:54:11 added/done.
59 *dst++ = c64;
60 n--;
61 }
62 }
63
64 template<>
65 void fill<uint64_t, kLinear_SkColorProfileType, true>(const Sk4f& c, uint64_t* d st, int n) {
66 fill<uint64_t, kLinear_SkColorProfileType, false>(premul_4f(c), dst, n);
67 }
68
69 template<typename DstType, SkColorProfileType profile, bool do_premul>
40 void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { 70 void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) {
41 SkASSERT(n > 0); 71 SkASSERT(n > 0);
42 72
43 const Sk4f dc2 = dc + dc; 73 const Sk4f dc2 = dc + dc;
44 const Sk4f dc4 = dc2 + dc2; 74 const Sk4f dc4 = dc2 + dc2;
45 75
46 Sk4f c0 = c ; 76 Sk4f c0 = c ;
47 Sk4f c1 = c + dc; 77 Sk4f c1 = c + dc;
48 Sk4f c2 = c0 + dc2; 78 Sk4f c2 = c0 + dc2;
49 Sk4f c3 = c1 + dc2; 79 Sk4f c3 = c1 + dc2;
50 80
51 while (n >= 4) { 81 while (n >= 4) {
52 store4x<DstType, do_premul>(c0, c1, c2, c3, dst); 82 store4x<DstType, profile, do_premul>(c0, c1, c2, c3, dst);
53 dst += 4; 83 dst += 4;
54 84
55 c0 = c0 + dc4; 85 c0 = c0 + dc4;
56 c1 = c1 + dc4; 86 c1 = c1 + dc4;
57 c2 = c2 + dc4; 87 c2 = c2 + dc4;
58 c3 = c3 + dc4; 88 c3 = c3 + dc4;
59 n -= 4; 89 n -= 4;
60 } 90 }
61 if (n & 2) { 91 if (n & 2) {
62 store<DstType, do_premul>(c0, dst++); 92 store<DstType, profile, do_premul>(c0, dst++);
63 store<DstType, do_premul>(c1, dst++); 93 store<DstType, profile, do_premul>(c1, dst++);
64 c0 = c0 + dc2; 94 c0 = c0 + dc2;
65 } 95 }
66 if (n & 1) { 96 if (n & 1) {
67 store<DstType, do_premul>(c0, dst); 97 store<DstType, profile, do_premul>(c0, dst);
68 } 98 }
69 } 99 }
70 100
71 template<SkShader::TileMode> 101 template<SkShader::TileMode>
72 SkScalar pinFx(SkScalar); 102 SkScalar pinFx(SkScalar);
73 103
74 template<> 104 template<>
75 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) { 105 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) {
76 return fx; 106 return fx;
77 } 107 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 void SkLinearGradient:: 186 void SkLinearGradient::
157 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { 187 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) {
158 if (!this->isFast()) { 188 if (!this->isFast()) {
159 this->INHERITED::shadeSpan(x, y, dst, count); 189 this->INHERITED::shadeSpan(x, y, dst, count);
160 return; 190 return;
161 } 191 }
162 192
163 // TODO: plumb dithering 193 // TODO: plumb dithering
164 SkASSERT(count > 0); 194 SkASSERT(count > 0);
165 if (fColorsArePremul) { 195 if (fColorsArePremul) {
166 this->shadePremulSpan<SkPMColor, false>(x, y, dst, count); 196 this->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, false>(x, y , dst, count);
167 } else { 197 } else {
168 this->shadePremulSpan<SkPMColor, true>(x, y, dst, count); 198 this->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, true>(x, y, dst, count);
169 } 199 }
170 } 200 }
171 201
172 void SkLinearGradient:: 202 void SkLinearGradient::
173 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { 203 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) {
174 if (!this->isFast()) { 204 if (!this->isFast()) {
175 this->INHERITED::shadeSpan4f(x, y, dst, count); 205 this->INHERITED::shadeSpan4f(x, y, dst, count);
176 return; 206 return;
177 } 207 }
178 208
179 // TONOTDO: plumb dithering 209 // TONOTDO: plumb dithering
180 SkASSERT(count > 0); 210 SkASSERT(count > 0);
181 if (fColorsArePremul) { 211 if (fColorsArePremul) {
182 this->shadePremulSpan<SkPM4f, false>(x, y, dst, count); 212 this->shadePremulSpan<SkPM4f, kLinear_SkColorProfileType, false>(x, y, d st, count);
183 } else { 213 } else {
184 this->shadePremulSpan<SkPM4f, true>(x, y, dst, count); 214 this->shadePremulSpan<SkPM4f, kLinear_SkColorProfileType, true>(x, y, ds t, count);
185 } 215 }
186 } 216 }
187 217
188 template<typename DstType, bool do_premul> 218 template<typename DstType, SkColorProfileType profile, bool do_premul>
189 void SkLinearGradient:: 219 void SkLinearGradient::
190 LinearGradient4fContext::shadePremulSpan(int x, int y, 220 LinearGradient4fContext::shadePremulSpan(int x, int y,
191 DstType dst[], 221 DstType dst[],
192 int count) const { 222 int count) const {
193 const SkLinearGradient& shader = 223 const SkLinearGradient& shader =
194 static_cast<const SkLinearGradient&>(fShader); 224 static_cast<const SkLinearGradient&>(fShader);
195 switch (shader.fTileMode) { 225 switch (shader.fTileMode) {
196 case kClamp_TileMode: 226 case kClamp_TileMode:
197 this->shadeSpanInternal<DstType, 227 this->shadeSpanInternal<DstType,
228 profile,
198 do_premul, 229 do_premul,
199 kClamp_TileMode>(x, y, dst, count); 230 kClamp_TileMode>(x, y, dst, count);
200 break; 231 break;
201 case kRepeat_TileMode: 232 case kRepeat_TileMode:
202 this->shadeSpanInternal<DstType, 233 this->shadeSpanInternal<DstType,
234 profile,
203 do_premul, 235 do_premul,
204 kRepeat_TileMode>(x, y, dst, count); 236 kRepeat_TileMode>(x, y, dst, count);
205 break; 237 break;
206 case kMirror_TileMode: 238 case kMirror_TileMode:
207 this->shadeSpanInternal<DstType, 239 this->shadeSpanInternal<DstType,
240 profile,
208 do_premul, 241 do_premul,
209 kMirror_TileMode>(x, y, dst, count); 242 kMirror_TileMode>(x, y, dst, count);
210 break; 243 break;
211 } 244 }
212 } 245 }
213 246
214 template<typename DstType, bool do_premul, SkShader::TileMode tileMode> 247 template<typename DstType, SkColorProfileType profile, bool do_premul,
248 SkShader::TileMode tileMode>
215 void SkLinearGradient:: 249 void SkLinearGradient::
216 LinearGradient4fContext::shadeSpanInternal(int x, int y, 250 LinearGradient4fContext::shadeSpanInternal(int x, int y,
217 DstType dst[], 251 DstType dst[],
218 int count) const { 252 int count) const {
219 SkPoint pt; 253 SkPoint pt;
220 fDstToPosProc(fDstToPos, 254 fDstToPosProc(fDstToPos,
221 x + SK_ScalarHalf, 255 x + SK_ScalarHalf,
222 y + SK_ScalarHalf, 256 y + SK_ScalarHalf,
223 &pt); 257 &pt);
224 const SkScalar fx = pinFx<tileMode>(pt.x()); 258 const SkScalar fx = pinFx<tileMode>(pt.x());
225 const SkScalar dx = fDstToPos.getScaleX(); 259 const SkScalar dx = fDstToPos.getScaleX();
226 LinearIntervalProcessor<DstType, tileMode> proc(fIntervals.begin(), 260 LinearIntervalProcessor<DstType, profile, tileMode> proc(fIntervals.begin(),
227 fIntervals.end() - 1, 261 fIntervals.end() - 1,
228 this->findInterval(fx), 262 this->findInterval( fx),
229 fx, 263 fx,
230 dx, 264 dx,
231 SkScalarNearlyZero(dx * coun t)); 265 SkScalarNearlyZero( dx * count));
232 while (count > 0) { 266 while (count > 0) {
233 // What we really want here is SkTPin(advance, 1, count) 267 // What we really want here is SkTPin(advance, 1, count)
234 // but that's a significant perf hit for >> stops; investigate. 268 // but that's a significant perf hit for >> stops; investigate.
235 const int n = SkScalarTruncToInt( 269 const int n = SkScalarTruncToInt(
236 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); 270 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count)));
237 271
238 // The current interval advance can be +inf (e.g. when reaching 272 // The current interval advance can be +inf (e.g. when reaching
239 // the clamp mode end intervals) - when that happens, we expect to 273 // the clamp mode end intervals) - when that happens, we expect to
240 // a) consume all remaining count in one swoop 274 // a) consume all remaining count in one swoop
241 // b) return a zero color gradient 275 // b) return a zero color gradient
242 SkASSERT(SkScalarIsFinite(proc.currentAdvance()) 276 SkASSERT(SkScalarIsFinite(proc.currentAdvance())
243 || (n == count && proc.currentRampIsZero())); 277 || (n == count && proc.currentRampIsZero()));
244 278
245 if (proc.currentRampIsZero()) { 279 if (proc.currentRampIsZero()) {
246 fill<DstType, do_premul>(proc.currentColor(), 280 fill<DstType, profile, do_premul>(proc.currentColor(),
247 dst, n); 281 dst, n);
248 } else { 282 } else {
249 ramp<DstType, do_premul>(proc.currentColor(), 283 ramp<DstType, profile, do_premul>(proc.currentColor(),
250 proc.currentColorGrad(), 284 proc.currentColorGrad(),
251 dst, n); 285 dst, n);
252 } 286 }
253 287
254 proc.advance(SkIntToScalar(n)); 288 proc.advance(SkIntToScalar(n));
255 count -= n; 289 count -= n;
256 dst += n; 290 dst += n;
257 } 291 }
258 } 292 }
259 293
260 template<typename DstType, SkShader::TileMode tileMode> 294 template<typename DstType, SkColorProfileType profile, SkShader::TileMode tileMo de>
261 class SkLinearGradient:: 295 class SkLinearGradient::
262 LinearGradient4fContext::LinearIntervalProcessor { 296 LinearGradient4fContext::LinearIntervalProcessor {
263 public: 297 public:
264 LinearIntervalProcessor(const Interval* firstInterval, 298 LinearIntervalProcessor(const Interval* firstInterval,
265 const Interval* lastInterval, 299 const Interval* lastInterval,
266 const Interval* i, 300 const Interval* i,
267 SkScalar fx, 301 SkScalar fx,
268 SkScalar dx, 302 SkScalar dx,
269 bool is_vertical) 303 bool is_vertical)
270 : fDstComponentScale(dst_component_scale<DstType>()) 304 : fAdvX((i->fP1 - fx) / dx)
271 , fAdvX((i->fP1 - fx) / dx)
272 , fFirstInterval(firstInterval) 305 , fFirstInterval(firstInterval)
273 , fLastInterval(lastInterval) 306 , fLastInterval(lastInterval)
274 , fInterval(i) 307 , fInterval(i)
275 , fDx(dx) 308 , fDx(dx)
276 , fIsVertical(is_vertical) 309 , fIsVertical(is_vertical)
277 { 310 {
278 SkASSERT(firstInterval <= lastInterval); 311 SkASSERT(firstInterval <= lastInterval);
279 SkASSERT(in_range(fx, i->fP0, i->fP1)); 312 SkASSERT(in_range(fx, i->fP0, i->fP1));
280 this->compute_interval_props(fx - i->fP0); 313 this->compute_interval_props(fx - i->fP0);
281 } 314 }
(...skipping 19 matching lines...) Expand all
301 334
302 fCc = fCc + fDcDx * Sk4f(advX); 335 fCc = fCc + fDcDx * Sk4f(advX);
303 fAdvX -= advX; 336 fAdvX -= advX;
304 } 337 }
305 338
306 private: 339 private:
307 void compute_interval_props(SkScalar t) { 340 void compute_interval_props(SkScalar t) {
308 fDc = dst_swizzle<DstType>(fInterval->fDc); 341 fDc = dst_swizzle<DstType>(fInterval->fDc);
309 fCc = dst_swizzle<DstType>(fInterval->fC0); 342 fCc = dst_swizzle<DstType>(fInterval->fC0);
310 fCc = fCc + fDc * Sk4f(t); 343 fCc = fCc + fDc * Sk4f(t);
311 fCc = fCc * fDstComponentScale; 344 fCc = scale_for_dest<DstType, profile>(fCc);
312 fDcDx = fDc * fDstComponentScale * Sk4f(fDx); 345 fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx));
313 fZeroRamp = fIsVertical || fInterval->isZeroRamp(); 346 fZeroRamp = fIsVertical || fInterval->isZeroRamp();
314 } 347 }
315 348
316 const Interval* next_interval(const Interval* i) const { 349 const Interval* next_interval(const Interval* i) const {
317 SkASSERT(i >= fFirstInterval); 350 SkASSERT(i >= fFirstInterval);
318 SkASSERT(i <= fLastInterval); 351 SkASSERT(i <= fLastInterval);
319 i++; 352 i++;
320 353
321 if (tileMode == kClamp_TileMode) { 354 if (tileMode == kClamp_TileMode) {
322 SkASSERT(i <= fLastInterval); 355 SkASSERT(i <= fLastInterval);
(...skipping 12 matching lines...) Expand all
335 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx; 368 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx;
336 SkASSERT(fAdvX > 0); 369 SkASSERT(fAdvX > 0);
337 } while (advX >= fAdvX); 370 } while (advX >= fAdvX);
338 371
339 compute_interval_props(0); 372 compute_interval_props(0);
340 373
341 SkASSERT(advX >= 0); 374 SkASSERT(advX >= 0);
342 return advX; 375 return advX;
343 } 376 }
344 377
345 const Sk4f fDstComponentScale; // cached dst scale (PMC: 255, PM4f: 1)
346
347 // Current interval properties. 378 // Current interval properties.
348 Sk4f fDc; // local color gradient (dc/dt) 379 Sk4f fDc; // local color gradient (dc/dt)
349 Sk4f fDcDx; // dst color gradient (dc/dx) 380 Sk4f fDcDx; // dst color gradient (dc/dx)
350 Sk4f fCc; // current color, interpolated in dst 381 Sk4f fCc; // current color, interpolated in dst
351 SkScalar fAdvX; // remaining interval advance in dst 382 SkScalar fAdvX; // remaining interval advance in dst
352 bool fZeroRamp; // current interval color grad is 0 383 bool fZeroRamp; // current interval color grad is 0
353 384
354 const Interval* fFirstInterval; 385 const Interval* fFirstInterval;
355 const Interval* fLastInterval; 386 const Interval* fLastInterval;
356 const Interval* fInterval; // current interval 387 const Interval* fInterval; // current interval
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 *ts++ = t4[0]; 426 *ts++ = t4[0];
396 } 427 }
397 } else { 428 } else {
398 for (int i = 0; i < count; ++i) { 429 for (int i = 0; i < count; ++i) {
399 fDstToPosProc(fDstToPos, sx, sy, &pt); 430 fDstToPosProc(fDstToPos, sx, sy, &pt);
400 ts[i] = pt.x(); 431 ts[i] = pt.x();
401 sx += SK_Scalar1; 432 sx += SK_Scalar1;
402 } 433 }
403 } 434 }
404 } 435 }
436
437 SkShader::Context::BlitProc SkLinearGradient::
438 LinearGradient4fContext::onChooseBlitProc(const SkImageInfo& info, BlitState* st ate) {
439 SkXfermode::Mode mode;
440 if (!SkXfermode::AsMode(state->fXfer, &mode)) {
441 return nullptr;
442 }
443
444 const SkGradientShaderBase& shader = static_cast<const SkGradientShaderBase& >(fShader);
445 if (mode != SkXfermode::kSrc_Mode &&
446 !(mode == SkXfermode::kSrcOver_Mode && shader.colorsAreOpaque())) {
447 return nullptr;
448 }
449
450 switch (info.colorType()) {
451 case kN32_SkColorType:
452 return D32_BlitProc;
453 case kRGBA_F16_SkColorType:
454 return D64_BlitProc;
455 default:
456 return nullptr;
457 }
458 }
459
460 void SkLinearGradient::
461 LinearGradient4fContext::D32_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst,
462 int count, const SkAlpha aa[]) {
463 // FIXME: ignoring coverage for now
464 const LinearGradient4fContext* ctx =
465 static_cast<const LinearGradient4fContext*>(state->fCtx);
466
467 if (dst.info().isLinear()) {
468 if (ctx->fColorsArePremul) {
469 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, false>(
470 x, y, dst.writable_addr32(x, y), count);
471 } else {
472 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, true>(
473 x, y, dst.writable_addr32(x, y), count);
474 }
475 } else {
476 if (ctx->fColorsArePremul) {
477 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, false>(
478 x, y, dst.writable_addr32(x, y), count);
479 } else {
480 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, true>(
481 x, y, dst.writable_addr32(x, y), count);
482 }
483 }
484 }
485
486 void SkLinearGradient::
487 LinearGradient4fContext::D64_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst,
488 int count, const SkAlpha aa[]) {
489 // FIXME: ignoring coverage for now
490 const LinearGradient4fContext* ctx =
491 static_cast<const LinearGradient4fContext*>(state->fCtx);
492
493 if (ctx->fColorsArePremul) {
494 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, false>(
495 x, y, dst.writable_addr64(x, y), count);
496 } else {
497 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, true>(
498 x, y, dst.writable_addr64(x, y), count);
499 }
500 }
OLDNEW
« src/effects/gradients/Sk4fGradientPriv.h ('K') | « src/effects/gradients/Sk4fLinearGradient.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698