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

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

Issue 1886233006: Add 8888 fast SrcOver mode. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Addresss mtk's review. Created 4 years, 7 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_core.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"
11 #include <algorithm> 10 #include <algorithm>
12 #include <cmath> 11 #include <cmath>
13 #include <limits> 12 #include <limits>
14 #include "SkColor.h"
15 #include "SkSize.h"
16 #include <tuple> 13 #include <tuple>
14
17 #include "SkLinearBitmapPipeline_core.h" 15 #include "SkLinearBitmapPipeline_core.h"
18 #include "SkLinearBitmapPipeline_matrix.h" 16 #include "SkLinearBitmapPipeline_matrix.h"
19 #include "SkLinearBitmapPipeline_tile.h" 17 #include "SkLinearBitmapPipeline_tile.h"
20 #include "SkLinearBitmapPipeline_sample.h" 18 #include "SkLinearBitmapPipeline_sample.h"
19 #include "SkNx.h"
20 #include "SkOpts.h"
21 #include "SkPM4f.h"
21 22
22 class SkLinearBitmapPipeline::PointProcessorInterface { 23 class SkLinearBitmapPipeline::PointProcessorInterface {
23 public: 24 public:
24 virtual ~PointProcessorInterface() { } 25 virtual ~PointProcessorInterface() { }
25 // Take the first n (where 0 < n && n < 4) items from xs and ys and sample t hose points. For 26 // Take the first n (where 0 < n && n < 4) items from xs and ys and sample t hose points. For
26 // nearest neighbor, that means just taking the floor xs and ys. For bilerp, this means 27 // nearest neighbor, that means just taking the floor xs and ys. For bilerp, this means
27 // to expand the bilerp filter around the point and sample using that filter . 28 // to expand the bilerp filter around the point and sample using that filter .
28 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0; 29 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0;
29 // Same as pointListFew, but n = 4. 30 // Same as pointListFew, but n = 4.
30 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0; 31 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0;
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 private: 549 private:
549 GeneralSampler<SourceStrategy, Next> fSampler; 550 GeneralSampler<SourceStrategy, Next> fSampler;
550 }; 551 };
551 552
552 //////////////////////////////////////////////////////////////////////////////// //////////////////// 553 //////////////////////////////////////////////////////////////////////////////// ////////////////////
553 // Specialized Samplers 554 // Specialized Samplers
554 555
555 // RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the sr c and destination 556 // RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the sr c and destination
556 // are the same format and do not need in transformations in pixel space. Theref ore, there is no 557 // are the same format and do not need in transformations in pixel space. Theref ore, there is no
557 // need to convert them to HiFi pixel format. 558 // need to convert them to HiFi pixel format.
558 class RGBA8888UnitRepeat final : public SkLinearBitmapPipeline::SampleProcessorI nterface, 559 class RGBA8888UnitRepeatSrc final : public SkLinearBitmapPipeline::SampleProcess orInterface,
559 public SkLinearBitmapPipeline::DestinationInter face { 560 public SkLinearBitmapPipeline::DestinationIn terface {
560 public: 561 public:
561 RGBA8888UnitRepeat(const uint32_t* src, int32_t width) 562 RGBA8888UnitRepeatSrc(const uint32_t* src, int32_t width)
562 : fSrc{src}, fWidth{width} { } 563 : fSrc{src}, fWidth{width} { }
563 564
564 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { 565 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
565 SkASSERT(fDest + n <= fEnd); 566 SkASSERT(fDest + n <= fEnd);
566 // At this point xs and ys should be >= 0, so trunc is the same as floor . 567 // At this point xs and ys should be >= 0, so trunc is the same as floor .
567 Sk4i iXs = SkNx_cast<int>(xs); 568 Sk4i iXs = SkNx_cast<int>(xs);
568 Sk4i iYs = SkNx_cast<int>(ys); 569 Sk4i iYs = SkNx_cast<int>(ys);
569 570
570 if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]); 571 if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
571 if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]); 572 if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 private: 620 private:
620 const uint32_t* pixelAddress(int32_t x, int32_t y) { 621 const uint32_t* pixelAddress(int32_t x, int32_t y) {
621 return &fSrc[fWidth * y + x]; 622 return &fSrc[fWidth * y + x];
622 } 623 }
623 const uint32_t* const fSrc; 624 const uint32_t* const fSrc;
624 const int32_t fWidth; 625 const int32_t fWidth;
625 uint32_t* fDest; 626 uint32_t* fDest;
626 uint32_t* fEnd; 627 uint32_t* fEnd;
627 }; 628 };
628 629
630 // RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the sr c and destination
631 // are the same format and do not need in transformations in pixel space. Theref ore, there is no
632 // need to convert them to HiFi pixel format.
633 class RGBA8888UnitRepeatSrcOver final : public SkLinearBitmapPipeline::SamplePro cessorInterface,
634 public SkLinearBitmapPipeline::Destinati onInterface {
635 public:
636 RGBA8888UnitRepeatSrcOver(const uint32_t* src, int32_t width)
637 : fSrc{src}, fWidth{width} { }
638
639 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
640 SkASSERT(fDest + n <= fEnd);
641 // At this point xs and ys should be >= 0, so trunc is the same as floor .
642 Sk4i iXs = SkNx_cast<int>(xs);
643 Sk4i iYs = SkNx_cast<int>(ys);
644
645 if (n >= 1) blendPixelAt(iXs[0], iYs[0]);
646 if (n >= 2) blendPixelAt(iXs[1], iYs[1]);
647 if (n >= 3) blendPixelAt(iXs[2], iYs[2]);
648 }
649
650 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
651 SkASSERT(fDest + 4 <= fEnd);
652 Sk4i iXs = SkNx_cast<int>(xs);
653 Sk4i iYs = SkNx_cast<int>(ys);
654 blendPixelAt(iXs[0], iYs[0]);
655 blendPixelAt(iXs[1], iYs[1]);
656 blendPixelAt(iXs[2], iYs[2]);
657 blendPixelAt(iXs[3], iYs[3]);
658 }
659
660 void pointSpan(Span span) override {
661 if (span.length() != 0.0f) {
662 this->repeatSpan(span, 1);
663 }
664 }
665
666 void repeatSpan(Span span, int32_t repeatCount) override {
667 SkASSERT(fDest + span.count() * repeatCount <= fEnd);
668 SkASSERT(span.count() > 0);
669 SkASSERT(repeatCount > 0);
670
671 int32_t x = (int32_t)span.startX();
672 int32_t y = (int32_t)span.startY();
673 const uint32_t* beginSpan = this->pixelAddress(x, y);
674
675 SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount, span.count());
676
677 fDest += span.count() * repeatCount;
678
679 SkASSERT(fDest <= fEnd);
680 }
681
682 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Implemen ted"); }
683
684 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
685
686 void setDestination(void* dst, int count) override {
687 SkASSERT(count > 0);
688 fDest = static_cast<uint32_t*>(dst);
689 fEnd = fDest + count;
690 }
691
692 private:
693 const uint32_t* pixelAddress(int32_t x, int32_t y) {
694 return &fSrc[fWidth * y + x];
695 }
696
697 void blendPixelAt(int32_t x, int32_t y) {
698 const uint32_t* src = this->pixelAddress(x, y);
699 SkOpts::srcover_srgb_srgb(fDest, src, 1, 1);
700 fDest += 1;
701 };
702
703 const uint32_t* const fSrc;
704 const int32_t fWidth;
705 uint32_t* fDest;
706 uint32_t* fEnd;
707 };
708
629 using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; 709 using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;
630 710
631 template<template <typename, typename> class Sampler> 711 template<template <typename, typename> class Sampler>
632 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba se( 712 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba se(
633 Blender* next, 713 Blender* next,
634 const SkPixmap& srcPixmap, 714 const SkPixmap& srcPixmap,
635 SkLinearBitmapPipeline::SampleStage* sampleStage) { 715 SkLinearBitmapPipeline::SampleStage* sampleStage) {
636 const SkImageInfo& imageInfo = srcPixmap.info(); 716 const SkImageInfo& imageInfo = srcPixmap.info();
637 switch (imageInfo.colorType()) { 717 switch (imageInfo.colorType()) {
638 case kRGBA_8888_SkColorType: 718 case kRGBA_8888_SkColorType:
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 const SkLinearBitmapPipeline& pipeline, 870 const SkLinearBitmapPipeline& pipeline,
791 SkMatrix::TypeMask matrixMask, 871 SkMatrix::TypeMask matrixMask,
792 SkShader::TileMode xTileMode, 872 SkShader::TileMode xTileMode,
793 SkShader::TileMode yTileMode, 873 SkShader::TileMode yTileMode,
794 SkFilterQuality filterQuality, 874 SkFilterQuality filterQuality,
795 const SkPixmap& srcPixmap, 875 const SkPixmap& srcPixmap,
796 float finalAlpha, 876 float finalAlpha,
797 SkXfermode::Mode xferMode, 877 SkXfermode::Mode xferMode,
798 const SkImageInfo& dstInfo) 878 const SkImageInfo& dstInfo)
799 { 879 {
880 if (xferMode == SkXfermode::kSrcOver_Mode
881 && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
882 xferMode = SkXfermode::kSrc_Mode;
883 }
884
800 if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; } 885 if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; }
801 if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; } 886 if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; }
802 if (finalAlpha != 1.0f) { return false; } 887 if (finalAlpha != 1.0f) { return false; }
803 if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType 888 if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType
804 || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; } 889 || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; }
805 890
806 if (srcPixmap.info().profileType() != dstInfo.profileType()) { return false; } 891 if (srcPixmap.info().profileType() != kSRGB_SkColorProfileType
892 || dstInfo.profileType() != kSRGB_SkColorProfileType) { return false; }
807 893
808 if (xTileMode != SkShader::kRepeat_TileMode || yTileMode != SkShader::kRepea t_TileMode) { 894 if (xferMode != SkXfermode::kSrc_Mode && xferMode != SkXfermode::kSrcOver_Mo de) {
809 return false; 895 return false;
810 } 896 }
811 897
812 if (xferMode == SkXfermode::kSrcOver_Mode
813 && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
814 xferMode = SkXfermode::kSrc_Mode;
815 }
816
817 if (xferMode != SkXfermode::kSrc_Mode) { return false; }
818
819 new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, d stInfo); 898 new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, d stInfo);
820 899
821 return true; 900 return true;
822 } 901 }
823 902
824 SkLinearBitmapPipeline::SkLinearBitmapPipeline( 903 SkLinearBitmapPipeline::SkLinearBitmapPipeline(
825 const SkLinearBitmapPipeline& pipeline, 904 const SkLinearBitmapPipeline& pipeline,
826 const SkPixmap& srcPixmap, 905 const SkPixmap& srcPixmap,
827 SkXfermode::Mode mode, 906 SkXfermode::Mode mode,
828 const SkImageInfo& dstInfo) 907 const SkImageInfo& dstInfo)
829 { 908 {
830 SkASSERT(mode == SkXfermode::kSrc_Mode); 909 SkASSERT(mode == SkXfermode::kSrc_Mode || mode == SkXfermode::kSrcOver_Mode) ;
831 SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType() 910 SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
832 && srcPixmap.info().colorType() == kRGBA_8888_SkColorType); 911 && srcPixmap.info().colorType() == kRGBA_8888_SkColorType);
833 912
834 fSampleStage.initSink<RGBA8888UnitRepeat>(srcPixmap.writable_addr32(0, 0), s rcPixmap.width()); 913 if (mode == SkXfermode::kSrc_Mode) {
914 fSampleStage.initSink<RGBA8888UnitRepeatSrc>(
915 srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
916 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888Uni tRepeatSrc>();
917 } else {
918 fSampleStage.initSink<RGBA8888UnitRepeatSrcOver>(
919 srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
920 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888Uni tRepeatSrcOver>();
921 }
922
835 auto sampleStage = fSampleStage.get(); 923 auto sampleStage = fSampleStage.get();
836 auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage) ; 924 auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage) ;
837 tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage; 925 tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage;
838 auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixSt age); 926 auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixSt age);
839 matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage; 927 matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage;
840 fFirstStage = matrixStage; 928 fFirstStage = matrixStage;
841 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRep eat>();
842 } 929 }
843 930
844 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 931 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
845 SkASSERT(count > 0); 932 SkASSERT(count > 0);
846 this->blitSpan(x, y, dst, count); 933 this->blitSpan(x, y, dst, count);
847 } 934 }
848 935
849 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { 936 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) {
850 SkASSERT(count > 0); 937 SkASSERT(count > 0);
851 fLastStage->setDestination(dst, count); 938 fLastStage->setDestination(dst, count);
852 939
853 // The count and length arguments start out in a precise relation in order t o keep the 940 // The count and length arguments start out in a precise relation in order t o keep the
854 // math correct through the different stages. Count is the number of pixel t o produce. 941 // math correct through the different stages. Count is the number of pixel t o produce.
855 // Since the code samples at pixel centers, length is the distance from the center of the 942 // Since the code samples at pixel centers, length is the distance from the center of the
856 // first pixel to the center of the last pixel. This implies that length is count-1. 943 // first pixel to the center of the last pixel. This implies that length is count-1.
857 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); 944 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
858 } 945 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkLinearBitmapPipeline_core.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698