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 #include "SkPM4f.h" | 9 #include "SkPM4f.h" |
10 | 10 |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | 738 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { |
739 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | 739 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
740 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | 740 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
741 Sk4i bufferLoc = YIs * fWidth + XIs; | 741 Sk4i bufferLoc = YIs * fWidth + XIs; |
742 *px0 = this->getPixel(fSrc, bufferLoc[0]); | 742 *px0 = this->getPixel(fSrc, bufferLoc[0]); |
743 *px1 = this->getPixel(fSrc, bufferLoc[1]); | 743 *px1 = this->getPixel(fSrc, bufferLoc[1]); |
744 *px2 = this->getPixel(fSrc, bufferLoc[2]); | 744 *px2 = this->getPixel(fSrc, bufferLoc[2]); |
745 *px3 = this->getPixel(fSrc, bufferLoc[3]); | 745 *px3 = this->getPixel(fSrc, bufferLoc[3]); |
746 } | 746 } |
747 | 747 |
748 Sk4f getPixel(const uint32_t* src, int index) { | 748 void get4Pixels(const void* vsrc, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { |
| 749 const uint32_t* src = static_cast<const uint32_t*>(vsrc); |
| 750 *px0 = this->getPixel(src, index + 0); |
| 751 *px1 = this->getPixel(src, index + 1); |
| 752 *px2 = this->getPixel(src, index + 2); |
| 753 *px3 = this->getPixel(src, index + 3); |
| 754 } |
| 755 |
| 756 Sk4f getPixel(const void* vsrc, int index) { |
| 757 const uint32_t* src = static_cast<const uint32_t*>(vsrc); |
749 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index])); | 758 Sk4b bytePixel = Sk4b::Load((uint8_t *)(&src[index])); |
750 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel); | 759 Sk4f pixel = SkNx_cast<float, uint8_t>(bytePixel); |
751 if (colorOrder == ColorOrder::kBGRA) { | 760 if (colorOrder == ColorOrder::kBGRA) { |
752 pixel = SkNx_shuffle<2, 1, 0, 3>(pixel); | 761 pixel = SkNx_shuffle<2, 1, 0, 3>(pixel); |
753 } | 762 } |
754 pixel = pixel * Sk4f{1.0f/255.0f}; | 763 pixel = pixel * Sk4f{1.0f/255.0f}; |
755 if (colorProfile == kSRGB_SkColorProfileType) { | 764 if (colorProfile == kSRGB_SkColorProfileType) { |
756 pixel = sRGBFast::sRGBToLinear(pixel); | 765 pixel = sRGBFast::sRGBToLinear(pixel); |
757 } | 766 } |
758 return pixel; | 767 return pixel; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 } | 831 } |
823 | 832 |
824 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override { | 833 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override { |
825 Sk4f px00, px10, px01, px11; | 834 Sk4f px00, px10, px01, px11; |
826 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); | 835 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); |
827 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); | 836 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
828 fNext->placePixel(pixel); | 837 fNext->placePixel(pixel); |
829 } | 838 } |
830 | 839 |
831 void pointSpan(Span span) override { | 840 void pointSpan(Span span) override { |
| 841 SkASSERT(!span.isEmpty()); |
| 842 SkPoint start; SkScalar length; int count; |
| 843 std::tie(start, length, count) = span; |
| 844 if (length < (count - 1)) { |
| 845 this->pointSpanSlowRate(span); |
| 846 } else if (length == (count - 1)) { |
| 847 this->pointSpanUnitRate(span); |
| 848 } else { |
| 849 this->pointSpanFastRate(span); |
| 850 } |
| 851 } |
| 852 |
| 853 private: |
| 854 // When moving through source space more slowly than dst space (zoomed in), |
| 855 // we'll be sampling from the same source pixel more than once. |
| 856 void pointSpanSlowRate(Span span) { |
| 857 SkPoint start; SkScalar length; int count; |
| 858 std::tie(start, length, count) = span; |
| 859 SkScalar x = X(start); |
| 860 SkFixed fx = SkScalarToFixed(x); |
| 861 SkScalar dx = length / (count - 1); |
| 862 SkFixed fdx = SkScalarToFixed(dx); |
| 863 |
| 864 const void* row = fStrategy.row((int)std::floor(Y(start))); |
| 865 SkLinearBitmapPipeline::PixelPlacerInterface* next = fNext; |
| 866 |
| 867 int ix = SkFixedFloorToInt(fx); |
| 868 int prevIX = ix; |
| 869 Sk4f fpixel = fStrategy.getPixel(row, ix); |
| 870 |
| 871 // When dx is less than one, each pixel is used more than once. Using th
e fixed point fx |
| 872 // allows the code to quickly check that the same pixel is being used. T
he code uses this |
| 873 // same pixel check to do the sRGB and normalization only once. |
| 874 auto getNextPixel = [&]() { |
| 875 if (ix != prevIX) { |
| 876 fpixel = fStrategy.getPixel(row, ix); |
| 877 prevIX = ix; |
| 878 } |
| 879 fx += fdx; |
| 880 ix = SkFixedFloorToInt(fx); |
| 881 return fpixel; |
| 882 }; |
| 883 |
| 884 while (count >= 4) { |
| 885 Sk4f px0 = getNextPixel(); |
| 886 Sk4f px1 = getNextPixel(); |
| 887 Sk4f px2 = getNextPixel(); |
| 888 Sk4f px3 = getNextPixel(); |
| 889 next->place4Pixels(px0, px1, px2, px3); |
| 890 count -= 4; |
| 891 } |
| 892 while (count > 0) { |
| 893 next->placePixel(getNextPixel()); |
| 894 count -= 1; |
| 895 } |
| 896 } |
| 897 |
| 898 // We're moving through source space at a rate of 1 source pixel per 1 dst p
ixel. |
| 899 // We'll never re-use pixels, but we can at least load contiguous pixels. |
| 900 void pointSpanUnitRate(Span span) { |
| 901 SkPoint start; SkScalar length; int count; |
| 902 std::tie(start, length, count) = span; |
| 903 int ix = SkScalarFloorToInt(X(start)); |
| 904 const void* row = fStrategy.row((int)std::floor(Y(start))); |
| 905 SkLinearBitmapPipeline::PixelPlacerInterface* next = fNext; |
| 906 while (count >= 4) { |
| 907 Sk4f px0, px1, px2, px3; |
| 908 fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3); |
| 909 next->place4Pixels(px0, px1, px2, px3); |
| 910 ix += 4; |
| 911 count -= 4; |
| 912 } |
| 913 |
| 914 while (count > 0) { |
| 915 next->placePixel(fStrategy.getPixel(row, ix)); |
| 916 ix += 1; |
| 917 count -= 1; |
| 918 } |
| 919 } |
| 920 |
| 921 // We're moving through source space faster than dst (zoomed out), |
| 922 // so we'll never reuse a source pixel or be able to do contiguous loads. |
| 923 void pointSpanFastRate(Span span) { |
832 span_fallback(span, this); | 924 span_fallback(span, this); |
833 } | 925 } |
834 | 926 |
835 private: | 927 private: |
836 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; | 928 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; |
837 SourceStrategy fStrategy; | 929 SourceStrategy fStrategy; |
838 }; | 930 }; |
839 | 931 |
840 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; | 932 using Pixel8888SRGB = Pixel8888<kSRGB_SkColorProfileType, ColorOrder::kRGBA>; |
841 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; | 933 using Pixel8888LRGB = Pixel8888<kLinear_SkColorProfileType, ColorOrder::kRGBA>; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
941 | 1033 |
942 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 1034 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
943 SkASSERT(count > 0); | 1035 SkASSERT(count > 0); |
944 fPixelStage->setDestination(dst); | 1036 fPixelStage->setDestination(dst); |
945 // The count and length arguments start out in a precise relation in order t
o keep the | 1037 // The count and length arguments start out in a precise relation in order t
o keep the |
946 // math correct through the different stages. Count is the number of pixel t
o produce. | 1038 // math correct through the different stages. Count is the number of pixel t
o produce. |
947 // Since the code samples at pixel centers, length is the distance from the
center of the | 1039 // Since the code samples at pixel centers, length is the distance from the
center of the |
948 // first pixel to the center of the last pixel. This implies that length is
count-1. | 1040 // first pixel to the center of the last pixel. This implies that length is
count-1. |
949 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count
}); | 1041 fFirstStage->pointSpan(Span{SkPoint{x + 0.5f, y + 0.5f}, count - 1.0f, count
}); |
950 } | 1042 } |
OLD | NEW |