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 #include "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
9 #include "SkPM4f.h" | 9 #include "SkPM4f.h" |
10 | 10 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 void clampToSinglePixel(SkPoint pixel) { | 125 void clampToSinglePixel(SkPoint pixel) { |
126 fStart = pixel; | 126 fStart = pixel; |
127 fLength = 0.0f; | 127 fLength = 0.0f; |
128 } | 128 } |
129 | 129 |
130 private: | 130 private: |
131 SkPoint fStart; | 131 SkPoint fStart; |
132 SkScalar fLength; | 132 SkScalar fLength; |
133 int fCount; | 133 int fCount; |
134 }; | 134 }; |
135 | |
mtklein_C
2016/03/01 16:34:09
Let'd document what a BilerpSpan represents, espec
herb_g
2016/03/01 22:13:58
Done.
| |
136 class BilerpSpan { | |
137 public: | |
138 BilerpSpan(SkScalar x, SkScalar y0, SkScalar y1, SkScalar length, int count) | |
139 : fX{x}, fY0{y0}, fY1{y1}, fLength{length}, fCount{count} { | |
140 SkASSERT(count >= 0); | |
141 SkASSERT(std::isfinite(length)); | |
142 } | |
143 | |
144 operator std::tuple<SkScalar&, SkScalar&, SkScalar&, SkScalar&, int&>() { | |
145 return std::tie(fX, fY0, fY1, fLength, fCount); | |
146 } | |
147 | |
148 bool isEmpty() const { return 0 == fCount; } | |
149 | |
150 private: | |
151 SkScalar fX; | |
152 SkScalar fY0; | |
153 SkScalar fY1; | |
154 SkScalar fLength; | |
155 int fCount; | |
156 }; | |
135 } // namespace | 157 } // namespace |
136 | 158 |
137 class SkLinearBitmapPipeline::PointProcessorInterface { | 159 class SkLinearBitmapPipeline::PointProcessorInterface { |
138 public: | 160 public: |
139 virtual ~PointProcessorInterface() { } | 161 virtual ~PointProcessorInterface() { } |
140 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0; | 162 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0; |
141 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0; | 163 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0; |
142 virtual void pointSpan(Span span) = 0; | 164 virtual void pointSpan(Span span) = 0; |
143 }; | 165 }; |
144 | 166 |
145 class SkLinearBitmapPipeline::BilerpProcessorInterface | 167 class SkLinearBitmapPipeline::BilerpProcessorInterface |
146 : public SkLinearBitmapPipeline::PointProcessorInterface { | 168 : public SkLinearBitmapPipeline::PointProcessorInterface { |
147 public: | 169 public: |
148 // The x's and y's are setup in the following order: | 170 // The x's and y's are setup in the following order: |
149 // +--------+--------+ | 171 // +--------+--------+ |
150 // | | | | 172 // | | | |
151 // | px00 | px10 | | 173 // | px00 | px10 | |
152 // | 0 | 1 | | 174 // | 0 | 1 | |
153 // +--------+--------+ | 175 // +--------+--------+ |
154 // | | | | 176 // | | | |
155 // | px01 | px11 | | 177 // | px01 | px11 | |
156 // | 2 | 3 | | 178 // | 2 | 3 | |
157 // +--------+--------+ | 179 // +--------+--------+ |
158 // These pixels coordinates are arranged in the following order in xs and ys : | 180 // These pixels coordinates are arranged in the following order in xs and ys : |
159 // px00 px10 px01 px11 | 181 // px00 px10 px01 px11 |
160 virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0; | 182 virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0; |
183 virtual void bilerpSpan(BilerpSpan span) = 0; | |
161 }; | 184 }; |
162 | 185 |
163 class SkLinearBitmapPipeline::PixelPlacerInterface { | 186 class SkLinearBitmapPipeline::PixelPlacerInterface { |
164 public: | 187 public: |
165 virtual ~PixelPlacerInterface() { } | 188 virtual ~PixelPlacerInterface() { } |
166 virtual void setDestination(SkPM4f* dst) = 0; | 189 virtual void setDestination(SkPM4f* dst) = 0; |
167 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; | 190 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; |
168 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; | 191 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; |
169 }; | 192 }; |
170 | 193 |
(...skipping 19 matching lines...) Expand all Loading... | |
190 while (count >= 4) { | 213 while (count >= 4) { |
191 stage->pointList4(xs, ys); | 214 stage->pointList4(xs, ys); |
192 xs = xs + fourDx; | 215 xs = xs + fourDx; |
193 count -= 4; | 216 count -= 4; |
194 } | 217 } |
195 if (count > 0) { | 218 if (count > 0) { |
196 stage->pointListFew(count, xs, ys); | 219 stage->pointListFew(count, xs, ys); |
197 } | 220 } |
198 } | 221 } |
199 | 222 |
223 template <typename Next> | |
224 void bilerp_span_fallback(BilerpSpan span, Next* next) { | |
225 | |
mtklein_C
2016/03/01 16:34:09
Stray newline.
herb_g
2016/03/01 22:13:58
Done.
| |
226 SkASSERT(!span.isEmpty()); | |
227 SkScalar x, y0, y1; SkScalar length; int count; | |
228 std::tie(x, y0, y1, length, count) = span; | |
229 float dx = length / (count - 1); | |
mtklein_C
2016/03/01 16:34:09
Do we not need the usual inf/NaN worries here, or
herb_g
2016/03/01 22:13:58
Done.
| |
230 | |
231 Sk4f xs = Sk4f{x} + Sk4f{0.0f, 1.0f, 0.0f, 1.0f}; | |
232 Sk4f ys = Sk4f{y0, y0, y1, y1}; | |
233 | |
234 while (count > 0) { | |
235 next->bilerpList(xs, ys); | |
236 xs = xs + dx; | |
237 count -= 1; | |
238 } | |
239 } | |
240 | |
200 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy | 241 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy |
201 // must implement the following methods: | 242 // must implement the following methods: |
202 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. | 243 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. |
203 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel s | 244 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel s |
204 // to work over. | 245 // to work over. |
205 // span - encapsulation of span. | 246 // span - encapsulation of span. |
206 // next - a pointer to the next stage. | 247 // next - a pointer to the next stage. |
207 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to | 248 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to |
208 // point lists for processing. | 249 // point lists for processing. |
209 template<typename Strategy, typename Next> | 250 template<typename Strategy, typename Next> |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
261 fNext->bilerpList(xs, ys); | 302 fNext->bilerpList(xs, ys); |
262 } | 303 } |
263 | 304 |
264 void pointSpan(Span span) override { | 305 void pointSpan(Span span) override { |
265 SkASSERT(!span.isEmpty()); | 306 SkASSERT(!span.isEmpty()); |
266 if (!fStrategy.maybeProcessSpan(span, fNext)) { | 307 if (!fStrategy.maybeProcessSpan(span, fNext)) { |
267 span_fallback(span, this); | 308 span_fallback(span, this); |
268 } | 309 } |
269 } | 310 } |
270 | 311 |
312 void bilerpSpan(BilerpSpan bSpan) override { | |
313 SkASSERT(!bSpan.isEmpty()); | |
314 if (!fStrategy.maybeProcessBilerpSpan(bSpan, fNext)) { | |
315 bilerp_span_fallback(bSpan, this); | |
316 } | |
317 } | |
318 | |
271 private: | 319 private: |
272 Next* const fNext; | 320 Next* const fNext; |
273 Strategy fStrategy; | 321 Strategy fStrategy; |
274 }; | 322 }; |
275 | 323 |
276 class TranslateMatrixStrategy { | 324 class TranslateMatrixStrategy { |
277 public: | 325 public: |
278 TranslateMatrixStrategy(SkVector offset) | 326 TranslateMatrixStrategy(SkVector offset) |
279 : fXOffset{X(offset)} | 327 : fXOffset{X(offset)} |
280 , fYOffset{Y(offset)} { } | 328 , fYOffset{Y(offset)} { } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets); | 450 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets); |
403 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets); | 451 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets); |
404 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets); | 452 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets); |
405 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets); | 453 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets); |
406 } | 454 } |
407 | 455 |
408 void pointSpan(Span span) override { | 456 void pointSpan(Span span) override { |
409 SkASSERT(!span.isEmpty()); | 457 SkASSERT(!span.isEmpty()); |
410 SkPoint start; SkScalar length; int count; | 458 SkPoint start; SkScalar length; int count; |
411 std::tie(start, length, count) = span; | 459 std::tie(start, length, count) = span; |
412 float dx = length / (count - 1); | 460 // Adjust the span so that it is in the correct phase with the pixel. |
413 | 461 BilerpSpan bSpan{X(start) - 0.5f, Y(start) - 0.5f, Y(start) + 0.5f, leng th, count}; |
414 Sk4f Xs = Sk4f{X(start)} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f}; | 462 fNext->bilerpSpan(bSpan); |
415 Sk4f Ys = Sk4f{Y(start)} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f}; | |
416 | |
417 Sk4f dXs{dx}; | |
418 while (count > 0) { | |
419 fNext->bilerpList(Xs, Ys); | |
420 Xs = Xs + dXs; | |
421 count -= 1; | |
422 } | |
423 } | 463 } |
424 | 464 |
425 private: | 465 private: |
426 Next* const fNext; | 466 Next* const fNext; |
427 }; | 467 }; |
428 | 468 |
429 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( | 469 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( |
430 SkLinearBitmapPipeline::BilerpProcessorInterface* next, | 470 SkLinearBitmapPipeline::BilerpProcessorInterface* next, |
431 SkFilterQuality filterQuailty, | 471 SkFilterQuality filterQuailty, |
432 SkLinearBitmapPipeline::FilterStage* filterProc) { | 472 SkLinearBitmapPipeline::FilterStage* filterProc) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 next->pointSpan(middle); | 573 next->pointSpan(middle); |
534 } | 574 } |
535 if (!span.isEmpty()) { | 575 if (!span.isEmpty()) { |
536 span.clampToSinglePixel({xMin, y}); | 576 span.clampToSinglePixel({xMin, y}); |
537 next->pointSpan(span); | 577 next->pointSpan(span); |
538 } | 578 } |
539 } | 579 } |
540 return true; | 580 return true; |
541 } | 581 } |
542 | 582 |
583 template <typename Next> | |
584 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) { | |
585 return false; | |
586 } | |
587 | |
543 private: | 588 private: |
544 const Sk4s fXMin{SK_FloatNegativeInfinity}; | 589 const Sk4s fXMin{SK_FloatNegativeInfinity}; |
545 const Sk4s fYMin{SK_FloatNegativeInfinity}; | 590 const Sk4s fYMin{SK_FloatNegativeInfinity}; |
546 const Sk4s fXMax{SK_FloatInfinity}; | 591 const Sk4s fXMax{SK_FloatInfinity}; |
547 const Sk4s fYMax{SK_FloatInfinity}; | 592 const Sk4s fYMax{SK_FloatInfinity}; |
548 }; | 593 }; |
549 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> | 594 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
550 using Clamp = BilerpProcessor<ClampStrategy, Next>; | 595 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
551 | 596 |
552 static SkScalar tile_mod(SkScalar x, SkScalar base) { | 597 static SkScalar tile_mod(SkScalar x, SkScalar base) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
636 } | 681 } |
637 | 682 |
638 // All on a single tile. | 683 // All on a single tile. |
639 if (!span.isEmpty()) { | 684 if (!span.isEmpty()) { |
640 next->pointSpan(span); | 685 next->pointSpan(span); |
641 } | 686 } |
642 | 687 |
643 return true; | 688 return true; |
644 } | 689 } |
645 | 690 |
691 template <typename Next> | |
692 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) { | |
693 return false; | |
694 } | |
695 | |
646 private: | 696 private: |
647 const Sk4s fXMax{0.0f}; | 697 const Sk4s fXMax{0.0f}; |
648 const Sk4s fXInvMax{0.0f}; | 698 const Sk4s fXInvMax{0.0f}; |
649 const Sk4s fYMax{0.0f}; | 699 const Sk4s fYMax{0.0f}; |
650 const Sk4s fYInvMax{0.0f}; | 700 const Sk4s fYInvMax{0.0f}; |
651 }; | 701 }; |
652 | 702 |
653 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> | 703 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
654 using Repeat = BilerpProcessor<RepeatStrategy, Next>; | 704 using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
655 | 705 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 Sk4f px00, px10, px01, px11; | 875 Sk4f px00, px10, px01, px11; |
826 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); | 876 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); |
827 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | 877 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
828 fNext->placePixel(pixel); | 878 fNext->placePixel(pixel); |
829 } | 879 } |
830 | 880 |
831 void pointSpan(Span span) override { | 881 void pointSpan(Span span) override { |
832 span_fallback(span, this); | 882 span_fallback(span, this); |
833 } | 883 } |
834 | 884 |
885 void bilerpSpan(BilerpSpan span) override { | |
886 bilerp_span_fallback(span, this); | |
887 } | |
888 | |
835 private: | 889 private: |
836 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; | 890 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; |
837 SourceStrategy fStrategy; | 891 SourceStrategy fStrategy; |
838 }; | 892 }; |
839 | 893 |
840 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; | 894 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; |
841 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; | 895 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; |
842 using Pixel8888SBGR = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kBGRA>; | 896 using Pixel8888SBGR = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kBGRA>; |
843 using Pixel8888LBGR = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kBGRA>; | 897 using Pixel8888LBGR = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kBGRA>; |
844 | 898 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
941 | 995 |
942 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 996 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
943 SkASSERT(count > 0); | 997 SkASSERT(count > 0); |
944 fPixelStage->setDestination(dst); | 998 fPixelStage->setDestination(dst); |
945 // The count and length arguments start out in a precise relation in order t o keep the | 999 // The count and length arguments start out in a precise relation in order t o keep the |
946 // math correct through the different stages. Count is the number of pixel t o produce. | 1000 // math correct through the different stages. Count is the number of pixel t o produce. |
947 // Since the code samples at pixel centers, length is the distance from the center of the | 1001 // Since the code samples at pixel centers, length is the distance from the center of the |
948 // first pixel to the center of the last pixel. This implies that length is count-1. | 1002 // first pixel to the center of the last pixel. This implies that length is count-1. |
949 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count }); | 1003 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count }); |
950 } | 1004 } |
OLD | NEW |