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

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

Issue 1767163003: Use float rather than SkFixed for gradient TileProcs. (Closed) Base URL: https://skia.googlesource.com/skia@scalar-pin-to-fixed
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 2012 Google Inc. 2 * Copyright 2012 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 "math.h"
9
8 #include "Sk4fLinearGradient.h" 10 #include "Sk4fLinearGradient.h"
9 #include "SkLinearGradient.h" 11 #include "SkLinearGradient.h"
10 12
11 // define to test the 4f gradient path 13 // define to test the 4f gradient path
12 // #define FORCE_4F_CONTEXT 14 // #define FORCE_4F_CONTEXT
13 15
14 static const float kInv255Float = 1.0f / 255; 16 static const float kInv255Float = 1.0f / 255;
15 17
16 static inline int repeat_8bits(int x) { 18 static inline int repeat_8bits(float x) {
17 return x & 0xFF; 19 float ignore;
20 const float frac = modff(x, &ignore);
21 return (int)(frac * 256) & 0xFF;
18 } 22 }
19 23
20 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly. 24 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
21 // See http://code.google.com/p/skia/issues/detail?id=472 25 // See http://code.google.com/p/skia/issues/detail?id=472
22 #if defined(_MSC_VER) && (_MSC_VER >= 1600) 26 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
23 #pragma optimize("", off) 27 #pragma optimize("", off)
24 #endif 28 #endif
25 29
26 static inline int mirror_8bits(int x) { 30 static inline int mirror_8bits(float x) {
27 if (x & 256) { 31 const float x_mod_2 = fmod(x, 2.0f);
28 x = ~x; 32 int x_9bits = (int)(x_mod_2 * 256);
33 if (x_9bits & 0x100) {
34 x_9bits = ~x_9bits;
29 } 35 }
30 return x & 255; 36 return x_9bits & 0xFF;
31 } 37 }
32 38
33 #if defined(_MSC_VER) && (_MSC_VER >= 1600) 39 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
34 #pragma optimize("", on) 40 #pragma optimize("", on)
35 #endif 41 #endif
36 42
37 static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) { 43 static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) {
38 SkVector vec = pts[1] - pts[0]; 44 SkVector vec = pts[1] - pts[0];
39 SkScalar mag = vec.length(); 45 SkScalar mag = vec.length();
40 SkScalar inv = mag ? SkScalarInvert(mag) : 0; 46 SkScalar inv = mag ? SkScalarInvert(mag) : 0;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 do { \ 186 do { \
181 unsigned fi = SkGradFixedToFixed(fx) >> SkGradientShaderBase::kCache32Shift; \ 187 unsigned fi = SkGradFixedToFixed(fx) >> SkGradientShaderBase::kCache32Shift; \
182 SkASSERT(fi <= 0xFF); \ 188 SkASSERT(fi <= 0xFF); \
183 fx += dx; \ 189 fx += dx; \
184 *dstC++ = cache[toggle + fi]; \ 190 *dstC++ = cache[toggle + fi]; \
185 toggle = next_dither_toggle(toggle); \ 191 toggle = next_dither_toggle(toggle); \
186 } while (0) 192 } while (0)
187 193
188 namespace { 194 namespace {
189 195
190 typedef void (*LinearShadeProc)(TileProc proc, SkGradFixed dx, SkGradFixed fx, 196 typedef void (*LinearShadeProc)(TileProc proc, float dx, float fx,
191 SkPMColor* dstC, const SkPMColor* cache, 197 SkPMColor* dstC, const SkPMColor* cache,
192 int toggle, int count); 198 int toggle, int count);
193 199
194 // Linear interpolation (lerp) is unnecessary if there are no sharp 200 // Linear interpolation (lerp) is unnecessary if there are no sharp
195 // discontinuities in the gradient - which must be true if there are 201 // discontinuities in the gradient - which must be true if there are
196 // only 2 colors - but it's cheap. 202 // only 2 colors - but it's cheap.
197 void shadeSpan_linear_vertical_lerp(TileProc proc, SkGradFixed dx, SkGradFixed f x, 203 void shadeSpan_linear_vertical_lerp(TileProc proc, float dx, float fx,
198 SkPMColor* SK_RESTRICT dstC, 204 SkPMColor* SK_RESTRICT dstC,
199 const SkPMColor* SK_RESTRICT cache, 205 const SkPMColor* SK_RESTRICT cache,
200 int toggle, int count) { 206 int toggle, int count) {
201 // We're a vertical gradient, so no change in a span. 207 // We're a vertical gradient, so no change in a span.
202 // If colors change sharply across the gradient, dithering is 208 // If colors change sharply across the gradient, dithering is
203 // insufficient (it subsamples the color space) and we need to lerp. 209 // insufficient (it subsamples the color space) and we need to lerp.
204 unsigned fullIndex = proc(SkGradFixedToFixed(fx)); 210 unsigned fullIndex = proc(fx);
205 unsigned fi = fullIndex >> SkGradientShaderBase::kCache32Shift; 211 unsigned fi = fullIndex >> SkGradientShaderBase::kCache32Shift;
206 unsigned remainder = fullIndex & ((1 << SkGradientShaderBase::kCache32Shift) - 1); 212 unsigned remainder = fullIndex & ((1 << SkGradientShaderBase::kCache32Shift) - 1);
207 213
208 int index0 = fi + toggle; 214 int index0 = fi + toggle;
209 int index1 = index0; 215 int index1 = index0;
210 if (fi < SkGradientShaderBase::kCache32Count - 1) { 216 if (fi < SkGradientShaderBase::kCache32Count - 1) {
211 index1 += 1; 217 index1 += 1;
212 } 218 }
213 SkPMColor lerp = SkFastFourByteInterp(cache[index1], cache[index0], remainde r); 219 SkPMColor lerp = SkFastFourByteInterp(cache[index1], cache[index0], remainde r);
214 index0 ^= SkGradientShaderBase::kDitherStride32; 220 index0 ^= SkGradientShaderBase::kDitherStride32;
215 index1 ^= SkGradientShaderBase::kDitherStride32; 221 index1 ^= SkGradientShaderBase::kDitherStride32;
216 SkPMColor dlerp = SkFastFourByteInterp(cache[index1], cache[index0], remaind er); 222 SkPMColor dlerp = SkFastFourByteInterp(cache[index1], cache[index0], remaind er);
217 sk_memset32_dither(dstC, lerp, dlerp, count); 223 sk_memset32_dither(dstC, lerp, dlerp, count);
218 } 224 }
219 225
220 void shadeSpan_linear_clamp(TileProc proc, SkGradFixed dx, SkGradFixed fx, 226 void shadeSpan_linear_clamp(TileProc proc, float float_dx, float float_fx,
221 SkPMColor* SK_RESTRICT dstC, 227 SkPMColor* SK_RESTRICT dstC,
222 const SkPMColor* SK_RESTRICT cache, 228 const SkPMColor* SK_RESTRICT cache,
223 int toggle, int count) { 229 int toggle, int count) {
224 SkClampRange range; 230 SkClampRange range;
225 range.init(fx, dx, count, 0, SkGradientShaderBase::kCache32Count - 1); 231 range.init(float_fx, float_dx, count, 0, SkGradientShaderBase::kCache32Count - 1);
226 range.validate(count); 232 range.validate(count);
227 233
228 if ((count = range.fCount0) > 0) { 234 if ((count = range.fCount0) > 0) {
229 sk_memset32_dither(dstC, 235 sk_memset32_dither(dstC,
230 cache[toggle + range.fV0], 236 cache[toggle + range.fV0],
231 cache[next_dither_toggle(toggle) + range.fV0], 237 cache[next_dither_toggle(toggle) + range.fV0],
232 count); 238 count);
233 dstC += count; 239 dstC += count;
234 } 240 }
235 if ((count = range.fCount1) > 0) { 241 if ((count = range.fCount1) > 0) {
236 int unroll = count >> 3; 242 int unroll = count >> 3;
237 fx = range.fFx1; 243 SkGradFixed fx = range.fFx1;
244 const SkGradFixed dx = SkFloatToGradFixed(float_dx);
238 for (int i = 0; i < unroll; i++) { 245 for (int i = 0; i < unroll; i++) {
239 NO_CHECK_ITER; NO_CHECK_ITER; 246 NO_CHECK_ITER; NO_CHECK_ITER;
240 NO_CHECK_ITER; NO_CHECK_ITER; 247 NO_CHECK_ITER; NO_CHECK_ITER;
241 NO_CHECK_ITER; NO_CHECK_ITER; 248 NO_CHECK_ITER; NO_CHECK_ITER;
242 NO_CHECK_ITER; NO_CHECK_ITER; 249 NO_CHECK_ITER; NO_CHECK_ITER;
243 } 250 }
244 if ((count &= 7) > 0) { 251 if ((count &= 7) > 0) {
245 do { 252 do {
246 NO_CHECK_ITER; 253 NO_CHECK_ITER;
247 } while (--count != 0); 254 } while (--count != 0);
248 } 255 }
249 } 256 }
250 if ((count = range.fCount2) > 0) { 257 if ((count = range.fCount2) > 0) {
251 sk_memset32_dither(dstC, 258 sk_memset32_dither(dstC,
252 cache[toggle + range.fV1], 259 cache[toggle + range.fV1],
253 cache[next_dither_toggle(toggle) + range.fV1], 260 cache[next_dither_toggle(toggle) + range.fV1],
254 count); 261 count);
255 } 262 }
256 } 263 }
257 264
258 void shadeSpan_linear_mirror(TileProc proc, SkGradFixed dx, SkGradFixed fx, 265 void shadeSpan_linear_mirror(TileProc proc, float dx, float fx,
259 SkPMColor* SK_RESTRICT dstC, 266 SkPMColor* SK_RESTRICT dstC,
260 const SkPMColor* SK_RESTRICT cache, 267 const SkPMColor* SK_RESTRICT cache,
261 int toggle, int count) { 268 int toggle, int count) {
262 do { 269 do {
263 unsigned fi = mirror_8bits(SkGradFixedToFixed(fx) >> 8); 270 unsigned fi = mirror_8bits(fx);
264 SkASSERT(fi <= 0xFF); 271 SkASSERT(fi <= 0xFF);
265 fx += dx; 272 fx += dx;
266 *dstC++ = cache[toggle + fi]; 273 *dstC++ = cache[toggle + fi];
267 toggle = next_dither_toggle(toggle); 274 toggle = next_dither_toggle(toggle);
268 } while (--count != 0); 275 } while (--count != 0);
269 } 276 }
270 277
271 void shadeSpan_linear_repeat(TileProc proc, SkGradFixed dx, SkGradFixed fx, 278 void shadeSpan_linear_repeat(TileProc proc, float dx, float fx,
272 SkPMColor* SK_RESTRICT dstC, 279 SkPMColor* SK_RESTRICT dstC,
273 const SkPMColor* SK_RESTRICT cache, 280 const SkPMColor* SK_RESTRICT cache,
274 int toggle, int count) { 281 int toggle, int count) {
275 do { 282 do {
276 unsigned fi = repeat_8bits(SkGradFixedToFixed(fx) >> 8); 283 unsigned fi = repeat_8bits(fx);
277 SkASSERT(fi <= 0xFF); 284 SkASSERT(fi <= 0xFF);
278 fx += dx; 285 fx += dx;
279 *dstC++ = cache[toggle + fi]; 286 *dstC++ = cache[toggle + fi];
280 toggle = next_dither_toggle(toggle); 287 toggle = next_dither_toggle(toggle);
281 } while (--count != 0); 288 } while (--count != 0);
282 } 289 }
283 290
284 } 291 }
285 292
286 void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, 293 void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
(...skipping 13 matching lines...) Expand all
300 307
301 SkPoint srcPt; 308 SkPoint srcPt;
302 SkMatrix::MapXYProc dstProc = fDstToIndexProc; 309 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
303 TileProc proc = linearGradient.fTileProc; 310 TileProc proc = linearGradient.fTileProc;
304 const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 311 const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
305 int toggle = init_dither_toggle(x, y); 312 int toggle = init_dither_toggle(x, y);
306 313
307 if (fDstToIndexClass != kPerspective_MatrixClass) { 314 if (fDstToIndexClass != kPerspective_MatrixClass) {
308 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 315 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
309 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 316 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
310 SkGradFixed dx, fx = SkScalarToGradFixed(srcPt.fX); 317 float dx, fx = SkScalarToFloat(srcPt.fX);
311 318
312 if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 319 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
313 const auto step = fDstToIndex.fixedStepInX(SkIntToScalar(y)); 320 const auto step = fDstToIndex.fixedStepInX(SkIntToScalar(y));
314 // todo: do we need a real/high-precision value for dx here? 321 dx = SkScalarToFloat(step.fX);
315 dx = SkScalarToGradFixed(step.fX);
316 } else { 322 } else {
317 SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 323 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
318 dx = SkScalarToGradFixed(fDstToIndex.getScaleX()); 324 dx = SkScalarToFloat(fDstToIndex.getScaleX());
319 } 325 }
320 326
321 LinearShadeProc shadeProc = shadeSpan_linear_repeat; 327 LinearShadeProc shadeProc = shadeSpan_linear_repeat;
322 if (0 == dx) { 328 if (SkScalarNearlyZero(dx)) {
323 shadeProc = shadeSpan_linear_vertical_lerp; 329 shadeProc = shadeSpan_linear_vertical_lerp;
324 } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) { 330 } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) {
325 shadeProc = shadeSpan_linear_clamp; 331 shadeProc = shadeSpan_linear_clamp;
326 } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) { 332 } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) {
327 shadeProc = shadeSpan_linear_mirror; 333 shadeProc = shadeSpan_linear_mirror;
328 } else { 334 } else {
329 SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode); 335 SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode);
330 } 336 }
331 (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count); 337 (*shadeProc)(proc, dx, fx, dstC, cache, toggle, count);
332 } else { 338 } else {
333 SkScalar dstX = SkIntToScalar(x); 339 SkScalar dstX = SkIntToScalar(x);
334 SkScalar dstY = SkIntToScalar(y); 340 SkScalar dstY = SkIntToScalar(y);
335 do { 341 do {
336 dstProc(fDstToIndex, dstX, dstY, &srcPt); 342 dstProc(fDstToIndex, dstX, dstY, &srcPt);
337 unsigned fi = proc(SkScalarToFixed(srcPt.fX)); 343 unsigned fi = proc(SkScalarToFloat(srcPt.fX));
338 SkASSERT(fi <= 0xFFFF); 344 SkASSERT(fi <= 0xFFFF);
339 *dstC++ = cache[toggle + (fi >> kCache32Shift)]; 345 *dstC++ = cache[toggle + (fi >> kCache32Shift)];
340 toggle = next_dither_toggle(toggle); 346 toggle = next_dither_toggle(toggle);
341 dstX += SK_Scalar1; 347 dstX += SK_Scalar1;
342 } while (--count != 0); 348 } while (--count != 0);
343 } 349 }
344 } 350 }
345 351
346 SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const { 352 SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
347 if (info) { 353 if (info) {
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe r); 768 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe r);
763 } 769 }
764 } else { 770 } else {
765 if (fApplyAlphaAfterInterp) { 771 if (fApplyAlphaAfterInterp) {
766 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe r); 772 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe r);
767 } else { 773 } else {
768 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith er); 774 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith er);
769 } 775 }
770 } 776 }
771 } 777 }
OLDNEW
« no previous file with comments | « src/effects/gradients/SkGradientShaderPriv.h ('k') | src/effects/gradients/SkRadialGradient.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698