diff options
-rw-r--r-- | src/core/SkLinearBitmapPipeline.cpp | 34 | ||||
-rw-r--r-- | src/core/SkLinearBitmapPipeline_sample.h | 355 |
2 files changed, 178 insertions, 211 deletions
diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp index 562e3ecf6f..6bb88d1bf6 100644 --- a/src/core/SkLinearBitmapPipeline.cpp +++ b/src/core/SkLinearBitmapPipeline.cpp @@ -468,7 +468,7 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( //////////////////////////////////////////////////////////////////////////////////////////////////// // Source Sampling Stage -template <typename SourceStrategy, typename Next> +template <SkColorType colorType, SkColorProfileType colorProfile, typename Next> class NearestNeighborSampler final : public SkLinearBitmapPipeline::SampleProcessorInterface { public: template <typename... Args> @@ -506,10 +506,10 @@ public: } private: - GeneralSampler<SourceStrategy, Next> fSampler; + GeneralSampler<colorType, colorProfile, Next> fSampler; }; -template <typename SourceStrategy, typename Next> +template <SkColorType colorType, SkColorProfileType colorProfile, typename Next> class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterface { public: template <typename... Args> @@ -547,7 +547,7 @@ public: } private: - GeneralSampler<SourceStrategy, Next> fSampler; + GeneralSampler<colorType, colorProfile, Next> fSampler; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -708,7 +708,7 @@ private: using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; -template<template <typename, typename> class Sampler> +template<template <SkColorType, SkColorProfileType, typename> class Sampler> static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_base( Blender* next, const SkPixmap& srcPixmap, @@ -717,27 +717,35 @@ static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba switch (imageInfo.colorType()) { case kRGBA_8888_SkColorType: if (imageInfo.profileType() == kSRGB_SkColorProfileType) { - sampleStage->initStage<Sampler<Pixel8888SRGB, Blender>>(next, srcPixmap); + using S = Sampler<kRGBA_8888_SkColorType, kSRGB_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } else { - sampleStage->initStage<Sampler<Pixel8888LRGB, Blender>>(next, srcPixmap); + using S = Sampler<kRGBA_8888_SkColorType, kLinear_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } break; case kBGRA_8888_SkColorType: if (imageInfo.profileType() == kSRGB_SkColorProfileType) { - sampleStage->initStage<Sampler<Pixel8888SBGR, Blender>>(next, srcPixmap); + using S = Sampler<kBGRA_8888_SkColorType, kSRGB_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } else { - sampleStage->initStage<Sampler<Pixel8888LBGR, Blender>>(next, srcPixmap); + using S = Sampler<kBGRA_8888_SkColorType, kLinear_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } break; case kIndex_8_SkColorType: if (imageInfo.profileType() == kSRGB_SkColorProfileType) { - sampleStage->initStage<Sampler<PixelIndex8SRGB, Blender>>(next, srcPixmap); + using S = Sampler<kIndex_8_SkColorType, kSRGB_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } else { - sampleStage->initStage<Sampler<PixelIndex8LRGB, Blender>>(next, srcPixmap); + using S = Sampler<kIndex_8_SkColorType, kLinear_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); } break; - case kRGBA_F16_SkColorType: - sampleStage->initStage<Sampler<PixelHalfLinear, Blender>>(next, srcPixmap); + case kRGBA_F16_SkColorType: { + using S = Sampler<kRGBA_F16_SkColorType, kLinear_SkColorProfileType, Blender>; + sampleStage->initStage<S>(next, srcPixmap); + } break; default: SkFAIL("Not implemented. Unsupported src"); diff --git a/src/core/SkLinearBitmapPipeline_sample.h b/src/core/SkLinearBitmapPipeline_sample.h index 566ed84ffe..78af038660 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 |