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

Side by Side Diff: src/core/SkLinearBitmapPipeline_tile.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_matrix.h ('k') | 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
(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_tile_DEFINED
9 #define SkLinearBitmapPipeline_tile_DEFINED
10
11 #include "SkLinearBitmapPipeline_core.h"
12 #include "SkPM4f.h"
13 #include <algorithm>
14 #include <cmath>
15 #include <limits>
16
17 namespace {
18 class ClampStrategy {
19 public:
20 ClampStrategy(X max)
21 : fXMin{0.0f}, fXMax{max - 1.0f} { }
22
23 ClampStrategy(Y max)
24 : fYMin{0.0f}, fYMax{max - 1.0f} { }
25
26 ClampStrategy(SkSize max)
27 : fXMin{0.0f}, fYMin{0.0f}, fXMax{X(max) - 1.0f}, fYMax{Y(max) - 1.0f} { }
28
29 void processPoints(Sk4s* xs, Sk4s* ys) {
30 *xs = Sk4s::Min(Sk4s::Max(*xs, fXMin), fXMax);
31 *ys = Sk4s::Min(Sk4s::Max(*ys, fYMin), fYMax);
32 }
33
34 template<typename Next>
35 bool maybeProcessSpan(Span originalSpan, Next* next) {
36 SkASSERT(!originalSpan.isEmpty());
37 SkPoint start;
38 SkScalar length;
39 int count;
40 std::tie(start, length, count) = originalSpan;
41 SkScalar xMin = fXMin[0];
42 SkScalar xMax = fXMax[0] + 1.0f;
43 SkScalar yMin = fYMin[0];
44 SkScalar yMax = fYMax[0];
45 SkScalar x = X(start);
46 SkScalar y = std::min(std::max<SkScalar>(yMin, Y(start)), yMax);
47
48 Span span{{x, y}, length, count};
49
50 if (span.completelyWithin(xMin, xMax)) {
51 next->pointSpan(span);
52 return true;
53 }
54 if (1 == count || 0.0f == length) {
55 return false;
56 }
57
58 SkScalar dx = length / (count - 1);
59
60 // A B C
61 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
62 // | *---*|---*---|*---*--||-*---*-|---*---|*---...| |--*---*|---*- --||*---*....
63 // | | | || | | | ... | | ||
64 // | | | || | | | | | ||
65 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
66 // ^ ^
67 // | xMin xMax- 1 | xMax
68 //
69 // *---*---*---... - track of samples. * = sample
70 //
71 // +-+ ||
72 // | | - pixels in source space. || - tile border.
73 // +-+ ||
74 //
75 // The length from A to B is the length in source space or 4 * dx or (co unt - 1) * dx
76 // where dx is the distance between samples. There are 5 destination pix els
77 // corresponding to 5 samples specified in the A, B span. The distance f rom A to the next
78 // span starting at C is 5 * dx, so count * dx.
79 // Remember, count is the number of pixels needed for the destination an d the number of
80 // samples.
81 // Overall Strategy:
82 // * Under - for portions of the span < xMin, take the color at pixel {x Min, y} and use it
83 // to fill in the 5 pixel sampled from A to B.
84 // * Middle - for the portion of the span between xMin and xMax sample n ormally.
85 // * Over - for the portion of the span > xMax, take the color at pixel {xMax-1, y} and
86 // use it to fill in the rest of the destination pixels.
87 if (dx >= 0) {
88 Span leftClamped = span.breakAt(xMin, dx);
89 if (!leftClamped.isEmpty()) {
90 leftClamped.clampToSinglePixel({xMin, y});
91 next->pointSpan(leftClamped);
92 }
93 Span middle = span.breakAt(xMax, dx);
94 if (!middle.isEmpty()) {
95 next->pointSpan(middle);
96 }
97 if (!span.isEmpty()) {
98 span.clampToSinglePixel({xMax - 1, y});
99 next->pointSpan(span);
100 }
101 } else {
102 Span rightClamped = span.breakAt(xMax, dx);
103 if (!rightClamped.isEmpty()) {
104 rightClamped.clampToSinglePixel({xMax - 1, y});
105 next->pointSpan(rightClamped);
106 }
107 Span middle = span.breakAt(xMin, dx);
108 if (!middle.isEmpty()) {
109 next->pointSpan(middle);
110 }
111 if (!span.isEmpty()) {
112 span.clampToSinglePixel({xMin, y});
113 next->pointSpan(span);
114 }
115 }
116 return true;
117 }
118
119 template <typename Next>
120 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
121 return false;
122 }
123
124 private:
125 const Sk4s fXMin{SK_FloatNegativeInfinity};
126 const Sk4s fYMin{SK_FloatNegativeInfinity};
127 const Sk4s fXMax{SK_FloatInfinity};
128 const Sk4s fYMax{SK_FloatInfinity};
129 };
130
131 class RepeatStrategy {
132 public:
133 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f / max} { }
134
135 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f / max} { }
136
137 RepeatStrategy(SkSize max)
138 : fXMax{X(max)}, fXInvMax{1.0f / X(max)}, fYMax{Y(max)}, fYInvMax{1.0f / Y(max)} { }
139
140 void processPoints(Sk4s* xs, Sk4s* ys) {
141 Sk4s divX = (*xs * fXInvMax).floor();
142 Sk4s divY = (*ys * fYInvMax).floor();
143 Sk4s baseX = (divX * fXMax);
144 Sk4s baseY = (divY * fYMax);
145 *xs = *xs - baseX;
146 *ys = *ys - baseY;
147 }
148
149 template<typename Next>
150 bool maybeProcessSpan(Span originalSpan, Next* next) {
151 SkASSERT(!originalSpan.isEmpty());
152 SkPoint start;
153 SkScalar length;
154 int count;
155 std::tie(start, length, count) = originalSpan;
156 // Make x and y in range on the tile.
157 SkScalar x = TileMod(X(start), fXMax[0]);
158 SkScalar y = TileMod(Y(start), fYMax[0]);
159 SkScalar xMax = fXMax[0];
160 SkScalar xMin = 0.0f;
161 SkScalar dx = length / (count - 1);
162
163 // No need trying to go fast because the steps are larger than a tile or there is one point.
164 if (SkScalarAbs(dx) >= xMax || count <= 1) {
165 return false;
166 }
167
168 // A B C D Z
169 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
170 // | | *---|*---*--||-*---*-|---*---|*---*--|| |--*---*| ||
171 // | | | || | | || ... | | ||
172 // | | | || | | || | | ||
173 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
174 // ^^ ^^ ^^
175 // xMax || xMin xMax || xMin xM ax || xMin
176 //
177 // *---*---*---... - track of samples. * = sample
178 //
179 // +-+ ||
180 // | | - pixels in source space. || - tile border.
181 // +-+ ||
182 //
183 //
184 // The given span starts at A and continues on through several tiles to sample point Z.
185 // The idea is to break this into several spans one on each tile the ent ire span
186 // intersects. The A to B span only covers a partial tile and has a coun t of 3 and the
187 // distance from A to B is (count - 1) * dx or 2 * dx. The distance from A to the start of
188 // the next span is count * dx or 3 * dx. Span C to D covers an entire t ile has a count
189 // of 5 and a length of 4 * dx. Remember, count is the number of pixels needed for the
190 // destination and the number of samples.
191 //
192 // Overall Strategy:
193 // While the span hangs over the edge of the tile, draw the span coverin g the tile then
194 // slide the span over to the next tile.
195
196 // The guard could have been count > 0, but then a bunch of math would b e done in the
197 // common case.
198
199 Span span({x, y}, length, count);
200 if (dx > 0) {
201 while (!span.isEmpty() && span.endX() > xMax) {
202 Span toDraw = span.breakAt(xMax, dx);
203 next->pointSpan(toDraw);
204 span.offset(-xMax);
205 }
206 } else {
207 while (!span.isEmpty() && span.endX() < xMin) {
208 Span toDraw = span.breakAt(xMin, dx);
209 next->pointSpan(toDraw);
210 span.offset(xMax);
211 }
212 }
213
214 // All on a single tile.
215 if (!span.isEmpty()) {
216 next->pointSpan(span);
217 }
218
219 return true;
220 }
221
222 template <typename Next>
223 bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
224 return false;
225 }
226
227 private:
228 SkScalar TileMod(SkScalar x, SkScalar base) {
229 return x - std::floor(x / base) * base;
230 }
231 const Sk4s fXMax{0.0f};
232 const Sk4s fXInvMax{0.0f};
233 const Sk4s fYMax{0.0f};
234 const Sk4s fYInvMax{0.0f};
235 };
236
237 } // namespace
238 #endif // SkLinearBitmapPipeline_tile_DEFINED
OLDNEW
« no previous file with comments | « src/core/SkLinearBitmapPipeline_matrix.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698