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

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: rename trunc_from_255 to quiet confused msvc 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
« no previous file with comments | « src/effects/gradients/Sk4fLinearGradient.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 * 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"
9 #include "Sk4fLinearGradient.h" 8 #include "Sk4fLinearGradient.h"
9 #include "SkUtils.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, ApplyPremul>
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, ApplyPremul::False>
19 (const Sk4f& c, SkPM4f* dst, int n) {
18 while (n > 0) { 20 while (n > 0) {
19 c.store(dst++); 21 c.store(dst++);
20 n--; 22 n--;
21 } 23 }
22 } 24 }
23 25
24 template<> 26 template<>
25 void fill<SkPM4f, true>(const Sk4f& c, SkPM4f* dst, int n) { 27 void fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True>
26 fill<SkPM4f, false>(premul_4f(c), dst, n); 28 (const Sk4f& c, SkPM4f* dst, int n) {
29 fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False>(premul_4f(c), d st, n);
27 } 30 }
28 31
29 template<> 32 template<>
30 void fill<SkPMColor, false>(const Sk4f& c, SkPMColor* dst, int n) { 33 void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False>
31 sk_memset32(dst, trunc_from_255<false>(c), n); 34 (const Sk4f& c, SkPMColor* dst, int n) {
35 sk_memset32(dst, trunc_from_4f_255<ApplyPremul::False>(c), n);
32 } 36 }
33 37
34 template<> 38 template<>
35 void fill<SkPMColor, true>(const Sk4f& c, SkPMColor* dst, int n) { 39 void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True>
36 sk_memset32(dst, trunc_from_255<true>(c), n); 40 (const Sk4f& c, SkPMColor* dst, int n) {
41 sk_memset32(dst, trunc_from_4f_255<ApplyPremul::True>(c), n);
37 } 42 }
38 43
39 template<typename DstType, bool do_premul> 44 template<>
45 void fill<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False>
46 (const Sk4f& c, SkPMColor* dst, int n) {
47 // FIXME: this assumes opaque colors. Handle unpremultiplication.
48 sk_memset32(dst, Sk4f_toS32(c), n);
49 }
50
51 template<>
52 void fill<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True>
53 (const Sk4f& c, SkPMColor* dst, int n) {
54 sk_memset32(dst, Sk4f_toS32(premul_4f(c)), n);
55 }
56
57 template<>
58 void fill<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False>
59 (const Sk4f& c, uint64_t* dst, int n) {
60 sk_memset64(dst, SkFloatToHalf_01(c), n);
61 }
62
63 template<>
64 void fill<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True>
65 (const Sk4f& c, uint64_t* dst, int n) {
66 sk_memset64(dst, SkFloatToHalf_01(premul_4f(c)), n);
67 }
68
69 template<typename DstType, SkColorProfileType profile, ApplyPremul 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, 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, premul>(c0, dst++);
63 store<DstType, do_premul>(c1, dst++); 93 store<DstType, profile, 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, 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,
197 kLinear_SkColorProfileType,
198 ApplyPremul::False>(x, y, dst, count);
167 } else { 199 } else {
168 this->shadePremulSpan<SkPMColor, true>(x, y, dst, count); 200 this->shadePremulSpan<SkPMColor,
201 kLinear_SkColorProfileType,
202 ApplyPremul::True>(x, y, dst, count);
169 } 203 }
170 } 204 }
171 205
172 void SkLinearGradient:: 206 void SkLinearGradient::
173 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { 207 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) {
174 if (!this->isFast()) { 208 if (!this->isFast()) {
175 this->INHERITED::shadeSpan4f(x, y, dst, count); 209 this->INHERITED::shadeSpan4f(x, y, dst, count);
176 return; 210 return;
177 } 211 }
178 212
179 // TONOTDO: plumb dithering 213 // TONOTDO: plumb dithering
180 SkASSERT(count > 0); 214 SkASSERT(count > 0);
181 if (fColorsArePremul) { 215 if (fColorsArePremul) {
182 this->shadePremulSpan<SkPM4f, false>(x, y, dst, count); 216 this->shadePremulSpan<SkPM4f,
217 kLinear_SkColorProfileType,
218 ApplyPremul::False>(x, y, dst, count);
183 } else { 219 } else {
184 this->shadePremulSpan<SkPM4f, true>(x, y, dst, count); 220 this->shadePremulSpan<SkPM4f,
221 kLinear_SkColorProfileType,
222 ApplyPremul::True>(x, y, dst, count);
185 } 223 }
186 } 224 }
187 225
188 template<typename DstType, bool do_premul> 226 template<typename DstType, SkColorProfileType profile, ApplyPremul premul>
189 void SkLinearGradient:: 227 void SkLinearGradient::
190 LinearGradient4fContext::shadePremulSpan(int x, int y, 228 LinearGradient4fContext::shadePremulSpan(int x, int y,
191 DstType dst[], 229 DstType dst[],
192 int count) const { 230 int count) const {
193 const SkLinearGradient& shader = 231 const SkLinearGradient& shader =
194 static_cast<const SkLinearGradient&>(fShader); 232 static_cast<const SkLinearGradient&>(fShader);
195 switch (shader.fTileMode) { 233 switch (shader.fTileMode) {
196 case kClamp_TileMode: 234 case kClamp_TileMode:
197 this->shadeSpanInternal<DstType, 235 this->shadeSpanInternal<DstType,
198 do_premul, 236 profile,
237 premul,
199 kClamp_TileMode>(x, y, dst, count); 238 kClamp_TileMode>(x, y, dst, count);
200 break; 239 break;
201 case kRepeat_TileMode: 240 case kRepeat_TileMode:
202 this->shadeSpanInternal<DstType, 241 this->shadeSpanInternal<DstType,
203 do_premul, 242 profile,
243 premul,
204 kRepeat_TileMode>(x, y, dst, count); 244 kRepeat_TileMode>(x, y, dst, count);
205 break; 245 break;
206 case kMirror_TileMode: 246 case kMirror_TileMode:
207 this->shadeSpanInternal<DstType, 247 this->shadeSpanInternal<DstType,
208 do_premul, 248 profile,
249 premul,
209 kMirror_TileMode>(x, y, dst, count); 250 kMirror_TileMode>(x, y, dst, count);
210 break; 251 break;
211 } 252 }
212 } 253 }
213 254
214 template<typename DstType, bool do_premul, SkShader::TileMode tileMode> 255 template<typename DstType, SkColorProfileType profile, ApplyPremul premul,
256 SkShader::TileMode tileMode>
215 void SkLinearGradient:: 257 void SkLinearGradient::
216 LinearGradient4fContext::shadeSpanInternal(int x, int y, 258 LinearGradient4fContext::shadeSpanInternal(int x, int y,
217 DstType dst[], 259 DstType dst[],
218 int count) const { 260 int count) const {
219 SkPoint pt; 261 SkPoint pt;
220 fDstToPosProc(fDstToPos, 262 fDstToPosProc(fDstToPos,
221 x + SK_ScalarHalf, 263 x + SK_ScalarHalf,
222 y + SK_ScalarHalf, 264 y + SK_ScalarHalf,
223 &pt); 265 &pt);
224 const SkScalar fx = pinFx<tileMode>(pt.x()); 266 const SkScalar fx = pinFx<tileMode>(pt.x());
225 const SkScalar dx = fDstToPos.getScaleX(); 267 const SkScalar dx = fDstToPos.getScaleX();
226 LinearIntervalProcessor<DstType, tileMode> proc(fIntervals.begin(), 268 LinearIntervalProcessor<DstType, profile, tileMode> proc(fIntervals.begin(),
227 fIntervals.end() - 1, 269 fIntervals.end() - 1,
228 this->findInterval(fx), 270 this->findInterval( fx),
229 fx, 271 fx,
230 dx, 272 dx,
231 SkScalarNearlyZero(dx * coun t)); 273 SkScalarNearlyZero( dx * count));
232 while (count > 0) { 274 while (count > 0) {
233 // What we really want here is SkTPin(advance, 1, count) 275 // What we really want here is SkTPin(advance, 1, count)
234 // but that's a significant perf hit for >> stops; investigate. 276 // but that's a significant perf hit for >> stops; investigate.
235 const int n = SkScalarTruncToInt( 277 const int n = SkScalarTruncToInt(
236 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); 278 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count)));
237 279
238 // The current interval advance can be +inf (e.g. when reaching 280 // The current interval advance can be +inf (e.g. when reaching
239 // the clamp mode end intervals) - when that happens, we expect to 281 // the clamp mode end intervals) - when that happens, we expect to
240 // a) consume all remaining count in one swoop 282 // a) consume all remaining count in one swoop
241 // b) return a zero color gradient 283 // b) return a zero color gradient
242 SkASSERT(SkScalarIsFinite(proc.currentAdvance()) 284 SkASSERT(SkScalarIsFinite(proc.currentAdvance())
243 || (n == count && proc.currentRampIsZero())); 285 || (n == count && proc.currentRampIsZero()));
244 286
245 if (proc.currentRampIsZero()) { 287 if (proc.currentRampIsZero()) {
246 fill<DstType, do_premul>(proc.currentColor(), 288 fill<DstType, profile, premul>(proc.currentColor(),
247 dst, n); 289 dst, n);
248 } else { 290 } else {
249 ramp<DstType, do_premul>(proc.currentColor(), 291 ramp<DstType, profile, premul>(proc.currentColor(),
250 proc.currentColorGrad(), 292 proc.currentColorGrad(),
251 dst, n); 293 dst, n);
252 } 294 }
253 295
254 proc.advance(SkIntToScalar(n)); 296 proc.advance(SkIntToScalar(n));
255 count -= n; 297 count -= n;
256 dst += n; 298 dst += n;
257 } 299 }
258 } 300 }
259 301
260 template<typename DstType, SkShader::TileMode tileMode> 302 template<typename DstType, SkColorProfileType profile, SkShader::TileMode tileMo de>
261 class SkLinearGradient:: 303 class SkLinearGradient::
262 LinearGradient4fContext::LinearIntervalProcessor { 304 LinearGradient4fContext::LinearIntervalProcessor {
263 public: 305 public:
264 LinearIntervalProcessor(const Interval* firstInterval, 306 LinearIntervalProcessor(const Interval* firstInterval,
265 const Interval* lastInterval, 307 const Interval* lastInterval,
266 const Interval* i, 308 const Interval* i,
267 SkScalar fx, 309 SkScalar fx,
268 SkScalar dx, 310 SkScalar dx,
269 bool is_vertical) 311 bool is_vertical)
270 : fDstComponentScale(dst_component_scale<DstType>()) 312 : fAdvX((i->fP1 - fx) / dx)
271 , fAdvX((i->fP1 - fx) / dx)
272 , fFirstInterval(firstInterval) 313 , fFirstInterval(firstInterval)
273 , fLastInterval(lastInterval) 314 , fLastInterval(lastInterval)
274 , fInterval(i) 315 , fInterval(i)
275 , fDx(dx) 316 , fDx(dx)
276 , fIsVertical(is_vertical) 317 , fIsVertical(is_vertical)
277 { 318 {
278 SkASSERT(firstInterval <= lastInterval); 319 SkASSERT(firstInterval <= lastInterval);
279 SkASSERT(in_range(fx, i->fP0, i->fP1)); 320 SkASSERT(in_range(fx, i->fP0, i->fP1));
280 this->compute_interval_props(fx - i->fP0); 321 this->compute_interval_props(fx - i->fP0);
281 } 322 }
(...skipping 19 matching lines...) Expand all
301 342
302 fCc = fCc + fDcDx * Sk4f(advX); 343 fCc = fCc + fDcDx * Sk4f(advX);
303 fAdvX -= advX; 344 fAdvX -= advX;
304 } 345 }
305 346
306 private: 347 private:
307 void compute_interval_props(SkScalar t) { 348 void compute_interval_props(SkScalar t) {
308 fDc = dst_swizzle<DstType>(fInterval->fDc); 349 fDc = dst_swizzle<DstType>(fInterval->fDc);
309 fCc = dst_swizzle<DstType>(fInterval->fC0); 350 fCc = dst_swizzle<DstType>(fInterval->fC0);
310 fCc = fCc + fDc * Sk4f(t); 351 fCc = fCc + fDc * Sk4f(t);
311 fCc = fCc * fDstComponentScale; 352 fCc = scale_for_dest<DstType, profile>(fCc);
312 fDcDx = fDc * fDstComponentScale * Sk4f(fDx); 353 fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx));
313 fZeroRamp = fIsVertical || fInterval->isZeroRamp(); 354 fZeroRamp = fIsVertical || fInterval->isZeroRamp();
314 } 355 }
315 356
316 const Interval* next_interval(const Interval* i) const { 357 const Interval* next_interval(const Interval* i) const {
317 SkASSERT(i >= fFirstInterval); 358 SkASSERT(i >= fFirstInterval);
318 SkASSERT(i <= fLastInterval); 359 SkASSERT(i <= fLastInterval);
319 i++; 360 i++;
320 361
321 if (tileMode == kClamp_TileMode) { 362 if (tileMode == kClamp_TileMode) {
322 SkASSERT(i <= fLastInterval); 363 SkASSERT(i <= fLastInterval);
(...skipping 12 matching lines...) Expand all
335 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx; 376 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx;
336 SkASSERT(fAdvX > 0); 377 SkASSERT(fAdvX > 0);
337 } while (advX >= fAdvX); 378 } while (advX >= fAdvX);
338 379
339 compute_interval_props(0); 380 compute_interval_props(0);
340 381
341 SkASSERT(advX >= 0); 382 SkASSERT(advX >= 0);
342 return advX; 383 return advX;
343 } 384 }
344 385
345 const Sk4f fDstComponentScale; // cached dst scale (PMC: 255, PM4f: 1)
346
347 // Current interval properties. 386 // Current interval properties.
348 Sk4f fDc; // local color gradient (dc/dt) 387 Sk4f fDc; // local color gradient (dc/dt)
349 Sk4f fDcDx; // dst color gradient (dc/dx) 388 Sk4f fDcDx; // dst color gradient (dc/dx)
350 Sk4f fCc; // current color, interpolated in dst 389 Sk4f fCc; // current color, interpolated in dst
351 SkScalar fAdvX; // remaining interval advance in dst 390 SkScalar fAdvX; // remaining interval advance in dst
352 bool fZeroRamp; // current interval color grad is 0 391 bool fZeroRamp; // current interval color grad is 0
353 392
354 const Interval* fFirstInterval; 393 const Interval* fFirstInterval;
355 const Interval* fLastInterval; 394 const Interval* fLastInterval;
356 const Interval* fInterval; // current interval 395 const Interval* fInterval; // current interval
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 *ts++ = t4[0]; 434 *ts++ = t4[0];
396 } 435 }
397 } else { 436 } else {
398 for (int i = 0; i < count; ++i) { 437 for (int i = 0; i < count; ++i) {
399 fDstToPosProc(fDstToPos, sx, sy, &pt); 438 fDstToPosProc(fDstToPos, sx, sy, &pt);
400 ts[i] = pt.x(); 439 ts[i] = pt.x();
401 sx += SK_Scalar1; 440 sx += SK_Scalar1;
402 } 441 }
403 } 442 }
404 } 443 }
444
445 SkShader::Context::BlitProc SkLinearGradient::
446 LinearGradient4fContext::onChooseBlitProc(const SkImageInfo& info, BlitState* st ate) {
447 SkXfermode::Mode mode;
448 if (!SkXfermode::AsMode(state->fXfer, &mode)) {
449 return nullptr;
450 }
451
452 const SkGradientShaderBase& shader = static_cast<const SkGradientShaderBase& >(fShader);
453 if (mode != SkXfermode::kSrc_Mode &&
454 !(mode == SkXfermode::kSrcOver_Mode && shader.colorsAreOpaque())) {
455 return nullptr;
456 }
457
458 switch (info.colorType()) {
459 case kN32_SkColorType:
460 return D32_BlitProc;
461 case kRGBA_F16_SkColorType:
462 return D64_BlitProc;
463 default:
464 return nullptr;
465 }
466 }
467
468 void SkLinearGradient::
469 LinearGradient4fContext::D32_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst,
470 int count, const SkAlpha aa[]) {
471 // FIXME: ignoring coverage for now
472 const LinearGradient4fContext* ctx =
473 static_cast<const LinearGradient4fContext*>(state->fCtx);
474
475 if (dst.info().isLinear()) {
476 if (ctx->fColorsArePremul) {
477 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPre mul::False>(
478 x, y, dst.writable_addr32(x, y), count);
479 } else {
480 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPre mul::True>(
481 x, y, dst.writable_addr32(x, y), count);
482 }
483 } else {
484 if (ctx->fColorsArePremul) {
485 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremu l::False>(
486 x, y, dst.writable_addr32(x, y), count);
487 } else {
488 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremu l::True>(
489 x, y, dst.writable_addr32(x, y), count);
490 }
491 }
492 }
493
494 void SkLinearGradient::
495 LinearGradient4fContext::D64_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst,
496 int count, const SkAlpha aa[]) {
497 // FIXME: ignoring coverage for now
498 const LinearGradient4fContext* ctx =
499 static_cast<const LinearGradient4fContext*>(state->fCtx);
500
501 if (ctx->fColorsArePremul) {
502 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul:: False>(
503 x, y, dst.writable_addr64(x, y), count);
504 } else {
505 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul:: True>(
506 x, y, dst.writable_addr64(x, y), count);
507 }
508 }
OLDNEW
« no previous file with comments | « src/effects/gradients/Sk4fLinearGradient.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698