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

Side by Side Diff: src/core/SkLinearBitmapPipeline_core.h

Issue 1765953002: break out the tile and matrix strategies (Closed) Base URL: https://skia.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/core/SkLinearBitmapPipeline.cpp ('k') | src/core/SkLinearBitmapPipeline_matrix.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkLinearBitmapPipeline_core_DEFINED
9 #define SkLinearBitmapPipeline_core_DEFINED
10
11 // Tweak ABI of functions that pass Sk4f by value to pass them via registers.
12 #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
13 #define VECTORCALL __vectorcall
14 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
15 #define VECTORCALL __attribute__((pcs("aapcs-vfp")))
16 #else
17 #define VECTORCALL
18 #endif
19
20 namespace {
21 struct X {
22 explicit X(SkScalar val) : fVal{val} { }
23 explicit X(SkPoint pt) : fVal{pt.fX} { }
24 explicit X(SkSize s) : fVal{s.fWidth} { }
25 explicit X(SkISize s) : fVal(s.fWidth) { }
26 operator SkScalar () const {return fVal;}
27 private:
28 SkScalar fVal;
29 };
30
31 struct Y {
32 explicit Y(SkScalar val) : fVal{val} { }
33 explicit Y(SkPoint pt) : fVal{pt.fY} { }
34 explicit Y(SkSize s) : fVal{s.fHeight} { }
35 explicit Y(SkISize s) : fVal(s.fHeight) { }
36 operator SkScalar () const {return fVal;}
37 private:
38 SkScalar fVal;
39 };
40
41 // The Span class enables efficient processing horizontal spans of pixels.
42 // * start - the point where to start the span.
43 // * length - the number of pixels to traverse in source space.
44 // * count - the number of pixels to produce in destination space.
45 // Both start and length are mapped through the inversion matrix to produce valu es in source
46 // space. After the matrix operation, the tilers may break the spans up into sma ller spans.
47 // The tilers can produce spans that seem nonsensical.
48 // * The clamp tiler can create spans with length of 0. This indicates to copy a n edge pixel out
49 // to the edge of the destination scan.
50 // * The mirror tiler can produce spans with negative length. This indicates tha t the source
51 // should be traversed in the opposite direction to the destination pixels.
52 class Span {
53 public:
54 Span(SkPoint start, SkScalar length, int count)
55 : fStart(start)
56 , fLength(length)
57 , fCount{count} {
58 SkASSERT(std::isfinite(length));
59 }
60
61 operator std::tuple<SkPoint&, SkScalar&, int&>() {
62 return std::tie(fStart, fLength, fCount);
63 }
64
65 bool isEmpty() const { return 0 == fCount; }
66 SkScalar length() const { return fLength; }
67 SkScalar startX() const { return X(fStart); }
68 SkScalar endX() const { return startX() + length(); }
69 void clear() {
70 fCount = 0;
71 }
72
73 bool completelyWithin(SkScalar xMin, SkScalar xMax) const {
74 SkScalar sMin, sMax;
75 std::tie(sMin, sMax) = std::minmax(startX(), endX());
76 return xMin <= sMin && sMax <= xMax;
77 }
78
79 void offset(SkScalar offsetX) {
80 fStart.offset(offsetX, 0.0f);
81 }
82
83 Span breakAt(SkScalar breakX, SkScalar dx) {
84 SkASSERT(std::isfinite(breakX));
85 SkASSERT(std::isfinite(dx));
86 SkASSERT(dx != 0.0f);
87
88 if (this->isEmpty()) {
89 return Span{{0.0, 0.0}, 0.0f, 0};
90 }
91
92 int dxSteps = SkScalarFloorToInt((breakX - this->startX()) / dx);
93 if (dxSteps < 0) {
94 // The span is wholly after breakX.
95 return Span{{0.0, 0.0}, 0.0f, 0};
96 } else if (dxSteps > fCount) {
97 // The span is wholly before breakX.
98 Span answer = *this;
99 this->clear();
100 return answer;
101 }
102
103 // Calculate the values for the span to cleave off.
104 SkPoint newStart = fStart;
105 SkScalar newLength = dxSteps * dx;
106 int newCount = dxSteps + 1;
107 SkASSERT(newCount > 0);
108
109 // Update this span to reflect the break.
110 SkScalar lengthToStart = newLength + dx;
111 fLength -= lengthToStart;
112 fCount -= newCount;
113 fStart = {this->startX() + lengthToStart, Y(fStart)};
114
115 return Span{newStart, newLength, newCount};
116 }
117
118 void clampToSinglePixel(SkPoint pixel) {
119 fStart = pixel;
120 fLength = 0.0f;
121 }
122
123 private:
124 SkPoint fStart;
125 SkScalar fLength;
126 int fCount;
127 };
128
129 // BilerpSpans are similar to Spans, but they represent four source samples conv erting to single
130 // destination pixel per count. The pixels for the four samples are collect alon g two horizontal
131 // lines; one starting at {x, y0} and the other starting at {x, y1}. There are t wo distinct lines
132 // to deal with the edge case of the tile mode. For example, y0 may be at the la st y position in
133 // a tile while y1 would be at the first.
134 // The step of a Bilerp (dx) is still length / (count - 1) and the start to the next sample is
135 // still dx * count, but the bounds are complicated by the sampling kernel so th at the pixels
136 // touched are from x to x + length + 1.
137 class BilerpSpan {
138 public:
139 BilerpSpan(SkScalar x, SkScalar y0, SkScalar y1, SkScalar length, int count)
140 : fX{x}, fY0{y0}, fY1{y1}, fLength{length}, fCount{count} {
141 SkASSERT(count >= 0);
142 SkASSERT(std::isfinite(length));
143 SkASSERT(std::isfinite(x));
144 SkASSERT(std::isfinite(y0));
145 SkASSERT(std::isfinite(y1));
146 }
147
148 operator std::tuple<SkScalar&, SkScalar&, SkScalar&, SkScalar&, int&>() {
149 return std::tie(fX, fY0, fY1, fLength, fCount);
150 }
151
152 bool isEmpty() const { return 0 == fCount; }
153
154 private:
155 SkScalar fX;
156 SkScalar fY0;
157 SkScalar fY1;
158 SkScalar fLength;
159 int fCount;
160 };
161
162 template<typename Stage>
163 void span_fallback(Span span, Stage* stage) {
164 SkPoint start;
165 SkScalar length;
166 int count;
167 std::tie(start, length, count) = span;
168 Sk4f xs{X(start)};
169 Sk4f ys{Y(start)};
170
171 // Initializing this is not needed, but some compilers can't figure this out .
172 Sk4s fourDx{0.0f};
173 if (count > 1) {
174 SkScalar dx = length / (count - 1);
175 xs = xs + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * dx;
176 // Only used if count is >= 4.
177 fourDx = Sk4f{4.0f * dx};
178 }
179
180 while (count >= 4) {
181 stage->pointList4(xs, ys);
182 xs = xs + fourDx;
183 count -= 4;
184 }
185 if (count > 0) {
186 stage->pointListFew(count, xs, ys);
187 }
188 }
189
190 template <typename Next>
191 void bilerp_span_fallback(BilerpSpan span, Next* next) {
192 SkScalar x, y0, y1; SkScalar length; int count;
193 std::tie(x, y0, y1, length, count) = span;
194
195 SkASSERT(!span.isEmpty());
196 float dx = length / (count - 1);
197
198 Sk4f xs = Sk4f{x} + Sk4f{0.0f, 1.0f, 0.0f, 1.0f};
199 Sk4f ys = Sk4f{y0, y0, y1, y1};
200
201 // If count == 1 then dx will be inf or NaN, but that is ok because the resu lting addition is
202 // never used.
203 while (count > 0) {
204 next->bilerpList(xs, ys);
205 xs = xs + dx;
206 count -= 1;
207 }
208 }
209 } // namespace
210
211 #endif // SkLinearBitmapPipeline_core_DEFINED
OLDNEW
« no previous file with comments | « src/core/SkLinearBitmapPipeline.cpp ('k') | src/core/SkLinearBitmapPipeline_matrix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698