Make PixelGetters much smaller, move more common code to PixelAccessor.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1971863002

Review-Url: https://codereview.chromium.org/1971863002
This commit is contained in:
herb 2016-05-12 11:37:00 -07:00 committed by Commit bot
parent dd4fcd4500
commit 15332a841d
2 changed files with 178 additions and 211 deletions

View File

@ -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");

View File

@ -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;
PixelAccessor<colorType, colorProfile> 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;
};
using PixelHalfLinear = PixelAccessor<PixelGetter<kRGBA_F16_SkColorType, kLinear_SkColorProfileType>>;
} // namespace