OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |