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

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: Clean CL 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" 10 #include "SkPM4f.h"
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 private: 548 private:
549 GeneralSampler<SourceStrategy, Next> fSampler; 549 GeneralSampler<SourceStrategy, Next> fSampler;
550 }; 550 };
551 551
552 //////////////////////////////////////////////////////////////////////////////// //////////////////// 552 //////////////////////////////////////////////////////////////////////////////// ////////////////////
553 // Specialized Samplers 553 // Specialized Samplers
554 554
555 // RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the sr c and destination 555 // 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 556 // 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. 557 // need to convert them to HiFi pixel format.
558 class RGBA8888UnitRepeat final : public SkLinearBitmapPipeline::SampleProcessorI nterface, 558 class RGBA8888UnitRepeatSrc final : public SkLinearBitmapPipeline::SampleProcess orInterface,
559 public SkLinearBitmapPipeline::DestinationInter face { 559 public SkLinearBitmapPipeline::DestinationIn terface {
560 public: 560 public:
561 RGBA8888UnitRepeat(const uint32_t* src, int32_t width) 561 RGBA8888UnitRepeatSrc(const uint32_t* src, int32_t width)
562 : fSrc{src}, fWidth{width} { } 562 : fSrc{src}, fWidth{width} { }
563 563
564 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { 564 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
565 SkASSERT(fDest + n <= fEnd); 565 SkASSERT(fDest + n <= fEnd);
566 // At this point xs and ys should be >= 0, so trunc is the same as floor . 566 // At this point xs and ys should be >= 0, so trunc is the same as floor .
567 Sk4i iXs = SkNx_cast<int>(xs); 567 Sk4i iXs = SkNx_cast<int>(xs);
568 Sk4i iYs = SkNx_cast<int>(ys); 568 Sk4i iYs = SkNx_cast<int>(ys);
569 569
570 if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]); 570 if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
571 if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]); 571 if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 private: 619 private:
620 const uint32_t* pixelAddress(int32_t x, int32_t y) { 620 const uint32_t* pixelAddress(int32_t x, int32_t y) {
621 return &fSrc[fWidth * y + x]; 621 return &fSrc[fWidth * y + x];
622 } 622 }
623 const uint32_t* const fSrc; 623 const uint32_t* const fSrc;
624 const int32_t fWidth; 624 const int32_t fWidth;
625 uint32_t* fDest; 625 uint32_t* fDest;
626 uint32_t* fEnd; 626 uint32_t* fEnd;
627 }; 627 };
628 628
629 void lerp_pixel(const uint32_t* src, uint32_t* dst) {
mtklein 2016/04/27 16:10:04 Let's not call this lerp. Lerp is a function of t
630 Sk4b srcAsBytes = Sk4b::Load(src);
mtklein 2016/04/27 16:10:04 I think this code would be more readable with fewe
631 Sk4f srcPixel = SkNx_cast<float>(srcAsBytes);
632 srcPixel = sRGBFast::sRGBToLinear(srcPixel / 255.0f);
mtklein 2016/04/27 16:10:04 Try not to write "x / 255.0f". "x *(1/255.0f)" is
633 Sk4b dstAsBytes = Sk4b::Load(dst);
634 Sk4f dstPixel = SkNx_cast<float>(dstAsBytes);
635 dstPixel = sRGBFast::sRGBToLinear(dstPixel / 255.0f);
636 Sk4f invAlpha = 1.0f - Sk4f{srcPixel[3]};
637 dstPixel *= invAlpha;
638 dstPixel += srcPixel;
639 dstPixel = sRGBFast::LinearTosRGB(dstPixel);
640 dstPixel *= 255.0f;
f(malita) 2016/04/27 15:51:17 Can we avoid the 255 divs/mult and lerp in 255-spa
mtklein 2016/04/27 16:10:04 neat.
641 dstAsBytes = SkNx_cast<uint8_t>(dstPixel);
642 dstAsBytes.store(dst);
643 }
644
645 void lerp_pixels(const uint32_t* src, uint32_t* dst, size_t count) {
646
647 while (count --> 0) {
648 lerp_pixel(src, dst);
649 dst += 1;
650 src += 1;
651 }
652 }
653
654 uint8_t extract_alpha(const uint32_t* pixel) {
655 const uint8_t* bPixel = reinterpret_cast<const uint8_t*>(pixel);
mtklein 2016/04/27 16:10:04 return *pixel >> 24; ?
656 return bPixel[3];
657 }
658
659 // RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the sr c and destination
660 // are the same format and do not need in transformations in pixel space. Theref ore, there is no
661 // need to convert them to HiFi pixel format.
662 class RGBA8888UnitRepeatSrcOver final : public SkLinearBitmapPipeline::SamplePro cessorInterface,
663 public SkLinearBitmapPipeline::Destinati onInterface {
664 public:
665 RGBA8888UnitRepeatSrcOver(const uint32_t* src, int32_t width)
666 : fSrc{src}, fWidth{width} { }
667
668 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
669 SkASSERT(fDest + n <= fEnd);
670 // At this point xs and ys should be >= 0, so trunc is the same as floor .
671 Sk4i iXs = SkNx_cast<int>(xs);
672 Sk4i iYs = SkNx_cast<int>(ys);
673
674 if (n >= 1) blendPixelAt(iXs[0], iYs[0]);
675 if (n >= 2) blendPixelAt(iXs[1], iYs[1]);
676 if (n >= 3) blendPixelAt(iXs[2], iYs[2]);
677 }
678
679 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
680 SkASSERT(fDest + 4 <= fEnd);
681 Sk4i iXs = SkNx_cast<int>(xs);
682 Sk4i iYs = SkNx_cast<int>(ys);
683 blendPixelAt(iXs[0], iYs[0]);
684 blendPixelAt(iXs[1], iYs[1]);
685 blendPixelAt(iXs[2], iYs[2]);
686 blendPixelAt(iXs[3], iYs[3]);
687 }
688
689 void pointSpan(Span span) override {
690 if (span.length() != 0.0f) {
691 this->repeatSpan(span, 1);
692 }
693 }
694
695 void repeatSpan(Span span, int32_t repeatCount) override {
696 SkASSERT(fDest + span.count() * repeatCount <= fEnd);
697 SkASSERT(span.count() > 0);
698 SkASSERT(repeatCount > 0);
699
700 int32_t x = (int32_t)span.startX();
701 int32_t y = (int32_t)span.startY();
702 const uint32_t* beginSpan = this->pixelAddress(x, y);
703 const uint32_t* endSpan = beginSpan + span.count();
704
705 while (repeatCount-- > 0) {
706 const uint32_t* src = beginSpan;
707 do {
708 const uint32_t* startSegment = src;
709 uint8_t currentAlpha = extract_alpha(src);
710 switch (currentAlpha) {
711 case 0x00:
712 do {
713 src += 1;
714 } while (src < endSpan && extract_alpha(src) == 0x00);
715
716 break;
717 case 0xFF:
718 do {
719 src += 1;
720 } while (src < endSpan && extract_alpha(src) == 0xFF);
721 memmove(fDest, startSegment, (src - startSegment) * size of(uint32_t));
722 break;
723 default:
724 do {
725 src += 1;
726 } while (src < endSpan
727 && extract_alpha(src) != 0xFF
728 && extract_alpha(src) != 0x00);
729 lerp_pixels(startSegment, fDest, src - startSegment);
730 }
731 fDest += src - startSegment;
732 } while (src < endSpan);
733 }
734 SkASSERT(fDest <= fEnd);
735 }
736
737 void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Implemen ted"); }
738
739 void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
740
741 void setDestination(void* dst, int count) override {
742 SkASSERT(count > 0);
743 fDest = static_cast<uint32_t*>(dst);
744 fEnd = fDest + count;
745 }
746
747 private:
748 const uint32_t* pixelAddress(int32_t x, int32_t y) {
749 return &fSrc[fWidth * y + x];
750 }
751
752 void blendPixelAt(int32_t x, int32_t y) {
753 const uint32_t* src = this->pixelAddress(x, y);
754 uint8_t alpha = extract_alpha(src);
755 if (alpha == 0xff) {
756 *fDest = *src;
757 } else if (alpha != 0x00) {
758 lerp_pixel(src, fDest);
mtklein 2016/04/27 16:10:04 It might make things globally simpler to fuse lerp
759 }
760 fDest += 1;
761 };
762
763 const uint32_t* const fSrc;
764 const int32_t fWidth;
765 uint32_t* fDest;
766 uint32_t* fEnd;
767 };
768
629 using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; 769 using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;
630 770
631 template<template <typename, typename> class Sampler> 771 template<template <typename, typename> class Sampler>
632 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba se( 772 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba se(
633 Blender* next, 773 Blender* next,
634 const SkPixmap& srcPixmap, 774 const SkPixmap& srcPixmap,
635 SkLinearBitmapPipeline::SampleStage* sampleStage) { 775 SkLinearBitmapPipeline::SampleStage* sampleStage) {
636 const SkImageInfo& imageInfo = srcPixmap.info(); 776 const SkImageInfo& imageInfo = srcPixmap.info();
637 switch (imageInfo.colorType()) { 777 switch (imageInfo.colorType()) {
638 case kRGBA_8888_SkColorType: 778 case kRGBA_8888_SkColorType:
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 const SkLinearBitmapPipeline& pipeline, 930 const SkLinearBitmapPipeline& pipeline,
791 SkMatrix::TypeMask matrixMask, 931 SkMatrix::TypeMask matrixMask,
792 SkShader::TileMode xTileMode, 932 SkShader::TileMode xTileMode,
793 SkShader::TileMode yTileMode, 933 SkShader::TileMode yTileMode,
794 SkFilterQuality filterQuality, 934 SkFilterQuality filterQuality,
795 const SkPixmap& srcPixmap, 935 const SkPixmap& srcPixmap,
796 float finalAlpha, 936 float finalAlpha,
797 SkXfermode::Mode xferMode, 937 SkXfermode::Mode xferMode,
798 const SkImageInfo& dstInfo) 938 const SkImageInfo& dstInfo)
799 { 939 {
940 if (xferMode == SkXfermode::kSrcOver_Mode
941 && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
942 xferMode = SkXfermode::kSrc_Mode;
943 }
944
800 if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; } 945 if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; }
801 if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; } 946 if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; }
802 if (finalAlpha != 1.0f) { return false; } 947 if (finalAlpha != 1.0f) { return false; }
803 if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType 948 if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType
804 || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; } 949 || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; }
805 950
806 if (srcPixmap.info().profileType() != dstInfo.profileType()) { return false; } 951 if (srcPixmap.info().profileType() != kSRGB_SkColorProfileType
952 || dstInfo.profileType() != kSRGB_SkColorProfileType) { return false; }
807 953
808 if (xTileMode != SkShader::kRepeat_TileMode || yTileMode != SkShader::kRepea t_TileMode) { 954 if (xferMode != SkXfermode::kSrc_Mode && xferMode != SkXfermode::kSrcOver_Mo de) {
809 return false; 955 return false;
810 } 956 }
811 957
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); 958 new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, d stInfo);
820 959
821 return true; 960 return true;
822 } 961 }
823 962
824 SkLinearBitmapPipeline::SkLinearBitmapPipeline( 963 SkLinearBitmapPipeline::SkLinearBitmapPipeline(
825 const SkLinearBitmapPipeline& pipeline, 964 const SkLinearBitmapPipeline& pipeline,
826 const SkPixmap& srcPixmap, 965 const SkPixmap& srcPixmap,
827 SkXfermode::Mode mode, 966 SkXfermode::Mode mode,
828 const SkImageInfo& dstInfo) 967 const SkImageInfo& dstInfo)
829 { 968 {
830 SkASSERT(mode == SkXfermode::kSrc_Mode); 969 SkASSERT(mode == SkXfermode::kSrc_Mode || mode == SkXfermode::kSrcOver_Mode) ;
831 SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType() 970 SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
832 && srcPixmap.info().colorType() == kRGBA_8888_SkColorType); 971 && srcPixmap.info().colorType() == kRGBA_8888_SkColorType);
833 972
834 fSampleStage.initSink<RGBA8888UnitRepeat>(srcPixmap.writable_addr32(0, 0), s rcPixmap.width()); 973 if (mode == SkXfermode::kSrc_Mode) {
974 fSampleStage.initSink<RGBA8888UnitRepeatSrc>(
975 srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
976 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888Uni tRepeatSrc>();
977 } else {
978 fSampleStage.initSink<RGBA8888UnitRepeatSrcOver>(
979 srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
980 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888Uni tRepeatSrcOver>();
981 }
982
835 auto sampleStage = fSampleStage.get(); 983 auto sampleStage = fSampleStage.get();
836 auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage) ; 984 auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage) ;
837 tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage; 985 tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage;
838 auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixSt age); 986 auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixSt age);
839 matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage; 987 matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage;
840 fFirstStage = matrixStage; 988 fFirstStage = matrixStage;
841 fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRep eat>();
842 } 989 }
843 990
844 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 991 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
845 SkASSERT(count > 0); 992 SkASSERT(count > 0);
846 this->blitSpan(x, y, dst, count); 993 this->blitSpan(x, y, dst, count);
847 } 994 }
848 995
849 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { 996 void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) {
850 SkASSERT(count > 0); 997 SkASSERT(count > 0);
851 fLastStage->setDestination(dst, count); 998 fLastStage->setDestination(dst, count);
852 999
853 // The count and length arguments start out in a precise relation in order t o keep the 1000 // 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. 1001 // 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 1002 // 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. 1003 // 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}); 1004 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
858 } 1005 }
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