OLD | NEW |
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 #ifndef SkLinearBitmapPipeline_tile_DEFINED | 8 #ifndef SkLinearBitmapPipeline_tile_DEFINED |
9 #define SkLinearBitmapPipeline_tile_DEFINED | 9 #define SkLinearBitmapPipeline_tile_DEFINED |
10 | 10 |
11 #include "SkLinearBitmapPipeline_core.h" | 11 #include "SkLinearBitmapPipeline_core.h" |
12 #include "SkPM4f.h" | 12 #include "SkPM4f.h" |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <cmath> | 14 #include <cmath> |
15 #include <limits> | 15 #include <limits> |
16 | 16 |
17 namespace { | 17 namespace { |
18 class XClampStrategy { | 18 class XClampStrategy { |
19 public: | 19 public: |
20 XClampStrategy(int32_t max) | 20 XClampStrategy(int32_t max) |
21 : fXsMax{SkScalar(max - 0.5f)} | 21 : fXMaxPixel{SkScalar(max - 0.5f)} |
22 , fXMax{SkScalar(max)} { } | 22 , fXMax{SkScalar(max)} { } |
23 | 23 |
24 void tileXPoints(Sk4s* xs) { | 24 void tileXPoints(Sk4s* xs) { |
25 *xs = Sk4s::Min(Sk4s::Max(*xs, 0.0f), fXsMax); | 25 *xs = Sk4s::Min(Sk4s::Max(*xs, 0.0f), fXMaxPixel); |
26 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); | 26 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); |
27 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); | 27 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); |
28 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); | 28 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); |
29 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); | 29 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); |
30 } | 30 } |
31 | 31 |
32 template<typename Next> | 32 template<typename Next> |
33 bool maybeProcessSpan(Span originalSpan, Next* next) { | 33 bool maybeProcessSpan(Span originalSpan, Next* next) { |
34 SkASSERT(!originalSpan.isEmpty()); | 34 SkASSERT(!originalSpan.isEmpty()); |
35 SkPoint start; SkScalar length; int count; | 35 SkPoint start; SkScalar length; int count; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 } | 101 } |
102 if (!span.isEmpty()) { | 102 if (!span.isEmpty()) { |
103 span.clampToSinglePixel({0.0f, y}); | 103 span.clampToSinglePixel({0.0f, y}); |
104 next->pointSpan(span); | 104 next->pointSpan(span); |
105 } | 105 } |
106 } | 106 } |
107 return true; | 107 return true; |
108 } | 108 } |
109 | 109 |
110 private: | 110 private: |
111 const Sk4s fXsMax; | 111 const SkScalar fXMaxPixel; |
112 const SkScalar fXMax; | 112 const SkScalar fXMax; |
113 }; | 113 }; |
114 | 114 |
115 class YClampStrategy { | 115 class YClampStrategy { |
116 public: | 116 public: |
117 YClampStrategy(int32_t max) | 117 YClampStrategy(int32_t max) |
118 : fYMax{SkScalar(max) - 0.5f} | 118 : fYMax{SkScalar(max) - 0.5f} { } |
119 , fYsMax{SkScalar(max) - 0.5f} { } | |
120 | 119 |
121 void tileYPoints(Sk4s* ys) { | 120 void tileYPoints(Sk4s* ys) { |
122 *ys = Sk4s::Min(Sk4s::Max(*ys, 0.0f), fYsMax); | 121 *ys = Sk4s::Min(Sk4s::Max(*ys, 0.0f), fYMax); |
123 SkASSERT(0 <= (*ys)[0] && (*ys)[0] <= fYMax); | 122 SkASSERT(0 <= (*ys)[0] && (*ys)[0] <= fYMax); |
124 SkASSERT(0 <= (*ys)[1] && (*ys)[1] <= fYMax); | 123 SkASSERT(0 <= (*ys)[1] && (*ys)[1] <= fYMax); |
125 SkASSERT(0 <= (*ys)[2] && (*ys)[2] <= fYMax); | 124 SkASSERT(0 <= (*ys)[2] && (*ys)[2] <= fYMax); |
126 SkASSERT(0 <= (*ys)[3] && (*ys)[3] <= fYMax); | 125 SkASSERT(0 <= (*ys)[3] && (*ys)[3] <= fYMax); |
127 } | 126 } |
128 | 127 |
129 SkScalar tileY(SkScalar y) { | 128 SkScalar tileY(SkScalar y) { |
130 return std::min(std::max<SkScalar>(0.0f, y), fYMax); | 129 return std::min(std::max<SkScalar>(0.0f, y), fYMax); |
131 } | 130 } |
132 | 131 |
133 private: | 132 private: |
134 const SkScalar fYMax; | 133 const SkScalar fYMax; |
135 const Sk4s fYsMax; | |
136 }; | 134 }; |
137 | 135 |
138 SkScalar tile_mod(SkScalar x, SkScalar base) { | 136 SkScalar tile_mod(SkScalar x, SkScalar base) { |
139 return x - SkScalarFloorToScalar(x / base) * base; | 137 return x - SkScalarFloorToScalar(x / base) * base; |
140 } | 138 } |
141 | 139 |
142 class XRepeatStrategy { | 140 class XRepeatStrategy { |
143 public: | 141 public: |
144 XRepeatStrategy(int32_t max) | 142 XRepeatStrategy(int32_t max) |
145 : fXMax{SkScalar(max)} | 143 : fXMax{SkScalar(max)} |
146 , fXsMax{SkScalar(max)} | 144 , fXCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} |
147 , fXsCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} | 145 , fXInvMax{1.0f / SkScalar(max)} { } |
148 , fXsInvMax{1.0f / SkScalar(max)} { } | |
149 | 146 |
150 void tileXPoints(Sk4s* xs) { | 147 void tileXPoints(Sk4s* xs) { |
151 Sk4s divX = *xs * fXsInvMax; | 148 Sk4s divX = *xs * fXInvMax; |
152 Sk4s modX = *xs - divX.floor() * fXsMax; | 149 Sk4s modX = *xs - divX.floor() * fXMax; |
153 *xs = Sk4s::Min(fXsCap, modX); | 150 *xs = Sk4s::Min(fXCap, modX); |
154 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); | 151 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); |
155 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); | 152 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); |
156 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); | 153 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); |
157 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); | 154 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); |
158 } | 155 } |
159 | 156 |
160 template<typename Next> | 157 template<typename Next> |
161 bool maybeProcessSpan(Span originalSpan, Next* next) { | 158 bool maybeProcessSpan(Span originalSpan, Next* next) { |
162 SkASSERT(!originalSpan.isEmpty()); | 159 SkASSERT(!originalSpan.isEmpty()); |
163 SkPoint start; SkScalar length; int count; | 160 SkPoint start; SkScalar length; int count; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 // All on a single tile. | 218 // All on a single tile. |
222 if (!span.isEmpty()) { | 219 if (!span.isEmpty()) { |
223 next->pointSpan(span); | 220 next->pointSpan(span); |
224 } | 221 } |
225 | 222 |
226 return true; | 223 return true; |
227 } | 224 } |
228 | 225 |
229 private: | 226 private: |
230 const SkScalar fXMax; | 227 const SkScalar fXMax; |
231 const Sk4s fXsMax; | 228 const SkScalar fXCap; |
232 const Sk4s fXsCap; | 229 const SkScalar fXInvMax; |
233 const Sk4s fXsInvMax; | |
234 }; | 230 }; |
235 | 231 |
236 // The XRepeatUnitScaleStrategy exploits the situation where dx = 1.0. The main
advantage is that | 232 // The XRepeatUnitScaleStrategy exploits the situation where dx = 1.0. The main
advantage is that |
237 // the relationship between the sample points and the source pixels does not cha
nge from tile to | 233 // the relationship between the sample points and the source pixels does not cha
nge from tile to |
238 // repeated tile. This allows the tiler to calculate the span once and re-use it
for each | 234 // repeated tile. This allows the tiler to calculate the span once and re-use it
for each |
239 // repeated tile. This is later exploited by some samplers to avoid converting p
ixels to linear | 235 // repeated tile. This is later exploited by some samplers to avoid converting p
ixels to linear |
240 // space allowing the use of memmove to place pixel in the destination. | 236 // space allowing the use of memmove to place pixel in the destination. |
241 class XRepeatUnitScaleStrategy { | 237 class XRepeatUnitScaleStrategy { |
242 public: | 238 public: |
243 XRepeatUnitScaleStrategy(int32_t max) | 239 XRepeatUnitScaleStrategy(int32_t max) |
244 : fXMax{SkScalar(max)} | 240 : fXMax{SkScalar(max)} |
245 , fXsMax{SkScalar(max)} | 241 , fXCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} |
246 , fXsCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} | 242 , fXInvMax{1.0f / SkScalar(max)} { } |
247 , fXsInvMax{1.0f / SkScalar(max)} { } | |
248 | 243 |
249 void tileXPoints(Sk4s* xs) { | 244 void tileXPoints(Sk4s* xs) { |
250 Sk4s divX = *xs * fXsInvMax; | 245 Sk4s divX = *xs * fXInvMax; |
251 Sk4s modX = *xs - divX.floor() * fXsMax; | 246 Sk4s modX = *xs - divX.floor() * fXMax; |
252 *xs = Sk4s::Min(fXsCap, modX); | 247 *xs = Sk4s::Min(fXCap, modX); |
253 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); | 248 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); |
254 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); | 249 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); |
255 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); | 250 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); |
256 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); | 251 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); |
257 } | 252 } |
258 | 253 |
259 template<typename Next> | 254 template<typename Next> |
260 bool maybeProcessSpan(Span originalSpan, Next* next) { | 255 bool maybeProcessSpan(Span originalSpan, Next* next) { |
261 SkASSERT(!originalSpan.isEmpty()); | 256 SkASSERT(!originalSpan.isEmpty()); |
262 SkPoint start; SkScalar length; int count; | 257 SkPoint start; SkScalar length; int count; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 span.offset(-advance); | 307 span.offset(-advance); |
313 SkASSERT(0.0f <= span.startX() && span.endX() < fXMax); | 308 SkASSERT(0.0f <= span.startX() && span.endX() < fXMax); |
314 next->pointSpan(span); | 309 next->pointSpan(span); |
315 } | 310 } |
316 | 311 |
317 return true; | 312 return true; |
318 } | 313 } |
319 | 314 |
320 private: | 315 private: |
321 const SkScalar fXMax; | 316 const SkScalar fXMax; |
322 const Sk4s fXsMax; | 317 const SkScalar fXCap; |
323 const Sk4s fXsCap; | 318 const SkScalar fXInvMax; |
324 const Sk4s fXsInvMax; | |
325 }; | 319 }; |
326 | 320 |
327 class YRepeatStrategy { | 321 class YRepeatStrategy { |
328 public: | 322 public: |
329 YRepeatStrategy(int32_t max) | 323 YRepeatStrategy(int32_t max) |
330 : fYMax{SkScalar(max)} | 324 : fYMax{SkScalar(max)} |
331 , fYsMax{SkScalar(max)} | |
332 , fYsInvMax{1.0f / SkScalar(max)} { } | 325 , fYsInvMax{1.0f / SkScalar(max)} { } |
333 | 326 |
334 void tileYPoints(Sk4s* ys) { | 327 void tileYPoints(Sk4s* ys) { |
335 Sk4s divY = *ys * fYsInvMax; | 328 Sk4s divY = *ys * fYsInvMax; |
336 Sk4s modY = *ys - divY.floor() * fYsMax; | 329 Sk4s modY = *ys - divY.floor() * fYMax; |
337 *ys = modY; | 330 *ys = modY; |
338 SkASSERT(0 <= (*ys)[0] && (*ys)[0] < fYMax); | 331 SkASSERT(0 <= (*ys)[0] && (*ys)[0] < fYMax); |
339 SkASSERT(0 <= (*ys)[1] && (*ys)[1] < fYMax); | 332 SkASSERT(0 <= (*ys)[1] && (*ys)[1] < fYMax); |
340 SkASSERT(0 <= (*ys)[2] && (*ys)[2] < fYMax); | 333 SkASSERT(0 <= (*ys)[2] && (*ys)[2] < fYMax); |
341 SkASSERT(0 <= (*ys)[3] && (*ys)[3] < fYMax); | 334 SkASSERT(0 <= (*ys)[3] && (*ys)[3] < fYMax); |
342 } | 335 } |
343 | 336 |
344 SkScalar tileY(SkScalar y) { | 337 SkScalar tileY(SkScalar y) { |
345 SkScalar answer = tile_mod(y, fYMax); | 338 SkScalar answer = tile_mod(y, fYMax); |
346 SkASSERT(0 <= answer && answer < fYMax); | 339 SkASSERT(0 <= answer && answer < fYMax); |
347 return answer; | 340 return answer; |
348 } | 341 } |
349 | 342 |
350 private: | 343 private: |
351 const SkScalar fYMax; | 344 const SkScalar fYMax; |
352 const Sk4s fYsMax; | 345 const SkScalar fYsInvMax; |
353 const Sk4s fYsInvMax; | |
354 }; | 346 }; |
355 // max = 40 | 347 // max = 40 |
356 // mq2[x_] := Abs[(x - 40) - Floor[(x - 40)/80] * 80 - 40] | 348 // mq2[x_] := Abs[(x - 40) - Floor[(x - 40)/80] * 80 - 40] |
357 class XMirrorStrategy { | 349 class XMirrorStrategy { |
358 public: | 350 public: |
359 XMirrorStrategy(int32_t max) | 351 XMirrorStrategy(int32_t max) |
360 : fXsMax{SkScalar(max)} | 352 : fXMax{SkScalar(max)} |
361 , fXsCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} | 353 , fXCap{SkScalar(nextafterf(SkScalar(max), 0.0f))} |
362 , fXsDoubleInvMax{1.0f / (2.0f * SkScalar(max))} { } | 354 , fXDoubleInvMax{1.0f / (2.0f * SkScalar(max))} { } |
363 | 355 |
364 void tileXPoints(Sk4s* xs) { | 356 void tileXPoints(Sk4s* xs) { |
365 Sk4f bias = *xs - fXsMax; | 357 Sk4f bias = *xs - fXMax; |
366 Sk4f div = bias * fXsDoubleInvMax; | 358 Sk4f div = bias * fXDoubleInvMax; |
367 Sk4f mod = bias - div.floor() * 2.0f * fXsMax; | 359 Sk4f mod = bias - div.floor() * 2.0f * fXMax; |
368 Sk4f unbias = mod - fXsMax; | 360 Sk4f unbias = mod - fXMax; |
369 *xs = Sk4f::Min(unbias.abs(), fXsCap); | 361 *xs = Sk4f::Min(unbias.abs(), fXCap); |
370 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXsMax[0]); | 362 SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax); |
371 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXsMax[0]); | 363 SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax); |
372 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXsMax[0]); | 364 SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax); |
373 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXsMax[0]); | 365 SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax); |
374 } | 366 } |
375 | 367 |
376 template <typename Next> | 368 template <typename Next> |
377 bool maybeProcessSpan(Span originalSpan, Next* next) { return false; } | 369 bool maybeProcessSpan(Span originalSpan, Next* next) { return false; } |
378 | 370 |
379 private: | 371 private: |
380 Sk4f fXsMax; | 372 SkScalar fXMax; |
381 Sk4f fXsCap; | 373 SkScalar fXCap; |
382 Sk4f fXsDoubleInvMax; | 374 SkScalar fXDoubleInvMax; |
383 }; | 375 }; |
384 | 376 |
385 class YMirrorStrategy { | 377 class YMirrorStrategy { |
386 public: | 378 public: |
387 YMirrorStrategy(int32_t max) | 379 YMirrorStrategy(int32_t max) |
388 : fYMax{SkScalar(max)} | 380 : fYMax{SkScalar(max)} |
389 , fYsMax{SkScalar(max)} | 381 , fYCap{nextafterf(SkScalar(max), 0.0f)} |
390 , fYsCap{nextafterf(SkScalar(max), 0.0f)} | 382 , fYDoubleInvMax{1.0f / (2.0f * SkScalar(max))} { } |
391 , fYsDoubleInvMax{1.0f / (2.0f * SkScalar(max))} { } | |
392 | 383 |
393 void tileYPoints(Sk4s* ys) { | 384 void tileYPoints(Sk4s* ys) { |
394 Sk4f bias = *ys - fYsMax; | 385 Sk4f bias = *ys - fYMax; |
395 Sk4f div = bias * fYsDoubleInvMax; | 386 Sk4f div = bias * fYDoubleInvMax; |
396 Sk4f mod = bias - div.floor() * 2.0f * fYsMax; | 387 Sk4f mod = bias - div.floor() * 2.0f * fYMax; |
397 Sk4f unbias = mod - fYsMax; | 388 Sk4f unbias = mod - fYMax; |
398 *ys = Sk4f::Min(unbias.abs(), fYsCap); | 389 *ys = Sk4f::Min(unbias.abs(), fYCap); |
399 SkASSERT(0 <= (*ys)[0] && (*ys)[0] < fYMax); | 390 SkASSERT(0 <= (*ys)[0] && (*ys)[0] < fYMax); |
400 SkASSERT(0 <= (*ys)[1] && (*ys)[1] < fYMax); | 391 SkASSERT(0 <= (*ys)[1] && (*ys)[1] < fYMax); |
401 SkASSERT(0 <= (*ys)[2] && (*ys)[2] < fYMax); | 392 SkASSERT(0 <= (*ys)[2] && (*ys)[2] < fYMax); |
402 SkASSERT(0 <= (*ys)[3] && (*ys)[3] < fYMax); | 393 SkASSERT(0 <= (*ys)[3] && (*ys)[3] < fYMax); |
403 } | 394 } |
404 | 395 |
405 SkScalar tileY(SkScalar y) { | 396 SkScalar tileY(SkScalar y) { |
406 SkScalar bias = y - fYMax; | 397 SkScalar bias = y - fYMax; |
407 SkScalar div = bias * fYsDoubleInvMax[0]; | 398 SkScalar div = bias * fYDoubleInvMax; |
408 SkScalar mod = bias - SkScalarFloorToScalar(div) * 2.0f * fYMax; | 399 SkScalar mod = bias - SkScalarFloorToScalar(div) * 2.0f * fYMax; |
409 SkScalar unbias = mod - fYMax; | 400 SkScalar unbias = mod - fYMax; |
410 SkScalar answer = SkMinScalar(SkScalarAbs(unbias), fYsCap[0]); | 401 SkScalar answer = SkMinScalar(SkScalarAbs(unbias), fYCap); |
411 SkASSERT(0 <= answer && answer < fYMax); | 402 SkASSERT(0 <= answer && answer < fYMax); |
412 return answer; | 403 return answer; |
413 } | 404 } |
414 | 405 |
415 private: | 406 private: |
416 SkScalar fYMax; | 407 SkScalar fYMax; |
417 Sk4f fYsMax; | 408 SkScalar fYCap; |
418 Sk4f fYsCap; | 409 SkScalar fYDoubleInvMax; |
419 Sk4f fYsDoubleInvMax; | |
420 }; | 410 }; |
421 | 411 |
422 } // namespace | 412 } // namespace |
423 #endif // SkLinearBitmapPipeline_tile_DEFINED | 413 #endif // SkLinearBitmapPipeline_tile_DEFINED |
OLD | NEW |