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

Side by Side Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 1751943002: Introduce bilerp spans (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Sync 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 | « no previous file | 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 "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
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
136 // BilerpSpans are similar to Spans, but they represent four source samples conv erting to single
137 // destination pixel per count. The pixels for the four samples are collect alon g two horizontal
138 // lines; one starting at {x, y0} and the other starting at {x, y1}. There are t wo distinct lines
139 // to deal with the edge case of the tile mode. For example, y0 may be at the la st y position in
140 // a tile while y1 would be at the first.
141 // The step of a Bilerp (dx) is still length / (count - 1) and the start to the next sample is
142 // still dx * count, but the bounds are complicated by the sampling kernel so th at the pixels
143 // touched are from x to x + length + 1.
144 class BilerpSpan {
145 public:
146 BilerpSpan(SkScalar x, SkScalar y0, SkScalar y1, SkScalar length, int count)
147 : fX{x}, fY0{y0}, fY1{y1}, fLength{length}, fCount{count} {
148 SkASSERT(count >= 0);
149 SkASSERT(std::isfinite(length));
150 SkASSERT(std::isfinite(x));
151 SkASSERT(std::isfinite(y0));
152 SkASSERT(std::isfinite(y1));
153 }
154
155 operator std::tuple<SkScalar&, SkScalar&, SkScalar&, SkScalar&, int&>() {
156 return std::tie(fX, fY0, fY1, fLength, fCount);
157 }
158
159 bool isEmpty() const { return 0 == fCount; }
160
161 private:
162 SkScalar fX;
163 SkScalar fY0;
164 SkScalar fY1;
165 SkScalar fLength;
166 int fCount;
167 };
135 } // namespace 168 } // namespace
136 169
137 class SkLinearBitmapPipeline::PointProcessorInterface { 170 class SkLinearBitmapPipeline::PointProcessorInterface {
138 public: 171 public:
139 virtual ~PointProcessorInterface() { } 172 virtual ~PointProcessorInterface() { }
140 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0; 173 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0;
141 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0; 174 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0;
142 virtual void pointSpan(Span span) = 0; 175 virtual void pointSpan(Span span) = 0;
143 }; 176 };
144 177
145 class SkLinearBitmapPipeline::BilerpProcessorInterface 178 class SkLinearBitmapPipeline::BilerpProcessorInterface
146 : public SkLinearBitmapPipeline::PointProcessorInterface { 179 : public SkLinearBitmapPipeline::PointProcessorInterface {
147 public: 180 public:
148 // The x's and y's are setup in the following order: 181 // The x's and y's are setup in the following order:
149 // +--------+--------+ 182 // +--------+--------+
150 // | | | 183 // | | |
151 // | px00 | px10 | 184 // | px00 | px10 |
152 // | 0 | 1 | 185 // | 0 | 1 |
153 // +--------+--------+ 186 // +--------+--------+
154 // | | | 187 // | | |
155 // | px01 | px11 | 188 // | px01 | px11 |
156 // | 2 | 3 | 189 // | 2 | 3 |
157 // +--------+--------+ 190 // +--------+--------+
158 // These pixels coordinates are arranged in the following order in xs and ys : 191 // These pixels coordinates are arranged in the following order in xs and ys :
159 // px00 px10 px01 px11 192 // px00 px10 px01 px11
160 virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0; 193 virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0;
194 virtual void bilerpSpan(BilerpSpan span) = 0;
161 }; 195 };
162 196
163 class SkLinearBitmapPipeline::PixelPlacerInterface { 197 class SkLinearBitmapPipeline::PixelPlacerInterface {
164 public: 198 public:
165 virtual ~PixelPlacerInterface() { } 199 virtual ~PixelPlacerInterface() { }
166 virtual void setDestination(SkPM4f* dst) = 0; 200 virtual void setDestination(SkPM4f* dst) = 0;
167 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; 201 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
168 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; 202 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ;
169 }; 203 };
170 204
(...skipping 19 matching lines...) Expand all
190 while (count >= 4) { 224 while (count >= 4) {
191 stage->pointList4(xs, ys); 225 stage->pointList4(xs, ys);
192 xs = xs + fourDx; 226 xs = xs + fourDx;
193 count -= 4; 227 count -= 4;
194 } 228 }
195 if (count > 0) { 229 if (count > 0) {
196 stage->pointListFew(count, xs, ys); 230 stage->pointListFew(count, xs, ys);
197 } 231 }
198 } 232 }
199 233
234 template <typename Next>
235 void bilerp_span_fallback(BilerpSpan span, Next* next) {
236 SkScalar x, y0, y1; SkScalar length; int count;
237 std::tie(x, y0, y1, length, count) = span;
238
239 SkASSERT(!span.isEmpty());
240 float dx = length / (count - 1);
241
242 Sk4f xs = Sk4f{x} + Sk4f{0.0f, 1.0f, 0.0f, 1.0f};
243 Sk4f ys = Sk4f{y0, y0, y1, y1};
244
245 // If count == 1 then dx will be inf or NaN, but that is ok because the resu lting addition is
246 // never used.
247 while (count > 0) {
248 next->bilerpList(xs, ys);
249 xs = xs + dx;
250 count -= 1;
251 }
252 }
253
200 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy 254 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy
201 // must implement the following methods: 255 // must implement the following methods:
202 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. 256 // * processPoints(xs, ys) - must mutate the xs and ys for the stage.
203 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel s 257 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel s
204 // to work over. 258 // to work over.
205 // span - encapsulation of span. 259 // span - encapsulation of span.
206 // next - a pointer to the next stage. 260 // next - a pointer to the next stage.
207 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to 261 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to
208 // point lists for processing. 262 // point lists for processing.
209 template<typename Strategy, typename Next> 263 template<typename Strategy, typename Next>
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 fNext->bilerpList(xs, ys); 315 fNext->bilerpList(xs, ys);
262 } 316 }
263 317
264 void pointSpan(Span span) override { 318 void pointSpan(Span span) override {
265 SkASSERT(!span.isEmpty()); 319 SkASSERT(!span.isEmpty());
266 if (!fStrategy.maybeProcessSpan(span, fNext)) { 320 if (!fStrategy.maybeProcessSpan(span, fNext)) {
267 span_fallback(span, this); 321 span_fallback(span, this);
268 } 322 }
269 } 323 }
270 324
325 void bilerpSpan(BilerpSpan bSpan) override {
326 SkASSERT(!bSpan.isEmpty());
327 if (!fStrategy.maybeProcessBilerpSpan(bSpan, fNext)) {
328 bilerp_span_fallback(bSpan, this);
329 }
330 }
331
271 private: 332 private:
272 Next* const fNext; 333 Next* const fNext;
273 Strategy fStrategy; 334 Strategy fStrategy;
274 }; 335 };
275 336
276 class TranslateMatrixStrategy { 337 class TranslateMatrixStrategy {
277 public: 338 public:
278 TranslateMatrixStrategy(SkVector offset) 339 TranslateMatrixStrategy(SkVector offset)
279 : fXOffset{X(offset)} 340 : fXOffset{X(offset)}
280 , fYOffset{Y(offset)} { } 341 , fYOffset{Y(offset)} { }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets); 463 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets);
403 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets); 464 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets);
404 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets); 465 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets);
405 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets); 466 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets);
406 } 467 }
407 468
408 void pointSpan(Span span) override { 469 void pointSpan(Span span) override {
409 SkASSERT(!span.isEmpty()); 470 SkASSERT(!span.isEmpty());
410 SkPoint start; SkScalar length; int count; 471 SkPoint start; SkScalar length; int count;
411 std::tie(start, length, count) = span; 472 std::tie(start, length, count) = span;
412 float dx = length / (count - 1); 473 // Adjust the span so that it is in the correct phase with the pixel.
413 474 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}; 475 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 } 476 }
424 477
425 private: 478 private:
426 Next* const fNext; 479 Next* const fNext;
427 }; 480 };
428 481
429 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( 482 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter(
430 SkLinearBitmapPipeline::BilerpProcessorInterface* next, 483 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
431 SkFilterQuality filterQuailty, 484 SkFilterQuality filterQuailty,
432 SkLinearBitmapPipeline::FilterStage* filterProc) { 485 SkLinearBitmapPipeline::FilterStage* filterProc) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 next->pointSpan(middle); 586 next->pointSpan(middle);
534 } 587 }
535 if (!span.isEmpty()) { 588 if (!span.isEmpty()) {
536 span.clampToSinglePixel({xMin, y}); 589 span.clampToSinglePixel({xMin, y});
537 next->pointSpan(span); 590 next->pointSpan(span);
538 } 591 }
539 } 592 }
540 return true; 593 return true;
541 } 594 }
542 595
596 template <typename Next>
597 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
598 return false;
599 }
600
543 private: 601 private:
544 const Sk4s fXMin{SK_FloatNegativeInfinity}; 602 const Sk4s fXMin{SK_FloatNegativeInfinity};
545 const Sk4s fYMin{SK_FloatNegativeInfinity}; 603 const Sk4s fYMin{SK_FloatNegativeInfinity};
546 const Sk4s fXMax{SK_FloatInfinity}; 604 const Sk4s fXMax{SK_FloatInfinity};
547 const Sk4s fYMax{SK_FloatInfinity}; 605 const Sk4s fYMax{SK_FloatInfinity};
548 }; 606 };
549 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 607 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
550 using Clamp = BilerpProcessor<ClampStrategy, Next>; 608 using Clamp = BilerpProcessor<ClampStrategy, Next>;
551 609
552 static SkScalar tile_mod(SkScalar x, SkScalar base) { 610 static SkScalar tile_mod(SkScalar x, SkScalar base) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 } 694 }
637 695
638 // All on a single tile. 696 // All on a single tile.
639 if (!span.isEmpty()) { 697 if (!span.isEmpty()) {
640 next->pointSpan(span); 698 next->pointSpan(span);
641 } 699 }
642 700
643 return true; 701 return true;
644 } 702 }
645 703
704 template <typename Next>
705 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
706 return false;
707 }
708
646 private: 709 private:
647 const Sk4s fXMax{0.0f}; 710 const Sk4s fXMax{0.0f};
648 const Sk4s fXInvMax{0.0f}; 711 const Sk4s fXInvMax{0.0f};
649 const Sk4s fYMax{0.0f}; 712 const Sk4s fYMax{0.0f};
650 const Sk4s fYInvMax{0.0f}; 713 const Sk4s fYInvMax{0.0f};
651 }; 714 };
652 715
653 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 716 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
654 using Repeat = BilerpProcessor<RepeatStrategy, Next>; 717 using Repeat = BilerpProcessor<RepeatStrategy, Next>;
655 718
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 count -= 1; 980 count -= 1;
918 } 981 }
919 } 982 }
920 983
921 // We're moving through source space faster than dst (zoomed out), 984 // We're moving through source space faster than dst (zoomed out),
922 // so we'll never reuse a source pixel or be able to do contiguous loads. 985 // so we'll never reuse a source pixel or be able to do contiguous loads.
923 void pointSpanFastRate(Span span) { 986 void pointSpanFastRate(Span span) {
924 span_fallback(span, this); 987 span_fallback(span, this);
925 } 988 }
926 989
990 void bilerpSpan(BilerpSpan span) override {
991 bilerp_span_fallback(span, this);
992 }
993
927 private: 994 private:
928 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; 995 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext;
929 SourceStrategy fStrategy; 996 SourceStrategy fStrategy;
930 }; 997 };
931 998
932 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; 999 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>;
933 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; 1000 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>;
934 using Pixel8888SBGR = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kBGRA>; 1001 using Pixel8888SBGR = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kBGRA>;
935 using Pixel8888LBGR = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kBGRA>; 1002 using Pixel8888LBGR = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kBGRA>;
936 1003
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 1100
1034 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 1101 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
1035 SkASSERT(count > 0); 1102 SkASSERT(count > 0);
1036 fPixelStage->setDestination(dst); 1103 fPixelStage->setDestination(dst);
1037 // The count and length arguments start out in a precise relation in order t o keep the 1104 // The count and length arguments start out in a precise relation in order t o keep the
1038 // math correct through the different stages. Count is the number of pixel t o produce. 1105 // math correct through the different stages. Count is the number of pixel t o produce.
1039 // Since the code samples at pixel centers, length is the distance from the center of the 1106 // Since the code samples at pixel centers, length is the distance from the center of the
1040 // first pixel to the center of the last pixel. This implies that length is count-1. 1107 // first pixel to the center of the last pixel. This implies that length is count-1.
1041 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count }); 1108 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count });
1042 } 1109 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698