Index: src/core/SkLinearBitmapPipeline_sample.h |
diff --git a/src/core/SkLinearBitmapPipeline_sample.h b/src/core/SkLinearBitmapPipeline_sample.h |
index 566ed84ffe8d2ac85f0067b717e5c62fec573481..78af038660f12094e3843644bfca58468ba4ef32 100644 |
--- a/src/core/SkLinearBitmapPipeline_sample.h |
+++ b/src/core/SkLinearBitmapPipeline_sample.h |
@@ -49,7 +49,162 @@ static Sk4s VECTORCALL bilerp4(Sk4s xs, Sk4s ys, Sk4f px00, Sk4f px10, |
return sum; |
} |
-template<typename SourceStrategy, typename Next> |
+//////////////////////////////////////////////////////////////////////////////////////////////////// |
+// PixelGetter is the lowest level interface to the source data. There is a PixelGetter for each |
+// of the different SkColorTypes. |
+template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGetter; |
+ |
+template <SkColorProfileType colorProfile> |
+class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { |
+public: |
+ using Element = uint32_t; |
+ PixelGetter(const SkPixmap& srcPixmap) { } |
+ |
+ Sk4f getPixelAt(const uint32_t* src) { |
+ return colorProfile == kSRGB_SkColorProfileType |
+ ? Sk4f_fromS32(*src) |
+ : Sk4f_fromL32(*src); |
+ } |
+}; |
+ |
+template <SkColorProfileType colorProfile> |
+class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { |
+public: |
+ using Element = uint32_t; |
+ PixelGetter(const SkPixmap& srcPixmap) { } |
+ |
+ Sk4f getPixelAt(const uint32_t* src) { |
+ Sk4f pixel = colorProfile == kSRGB_SkColorProfileType |
+ ? Sk4f_fromS32(*src) |
+ : Sk4f_fromL32(*src); |
+ return SkNx_shuffle<2, 1, 0, 3>(pixel); |
+ } |
+}; |
+ |
+template <SkColorProfileType colorProfile> |
+class PixelGetter<kIndex_8_SkColorType, colorProfile> { |
+public: |
+ using Element = uint8_t; |
+ PixelGetter(const SkPixmap& srcPixmap) { |
+ SkColorTable* skColorTable = srcPixmap.ctable(); |
+ SkASSERT(skColorTable != nullptr); |
+ |
+ fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
+ for (int i = 0; i < skColorTable->count(); i++) { |
+ fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
+ } |
+ } |
+ |
+ PixelGetter(const PixelGetter& strategy) { |
+ fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
+ // TODO: figure out the count. |
+ for (int i = 0; i < 256; i++) { |
+ fColorTable[i] = strategy.fColorTable[i]; |
+ } |
+ } |
+ |
+ Sk4f getPixelAt(const uint8_t* src) { |
+ return fColorTable[*src]; |
+ } |
+ |
+private: |
+ static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
+ Sk4f convertPixel(SkPMColor pmColor) { |
+ Sk4f pixel = to_4f(pmColor); |
+ float alpha = get_alpha(pixel); |
+ if (alpha != 0.0f) { |
+ float invAlpha = 1.0f / alpha; |
+ Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
+ pixel = pixel * normalize; |
+ if (colorProfile == kSRGB_SkColorProfileType) { |
+ pixel = linear_to_srgb(pixel); |
+ } |
+ return pixel; |
+ } else { |
+ return Sk4f{0.0f}; |
+ } |
+ } |
+ SkAutoMalloc fColorTableStorage{kColorTableSize}; |
+ Sk4f* fColorTable; |
+}; |
+ |
+template <> |
+class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { |
+public: |
+ using Element = uint64_t; |
+ PixelGetter(const SkPixmap& srcPixmap) { } |
+ |
+ Sk4f getPixelAt(const uint64_t* src) { |
+ return SkHalfToFloat_01(*src); |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////////////////////////// |
+// PixelAccessor handles all the same plumbing for all the PixelGetters. |
+template <SkColorType colorType, SkColorProfileType colorProfile> |
+class PixelAccessor { |
+ using Element = typename PixelGetter<colorType, colorProfile>::Element; |
+public: |
+ PixelAccessor(const SkPixmap& srcPixmap) |
+ : fSrc{static_cast<const Element*>(srcPixmap.addr())} |
+ , fWidth{srcPixmap.rowBytesAsPixels()} |
+ , fGetter{srcPixmap} { } |
+ |
+ void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { |
+ Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
+ Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
+ Sk4i bufferLoc = YIs * fWidth + XIs; |
+ switch (n) { |
+ case 3: |
+ *px2 = this->getPixelAt(bufferLoc[2]); |
+ case 2: |
+ *px1 = this->getPixelAt(bufferLoc[1]); |
+ case 1: |
+ *px0 = this->getPixelAt(bufferLoc[0]); |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
+ Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
+ Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
+ Sk4i bufferLoc = YIs * fWidth + XIs; |
+ *px0 = this->getPixelAt(bufferLoc[0]); |
+ *px1 = this->getPixelAt(bufferLoc[1]); |
+ *px2 = this->getPixelAt(bufferLoc[2]); |
+ *px3 = this->getPixelAt(bufferLoc[3]); |
+ } |
+ |
+ void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
+ *px0 = this->getPixelFromRow(src, index + 0); |
+ *px1 = this->getPixelFromRow(src, index + 1); |
+ *px2 = this->getPixelFromRow(src, index + 2); |
+ *px3 = this->getPixelFromRow(src, index + 3); |
+ } |
+ |
+ Sk4f getPixelFromRow(const void* row, int index) { |
+ const Element* src = static_cast<const Element*>(row); |
+ return fGetter.getPixelAt(src + index); |
+ } |
+ |
+ Sk4f getPixelAt(int index) { |
+ return this->getPixelFromRow(fSrc, index); |
+ } |
+ |
+ const void* row(int y) const { return fSrc + y * fWidth[0]; } |
+ |
+private: |
+ const Element* const fSrc; |
+ const Sk4i fWidth; |
+ PixelGetter<colorType, colorProfile> fGetter; |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////////////////////////// |
+// GeneralSampler handles all the different sampling scenarios. It makes runtime decisions to |
+// choose the fastest stratagy given a particular job. It ultimately uses PixelGetters to access |
+// the pixels. |
+template<SkColorType colorType, SkColorProfileType colorProfile, typename Next> |
class GeneralSampler { |
public: |
template<typename... Args> |
@@ -557,205 +712,9 @@ private: |
} |
Next* const fNext; |
- SourceStrategy fStrategy; |
-}; |
- |
-template <typename PixelGetter> |
-class PixelAccessor { |
-public: |
- PixelAccessor(const SkPixmap& srcPixmap) |
- : fWidth{srcPixmap.rowBytesAsPixels()} |
- , fGetter{srcPixmap} { } |
- |
- void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { |
- Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
- Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
- Sk4i bufferLoc = YIs * fWidth + XIs; |
- switch (n) { |
- case 3: |
- *px2 = fGetter.getPixelAt(bufferLoc[2]); |
- case 2: |
- *px1 = fGetter.getPixelAt(bufferLoc[1]); |
- case 1: |
- *px0 = fGetter.getPixelAt(bufferLoc[0]); |
- default: |
- break; |
- } |
- } |
- |
- void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
- Sk4i XIs = SkNx_cast<int, SkScalar>(xs); |
- Sk4i YIs = SkNx_cast<int, SkScalar>(ys); |
- Sk4i bufferLoc = YIs * fWidth + XIs; |
- *px0 = fGetter.getPixelAt(bufferLoc[0]); |
- *px1 = fGetter.getPixelAt(bufferLoc[1]); |
- *px2 = fGetter.getPixelAt(bufferLoc[2]); |
- *px3 = fGetter.getPixelAt(bufferLoc[3]); |
- } |
- |
- void get4Pixels(const void* src, int index, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
- *px0 = fGetter.getPixelFromRow(src, index + 0); |
- *px1 = fGetter.getPixelFromRow(src, index + 1); |
- *px2 = fGetter.getPixelFromRow(src, index + 2); |
- *px3 = fGetter.getPixelFromRow(src, index + 3); |
- } |
- |
- Sk4f getPixelFromRow(const void* row, int index) { |
- return fGetter.getPixelFromRow(row, index); |
- } |
- |
- const void* row(int y) { return fGetter.row(y); } |
- |
-private: |
- const Sk4i fWidth; |
- PixelGetter fGetter; |
-}; |
- |
-template <SkColorType colorType, SkColorProfileType colorProfile> class PixelGetter; |
- |
-template <SkColorProfileType colorProfile> |
-class PixelGetter<kRGBA_8888_SkColorType, colorProfile> { |
-public: |
- PixelGetter(const SkPixmap& srcPixmap) |
- : fSrc{srcPixmap.addr32()} |
- , fWidth{srcPixmap.rowBytesAsPixels()} { } |
- |
- Sk4f getPixelFromRow(const void* row, int index) { |
- const uint32_t* src = static_cast<const uint32_t*>(row) + index; |
- return colorProfile == kSRGB_SkColorProfileType |
- ? Sk4f_fromS32(*src) |
- : Sk4f_fromL32(*src); |
- } |
- |
- Sk4f getPixelAt(int index) { |
- return this->getPixelFromRow(fSrc, index); |
- } |
- |
- const void* row(int y) { return fSrc + y * fWidth; } |
- |
-private: |
- const uint32_t* const fSrc; |
- const int fWidth; |
-}; |
- |
-using Pixel8888SRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kSRGB_SkColorProfileType>>; |
-using Pixel8888LRGB = PixelAccessor<PixelGetter<kRGBA_8888_SkColorType, kLinear_SkColorProfileType>>; |
- |
-template <SkColorProfileType colorProfile> |
-class PixelGetter<kBGRA_8888_SkColorType, colorProfile> { |
-public: |
- PixelGetter(const SkPixmap& srcPixmap) |
- : fSrc{srcPixmap.addr32()} |
- , fWidth{srcPixmap.rowBytesAsPixels()} { } |
- |
- Sk4f getPixelFromRow(const void* row, int index) { |
- const uint32_t* src = static_cast<const uint32_t*>(row) + index; |
- Sk4f pixel = colorProfile == kSRGB_SkColorProfileType |
- ? Sk4f_fromS32(*src) |
- : Sk4f_fromL32(*src); |
- return SkNx_shuffle<2, 1, 0, 3>(pixel); |
- } |
- |
- Sk4f getPixelAt(int index) { |
- return this->getPixelFromRow(fSrc, index); |
- } |
- |
- const void* row(int y) { return fSrc + y * fWidth; } |
- |
-private: |
- const uint32_t* const fSrc; |
- const int fWidth; |
-}; |
- |
-using Pixel8888SBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kSRGB_SkColorProfileType>>; |
-using Pixel8888LBGR = PixelAccessor<PixelGetter<kBGRA_8888_SkColorType, kLinear_SkColorProfileType>>; |
- |
-template <SkColorProfileType colorProfile> |
-class PixelGetter<kIndex_8_SkColorType, colorProfile> { |
-public: |
- PixelGetter(const SkPixmap& srcPixmap) |
- : fSrc{srcPixmap.addr8()}, fWidth{static_cast<int>(srcPixmap.rowBytes())} { |
- SkASSERT(srcPixmap.colorType() == kIndex_8_SkColorType); |
- SkColorTable* skColorTable = srcPixmap.ctable(); |
- SkASSERT(skColorTable != nullptr); |
- |
- fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
- for (int i = 0; i < skColorTable->count(); i++) { |
- fColorTable[i] = this->convertPixel((*skColorTable)[i]); |
- } |
- } |
- |
- PixelGetter(const PixelGetter& strategy) |
- : fSrc{strategy.fSrc}, fWidth{strategy.fWidth} { |
- fColorTable = (Sk4f*)SkAlign16((intptr_t)fColorTableStorage.get()); |
- // TODO: figure out the count. |
- for (int i = 0; i < 256; i++) { |
- fColorTable[i] = strategy.fColorTable[i]; |
- } |
- } |
- |
- Sk4f getPixelFromRow(const void* row, int index) { |
- const uint8_t* src = static_cast<const uint8_t*>(row) + index; |
- Sk4f pixel = fColorTable[*src]; |
- return pixel; |
- } |
- |
- Sk4f getPixelAt(int index) { |
- return this->getPixelFromRow(fSrc, index); |
- } |
- |
- const void* row(int y) { return fSrc + y * fWidth; } |
- |
-private: |
- static const size_t kColorTableSize = sizeof(Sk4f[256]) + 12; |
- Sk4f convertPixel(SkPMColor pmColor) { |
- Sk4f pixel = to_4f(pmColor); |
- float alpha = get_alpha(pixel); |
- if (alpha != 0.0f) { |
- float invAlpha = 1.0f / alpha; |
- Sk4f normalize = {invAlpha, invAlpha, invAlpha, 1.0f / 255.0f}; |
- pixel = pixel * normalize; |
- if (colorProfile == kSRGB_SkColorProfileType) { |
- pixel = linear_to_srgb(pixel); |
- } |
- return pixel; |
- } else { |
- return Sk4f{0.0f}; |
- } |
- } |
- const uint8_t* const fSrc; |
- const int fWidth; |
- SkAutoMalloc fColorTableStorage{kColorTableSize}; |
- Sk4f* fColorTable; |
-}; |
- |
-using PixelIndex8SRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kSRGB_SkColorProfileType>>; |
-using PixelIndex8LRGB = PixelAccessor<PixelGetter<kIndex_8_SkColorType, kLinear_SkColorProfileType>>; |
- |
-template <> |
-class PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType> { |
-public: |
- PixelGetter(const SkPixmap& srcPixmap) |
- : fSrc{srcPixmap.addr64()} |
- , fWidth{static_cast<int>(srcPixmap.rowBytesAsPixels())} { } |
- |
- Sk4f getPixelFromRow(const void* row, int index) { |
- const uint64_t* src = static_cast<const uint64_t*>(row) + index; |
- return SkHalfToFloat_01(*src); |
- } |
- |
- Sk4f getPixelAt(int index) { |
- return this->getPixelFromRow(fSrc, index); |
- } |
- |
- const void* row(int y) { return fSrc + y * fWidth; } |
- |
-private: |
- const uint64_t* const fSrc; |
- const int fWidth; |
+ PixelAccessor<colorType, colorProfile> fStrategy; |
}; |
-using PixelHalfLinear = PixelAccessor<PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType>>; |
} // namespace |