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

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

Issue 1861253003: Use a faster repeat tiler when translate only matrix. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments. Created 4 years, 8 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 | src/core/SkLinearBitmapPipeline_tile.h » ('j') | 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 9
10 #include "SkPM4f.h" 10 #include "SkPM4f.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // A span represents sample points that have been mapped from destination sp ace to source 58 // A span represents sample points that have been mapped from destination sp ace to source
59 // space. Each sample point is then expanded to the four bilerp points by ad d +/- 0.5. The 59 // space. Each sample point is then expanded to the four bilerp points by ad d +/- 0.5. The
60 // resulting Y values my be off the tile. When y +/- 0.5 are more than 1 apa rt because of 60 // resulting Y values my be off the tile. When y +/- 0.5 are more than 1 apa rt because of
61 // tiling, the second Y is used to denote the retiled Y value. 61 // tiling, the second Y is used to denote the retiled Y value.
62 virtual void bilerpSpan(Span span, SkScalar y) = 0; 62 virtual void bilerpSpan(Span span, SkScalar y) = 0;
63 }; 63 };
64 64
65 class SkLinearBitmapPipeline::PixelPlacerInterface { 65 class SkLinearBitmapPipeline::PixelPlacerInterface {
66 public: 66 public:
67 virtual ~PixelPlacerInterface() { } 67 virtual ~PixelPlacerInterface() { }
68 virtual void setDestination(SkPM4f* dst) = 0; 68 // Count is normally not needed, but in these early stages of development it is useful to
69 // check bounds.
70 // TODO(herb): 4/6/2016 - remove count when code is stable.
71 virtual void setDestination(void* dst, int count) = 0;
69 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; 72 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
70 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; 73 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ;
71 }; 74 };
72 75
73 namespace { 76 namespace {
74 77
75 //////////////////////////////////////////////////////////////////////////////// //////////////////// 78 //////////////////////////////////////////////////////////////////////////////// ////////////////////
76 // Matrix Stage 79 // Matrix Stage
77 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy 80 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy
78 // must implement the following methods: 81 // must implement the following methods:
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 this->bilerpPoint(xs[1], ys[1]); 234 this->bilerpPoint(xs[1], ys[1]);
232 this->bilerpPoint(xs[2], ys[2]); 235 this->bilerpPoint(xs[2], ys[2]);
233 this->bilerpPoint(xs[3], ys[3]); 236 this->bilerpPoint(xs[3], ys[3]);
234 } 237 }
235 238
236 struct Wrapper { 239 struct Wrapper {
237 void pointSpan(Span span) { 240 void pointSpan(Span span) {
238 processor->breakIntoEdges(span); 241 processor->breakIntoEdges(span);
239 } 242 }
240 243
244 void repeatSpan(Span span, int32_t repeatCount) {
245 while (repeatCount --> 0) {
246 processor->pointSpan(span);
247 }
248 }
249
241 BilerpTileStage* processor; 250 BilerpTileStage* processor;
242 }; 251 };
243 252
244 // The span you pass must not be empty. 253 // The span you pass must not be empty.
245 void pointSpan(Span span) override { 254 void pointSpan(Span span) override {
246 SkASSERT(!span.isEmpty()); 255 SkASSERT(!span.isEmpty());
247 256
248 Wrapper wrapper = {this}; 257 Wrapper wrapper = {this};
249 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) { 258 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) {
250 span_fallback(span, this); 259 span_fallback(span, this);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 break; 366 break;
358 } 367 }
359 }; 368 };
360 369
361 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( 370 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler(
362 SkLinearBitmapPipeline::SampleProcessorInterface* next, 371 SkLinearBitmapPipeline::SampleProcessorInterface* next,
363 SkISize dimensions, 372 SkISize dimensions,
364 SkShader::TileMode xMode, 373 SkShader::TileMode xMode,
365 SkShader::TileMode yMode, 374 SkShader::TileMode yMode,
366 SkFilterQuality filterQuality, 375 SkFilterQuality filterQuality,
367 SkLinearBitmapPipeline::TileStage* tileStage) { 376 SkScalar dx,
377 SkLinearBitmapPipeline::TileStage* tileStage)
378 {
368 switch (xMode) { 379 switch (xMode) {
369 case SkShader::kClamp_TileMode: 380 case SkShader::kClamp_TileMode:
370 choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions, next, tileStage); 381 choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions, next, tileStage);
371 break; 382 break;
372 case SkShader::kRepeat_TileMode: 383 case SkShader::kRepeat_TileMode:
373 choose_tiler_ymode<XRepeatStrategy>(yMode, filterQuality, dimensions , next, tileStage); 384 if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) {
385 choose_tiler_ymode<XRepeatUnitScaleStrategy>(
386 yMode, kNone_SkFilterQuality, dimensions, next, tileStage);
387 } else {
388 choose_tiler_ymode<XRepeatStrategy>(
389 yMode, filterQuality, dimensions, next, tileStage);
390 }
374 break; 391 break;
375 case SkShader::kMirror_TileMode: 392 case SkShader::kMirror_TileMode:
376 choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions , next, tileStage); 393 choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions , next, tileStage);
377 break; 394 break;
378 } 395 }
379 396
380 return tileStage->get(); 397 return tileStage->get();
381 } 398 }
382 399
383 400
(...skipping 11 matching lines...) Expand all
395 } 412 }
396 413
397 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { 414 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
398 fSampler.nearestList4(xs, ys); 415 fSampler.nearestList4(xs, ys);
399 } 416 }
400 417
401 void pointSpan(Span span) override { 418 void pointSpan(Span span) override {
402 fSampler.nearestSpan(span); 419 fSampler.nearestSpan(span);
403 } 420 }
404 421
405 virtual void repeatSpan(Span span, int32_t repeatCount) override { 422 void repeatSpan(Span span, int32_t repeatCount) override {
406 while (repeatCount > 0) { 423 while (repeatCount > 0) {
407 fSampler.nearestSpan(span); 424 fSampler.nearestSpan(span);
408 repeatCount--; 425 repeatCount--;
409 } 426 }
410 } 427 }
411 428
412 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { 429 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override {
413 SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge."); 430 SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge.");
414 } 431 }
415 432
416 virtual void bilerpSpan(Span span, SkScalar y) override { 433 void bilerpSpan(Span span, SkScalar y) override {
417 SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan."); 434 SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan.");
418 } 435 }
419 436
420 private: 437 private:
421 GeneralSampler<SourceStrategy, Next> fSampler; 438 GeneralSampler<SourceStrategy, Next> fSampler;
422 }; 439 };
423 440
424 template <typename SourceStrategy, typename Next> 441 template <typename SourceStrategy, typename Next>
425 class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterf ace { 442 class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterf ace {
426 public: 443 public:
427 template <typename... Args> 444 template <typename... Args>
428 BilerpSampler(Next* next, Args&&... args) 445 BilerpSampler(Next* next, Args&&... args)
429 : fSampler{next, std::forward<Args>(args)...} { } 446 : fSampler{next, std::forward<Args>(args)...} { }
430 447
431 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { 448 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
432 fSampler.bilerpListFew(n, xs, ys); 449 fSampler.bilerpListFew(n, xs, ys);
433 } 450 }
434 451
435 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { 452 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
436 fSampler.bilerpList4(xs, ys); 453 fSampler.bilerpList4(xs, ys);
437 } 454 }
438 455
439 void pointSpan(Span span) override { 456 void pointSpan(Span span) override {
440 fSampler.bilerpSpan(span); 457 fSampler.bilerpSpan(span);
441 } 458 }
442 459
443 virtual void repeatSpan(Span span, int32_t repeatCount) override { 460 void repeatSpan(Span span, int32_t repeatCount) override {
444 while (repeatCount > 0) { 461 while (repeatCount > 0) {
445 fSampler.bilerpSpan(span); 462 fSampler.bilerpSpan(span);
446 repeatCount--; 463 repeatCount--;
447 } 464 }
448 } 465 }
449 466
450 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { 467 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override {
451 fSampler.bilerpEdge(xs, ys); 468 fSampler.bilerpEdge(xs, ys);
452 } 469 }
453 470
454 virtual void bilerpSpan(Span span, SkScalar y) override { 471 void bilerpSpan(Span span, SkScalar y) override {
455 fSampler.bilerpSpanWithY(span, y); 472 fSampler.bilerpSpanWithY(span, y);
456 } 473 }
457 474
458 private: 475 private:
459 GeneralSampler<SourceStrategy, Next> fSampler; 476 GeneralSampler<SourceStrategy, Next> fSampler;
460 }; 477 };
461 478
462 using Placer = SkLinearBitmapPipeline::PixelPlacerInterface; 479 using Placer = SkLinearBitmapPipeline::PixelPlacerInterface;
463 480
464 template<template <typename, typename> class Sampler> 481 template<template <typename, typename> class Sampler>
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 } 525 }
509 } 526 }
510 527
511 //////////////////////////////////////////////////////////////////////////////// //////////////////// 528 //////////////////////////////////////////////////////////////////////////////// ////////////////////
512 // Pixel Placement Stage 529 // Pixel Placement Stage
513 template <SkAlphaType alphaType> 530 template <SkAlphaType alphaType>
514 class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { 531 class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface {
515 public: 532 public:
516 PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } 533 PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
517 void VECTORCALL placePixel(Sk4f pixel) override { 534 void VECTORCALL placePixel(Sk4f pixel) override {
535 SkASSERT(fDst + 1 <= fEnd );
518 PlacePixel(fDst, pixel, 0); 536 PlacePixel(fDst, pixel, 0);
519 fDst += 1; 537 fDst += 1;
520 } 538 }
521 539
522 void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { 540 void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
541 SkASSERT(fDst + 4 <= fEnd);
523 SkPM4f* dst = fDst; 542 SkPM4f* dst = fDst;
524 PlacePixel(dst, p0, 0); 543 PlacePixel(dst, p0, 0);
525 PlacePixel(dst, p1, 1); 544 PlacePixel(dst, p1, 1);
526 PlacePixel(dst, p2, 2); 545 PlacePixel(dst, p2, 2);
527 PlacePixel(dst, p3, 3); 546 PlacePixel(dst, p3, 3);
528 fDst += 4; 547 fDst += 4;
529 } 548 }
530 549
531 void setDestination(SkPM4f* dst) override { 550 void setDestination(void* dst, int count) override {
532 fDst = dst; 551 fDst = static_cast<SkPM4f*>(dst);
552 fEnd = fDst + count;
533 } 553 }
534 554
535 private: 555 private:
536 void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) { 556 void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) {
537 Sk4f newPixel = pixel; 557 Sk4f newPixel = pixel;
538 if (alphaType == kUnpremul_SkAlphaType) { 558 if (alphaType == kUnpremul_SkAlphaType) {
539 newPixel = Premultiply(pixel); 559 newPixel = Premultiply(pixel);
540 } 560 }
541 newPixel = newPixel * fPostAlpha; 561 newPixel = newPixel * fPostAlpha;
542 newPixel.store(dst + index); 562 newPixel.store(dst + index);
543 } 563 }
544 static Sk4f VECTORCALL Premultiply(Sk4f pixel) { 564 static Sk4f VECTORCALL Premultiply(Sk4f pixel) {
545 float alpha = pixel[3]; 565 float alpha = pixel[3];
546 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; 566 return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
547 } 567 }
548 568
549 SkPM4f* fDst; 569 SkPM4f* fDst;
570 SkPM4f* fEnd;
550 Sk4f fPostAlpha; 571 Sk4f fPostAlpha;
551 }; 572 };
552 573
553 static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer( 574 static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer(
554 SkAlphaType alphaType, 575 SkAlphaType alphaType,
555 float postAlpha, 576 float postAlpha,
556 SkLinearBitmapPipeline::PixelStage* placerStage) { 577 SkLinearBitmapPipeline::PixelStage* placerStage) {
557 if (alphaType == kUnpremul_SkAlphaType) { 578 if (alphaType == kUnpremul_SkAlphaType) {
558 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha); 579 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
559 } else { 580 } else {
560 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType 581 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
561 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha); 582 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha);
562 } 583 }
563 return placerStage->get(); 584 return placerStage->get();
564 } 585 }
565 } // namespace 586 } // namespace
566 587
567 //////////////////////////////////////////////////////////////////////////////// //////////////////// 588 //////////////////////////////////////////////////////////////////////////////// ////////////////////
568 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} 589 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {}
569 590
570 SkLinearBitmapPipeline::SkLinearBitmapPipeline( 591 SkLinearBitmapPipeline::SkLinearBitmapPipeline(
571 const SkMatrix& inverse, 592 const SkMatrix& inverse,
572 SkFilterQuality filterQuality, 593 SkFilterQuality filterQuality,
573 SkShader::TileMode xTile, SkShader::TileMode yTile, 594 SkShader::TileMode xTile, SkShader::TileMode yTile,
574 float postAlpha, 595 float postAlpha,
575 const SkPixmap& srcPixmap) { 596 const SkPixmap& srcPixmap)
597 {
576 SkISize dimensions = srcPixmap.info().dimensions(); 598 SkISize dimensions = srcPixmap.info().dimensions();
577 const SkImageInfo& srcImageInfo = srcPixmap.info(); 599 const SkImageInfo& srcImageInfo = srcPixmap.info();
578 600
579 SkMatrix adjustedInverse = inverse; 601 SkMatrix adjustedInverse = inverse;
580 if (filterQuality == kNone_SkFilterQuality) { 602 if (filterQuality == kNone_SkFilterQuality) {
581 if (inverse.getScaleX() >= 0.0f) { 603 if (inverse.getScaleX() >= 0.0f) {
582 adjustedInverse.setTranslateX( 604 adjustedInverse.setTranslateX(
583 nextafterf(inverse.getTranslateX(), std::floor(inverse.getTransl ateX()))); 605 nextafterf(inverse.getTranslateX(), std::floor(inverse.getTransl ateX())));
584 } 606 }
585 if (inverse.getScaleY() >= 0.0f) { 607 if (inverse.getScaleY() >= 0.0f) {
586 adjustedInverse.setTranslateY( 608 adjustedInverse.setTranslateY(
587 nextafterf(inverse.getTranslateY(), std::floor(inverse.getTransl ateY()))); 609 nextafterf(inverse.getTranslateY(), std::floor(inverse.getTransl ateY())));
588 } 610 }
589 } 611 }
590 612
613 SkScalar dx = adjustedInverse.getScaleX();
614
591 // If it is an index 8 color type, the sampler converts to unpremul for bett er fidelity. 615 // If it is an index 8 color type, the sampler converts to unpremul for bett er fidelity.
592 SkAlphaType alphaType = srcImageInfo.alphaType(); 616 SkAlphaType alphaType = srcImageInfo.alphaType();
593 if (srcPixmap.colorType() == kIndex_8_SkColorType) { 617 if (srcPixmap.colorType() == kIndex_8_SkColorType) {
594 alphaType = kUnpremul_SkAlphaType; 618 alphaType = kUnpremul_SkAlphaType;
595 } 619 }
596 620
597 // As the stages are built, the chooser function may skip a stage. For examp le, with the 621 // As the stages are built, the chooser function may skip a stage. For examp le, with the
598 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. 622 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage.
599 auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage ); 623 auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage );
600 auto samplerStage = choose_pixel_sampler(placementStage, 624 auto samplerStage = choose_pixel_sampler(placementStage,
601 filterQuality, srcPixmap, &fSampl eStage); 625 filterQuality, srcPixmap, &fSampl eStage);
602 auto tilerStage = choose_tiler(samplerStage, 626 auto tilerStage = choose_tiler(samplerStage,
603 dimensions, xTile, yTile, filterQuality, &fTiler); 627 dimensions, xTile, yTile, filterQuality, dx, &fTiler);
604 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixSta ge); 628 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixSta ge);
605 } 629 }
606 630
607 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 631 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
608 SkASSERT(count > 0); 632 SkASSERT(count > 0);
609 fPixelStage->setDestination(dst); 633 fPixelStage->setDestination(dst, count);
610 // The count and length arguments start out in a precise relation in order t o keep the 634 // The count and length arguments start out in a precise relation in order t o keep the
611 // math correct through the different stages. Count is the number of pixel t o produce. 635 // math correct through the different stages. Count is the number of pixel t o produce.
612 // Since the code samples at pixel centers, length is the distance from the center of the 636 // Since the code samples at pixel centers, length is the distance from the center of the
613 // first pixel to the center of the last pixel. This implies that length is count-1. 637 // first pixel to the center of the last pixel. This implies that length is count-1.
614 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); 638 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
615 } 639 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkLinearBitmapPipeline_tile.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698