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