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

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

Issue 1704583003: Simplified linear pipeline. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 10 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
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 #include "SkLinearBitmapPipeline.h"
9
10 struct X {
11 explicit X(SkScalar val) : fVal{val} { }
12 explicit X(SkPoint pt) : fVal{pt.fX} { }
13 explicit X(SkSize s) : fVal{s.fWidth} { }
14 explicit X(SkISize s) : fVal(s.fWidth) { }
15 operator float () const {return fVal;}
16 private:
17 float fVal;
18 };
19
20 struct Y {
21 explicit Y(SkScalar val) : fVal{val} { }
22 explicit Y(SkPoint pt) : fVal{pt.fY} { }
23 explicit Y(SkSize s) : fVal{s.fHeight} { }
24 explicit Y(SkISize s) : fVal(s.fHeight) { }
25
26 operator float () const {return fVal;}
27 private:
28 float fVal;
29 };
30
31 template <typename Next>
32 void SpanFallback(SkPoint start, SkScalar length, int count, Next* next) {
mtklein 2016/02/16 21:13:10 suspiciously similar to shadeSpan
herb_g 2016/02/16 22:04:24 removed
33 float dx = length / (count - 1);
34
35 Sk4f Xs = Sk4f(X(start)) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * Sk4f{dx};
36 Sk4f Ys{Y(start)};
37 Sk4f fours = {4.0f * dx};
38
39 while (count >= 4) {
40 next->pointList4(Xs, Ys);
41 Xs = Xs + fours;
42 count -= 4;
43 }
44 if (count > 0) {
45 next->pointListFew(count, Xs, Ys);
46 }
47 }
48
49 template<typename Strategy, typename Next>
50 class PointProcessor : public PointProcessorInterface {
51 public:
52 template <typename... Args>
53 PointProcessor(Next* next, Args&&... args)
54 : fNext{next}
55 , fStrategy{std::forward<Args>(args)...}{ }
56
57 void pointListFew(int n, Sk4f xs, Sk4f ys) override {
58 fStrategy.processPoints(n, &xs, &ys);
mtklein 2016/02/16 21:13:10 it looks like no strategy needs n
herb_g 2016/02/16 22:04:25 Done.
59 fNext->pointListFew(n, xs, ys);
60 }
61
62 void pointList4(Sk4f xs, Sk4f ys) override {
63 fStrategy.processPoints(4, &xs, &ys);
mtklein 2016/02/16 21:13:10 ditto
herb_g 2016/02/16 22:04:25 Done.
64 fNext->pointList4(xs, ys);
65 }
66
67 private:
68 Next* const fNext;
69 Strategy fStrategy;
70 };
71
72 class AbortPointProcessor final : public PointProcessorInterface {
mtklein 2016/02/16 21:13:10 SkippedStage?
herb_g 2016/02/16 22:04:24 Done.
73 void pointListFew(int n, Sk4f x, Sk4f y) override {
74 SkFAIL("Abort tiler.");
75 }
76 void pointList4(Sk4f Xs, Sk4f Ys) override {
77 SkFAIL("Abort point processor.");
78 }
79 };
80
81 class IdentityMatrixStrategy {
mtklein 2016/02/16 21:13:10 dead code?
herb_g 2016/02/16 22:04:25 Done.
82 public:
83 void processPoints(int n, Sk4f* xs, Sk4f* ys) { }
84 };
85 template <typename Next = PointProcessorInterface>
86 using IdentityMatrix = PointProcessor<IdentityMatrixStrategy, Next>;
87
88 class TranslateMatrixStrategy {
89 public:
90 TranslateMatrixStrategy(SkVector offset)
91 : fXOffset{X(offset)}
92 , fYOffset{Y(offset)} { }
93 void processPoints(int n, Sk4f* xs, Sk4f* ys) {
94 *xs = *xs + fXOffset;
95 *ys = *ys + fYOffset;
96 }
97
98 private:
99 const Sk4f fXOffset, fYOffset;
100 };
101 template <typename Next = PointProcessorInterface>
102 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>;
103
104 class ScaleMatrixStrategy {
105 public:
106 ScaleMatrixStrategy(SkVector offset, SkVector scale)
107 : fXOffset{X(offset)}, fYOffset{Y(offset)}
108 , fXScale{X(scale)}, fYScale{Y(scale)} { }
109 void processPoints(int n, Sk4f* xs, Sk4f* ys) {
110 *xs = *xs * fXScale + fXOffset;
111 *ys = *ys * fYScale + fYOffset;
112 }
113
114 private:
115 const Sk4f fXOffset, fYOffset;
116 const Sk4f fXScale, fYScale;
117 };
118 template <typename Next = PointProcessorInterface>
119 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>;
120
121 class AffineMatrixStrategy {
122 public:
123 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew)
124 : fXOffset{X(offset)}, fYOffset{Y(offset)}
125 , fXScale{X(scale)}, fYScale{Y(scale)}
126 , fXSkew{X(skew)}, fYSkew{Y(skew)} { }
127 void processPoints(int n, Sk4f* xs, Sk4f* ys) {
128 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset;
129 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset;
130
131 *xs = newXs;
132 *ys = newYs;
133 }
134
135 private:
136 const Sk4f fXOffset, fYOffset;
137 const Sk4f fXScale, fYScale;
138 const Sk4f fXSkew, fYSkew;
139 };
140 template <typename Next = PointProcessorInterface>
141 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>;
142
143 static PointProcessorInterface* choose_matrix(
144 PointProcessorInterface* next,
145 const SkMatrix& inverse,
146 MatrixStage* matrixProc) {
147 if (inverse.hasPerspective()) {
148 SkFAIL("Not implemented.");
149 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
150 matrixProc->Initialize<AffineMatrix<>>(
151 next,
152 SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
153 SkVector{inverse.getScaleX(), inverse.getScaleY()},
154 SkVector{inverse.getSkewX(), inverse.getSkewY()});
155 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
156 matrixProc->Initialize<ScaleMatrix<>>(
157 next,
158 SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
159 SkVector{inverse.getScaleX(), inverse.getScaleY()});
160 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0 f) {
161 matrixProc->Initialize<TranslateMatrix<>>(
162 next,
163 SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
164 } else {
165 matrixProc->Initialize<AbortPointProcessor>();
166 return next;
167 }
168 return matrixProc->get();
169 }
170
171 class ClampStrategy {
172 public:
173 ClampStrategy(X max)
174 : fXMin{0.0f}
175 , fXMax{max - 1.0f} { }
176 ClampStrategy(Y max)
177 : fYMin{0.0f}
178 , fYMax{max - 1.0f} { }
179 ClampStrategy(SkSize max)
180 : fXMin{0.0f}
181 , fYMin{0.0f}
182 , fXMax{X(max) - 1.0f}
183 , fYMax{Y(max) - 1.0f} { }
184
185 void processPoints(int n, Sk4f* xs, Sk4f* ys) {
186 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax);
187 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax);
188 }
189
190 private:
191 const Sk4f fXMin{SK_FloatNegativeInfinity};
192 const Sk4f fYMin{SK_FloatNegativeInfinity};
193 const Sk4f fXMax{SK_FloatInfinity};
194 const Sk4f fYMax{SK_FloatInfinity};
195 };
196 template <typename Next = PointProcessorInterface>
197 using Clamp = PointProcessor<ClampStrategy, Next>;
198
199 class RepeatStrategy {
200 public:
201 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { }
202 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { }
203 RepeatStrategy(SkSize max)
204 : fXMax{X(max)}
205 , fXInvMax{1.0f / X(max)}
206 , fYMax{Y(max)}
207 , fYInvMax{1.0f / Y(max)} { }
208
209 void processPoints(int n, Sk4f* xs, Sk4f* ys) {
210 Sk4f divX = (*xs * fXInvMax).floor();
211 Sk4f divY = (*ys * fYInvMax).floor();
212 Sk4f baseX = (divX * fXMax);
213 Sk4f baseY = (divY * fYMax);
214 *xs = *xs - baseX;
215 *ys = *ys - baseY;
216 }
217
218 private:
219 const Sk4f fXMax{0.0f};
220 const Sk4f fXInvMax{0.0f};
221 const Sk4f fYMax{0.0f};
222 const Sk4f fYInvMax{0.0f};
223 };
224
225 template <typename Next = PointProcessorInterface>
226 using Repeat = PointProcessor<RepeatStrategy, Next>;
227
228 static PointProcessorInterface* choose_tiler(
229 PointProcessorInterface* next,
230 SkSize dimensions,
231 SkShader::TileMode xMode,
232 SkShader::TileMode yMode,
233 TileStage* tileProcXOrBoth,
234 TileStage* tileProcY) {
235 if (xMode == yMode) {
236 switch (xMode) {
237 case SkShader::kClamp_TileMode:
238 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions);
239 break;
240 case SkShader::kRepeat_TileMode:
241 tileProcXOrBoth->Initialize<Repeat<>>(next, dimensions);
242 break;
243 case SkShader::kMirror_TileMode:
244 SkFAIL("Not implemented.");
245 break;
246 }
247 tileProcY->Initialize<AbortPointProcessor>();
248 } else {
249 switch (yMode) {
250 case SkShader::kClamp_TileMode:
251 tileProcY->Initialize<Clamp<>>(next, Y(dimensions));
252 break;
253 case SkShader::kRepeat_TileMode:
254 tileProcY->Initialize<Repeat<>>(next, Y(dimensions));
255 break;
256 case SkShader::kMirror_TileMode:
257 SkFAIL("Not implemented.");
258 break;
259 }
260 switch (xMode) {
261 case SkShader::kClamp_TileMode:
262 tileProcXOrBoth->Initialize<Clamp<>>(tileProcY->get(), X(dimensi ons));
263 break;
264 case SkShader::kRepeat_TileMode:
265 tileProcXOrBoth->Initialize<Repeat<>>(tileProcY->get(), X(dimens ions));
266 break;
267 case SkShader::kMirror_TileMode:
268 SkFAIL("Not implemented.");
269 break;
270 }
271 }
272 return tileProcXOrBoth->get();
273 }
274
275 inline Sk4f bilerp4(SkPoint pt, Sk4f pixel00, Sk4f pixel01,
mtklein 2016/02/16 21:13:10 die
herb_g 2016/02/16 22:04:25 Done.
276 Sk4f pixel10, Sk4f pixel11) {
277 Sk4f Xs{X(pt) - std::floor(X(pt))};
278 Sk4f Ys{Y(pt) - std::floor(Y(pt))};
279 Sk4f XYs{Xs * Ys};
280 Sk4f sum = pixel11 * XYs;
281 sum = sum + pixel01 * (Xs - XYs);
282 sum = sum + pixel10 * (Ys - XYs);
283 sum = sum + pixel00 * (Sk4f{1.0f} - Xs - Ys + XYs);
284 return sum;
285 }
286
287 class sRGBFast {
288 public:
289 static Sk4f sRGBToLinear(Sk4f pixel) {
290 Sk4f l = pixel * pixel;
291 return Sk4f{l[0], l[1], l[2], pixel[3]};
292 }
293 };
294
295 template <SkColorProfileType colorProfile>
296 class Passthrough8888 {
297 public:
298 Passthrough8888(int width, const uint32_t* src)
299 : fSrc{src}, fWidth{width}{ }
300
301 Sk4f getPixel(const uint32_t* src, int index) {
mtklein 2016/02/16 21:13:10 private?
herb_g 2016/02/16 22:04:25 Done.
302 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index]));
303 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel);
304 pixel = pixel * Sk4f{1.0f/255.0f};
305 if (colorProfile == kSRGB_SkColorProfileType) {
306 pixel = sRGBFast::sRGBToLinear(pixel);
307 }
308 return pixel;
309 }
310
311 void getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) {
312 Sk4i XIs = SkNx_cast<int, float>(xs);
313 Sk4i YIs = SkNx_cast<int, float>(ys);
314 Sk4i bufferLoc = YIs * fWidth + XIs;
315 switch (n) {
316 case 4:
317 *px3 = getPixel(fSrc, bufferLoc[3]);
318 case 3:
319 *px2 = getPixel(fSrc, bufferLoc[2]);
320 case 2:
321 *px1 = getPixel(fSrc, bufferLoc[1]);
322 case 1:
323 *px0 = getPixel(fSrc, bufferLoc[0]);
324 default:
325 break;
326 }
327 }
328
329 void get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3 ) {
330 Sk4i XIs = SkNx_cast<int, float>(xs);
331 Sk4i YIs = SkNx_cast<int, float>(ys);
332 Sk4i bufferLoc = YIs * fWidth + XIs;
333 *px0 = getPixel(fSrc, bufferLoc[0]);
334 *px1 = getPixel(fSrc, bufferLoc[1]);
335 *px2 = getPixel(fSrc, bufferLoc[2]);
336 *px3 = getPixel(fSrc, bufferLoc[3]);
337 }
338
339 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; }
340
341 private:
342 const uint32_t* const fSrc;
343 const Sk4i fWidth;
344 };
345
346 template <typename SourceStrategy>
347 class Sampler final : public PointProcessorInterface {
348 public:
349 template <typename... Args>
350 Sampler(PixelPlacerInterface* next, Args&&... args)
351 : fNext{next}
352 , fStrategy{std::forward<Args>(args)...} { }
353
354 void pointListFew(int n, Sk4f xs, Sk4f ys) override {
355 Sk4f px0, px1, px2, px3;
356 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2, &px3);
mtklein 2016/02/16 21:13:10 should not need px3?
herb_g 2016/02/16 22:04:25 Done.
357 if (0 == n) return;
mtklein 2016/02/16 21:13:10 assert n < 4 && n > 0?
herb_g 2016/02/16 22:04:24 Done.
358 fNext->placePixel(px0);
mtklein 2016/02/16 21:13:10 if (n > 0) { fNext->placePixel(px0); } if (n > 1)
herb_g 2016/02/16 22:04:25 Done.
359 if (1 == n) return;
360 fNext->placePixel(px1);
361 if (2 == n) return;
362 fNext->placePixel(px2);
363 if (3 == n) return;
364
365 fNext->placePixel(px3);
366 }
367
368 void pointList4(Sk4f xs, Sk4f ys) override {
369 Sk4f px0, px1, px2, px3;
370 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
371 fNext->place4Pixels(px0, px1, px2, px3);
372 }
373
374 private:
375 PixelPlacerInterface* const fNext;
376 SourceStrategy fStrategy;
377 };
378
379 template <SkAlphaType alphaType>
380 class PlaceFPPixel final : public PixelPlacerInterface {
381 public:
382 void placePixel(Sk4f pixel) override {
383 PlacePixel(fDst, pixel, 0);
384 fDst += 1;
385 }
386
387 void place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
388 SkPM4f* dst = fDst;
389 PlacePixel(dst, p0, 0);
390 PlacePixel(dst, p1, 1);
391 PlacePixel(dst, p2, 2);
392 PlacePixel(dst, p3, 3);
393 fDst += 4;
394 }
395
396 void setDestination(SkPM4f* dst) override {
397 fDst = dst;
398 }
399
400 private:
401 static void PlacePixel(SkPM4f* dst, Sk4f pixel, int index) {
402 if (alphaType == kUnpremul_SkAlphaType) {
403 pixel = Premultiply(pixel);
404 }
405 pixel.store(dst + index);
406 }
407 static Sk4f Premultiply(Sk4f pixel) {
408 float alpha = pixel[3];
409 return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
410 }
411
412 SkPM4f* fDst;
413 };
414
415 static PointProcessorInterface* choose_pixel_sampler(
416 PixelPlacerInterface* next,
417 const SkImageInfo& imageInfo,
418 const void* imageData,
419 SampleStage* sampleStage) {
420 switch (imageInfo.colorType()) {
421 case kRGBA_8888_SkColorType:
422 if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
423 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColorPro fileType>>>(
424 next, imageInfo.width(),
425 (uint32_t *)imageData);
426 } else {
427 sampleStage->Initialize<Sampler<Passthrough8888<kLinear_SkColorP rofileType>>>(
428 next, imageInfo.width(),
429 (uint32_t *)imageData);
430 }
431 break;
432 default:
433 SkFAIL("Not implemented. Unsupported src");
434 break;
435 }
436 return sampleStage->get();
437 }
438
439 static PixelPlacerInterface* choose_pixel_placer(SkAlphaType alphaType, PixelSta ge* placerStage) {
440 if (alphaType == kUnpremul_SkAlphaType) {
441 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>();
442 } else {
443 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
444 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>();
445 }
446 return placerStage->get();
447 }
448
449 SkLinearBitmapPipeline::SkLinearBitmapPipeline(
450 const SkMatrix& inverse,
451 SkShader::TileMode xTile, SkShader::TileMode yTile,
452 const SkImageInfo& srcImageInfo,
453 const void* srcImageData) {
454 SkSize size;
455 size = srcImageInfo.dimensions();
456 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS tage);
mtklein 2016/02/16 21:13:10 Let's explain how the stages may be missing, etc.
herb_g 2016/02/16 22:04:25 Done.
457 auto samplerStage = choose_pixel_sampler(placementStage, srcImageInfo,
458 srcImageData, &fSampleStage);
459 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage,
460 &fTileYStage);
461 fFirstStage = choose_matrix(tilerStage, inverse, &fMatrixStage);
462 }
463
464 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
465 fPixelStage->setDestination(dst);
466
467 Sk4f Xs = Sk4f(x) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f};
mtklein 2016/02/16 21:13:10 + 0.5?
herb_g 2016/02/16 22:04:25 Done.
468 Sk4f Ys(y);
469 Sk4f fours{4.0f};
470
471 while (count >= 4) {
472 fFirstStage->pointList4(Xs, Ys);
473 Xs = Xs + fours;
474 count -= 4;
475 }
476 if (count > 0) {
477 fFirstStage->pointListFew(count, Xs, Ys);
478 }
479 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698