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 #ifndef SkLinearBitmapPipeline_sampler_DEFINED | 8 #ifndef SkLinearBitmapPipeline_sampler_DEFINED |
9 #define SkLinearBitmapPipeline_sampler_DEFINED | 9 #define SkLinearBitmapPipeline_sampler_DEFINED |
10 | 10 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 Sk4s fxs = xs - xs.floor(); | 42 Sk4s fxs = xs - xs.floor(); |
43 Sk4s fys = ys - ys.floor(); | 43 Sk4s fys = ys - ys.floor(); |
44 Sk4s fxys{fxs * fys}; | 44 Sk4s fxys{fxs * fys}; |
45 Sk4f sum = px11 * fxys; | 45 Sk4f sum = px11 * fxys; |
46 sum = sum + px01 * (fys - fxys); | 46 sum = sum + px01 * (fys - fxys); |
47 sum = sum + px10 * (fxs - fxys); | 47 sum = sum + px10 * (fxs - fxys); |
48 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); | 48 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); |
49 return sum; | 49 return sum; |
50 } | 50 } |
51 | 51 |
52 template<typename SourceStrategy, typename Next> | 52 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 53 // PixelGetter is the lowest level interface to the source data. There is a Pixe
lGetter for each |
| 54 // of the different SkColorTypes. |
| 55 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; |
| 56 |
| 57 template <SkColorProfileType colorProfile> |
| 58 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { |
| 59 public: |
| 60 using Element = uint32_t; |
| 61 PixelGetter(const SkPixmap& srcPixmap) { } |
| 62 |
| 63 Sk4f getPixelAt(const uint32_t* src) { |
| 64 return colorProfile == kSRGB_SkColorProfileType |
| 65 ? Sk4f_fromS32(*src) |
| 66 : Sk4f_fromL32(*src); |
| 67 } |
| 68 }; |
| 69 |
| 70 template <SkColorProfileType colorProfile> |
| 71 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { |
| 72 public: |
| 73 using Element = uint32_t; |
| 74 PixelGetter(const SkPixmap& srcPixmap) { } |
| 75 |
| 76 Sk4f getPixelAt(const uint32_t* src) { |
| 77 Sk4f pixel = colorProfile == kSRGB_SkColorProfileType |
| 78 ? Sk4f_fromS32(*src) |
| 79 : Sk4f_fromL32(*src); |
| 80 return SkNx_shuffle<2, 1, 0, 3>(pixel); |
| 81 } |
| 82 }; |
| 83 |
| 84 template <SkColorProfileType colorProfile> |
| 85 class PixelGetter<kIndex_8_SkColorType, colorProfile> { |
| 86 public: |
| 87 using Element = uint8_t; |
| 88 PixelGetter(const SkPixmap& srcPixmap) { |
| 89 SkColorTable* skColorTable = srcPixmap.ctable(); |
| 90 SkASSERT(skColorTable != nullptr); |
| 91 |
| 92 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 93 for (int i = 0; i < skColorTable->count(); i++) { |
| 94 fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
| 95 } |
| 96 } |
| 97 |
| 98 PixelGetter(const PixelGetter& strategy) { |
| 99 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
| 100 // TODO: figure out the count. |
| 101 for (int i = 0; i < 256; i++) { |
| 102 fColorTable[i] = strategy.fColorTable[i]; |
| 103 } |
| 104 } |
| 105 |
| 106 Sk4f getPixelAt(const uint8_t* src) { |
| 107 return fColorTable[*src]; |
| 108 } |
| 109 |
| 110 private: |
| 111 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
| 112 Sk4f convertPixel(SkPMColor pmColor) { |
| 113 Sk4f pixel = to_4f(pmColor); |
| 114 float alpha = get_alpha(pixel); |
| 115 if (alpha != 0.0f) { |
| 116 float invAlpha = 1.0f / alpha; |
| 117 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
| 118 pixel = pixel * normalize; |
| 119 if (colorProfile == kSRGB_SkColorProfileType) { |
| 120 pixel = linear_to_srgb(pixel); |
| 121 } |
| 122 return pixel; |
| 123 } else { |
| 124 return Sk4f{0.0f}; |
| 125 } |
| 126 } |
| 127 SkAutoMalloc fColorTableStorage{kColorTableSize}; |
| 128 Sk4f* fColorTable; |
| 129 }; |
| 130 |
| 131 template <> |
| 132 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { |
| 133 public: |
| 134 using Element = uint64_t; |
| 135 PixelGetter(const SkPixmap& srcPixmap) { } |
| 136 |
| 137 Sk4f getPixelAt(const uint64_t* src) { |
| 138 return SkHalfToFloat_01(*src); |
| 139 } |
| 140 }; |
| 141 |
| 142 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 143 // PixelAccessor handles all the same plumbing for all the PixelGetters. |
| 144 template <SkColorType colorType, SkColorProfileType colorProfile> |
| 145 class PixelAccessor { |
| 146 using Element = typename PixelGetter<colorType, colorProfile>::Element; |
| 147 public: |
| 148 PixelAccessor(const SkPixmap& srcPixmap) |
| 149 : fSrc{static_cast<const Element*>(srcPixmap.addr())} |
| 150 , fWidth{srcPixmap.rowBytesAsPixels()} |
| 151 , fGetter{srcPixmap} { } |
| 152 |
| 153 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { |
| 154 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 155 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 156 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 157 switch (n) { |
| 158 case 3: |
| 159 *px2 = this->getPixelAt(bufferLoc[2]); |
| 160 case 2: |
| 161 *px1 = this->getPixelAt(bufferLoc[1]); |
| 162 case 1: |
| 163 *px0 = this->getPixelAt(bufferLoc[0]); |
| 164 default: |
| 165 break; |
| 166 } |
| 167 } |
| 168 |
| 169 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { |
| 170 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
| 171 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
| 172 Sk4i bufferLoc = YIs * fWidth + XIs; |
| 173 *px0 = this->getPixelAt(bufferLoc[0]); |
| 174 *px1 = this->getPixelAt(bufferLoc[1]); |
| 175 *px2 = this->getPixelAt(bufferLoc[2]); |
| 176 *px3 = this->getPixelAt(bufferLoc[3]); |
| 177 } |
| 178 |
| 179 void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2,
Sk4f* px3) { |
| 180 *px0 = this->getPixelFromRow(src, index + 0); |
| 181 *px1 = this->getPixelFromRow(src, index + 1); |
| 182 *px2 = this->getPixelFromRow(src, index + 2); |
| 183 *px3 = this->getPixelFromRow(src, index + 3); |
| 184 } |
| 185 |
| 186 Sk4f getPixelFromRow(const void* row, int index) { |
| 187 const Element* src = static_cast<const Element*>(row); |
| 188 return fGetter.getPixelAt(src + index); |
| 189 } |
| 190 |
| 191 Sk4f getPixelAt(int index) { |
| 192 return this->getPixelFromRow(fSrc, index); |
| 193 } |
| 194 |
| 195 const void* row(int y) const { return fSrc + y * fWidth[0]; } |
| 196 |
| 197 private: |
| 198 const Element* const fSrc; |
| 199 const Sk4i fWidth; |
| 200 PixelGetter<colorType, colorProfile> fGetter; |
| 201 }; |
| 202 |
| 203 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 204 // GeneralSampler handles all the different sampling scenarios. It makes runtime
decisions to |
| 205 // choose the fastest stratagy given a particular job. It ultimately uses PixelG
etters to access |
| 206 // the pixels. |
| 207 template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> |
53 class GeneralSampler { | 208 class GeneralSampler { |
54 public: | 209 public: |
55 template<typename... Args> | 210 template<typename... Args> |
56 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) | 211 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&&
... args) |
57 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } | 212 : fNext{next}, fStrategy{std::forward<Args>(args)...} { } |
58 | 213 |
59 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, | 214 GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, |
60 const GeneralSampler& sampler) | 215 const GeneralSampler& sampler) |
61 : fNext{next}, fStrategy{sampler.fStrategy} { } | 216 : fNext{next}, fStrategy{sampler.fStrategy} { } |
62 | 217 |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 while (count > 0) { | 705 while (count > 0) { |
551 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; | 706 Sk4f xs = Sk4f{-0.5f, 0.5f, -0.5f, 0.5f} + Sk4f{x}; |
552 this->bilerpEdge(xs, ys); | 707 this->bilerpEdge(xs, ys); |
553 x += dx; | 708 x += dx; |
554 count -= 1; | 709 count -= 1; |
555 } | 710 } |
556 } | 711 } |
557 } | 712 } |
558 | 713 |
559 Next* const fNext; | 714 Next* const fNext; |
560 SourceStrategy fStrategy; | 715 PixelAccessor<colorType, colorProfile> fStrategy; |
561 }; | 716 }; |
562 | 717 |
563 template <typename PixelGetter> | |
564 class PixelAccessor { | |
565 public: | |
566 PixelAccessor(const SkPixmap& srcPixmap) | |
567 : fWidth{srcPixmap.rowBytesAsPixels()} | |
568 , fGetter{srcPixmap} { } | |
569 | |
570 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1,
Sk4f* px2) { | |
571 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
572 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
573 Sk4i bufferLoc = YIs * fWidth + XIs; | |
574 switch (n) { | |
575 case 3: | |
576 *px2 = fGetter.getPixelAt(bufferLoc[2]); | |
577 case 2: | |
578 *px1 = fGetter.getPixelAt(bufferLoc[1]); | |
579 case 1: | |
580 *px0 = fGetter.getPixelAt(bufferLoc[0]); | |
581 default: | |
582 break; | |
583 } | |
584 } | |
585 | |
586 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2
, Sk4f* px3) { | |
587 Sk4i XIs = SkNx_cast<int, SkScalar>(xs); | |
588 Sk4i YIs = SkNx_cast<int, SkScalar>(ys); | |
589 Sk4i bufferLoc = YIs * fWidth + XIs; | |
590 *px0 = fGetter.getPixelAt(bufferLoc[0]); | |
591 *px1 = fGetter.getPixelAt(bufferLoc[1]); | |
592 *px2 = fGetter.getPixelAt(bufferLoc[2]); | |
593 *px3 = fGetter.getPixelAt(bufferLoc[3]); | |
594 } | |
595 | |
596 void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2,
Sk4f* px3) { | |
597 *px0 = fGetter.getPixelFromRow(src, index + 0); | |
598 *px1 = fGetter.getPixelFromRow(src, index + 1); | |
599 *px2 = fGetter.getPixelFromRow(src, index + 2); | |
600 *px3 = fGetter.getPixelFromRow(src, index + 3); | |
601 } | |
602 | |
603 Sk4f getPixelFromRow(const void* row, int index) { | |
604 return fGetter.getPixelFromRow(row, index); | |
605 } | |
606 | |
607 const void* row(int y) { return fGetter.row(y); } | |
608 | |
609 private: | |
610 const Sk4i fWidth; | |
611 PixelGetter fGetter; | |
612 }; | |
613 | |
614 template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGet
ter; | |
615 | |
616 template <SkColorProfileType colorProfile> | |
617 class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { | |
618 public: | |
619 PixelGetter(const SkPixmap& srcPixmap) | |
620 : fSrc{srcPixmap.addr32()} | |
621 , fWidth{srcPixmap.rowBytesAsPixels()} { } | |
622 | |
623 Sk4f getPixelFromRow(const void* row, int index) { | |
624 const uint32_t* src = static_cast<const uint32_t*>(row) + index; | |
625 return colorProfile == kSRGB_SkColorProfileType | |
626 ? Sk4f_fromS32(*src) | |
627 : Sk4f_fromL32(*src); | |
628 } | |
629 | |
630 Sk4f getPixelAt(int index) { | |
631 return this->getPixelFromRow(fSrc, index); | |
632 } | |
633 | |
634 const void* row(int y) { return fSrc + y * fWidth; } | |
635 | |
636 private: | |
637 const uint32_t* const fSrc; | |
638 const int fWidth; | |
639 }; | |
640 | |
641 using Pixel8888SRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
642 using Pixel8888LRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kLinear_
SkColorProfileType>>; | |
643 | |
644 template <SkColorProfileType colorProfile> | |
645 class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { | |
646 public: | |
647 PixelGetter(const SkPixmap& srcPixmap) | |
648 : fSrc{srcPixmap.addr32()} | |
649 , fWidth{srcPixmap.rowBytesAsPixels()} { } | |
650 | |
651 Sk4f getPixelFromRow(const void* row, int index) { | |
652 const uint32_t* src = static_cast<const uint32_t*>(row) + index; | |
653 Sk4f pixel = colorProfile == kSRGB_SkColorProfileType | |
654 ? Sk4f_fromS32(*src) | |
655 : Sk4f_fromL32(*src); | |
656 return SkNx_shuffle<2, 1, 0, 3>(pixel); | |
657 } | |
658 | |
659 Sk4f getPixelAt(int index) { | |
660 return this->getPixelFromRow(fSrc, index); | |
661 } | |
662 | |
663 const void* row(int y) { return fSrc + y * fWidth; } | |
664 | |
665 private: | |
666 const uint32_t* const fSrc; | |
667 const int fWidth; | |
668 }; | |
669 | |
670 using Pixel8888SBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
671 using Pixel8888LBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kLinear_
SkColorProfileType>>; | |
672 | |
673 template <SkColorProfileType colorProfile> | |
674 class PixelGetter<kIndex_8_SkColorType, colorProfile> { | |
675 public: | |
676 PixelGetter(const SkPixmap& srcPixmap) | |
677 : fSrc{srcPixmap.addr8()}, fWidth{static_cast<int>(srcPixmap.rowBytes())
} { | |
678 SkASSERT(srcPixmap.colorType() == kIndex_8_SkColorType); | |
679 SkColorTable* skColorTable = srcPixmap.ctable(); | |
680 SkASSERT(skColorTable != nullptr); | |
681 | |
682 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | |
683 for (int i = 0; i < skColorTable->count(); i++) { | |
684 fColorTable[i] = this->convertPixel((*skColorTable)[i]); | |
685 } | |
686 } | |
687 | |
688 PixelGetter(const PixelGetter& strategy) | |
689 : fSrc{strategy.fSrc}, fWidth{strategy.fWidth} { | |
690 fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); | |
691 // TODO: figure out the count. | |
692 for (int i = 0; i < 256; i++) { | |
693 fColorTable[i] = strategy.fColorTable[i]; | |
694 } | |
695 } | |
696 | |
697 Sk4f getPixelFromRow(const void* row, int index) { | |
698 const uint8_t* src = static_cast<const uint8_t*>(row) + index; | |
699 Sk4f pixel = fColorTable[*src]; | |
700 return pixel; | |
701 } | |
702 | |
703 Sk4f getPixelAt(int index) { | |
704 return this->getPixelFromRow(fSrc, index); | |
705 } | |
706 | |
707 const void* row(int y) { return fSrc + y * fWidth; } | |
708 | |
709 private: | |
710 static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; | |
711 Sk4f convertPixel(SkPMColor pmColor) { | |
712 Sk4f pixel = to_4f(pmColor); | |
713 float alpha = get_alpha(pixel); | |
714 if (alpha != 0.0f) { | |
715 float invAlpha = 1.0f / alpha; | |
716 Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; | |
717 pixel = pixel * normalize; | |
718 if (colorProfile == kSRGB_SkColorProfileType) { | |
719 pixel = linear_to_srgb(pixel); | |
720 } | |
721 return pixel; | |
722 } else { | |
723 return Sk4f{0.0f}; | |
724 } | |
725 } | |
726 const uint8_t* const fSrc; | |
727 const int fWidth; | |
728 SkAutoMalloc fColorTableStorage{kColorTableSize}; | |
729 Sk4f* fColorTable; | |
730 }; | |
731 | |
732 using PixelIndex8SRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kSRGB_Sk
ColorProfileType>>; | |
733 using PixelIndex8LRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kLinear_
SkColorProfileType>>; | |
734 | |
735 template <> | |
736 class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { | |
737 public: | |
738 PixelGetter(const SkPixmap& srcPixmap) | |
739 : fSrc{srcPixmap.addr64()} | |
740 , fWidth{static_cast<int>(srcPixmap.rowBytesAsPixels())} { } | |
741 | |
742 Sk4f getPixelFromRow(const void* row, int index) { | |
743 const uint64_t* src = static_cast<const uint64_t*>(row) + index; | |
744 return SkHalfToFloat_01(*src); | |
745 } | |
746 | |
747 Sk4f getPixelAt(int index) { | |
748 return this->getPixelFromRow(fSrc, index); | |
749 } | |
750 | |
751 const void* row(int y) { return fSrc + y * fWidth; } | |
752 | |
753 private: | |
754 const uint64_t* const fSrc; | |
755 const int fWidth; | |
756 }; | |
757 | |
758 using PixelHalfLinear = PixelAccessor<PixelGetter<kRGBA_F16_SkColorType, kLinear
_SkColorProfileType>>; | |
759 | 718 |
760 } // namespace | 719 } // namespace |
761 | 720 |
762 #endif // SkLinearBitmapPipeline_sampler_DEFINED | 721 #endif // SkLinearBitmapPipeline_sampler_DEFINED |
OLD | NEW |