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

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

Issue 1816883002: Refactor 4f gradients using trait templates (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
« 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 "Sk4fLinearGradient.h" 8 #include "Sk4fLinearGradient.h"
9 #include "SkUtils.h"
10 #include "SkXfermode.h" 9 #include "SkXfermode.h"
11 10
12 namespace { 11 namespace {
13 12
14 template<typename DstType, SkColorProfileType, ApplyPremul> 13 template<DstType dstType, ApplyPremul premul>
15 void fill(const Sk4f& c, DstType* dst, int n); 14 void ramp(const Sk4f& c, const Sk4f& dc, typename DstTraits<dstType, premul>::Ty pe dst[], int n) {
16
17 template<>
18 void fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False>
19 (const Sk4f& c, SkPM4f* dst, int n) {
20 while (n > 0) {
21 c.store(dst++);
22 n--;
23 }
24 }
25
26 template<>
27 void fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True>
28 (const Sk4f& c, SkPM4f* dst, int n) {
29 fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False>(premul_4f(c), d st, n);
30 }
31
32 template<>
33 void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False>
34 (const Sk4f& c, SkPMColor* dst, int n) {
35 sk_memset32(dst, trunc_from_4f_255<ApplyPremul::False>(c), n);
36 }
37
38 template<>
39 void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True>
40 (const Sk4f& c, SkPMColor* dst, int n) {
41 sk_memset32(dst, trunc_from_4f_255<ApplyPremul::True>(c), n);
42 }
43
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>
70 void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) {
71 SkASSERT(n > 0); 15 SkASSERT(n > 0);
72 16
73 const Sk4f dc2 = dc + dc; 17 const Sk4f dc2 = dc + dc;
74 const Sk4f dc4 = dc2 + dc2; 18 const Sk4f dc4 = dc2 + dc2;
75 19
76 Sk4f c0 = c ; 20 Sk4f c0 = c ;
77 Sk4f c1 = c + dc; 21 Sk4f c1 = c + dc;
78 Sk4f c2 = c0 + dc2; 22 Sk4f c2 = c0 + dc2;
79 Sk4f c3 = c1 + dc2; 23 Sk4f c3 = c1 + dc2;
80 24
81 while (n >= 4) { 25 while (n >= 4) {
82 store4x<DstType, profile, premul>(c0, c1, c2, c3, dst); 26 DstTraits<dstType, premul>::store4x(c0, c1, c2, c3, dst);
83 dst += 4; 27 dst += 4;
84 28
85 c0 = c0 + dc4; 29 c0 = c0 + dc4;
86 c1 = c1 + dc4; 30 c1 = c1 + dc4;
87 c2 = c2 + dc4; 31 c2 = c2 + dc4;
88 c3 = c3 + dc4; 32 c3 = c3 + dc4;
89 n -= 4; 33 n -= 4;
90 } 34 }
91 if (n & 2) { 35 if (n & 2) {
92 store<DstType, profile, premul>(c0, dst++); 36 DstTraits<dstType, premul>::store(c0, dst++);
93 store<DstType, profile, premul>(c1, dst++); 37 DstTraits<dstType, premul>::store(c1, dst++);
94 c0 = c0 + dc2; 38 c0 = c0 + dc2;
95 } 39 }
96 if (n & 1) { 40 if (n & 1) {
97 store<DstType, profile, premul>(c0, dst); 41 DstTraits<dstType, premul>::store(c0, dst);
98 } 42 }
99 } 43 }
100 44
101 template<SkShader::TileMode> 45 template<SkShader::TileMode>
102 SkScalar pinFx(SkScalar); 46 SkScalar pinFx(SkScalar);
103 47
104 template<> 48 template<>
105 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) { 49 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) {
106 return fx; 50 return fx;
107 } 51 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 void SkLinearGradient:: 130 void SkLinearGradient::
187 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { 131 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) {
188 if (!this->isFast()) { 132 if (!this->isFast()) {
189 this->INHERITED::shadeSpan(x, y, dst, count); 133 this->INHERITED::shadeSpan(x, y, dst, count);
190 return; 134 return;
191 } 135 }
192 136
193 // TODO: plumb dithering 137 // TODO: plumb dithering
194 SkASSERT(count > 0); 138 SkASSERT(count > 0);
195 if (fColorsArePremul) { 139 if (fColorsArePremul) {
196 this->shadePremulSpan<SkPMColor, 140 this->shadePremulSpan<DstType::L32,
197 kLinear_SkColorProfileType,
198 ApplyPremul::False>(x, y, dst, count); 141 ApplyPremul::False>(x, y, dst, count);
199 } else { 142 } else {
200 this->shadePremulSpan<SkPMColor, 143 this->shadePremulSpan<DstType::L32,
201 kLinear_SkColorProfileType,
202 ApplyPremul::True>(x, y, dst, count); 144 ApplyPremul::True>(x, y, dst, count);
203 } 145 }
204 } 146 }
205 147
206 void SkLinearGradient:: 148 void SkLinearGradient::
207 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { 149 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) {
208 if (!this->isFast()) { 150 if (!this->isFast()) {
209 this->INHERITED::shadeSpan4f(x, y, dst, count); 151 this->INHERITED::shadeSpan4f(x, y, dst, count);
210 return; 152 return;
211 } 153 }
212 154
213 // TONOTDO: plumb dithering 155 // TONOTDO: plumb dithering
214 SkASSERT(count > 0); 156 SkASSERT(count > 0);
215 if (fColorsArePremul) { 157 if (fColorsArePremul) {
216 this->shadePremulSpan<SkPM4f, 158 this->shadePremulSpan<DstType::F32,
217 kLinear_SkColorProfileType,
218 ApplyPremul::False>(x, y, dst, count); 159 ApplyPremul::False>(x, y, dst, count);
219 } else { 160 } else {
220 this->shadePremulSpan<SkPM4f, 161 this->shadePremulSpan<DstType::F32,
221 kLinear_SkColorProfileType,
222 ApplyPremul::True>(x, y, dst, count); 162 ApplyPremul::True>(x, y, dst, count);
223 } 163 }
224 } 164 }
225 165
226 template<typename DstType, SkColorProfileType profile, ApplyPremul premul> 166 template<DstType dstType, ApplyPremul premul>
227 void SkLinearGradient:: 167 void SkLinearGradient::
228 LinearGradient4fContext::shadePremulSpan(int x, int y, 168 LinearGradient4fContext::shadePremulSpan(int x, int y,
229 DstType dst[], 169 typename DstTraits<dstType, premul>::Ty pe dst[],
230 int count) const { 170 int count) const {
231 const SkLinearGradient& shader = 171 const SkLinearGradient& shader =
232 static_cast<const SkLinearGradient&>(fShader); 172 static_cast<const SkLinearGradient&>(fShader);
233 switch (shader.fTileMode) { 173 switch (shader.fTileMode) {
234 case kClamp_TileMode: 174 case kClamp_TileMode:
235 this->shadeSpanInternal<DstType, 175 this->shadeSpanInternal<dstType,
236 profile,
237 premul, 176 premul,
238 kClamp_TileMode>(x, y, dst, count); 177 kClamp_TileMode>(x, y, dst, count);
239 break; 178 break;
240 case kRepeat_TileMode: 179 case kRepeat_TileMode:
241 this->shadeSpanInternal<DstType, 180 this->shadeSpanInternal<dstType,
242 profile,
243 premul, 181 premul,
244 kRepeat_TileMode>(x, y, dst, count); 182 kRepeat_TileMode>(x, y, dst, count);
245 break; 183 break;
246 case kMirror_TileMode: 184 case kMirror_TileMode:
247 this->shadeSpanInternal<DstType, 185 this->shadeSpanInternal<dstType,
248 profile,
249 premul, 186 premul,
250 kMirror_TileMode>(x, y, dst, count); 187 kMirror_TileMode>(x, y, dst, count);
251 break; 188 break;
252 } 189 }
253 } 190 }
254 191
255 template<typename DstType, SkColorProfileType profile, ApplyPremul premul, 192 template<DstType dstType, ApplyPremul premul, SkShader::TileMode tileMode>
256 SkShader::TileMode tileMode>
257 void SkLinearGradient:: 193 void SkLinearGradient::
258 LinearGradient4fContext::shadeSpanInternal(int x, int y, 194 LinearGradient4fContext::shadeSpanInternal(int x, int y,
259 DstType dst[], 195 typename DstTraits<dstType, premul>:: Type dst[],
260 int count) const { 196 int count) const {
261 SkPoint pt; 197 SkPoint pt;
262 fDstToPosProc(fDstToPos, 198 fDstToPosProc(fDstToPos,
263 x + SK_ScalarHalf, 199 x + SK_ScalarHalf,
264 y + SK_ScalarHalf, 200 y + SK_ScalarHalf,
265 &pt); 201 &pt);
266 const SkScalar fx = pinFx<tileMode>(pt.x()); 202 const SkScalar fx = pinFx<tileMode>(pt.x());
267 const SkScalar dx = fDstToPos.getScaleX(); 203 const SkScalar dx = fDstToPos.getScaleX();
268 LinearIntervalProcessor<DstType, profile, tileMode> proc(fIntervals.begin(), 204 LinearIntervalProcessor<dstType, tileMode> proc(fIntervals.begin(),
269 fIntervals.end() - 1, 205 fIntervals.end() - 1,
270 this->findInterval( fx), 206 this->findInterval(fx),
271 fx, 207 fx,
272 dx, 208 dx,
273 SkScalarNearlyZero( dx * count)); 209 SkScalarNearlyZero(dx * coun t));
274 while (count > 0) { 210 while (count > 0) {
275 // What we really want here is SkTPin(advance, 1, count) 211 // What we really want here is SkTPin(advance, 1, count)
276 // but that's a significant perf hit for >> stops; investigate. 212 // but that's a significant perf hit for >> stops; investigate.
277 const int n = SkScalarTruncToInt( 213 const int n = SkScalarTruncToInt(
278 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); 214 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count)));
279 215
280 // The current interval advance can be +inf (e.g. when reaching 216 // The current interval advance can be +inf (e.g. when reaching
281 // the clamp mode end intervals) - when that happens, we expect to 217 // the clamp mode end intervals) - when that happens, we expect to
282 // a) consume all remaining count in one swoop 218 // a) consume all remaining count in one swoop
283 // b) return a zero color gradient 219 // b) return a zero color gradient
284 SkASSERT(SkScalarIsFinite(proc.currentAdvance()) 220 SkASSERT(SkScalarIsFinite(proc.currentAdvance())
285 || (n == count && proc.currentRampIsZero())); 221 || (n == count && proc.currentRampIsZero()));
286 222
287 if (proc.currentRampIsZero()) { 223 if (proc.currentRampIsZero()) {
288 fill<DstType, profile, premul>(proc.currentColor(), 224 DstTraits<dstType, premul>::store(proc.currentColor(),
289 dst, n); 225 dst, n);
290 } else { 226 } else {
291 ramp<DstType, profile, premul>(proc.currentColor(), 227 ramp<dstType, premul>(proc.currentColor(),
292 proc.currentColorGrad(), 228 proc.currentColorGrad(),
293 dst, n); 229 dst, n);
294 } 230 }
295 231
296 proc.advance(SkIntToScalar(n)); 232 proc.advance(SkIntToScalar(n));
297 count -= n; 233 count -= n;
298 dst += n; 234 dst += n;
299 } 235 }
300 } 236 }
301 237
302 template<typename DstType, SkColorProfileType profile, SkShader::TileMode tileMo de> 238 template<DstType dstType, SkShader::TileMode tileMode>
303 class SkLinearGradient:: 239 class SkLinearGradient::
304 LinearGradient4fContext::LinearIntervalProcessor { 240 LinearGradient4fContext::LinearIntervalProcessor {
305 public: 241 public:
306 LinearIntervalProcessor(const Interval* firstInterval, 242 LinearIntervalProcessor(const Interval* firstInterval,
307 const Interval* lastInterval, 243 const Interval* lastInterval,
308 const Interval* i, 244 const Interval* i,
309 SkScalar fx, 245 SkScalar fx,
310 SkScalar dx, 246 SkScalar dx,
311 bool is_vertical) 247 bool is_vertical)
312 : fAdvX((i->fP1 - fx) / dx) 248 : fAdvX((i->fP1 - fx) / dx)
(...skipping 26 matching lines...) Expand all
339 advX = this->advance_interval(advX); 275 advX = this->advance_interval(advX);
340 } 276 }
341 SkASSERT(advX < fAdvX); 277 SkASSERT(advX < fAdvX);
342 278
343 fCc = fCc + fDcDx * Sk4f(advX); 279 fCc = fCc + fDcDx * Sk4f(advX);
344 fAdvX -= advX; 280 fAdvX -= advX;
345 } 281 }
346 282
347 private: 283 private:
348 void compute_interval_props(SkScalar t) { 284 void compute_interval_props(SkScalar t) {
349 fDc = dst_swizzle<DstType>(fInterval->fDc); 285 const Sk4f dC = DstTraits<dstType>::load(fInterval->fDc);
350 fCc = dst_swizzle<DstType>(fInterval->fC0); 286 fCc = DstTraits<dstType>::load(fInterval->fC0);
351 fCc = fCc + fDc * Sk4f(t); 287 fCc = fCc + dC * Sk4f(t);
352 fCc = scale_for_dest<DstType, profile>(fCc); 288 fDcDx = dC * fDx;
353 fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx)); 289 fZeroRamp = fIsVertical || fInterval->isZeroRamp();
354 fZeroRamp = fIsVertical || fInterval->isZeroRamp();
355 } 290 }
356 291
357 const Interval* next_interval(const Interval* i) const { 292 const Interval* next_interval(const Interval* i) const {
358 SkASSERT(i >= fFirstInterval); 293 SkASSERT(i >= fFirstInterval);
359 SkASSERT(i <= fLastInterval); 294 SkASSERT(i <= fLastInterval);
360 i++; 295 i++;
361 296
362 if (tileMode == kClamp_TileMode) { 297 if (tileMode == kClamp_TileMode) {
363 SkASSERT(i <= fLastInterval); 298 SkASSERT(i <= fLastInterval);
364 return i; 299 return i;
(...skipping 12 matching lines...) Expand all
377 SkASSERT(fAdvX > 0); 312 SkASSERT(fAdvX > 0);
378 } while (advX >= fAdvX); 313 } while (advX >= fAdvX);
379 314
380 compute_interval_props(0); 315 compute_interval_props(0);
381 316
382 SkASSERT(advX >= 0); 317 SkASSERT(advX >= 0);
383 return advX; 318 return advX;
384 } 319 }
385 320
386 // Current interval properties. 321 // Current interval properties.
387 Sk4f fDc; // local color gradient (dc/dt)
388 Sk4f fDcDx; // dst color gradient (dc/dx) 322 Sk4f fDcDx; // dst color gradient (dc/dx)
389 Sk4f fCc; // current color, interpolated in dst 323 Sk4f fCc; // current color, interpolated in dst
390 SkScalar fAdvX; // remaining interval advance in dst 324 SkScalar fAdvX; // remaining interval advance in dst
391 bool fZeroRamp; // current interval color grad is 0 325 bool fZeroRamp; // current interval color grad is 0
392 326
393 const Interval* fFirstInterval; 327 const Interval* fFirstInterval;
394 const Interval* fLastInterval; 328 const Interval* fLastInterval;
395 const Interval* fInterval; // current interval 329 const Interval* fInterval; // current interval
396 const SkScalar fDx; // 'dx' for consistency with other impls; actual ly dt/dx 330 const SkScalar fDx; // 'dx' for consistency with other impls; actual ly dt/dx
397 const bool fIsVertical; 331 const bool fIsVertical;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 403
470 void SkLinearGradient:: 404 void SkLinearGradient::
471 LinearGradient4fContext::D32_BlitBW(BlitState* state, int x, int y, const SkPixm ap& dst, 405 LinearGradient4fContext::D32_BlitBW(BlitState* state, int x, int y, const SkPixm ap& dst,
472 int count) { 406 int count) {
473 // FIXME: ignoring coverage for now 407 // FIXME: ignoring coverage for now
474 const LinearGradient4fContext* ctx = 408 const LinearGradient4fContext* ctx =
475 static_cast<const LinearGradient4fContext*>(state->fCtx); 409 static_cast<const LinearGradient4fContext*>(state->fCtx);
476 410
477 if (dst.info().isLinear()) { 411 if (dst.info().isLinear()) {
478 if (ctx->fColorsArePremul) { 412 if (ctx->fColorsArePremul) {
479 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPre mul::False>( 413 ctx->shadePremulSpan<DstType::L32, ApplyPremul::False>(
480 x, y, dst.writable_addr32(x, y), count); 414 x, y, dst.writable_addr32(x, y), count);
481 } else { 415 } else {
482 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPre mul::True>( 416 ctx->shadePremulSpan<DstType::L32, ApplyPremul::True>(
483 x, y, dst.writable_addr32(x, y), count); 417 x, y, dst.writable_addr32(x, y), count);
484 } 418 }
485 } else { 419 } else {
486 if (ctx->fColorsArePremul) { 420 if (ctx->fColorsArePremul) {
487 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremu l::False>( 421 ctx->shadePremulSpan<DstType::S32, ApplyPremul::False>(
488 x, y, dst.writable_addr32(x, y), count); 422 x, y, dst.writable_addr32(x, y), count);
489 } else { 423 } else {
490 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremu l::True>( 424 ctx->shadePremulSpan<DstType::S32, ApplyPremul::True>(
491 x, y, dst.writable_addr32(x, y), count); 425 x, y, dst.writable_addr32(x, y), count);
492 } 426 }
493 } 427 }
494 } 428 }
495 429
496 void SkLinearGradient:: 430 void SkLinearGradient::
497 LinearGradient4fContext::D64_BlitBW(BlitState* state, int x, int y, const SkPixm ap& dst, 431 LinearGradient4fContext::D64_BlitBW(BlitState* state, int x, int y, const SkPixm ap& dst,
498 int count) { 432 int count) {
499 // FIXME: ignoring coverage for now 433 // FIXME: ignoring coverage for now
500 const LinearGradient4fContext* ctx = 434 const LinearGradient4fContext* ctx =
501 static_cast<const LinearGradient4fContext*>(state->fCtx); 435 static_cast<const LinearGradient4fContext*>(state->fCtx);
502 436
503 if (ctx->fColorsArePremul) { 437 if (ctx->fColorsArePremul) {
504 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul:: False>( 438 ctx->shadePremulSpan<DstType::F16, ApplyPremul::False>(
505 x, y, dst.writable_addr64(x, y), count); 439 x, y, dst.writable_addr64(x, y), count);
506 } else { 440 } else {
507 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul:: True>( 441 ctx->shadePremulSpan<DstType::F16, ApplyPremul::True>(
508 x, y, dst.writable_addr64(x, y), count); 442 x, y, dst.writable_addr64(x, y), count);
509 } 443 }
510 } 444 }
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