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

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

Issue 2134893002: Redo Tiling (Closed) Base URL: https://skia.googlesource.com/skia.git@reduce-LBP-sample
Patch Set: Fix perf problem. Created 4 years, 5 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
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 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } else { 158 } else {
159 return next; 159 return next;
160 } 160 }
161 return matrixProc->get(); 161 return matrixProc->get();
162 } 162 }
163 163
164 //////////////////////////////////////////////////////////////////////////////// //////////////////// 164 //////////////////////////////////////////////////////////////////////////////// ////////////////////
165 // Tile Stage 165 // Tile Stage
166 166
167 template<typename XStrategy, typename YStrategy, typename Next> 167 template<typename XStrategy, typename YStrategy, typename Next>
168 class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInte rface { 168 class CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInt erface {
169 public: 169 public:
170 template <typename... Args> 170 CombinedTileStage(Next* next, SkISize dimensions)
171 NearestTileStage(Next* next, SkISize dimensions)
172 : fNext{next} 171 : fNext{next}
173 , fXStrategy{dimensions.width()} 172 , fXStrategy{dimensions.width()}
174 , fYStrategy{dimensions.height()}{ } 173 , fYStrategy{dimensions.height()}{ }
175 174
176 NearestTileStage(Next* next, const NearestTileStage& stage) 175 CombinedTileStage(Next* next, const CombinedTileStage& stage)
177 : fNext{next} 176 : fNext{next}
178 , fXStrategy{stage.fXStrategy} 177 , fXStrategy{stage.fXStrategy}
179 , fYStrategy{stage.fYStrategy} { } 178 , fYStrategy{stage.fYStrategy} { }
180 179
181 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { 180 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
182 fXStrategy.tileXPoints(&xs); 181 fXStrategy.tileXPoints(&xs);
183 fYStrategy.tileYPoints(&ys); 182 fYStrategy.tileYPoints(&ys);
184 fNext->pointListFew(n, xs, ys); 183 fNext->pointListFew(n, xs, ys);
185 } 184 }
186 185
187 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { 186 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
188 fXStrategy.tileXPoints(&xs); 187 fXStrategy.tileXPoints(&xs);
189 fYStrategy.tileYPoints(&ys); 188 fYStrategy.tileYPoints(&ys);
190 fNext->pointList4(xs, ys); 189 fNext->pointList4(xs, ys);
191 } 190 }
192 191
193 // The span you pass must not be empty. 192 // The span you pass must not be empty.
194 void pointSpan(Span span) override { 193 void pointSpan(Span span) override {
195 SkASSERT(!span.isEmpty()); 194 SkASSERT(!span.isEmpty());
196 SkPoint start; SkScalar length; int count; 195 SkPoint start; SkScalar length; int count;
197 std::tie(start, length, count) = span; 196 std::tie(start, length, count) = span;
197
198 if (span.count() == 1) {
199 this->pointListFew(1, span.startX(), span.startY());
200 return;
201 }
202
198 SkScalar x = X(start); 203 SkScalar x = X(start);
199 SkScalar y = fYStrategy.tileY(Y(start)); 204 SkScalar y = fYStrategy.tileY(Y(start));
200 Span yAdjustedSpan{{x, y}, length, count}; 205 Span yAdjustedSpan{{x, y}, length, count};
206
201 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) { 207 if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) {
202 span_fallback(span, this); 208 span_fallback(span, this);
203 } 209 }
204 } 210 }
205 211
206 private: 212 private:
207 Next* const fNext; 213 Next* const fNext;
208 XStrategy fXStrategy; 214 XStrategy fXStrategy;
209 YStrategy fYStrategy; 215 YStrategy fYStrategy;
210 }; 216 };
211 217
212 template<typename XStrategy, typename YStrategy, typename Next> 218 template <typename XStrategy, typename Next>
213 class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter face {
214 public:
215 template <typename... Args>
216 BilerpTileStage(Next* next, SkISize dimensions)
217 : fNext{next}
218 , fXMax(dimensions.width())
219 , fYMax(dimensions.height())
220 , fXStrategy{dimensions.width()}
221 , fYStrategy{dimensions.height()} { }
222
223 BilerpTileStage(Next* next, const BilerpTileStage& stage)
224 : fNext{next}
225 , fXMax{stage.fXMax}
226 , fYMax{stage.fYMax}
227 , fXStrategy{stage.fXStrategy}
228 , fYStrategy{stage.fYStrategy} { }
229
230 void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
231 fXStrategy.tileXPoints(&xs);
232 fYStrategy.tileYPoints(&ys);
233 // TODO: check to see if xs and ys are in range then just call pointList Few on next.
234 if (n >= 1) this->bilerpPoint(xs[0], ys[0]);
235 if (n >= 2) this->bilerpPoint(xs[1], ys[1]);
236 if (n >= 3) this->bilerpPoint(xs[2], ys[2]);
237 }
238
239 void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
240 fXStrategy.tileXPoints(&xs);
241 fYStrategy.tileYPoints(&ys);
242 // TODO: check to see if xs and ys are in range then just call pointList 4 on next.
243 this->bilerpPoint(xs[0], ys[0]);
244 this->bilerpPoint(xs[1], ys[1]);
245 this->bilerpPoint(xs[2], ys[2]);
246 this->bilerpPoint(xs[3], ys[3]);
247 }
248
249 struct Wrapper {
250 void pointSpan(Span span) {
251 processor->breakIntoEdges(span);
252 }
253
254 void repeatSpan(Span span, int32_t repeatCount) {
255 while (repeatCount --> 0) {
256 processor->pointSpan(span);
257 }
258 }
259
260 BilerpTileStage* processor;
261 };
262
263 // The span you pass must not be empty.
264 void pointSpan(Span span) override {
265 SkASSERT(!span.isEmpty());
266
267 Wrapper wrapper = {this};
268 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) {
269 span_fallback(span, this);
270 }
271 }
272
273 private:
274 void bilerpPoint(SkScalar x, SkScalar y) {
275 Sk4f txs = Sk4f{x} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f};
276 Sk4f tys = Sk4f{y} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f};
277 fXStrategy.tileXPoints(&txs);
278 fYStrategy.tileYPoints(&tys);
279 fNext->bilerpEdge(txs, tys);
280 }
281
282 void handleEdges(Span span, SkScalar dx) {
283 SkPoint start; SkScalar length; int count;
284 std::tie(start, length, count) = span;
285 SkScalar x = X(start);
286 SkScalar y = Y(start);
287 SkScalar tiledY = fYStrategy.tileY(y);
288 while (count > 0) {
289 this->bilerpPoint(x, tiledY);
290 x += dx;
291 count -= 1;
292 }
293 }
294
295 void yProcessSpan(Span span) {
296 SkScalar tiledY = fYStrategy.tileY(span.startY());
297 if (0.5f <= tiledY && tiledY < fYMax - 0.5f ) {
298 Span tiledSpan{{span.startX(), tiledY}, span.length(), span.count()} ;
299 fNext->pointSpan(tiledSpan);
300 } else {
301 // Convert to the Y0 bilerp sample set by shifting by -0.5f. Then ti le that new y
302 // value and shift it back resulting in the working Y0. Do the same thing with Y1 but
303 // in the opposite direction.
304 SkScalar y0 = fYStrategy.tileY(span.startY() - 0.5f) + 0.5f;
305 SkScalar y1 = fYStrategy.tileY(span.startY() + 0.5f) - 0.5f;
306 Span newSpan{{span.startX(), y0}, span.length(), span.count()};
307 fNext->bilerpSpan(newSpan, y1);
308 }
309 }
310 void breakIntoEdges(Span span) {
311 if (span.count() == 1) {
312 this->bilerpPoint(span.startX(), span.startY());
313 } else if (span.length() == 0) {
314 yProcessSpan(span);
315 } else {
316 SkScalar dx = span.length() / (span.count() - 1);
317 if (span.length() > 0) {
318 Span leftBorder = span.breakAt(0.5f, dx);
319 if (!leftBorder.isEmpty()) {
320 this->handleEdges(leftBorder, dx);
321 }
322 Span center = span.breakAt(fXMax - 0.5f, dx);
323 if (!center.isEmpty()) {
324 this->yProcessSpan(center);
325 }
326
327 if (!span.isEmpty()) {
328 this->handleEdges(span, dx);
329 }
330 } else {
331 Span center = span.breakAt(fXMax + 0.5f, dx);
332 if (!span.isEmpty()) {
333 this->handleEdges(span, dx);
334 }
335 Span leftEdge = center.breakAt(0.5f, dx);
336 if (!center.isEmpty()) {
337 this->yProcessSpan(center);
338 }
339 if (!leftEdge.isEmpty()) {
340 this->handleEdges(leftEdge, dx);
341 }
342
343 }
344 }
345 }
346
347 Next* const fNext;
348 SkScalar fXMax;
349 SkScalar fYMax;
350 XStrategy fXStrategy;
351 YStrategy fYStrategy;
352 };
353
354 template <typename XStrategy, typename YStrategy, typename Next>
355 void make_tile_stage(
356 SkFilterQuality filterQuality, SkISize dimensions,
357 Next* next, SkLinearBitmapPipeline::TileStage* tileStage) {
358 if (filterQuality == kNone_SkFilterQuality) {
359 tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
360 } else {
361 tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
362 }
363 }
364 template <typename XStrategy>
365 void choose_tiler_ymode( 219 void choose_tiler_ymode(
366 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, 220 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions,
367 SkLinearBitmapPipeline::SampleProcessorInterface* next, 221 Next* next,
368 SkLinearBitmapPipeline::TileStage* tileStage) { 222 SkLinearBitmapPipeline::TileStage* tileStage) {
369 switch (yMode) { 223 switch (yMode) {
370 case SkShader::kClamp_TileMode: 224 case SkShader::kClamp_TileMode: {
371 make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions , next, tileStage); 225 using Tiler = CombinedTileStage<XStrategy, YClampStrategy, Next>;
226 tileStage->initStage<Tiler>(next, dimensions);
372 break; 227 break;
373 case SkShader::kRepeat_TileMode: 228 }
374 make_tile_stage<XStrategy, YRepeatStrategy>(filterQuality, dimension s, next, tileStage); 229 case SkShader::kRepeat_TileMode: {
230 using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, Next>;
231 tileStage->initStage<Tiler>(next, dimensions);
375 break; 232 break;
376 case SkShader::kMirror_TileMode: 233 }
377 make_tile_stage<XStrategy, YMirrorStrategy>(filterQuality, dimension s, next, tileStage); 234 case SkShader::kMirror_TileMode: {
235 using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, Next>;
236 tileStage->initStage<Tiler>(next, dimensions);
378 break; 237 break;
238 }
379 } 239 }
380 }; 240 };
381 241
382 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( 242 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler(
383 SkLinearBitmapPipeline::SampleProcessorInterface* next, 243 SkLinearBitmapPipeline::SampleProcessorInterface* next,
384 SkISize dimensions, 244 SkISize dimensions,
385 SkShader::TileMode xMode, 245 SkShader::TileMode xMode,
386 SkShader::TileMode yMode, 246 SkShader::TileMode yMode,
387 SkFilterQuality filterQuality, 247 SkFilterQuality filterQuality,
388 SkScalar dx, 248 SkScalar dx,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 int32_t y = SkScalarTruncToInt(span.startY()); 320 int32_t y = SkScalarTruncToInt(span.startY());
461 const uint32_t* src = this->pixelAddress(x, y); 321 const uint32_t* src = this->pixelAddress(x, y);
462 uint32_t* dest = fDest; 322 uint32_t* dest = fDest;
463 while (repeatCount --> 0) { 323 while (repeatCount --> 0) {
464 memmove(dest, src, span.count() * sizeof(uint32_t)); 324 memmove(dest, src, span.count() * sizeof(uint32_t));
465 dest += span.count(); 325 dest += span.count();
466 } 326 }
467 fDest = dest; 327 fDest = dest;
468 } 328 }
469 329
470 void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Imple mented"); }
471
472 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
473
474 void setDestination(void* dst, int count) override { 330 void setDestination(void* dst, int count) override {
475 fDest = static_cast<uint32_t*>(dst); 331 fDest = static_cast<uint32_t*>(dst);
476 fEnd = fDest + count; 332 fEnd = fDest + count;
477 } 333 }
478 334
479 private: 335 private:
480 const uint32_t* pixelAddress(int32_t x, int32_t y) { 336 const uint32_t* pixelAddress(int32_t x, int32_t y) {
481 return &fSrc[fWidth * y + x]; 337 return &fSrc[fWidth * y + x];
482 } 338 }
483 const uint32_t* const fSrc; 339 const uint32_t* const fSrc;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 int32_t y = (int32_t)span.startY(); 387 int32_t y = (int32_t)span.startY();
532 const uint32_t* beginSpan = this->pixelAddress(x, y); 388 const uint32_t* beginSpan = this->pixelAddress(x, y);
533 389
534 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount, span.count()); 390 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount, span.count());
535 391
536 fDest += span.count() * repeatCount; 392 fDest += span.count() * repeatCount;
537 393
538 SkASSERT(fDest <= fEnd); 394 SkASSERT(fDest <= fEnd);
539 } 395 }
540 396
541 void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Imple mented"); }
542
543 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
544
545 void setDestination(void* dst, int count) override { 397 void setDestination(void* dst, int count) override {
546 SkASSERT(count > 0); 398 SkASSERT(count > 0);
547 fDest = static_cast<uint32_t*>(dst); 399 fDest = static_cast<uint32_t*>(dst);
548 fEnd = fDest + count; 400 fEnd = fDest + count;
549 } 401 }
550 402
551 private: 403 private:
552 const uint32_t* pixelAddress(int32_t x, int32_t y) { 404 const uint32_t* pixelAddress(int32_t x, int32_t y) {
553 return &fSrc[fWidth * y + x]; 405 return &fSrc[fWidth * y + x];
554 } 406 }
(...skipping 20 matching lines...) Expand all
575 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>; 427 using PA = PixelAccessor<colorType, kSRGB_SkGammaType>;
576 accessor->init<PA>(srcPixmap); 428 accessor->init<PA>(srcPixmap);
577 return accessor->get(); 429 return accessor->get();
578 } else { 430 } else {
579 using PA = PixelAccessor<colorType, kLinear_SkGammaType>; 431 using PA = PixelAccessor<colorType, kLinear_SkGammaType>;
580 accessor->init<PA>(srcPixmap); 432 accessor->init<PA>(srcPixmap);
581 return accessor->get(); 433 return accessor->get();
582 } 434 }
583 } 435 }
584 436
585 template<template <typename, typename> class Sampler> 437 static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor(
586 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba se(
587 Blender* next,
588 const SkPixmap& srcPixmap, 438 const SkPixmap& srcPixmap,
589 const SkColor A8TintColor, 439 const SkColor A8TintColor,
590 SkLinearBitmapPipeline::SampleStage* sampleStage,
591 SkLinearBitmapPipeline::Accessor* accessor) 440 SkLinearBitmapPipeline::Accessor* accessor)
592 { 441 {
593 const SkImageInfo& imageInfo = srcPixmap.info(); 442 const SkImageInfo& imageInfo = srcPixmap.info();
594 443
595 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; 444 SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr;
596 switch (imageInfo.colorType()) { 445 switch (imageInfo.colorType()) {
597 case kAlpha_8_SkColorType: { 446 case kAlpha_8_SkColorType: {
598 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy pe>; 447 using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaTy pe>;
599 accessor->init<PA>(srcPixmap, A8TintColor); 448 accessor->init<PA>(srcPixmap, A8TintColor);
600 pixelAccessor = accessor->get(); 449 pixelAccessor = accessor->get();
(...skipping 21 matching lines...) Expand all
622 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT ype>; 471 using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaT ype>;
623 accessor->init<PA>(srcPixmap); 472 accessor->init<PA>(srcPixmap);
624 pixelAccessor = accessor->get(); 473 pixelAccessor = accessor->get();
625 } 474 }
626 break; 475 break;
627 default: 476 default:
628 SkFAIL("Not implemented. Unsupported src"); 477 SkFAIL("Not implemented. Unsupported src");
629 break; 478 break;
630 } 479 }
631 480
632 using S = Sampler<PixelAccessorShim, Blender>; 481 return pixelAccessor;
633 sampleStage->initStage<S>(next, pixelAccessor);
634 return sampleStage->get();
635 } 482 }
636 483
637 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( 484 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
638 Blender* next, 485 Blender* next,
639 SkFilterQuality filterQuality, 486 SkFilterQuality filterQuality,
487 SkShader::TileMode xTile, SkShader::TileMode yTile,
640 const SkPixmap& srcPixmap, 488 const SkPixmap& srcPixmap,
641 const SkColor A8TintColor, 489 const SkColor A8TintColor,
642 SkLinearBitmapPipeline::SampleStage* sampleStage, 490 SkLinearBitmapPipeline::SampleStage* sampleStage,
643 SkLinearBitmapPipeline::Accessor* accessor) { 491 SkLinearBitmapPipeline::Accessor* accessor) {
644 const SkImageInfo& imageInfo = srcPixmap.info(); 492 const SkImageInfo& imageInfo = srcPixmap.info();
493 SkISize dimensions = imageInfo.dimensions();
645 494
646 // Special case samplers with fully expanded templates 495 // Special case samplers with fully expanded templates
647 if (imageInfo.gammaCloseToSRGB()) { 496 if (imageInfo.gammaCloseToSRGB()) {
648 if (filterQuality == kNone_SkFilterQuality) { 497 if (filterQuality == kNone_SkFilterQuality) {
649 switch (imageInfo.colorType()) { 498 switch (imageInfo.colorType()) {
650 case kN32_SkColorType: { 499 case kN32_SkColorType: {
651 using S = 500 using S =
652 NearestNeighborSampler< 501 NearestNeighborSampler<
653 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen der>; 502 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen der>;
654 sampleStage->initStage<S>(next, srcPixmap); 503 sampleStage->initStage<S>(next, srcPixmap);
655 return sampleStage->get(); 504 return sampleStage->get();
656 } 505 }
657 case kIndex_8_SkColorType: { 506 case kIndex_8_SkColorType: {
658 using S = 507 using S =
659 NearestNeighborSampler< 508 NearestNeighborSampler<
660 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>; 509 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
661 sampleStage->initStage<S>(next, srcPixmap); 510 sampleStage->initStage<S>(next, srcPixmap);
662 return sampleStage->get(); 511 return sampleStage->get();
663 } 512 }
664 default: 513 default:
665 break; 514 break;
666 } 515 }
667 } else { 516 } else {
668 switch (imageInfo.colorType()) { 517 switch (imageInfo.colorType()) {
669 case kN32_SkColorType: { 518 case kN32_SkColorType: {
670 using S = 519 using S =
671 BilerpSampler< 520 BilerpSampler<
672 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen der>; 521 PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blen der>;
673 sampleStage->initStage<S>(next, srcPixmap); 522 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr cPixmap);
674 return sampleStage->get(); 523 return sampleStage->get();
675 } 524 }
676 case kIndex_8_SkColorType: { 525 case kIndex_8_SkColorType: {
677 using S = 526 using S =
678 BilerpSampler< 527 BilerpSampler<
679 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>; 528 PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
680 sampleStage->initStage<S>(next, srcPixmap); 529 sampleStage->initStage<S>(next, dimensions, xTile, yTile, sr cPixmap);
681 return sampleStage->get(); 530 return sampleStage->get();
682 } 531 }
683 default: 532 default:
684 break; 533 break;
685 } 534 }
686 } 535 }
687 } 536 }
688 537
538 auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor) ;
689 // General cases. 539 // General cases.
690 if (filterQuality == kNone_SkFilterQuality) { 540 if (filterQuality == kNone_SkFilterQuality) {
691 return choose_pixel_sampler_base<NearestNeighborSampler>( 541 using S = NearestNeighborSampler<PixelAccessorShim, Blender>;
692 next, srcPixmap, A8TintColor, sampleStage, accessor); 542 sampleStage->initStage<S>(next, pixelAccessor);
693 } else { 543 } else {
694 return choose_pixel_sampler_base<BilerpSampler>( 544 using S = BilerpSampler<PixelAccessorShim, Blender>;
695 next, srcPixmap, A8TintColor, sampleStage, accessor); 545 sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor) ;
696 } 546 }
547 return sampleStage->get();
697 } 548 }
698 549
699 //////////////////////////////////////////////////////////////////////////////// //////////////////// 550 //////////////////////////////////////////////////////////////////////////////// ////////////////////
700 // Pixel Blender Stage 551 // Pixel Blender Stage
701 template <SkAlphaType alphaType> 552 template <SkAlphaType alphaType>
702 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface { 553 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface {
703 public: 554 public:
704 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } 555 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
705 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} 556 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {}
706 void SK_VECTORCALL blendPixel(Sk4f pixel) override { 557 void SK_VECTORCALL blendPixel(Sk4f pixel) override {
707 SkASSERT(fDst + 1 <= fEnd ); 558 SkASSERT(fDst + 1 <= fEnd );
708 SrcPixel(fDst, pixel, 0); 559 this->srcPixel(fDst, pixel, 0);
709 fDst += 1; 560 fDst += 1;
710 } 561 }
711 562
712 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { 563 void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
713 SkASSERT(fDst + 4 <= fEnd); 564 SkASSERT(fDst + 4 <= fEnd);
714 SkPM4f* dst = fDst; 565 SkPM4f* dst = fDst;
715 SrcPixel(dst, p0, 0); 566 this->srcPixel(dst, p0, 0);
716 SrcPixel(dst, p1, 1); 567 this->srcPixel(dst, p1, 1);
717 SrcPixel(dst, p2, 2); 568 this->srcPixel(dst, p2, 2);
718 SrcPixel(dst, p3, 3); 569 this->srcPixel(dst, p3, 3);
719 fDst += 4; 570 fDst += 4;
720 } 571 }
721 572
722 void setDestination(void* dst, int count) override { 573 void setDestination(void* dst, int count) override {
723 fDst = static_cast<SkPM4f*>(dst); 574 fDst = static_cast<SkPM4f*>(dst);
724 fEnd = fDst + count; 575 fEnd = fDst + count;
725 } 576 }
726 577
727 private: 578 private:
728 void SK_VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) { 579 void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) {
580 check_pixel(pixel);
581
729 Sk4f newPixel = pixel; 582 Sk4f newPixel = pixel;
730 if (alphaType == kUnpremul_SkAlphaType) { 583 if (alphaType == kUnpremul_SkAlphaType) {
731 newPixel = Premultiply(pixel); 584 newPixel = Premultiply(pixel);
732 } 585 }
733 newPixel = newPixel * fPostAlpha; 586 newPixel = newPixel * fPostAlpha;
734 newPixel.store(dst + index); 587 newPixel.store(dst + index);
735 } 588 }
736 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) { 589 static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) {
737 float alpha = pixel[3]; 590 float alpha = pixel[3];
738 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; 591 return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 SkAlphaType alphaType = srcImageInfo.alphaType(); 643 SkAlphaType alphaType = srcImageInfo.alphaType();
791 if (srcPixmap.colorType() == kIndex_8_SkColorType) { 644 if (srcPixmap.colorType() == kIndex_8_SkColorType) {
792 alphaType = kUnpremul_SkAlphaType; 645 alphaType = kUnpremul_SkAlphaType;
793 } 646 }
794 647
795 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f); 648 float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f);
796 // As the stages are built, the chooser function may skip a stage. For examp le, with the 649 // As the stages are built, the chooser function may skip a stage. For examp le, with the
797 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. 650 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage.
798 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend erStage); 651 auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlend erStage);
799 auto samplerStage = choose_pixel_sampler( 652 auto samplerStage = choose_pixel_sampler(
800 blenderStage, filterQuality, srcPixmap, paintColor, &fSampleStage, &fAcc essor); 653 blenderStage, filterQuality, xTile, yTile,
654 srcPixmap, paintColor, &fSampleStage, &fAccessor);
801 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, 655 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile,
802 filterQuality, dx, &fTileStage); 656 filterQuality, dx, &fTileStage);
803 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage ); 657 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage );
804 fLastStage = blenderStage; 658 fLastStage = blenderStage;
805 } 659 }
806 660
807 bool SkLinearBitmapPipeline::ClonePipelineForBlitting( 661 bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
808 SkEmbeddableLinearPipeline* pipelineStorage, 662 SkEmbeddableLinearPipeline* pipelineStorage,
809 const SkLinearBitmapPipeline& pipeline, 663 const SkLinearBitmapPipeline& pipeline,
810 SkMatrix::TypeMask matrixMask, 664 SkMatrix::TypeMask matrixMask,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { 730 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) {
877 SkASSERT(count > 0); 731 SkASSERT(count > 0);
878 fLastStage->setDestination(dst, count); 732 fLastStage->setDestination(dst, count);
879 733
880 // The count and length arguments start out in a precise relation in order t o keep the 734 // The count and length arguments start out in a precise relation in order t o keep the
881 // math correct through the different stages. Count is the number of pixel t o produce. 735 // math correct through the different stages. Count is the number of pixel t o produce.
882 // Since the code samples at pixel centers, length is the distance from the center of the 736 // Since the code samples at pixel centers, length is the distance from the center of the
883 // first pixel to the center of the last pixel. This implies that length is count-1. 737 // first pixel to the center of the last pixel. This implies that length is count-1.
884 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); 738 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
885 } 739 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698