Add clone to Stage. Rename place to mix and PolymorphicUnion to Stage. Cleanup.

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

Review URL: https://codereview.chromium.org/1877483002
This commit is contained in:
herb 2016-04-08 13:25:28 -07:00 committed by Commit bot
parent c265a92741
commit 9e0efe57ac
6 changed files with 193 additions and 121 deletions

View File

@ -59,7 +59,7 @@ static void draw_rect_orig(SkCanvas* canvas, const SkRect& r, SkColor c, const S
sk_sp<SkImage> image(SkImage::MakeRasterCopy(SkPixmap(info, pmsrc.addr32(), pmsrc.rowBytes())));
SkPaint paint;
int32_t storage[300];
int32_t storage[400];
sk_sp<SkShader> shader = image->makeShader(SkShader::kRepeat_TileMode,
SkShader::kRepeat_TileMode);

View File

@ -55,7 +55,7 @@ private:
// an Sk3DBlitter in SkDraw.cpp
// Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
// yet found a situation where the size below isn't big enough.
typedef SkSmallAllocator<3, 2100> SkTBlitterAllocator;
typedef SkSmallAllocator<3, 2400> SkTBlitterAllocator;
// If alloc is non-nullptr, it will be used to allocate the returned SkShader, and MUST outlive
// the SkShader.

View File

@ -65,21 +65,66 @@ public:
class SkLinearBitmapPipeline::DestinationInterface {
public:
virtual ~DestinationInterface() { }
virtual void setDestination(void* dst, int count) = 0;
};
class SkLinearBitmapPipeline::PixelPlacerInterface
: public SkLinearBitmapPipeline::DestinationInterface {
public:
virtual ~PixelPlacerInterface() { }
// Count is normally not needed, but in these early stages of development it is useful to
// check bounds.
// TODO(herb): 4/6/2016 - remove count when code is stable.
virtual void setDestination(void* dst, int count) = 0;
virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0;
};
class SkLinearBitmapPipeline::BlendProcessorInterface
: public SkLinearBitmapPipeline::DestinationInterface {
public:
virtual void VECTORCALL blendPixel(Sk4f pixel0) = 0;
virtual void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline::Stage
template<typename Base, size_t kSize, typename Next>
SkLinearBitmapPipeline::Stage<Base, kSize, Next>::~Stage() {
if (fIsInitialized) {
this->get()->~Base();
}
}
template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Args&& ... args) {
SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
"Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));
new (&fSpace) Variant(next, std::forward<Args>(args)...);
fStageCloner = [this](Next* nextClone, void* addr) {
new (addr) Variant(nextClone, (const Variant&)*this->get());
};
fIsInitialized = true;
};
template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(Args&& ... args) {
SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
"Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));
new (&fSpace) Variant(std::forward<Args>(args)...);
fIsInitialized = true;
};
template<typename Base, size_t kSize, typename Next>
template <typename To, typename From>
To* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::getInterface() {
From* down = static_cast<From*>(this->get());
return static_cast<To*>(down);
}
template<typename Base, size_t kSize, typename Next>
Base* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::cloneStageTo(
Next* next, Stage* cloneToStage) const
{
if (!fIsInitialized) return nullptr;
fStageCloner(next, &cloneToStage->fSpace);
return cloneToStage->get();
}
namespace {
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -101,6 +146,10 @@ public:
: fNext{next}
, fStrategy{std::forward<Args>(args)...}{ }
MatrixStage(Next* next, const MatrixStage& stage)
: fNext{next}
, fStrategy{stage.fStrategy} { }
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
fStrategy.processPoints(&xs, &ys);
fNext->pointListFew(n, xs, ys);
@ -142,7 +191,7 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
const SkMatrix& inverse,
SkLinearBitmapPipeline::MatrixStage* matrixProc) {
if (inverse.hasPerspective()) {
matrixProc->Initialize<PerspectiveMatrix<>>(
matrixProc->initStage<PerspectiveMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()},
@ -150,18 +199,18 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
SkVector{inverse.getPerspX(), inverse.getPerspY()},
inverse.get(SkMatrix::kMPersp2));
} else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
matrixProc->Initialize<AffineMatrix<>>(
matrixProc->initStage<AffineMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()},
SkVector{inverse.getSkewX(), inverse.getSkewY()});
} else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
matrixProc->Initialize<ScaleMatrix<>>(
matrixProc->initStage<ScaleMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()});
} else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) {
matrixProc->Initialize<TranslateMatrix<>>(
matrixProc->initStage<TranslateMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
} else {
@ -182,6 +231,11 @@ public:
, fXStrategy{dimensions.width()}
, fYStrategy{dimensions.height()}{ }
NearestTileStage(Next* next, const NearestTileStage& stage)
: fNext{next}
, fXStrategy{stage.fXStrategy}
, fYStrategy{stage.fYStrategy} { }
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
fXStrategy.tileXPoints(&xs);
fYStrategy.tileYPoints(&ys);
@ -218,11 +272,18 @@ class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter
public:
template <typename... Args>
BilerpTileStage(Next* next, SkISize dimensions)
: fXMax(dimensions.width())
: fNext{next}
, fXMax(dimensions.width())
, fYMax(dimensions.height())
, fNext{next}
, fXStrategy{dimensions.width()}
, fYStrategy{dimensions.height()}{ }
, fYStrategy{dimensions.height()} { }
BilerpTileStage(Next* next, const BilerpTileStage& stage)
: fNext{next}
, fXMax{stage.fXMax}
, fYMax{stage.fYMax}
, fXStrategy{stage.fXStrategy}
, fYStrategy{stage.fYStrategy} { }
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
fXStrategy.tileXPoints(&xs);
@ -339,9 +400,9 @@ private:
}
}
Next* const fNext;
SkScalar fXMax;
SkScalar fYMax;
Next* const fNext;
XStrategy fXStrategy;
YStrategy fYStrategy;
};
@ -351,9 +412,9 @@ void make_tile_stage(
SkFilterQuality filterQuality, SkISize dimensions,
Next* next, SkLinearBitmapPipeline::TileStage* tileStage) {
if (filterQuality == kNone_SkFilterQuality) {
tileStage->Initialize<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
} else {
tileStage->Initialize<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
}
}
template <typename XStrategy>
@ -413,6 +474,9 @@ public:
NearestNeighborSampler(Next* next, Args&&... args)
: fSampler{next, std::forward<Args>(args)...} { }
NearestNeighborSampler(Next* next, const NearestNeighborSampler& sampler)
: fSampler{next, sampler.fSampler} { }
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
fSampler.nearestListFew(n, xs, ys);
}
@ -451,6 +515,9 @@ public:
BilerpSampler(Next* next, Args&&... args)
: fSampler{next, std::forward<Args>(args)...} { }
BilerpSampler(Next* next, const BilerpSampler& sampler)
: fSampler{next, sampler.fSampler} { }
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
fSampler.bilerpListFew(n, xs, ys);
}
@ -554,34 +621,34 @@ private:
uint32_t* fEnd;
};
using Placer = SkLinearBitmapPipeline::PixelPlacerInterface;
using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;
template<template <typename, typename> class Sampler>
static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_base(
Placer* next,
Blender* next,
const SkPixmap& srcPixmap,
SkLinearBitmapPipeline::SampleStage* sampleStage) {
const SkImageInfo& imageInfo = srcPixmap.info();
switch (imageInfo.colorType()) {
case kRGBA_8888_SkColorType:
if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
sampleStage->Initialize<Sampler<Pixel8888SRGB, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<Pixel8888SRGB, Blender>>(next, srcPixmap);
} else {
sampleStage->Initialize<Sampler<Pixel8888LRGB, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<Pixel8888LRGB, Blender>>(next, srcPixmap);
}
break;
case kBGRA_8888_SkColorType:
if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
sampleStage->Initialize<Sampler<Pixel8888SBGR, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<Pixel8888SBGR, Blender>>(next, srcPixmap);
} else {
sampleStage->Initialize<Sampler<Pixel8888LBGR, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<Pixel8888LBGR, Blender>>(next, srcPixmap);
}
break;
case kIndex_8_SkColorType:
if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
sampleStage->Initialize<Sampler<PixelIndex8SRGB, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<PixelIndex8SRGB, Blender>>(next, srcPixmap);
} else {
sampleStage->Initialize<Sampler<PixelIndex8LRGB, Placer>>(next, srcPixmap);
sampleStage->initStage<Sampler<PixelIndex8LRGB, Blender>>(next, srcPixmap);
}
break;
default:
@ -592,10 +659,11 @@ static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba
}
SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
Placer* next,
Blender* next,
SkFilterQuality filterQuality,
const SkPixmap& srcPixmap,
SkLinearBitmapPipeline::SampleStage* sampleStage) {
SkLinearBitmapPipeline::SampleStage* sampleStage)
{
if (filterQuality == kNone_SkFilterQuality) {
return choose_pixel_sampler_base<NearestNeighborSampler>(next, srcPixmap, sampleStage);
} else {
@ -604,25 +672,25 @@ SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Placement Stage
// Pixel Blender Stage
template <SkAlphaType alphaType>
class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface {
class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface {
public:
PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
void VECTORCALL placePixel(Sk4f pixel) override {
SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {}
void VECTORCALL blendPixel(Sk4f pixel) override {
SkASSERT(fDst + 1 <= fEnd );
PlacePixel(fDst, pixel, 0);
SrcPixel(fDst, pixel, 0);
fDst += 1;
}
void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
SkASSERT(fDst + 4 <= fEnd);
SkPM4f* dst = fDst;
PlacePixel(dst, p0, 0);
PlacePixel(dst, p1, 1);
PlacePixel(dst, p2, 2);
PlacePixel(dst, p3, 3);
SrcPixel(dst, p0, 0);
SrcPixel(dst, p1, 1);
SrcPixel(dst, p2, 2);
SrcPixel(dst, p3, 3);
fDst += 4;
}
@ -632,7 +700,7 @@ public:
}
private:
void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) {
void VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) {
Sk4f newPixel = pixel;
if (alphaType == kUnpremul_SkAlphaType) {
newPixel = Premultiply(pixel);
@ -650,21 +718,22 @@ private:
Sk4f fPostAlpha;
};
static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer(
static SkLinearBitmapPipeline::BlendProcessorInterface* choose_blender(
SkAlphaType alphaType,
float postAlpha,
SkLinearBitmapPipeline::PixelStage* placerStage) {
SkLinearBitmapPipeline::BlenderStage* blenderStage) {
if (alphaType == kUnpremul_SkAlphaType) {
placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
blenderStage->initSink<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
} else {
// kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha);
blenderStage->initSink<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha);
}
return placerStage->get();
return blenderStage->get();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline
SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {}
SkLinearBitmapPipeline::SkLinearBitmapPipeline(
@ -699,14 +768,12 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
// As the stages are built, the chooser function may skip a stage. For example, with the
// identity matrix, the matrix stage is skipped, and the tilerStage is the first stage.
auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage);
auto samplerStage = choose_pixel_sampler(placementStage,
filterQuality, srcPixmap, &fSampleStage);
auto tilerStage = choose_tiler(samplerStage,
dimensions, xTile, yTile, filterQuality, dx, &fTiler);
fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage);
fLastStage = placementStage;
auto blenderStage = choose_blender(alphaType, postAlpha, &fBlenderStage);
auto samplerStage = choose_pixel_sampler(blenderStage, filterQuality, srcPixmap, &fSampleStage);
auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile,
filterQuality, dx, &fTileStage);
fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage);
fLastStage = blenderStage;
}
void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {

View File

@ -8,11 +8,9 @@
#ifndef SkLinearBitmapPipeline_DEFINED
#define SkLinearBitmapPipeline_DEFINED
#include "SkColor.h"
#include "SkImageInfo.h"
#include "SkMatrix.h"
#include "SkNx.h"
#include "SkShader.h"
class SkLinearBitmapPipeline {
@ -27,31 +25,33 @@ public:
void shadeSpan4f(int x, int y, SkPM4f* dst, int count);
template<typename Base, size_t kSize>
class PolymorphicUnion {
template<typename Base, size_t kSize, typename Next = void>
class Stage {
public:
PolymorphicUnion() : fIsInitialized{false} {}
~PolymorphicUnion() {
if (fIsInitialized) {
this->get()->~Base();
}
}
Stage() : fIsInitialized{false} {}
~Stage();
template<typename Variant, typename... Args>
void Initialize(Args&&... args) {
SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
"Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));
void initStage(Next* next, Args&& ... args);
new(&fSpace) Variant(std::forward<Args>(args)...);
fIsInitialized = true;
};
template<typename Variant, typename... Args>
void initSink(Args&& ... args);
template <typename To, typename From>
To* getInterface();
// Copy this stage to `cloneToStage` with `next` as its next stage
// (not necessarily the same as our next, you see), returning `cloneToStage`.
// Note: There is no cloneSinkTo method because the code usually places the top part of
// the pipeline on a new sampler.
Base* cloneStageTo(Next* next, Stage* cloneToStage) const;
Base* get() const { return reinterpret_cast<Base*>(&fSpace); }
Base* operator->() const { return this->get(); }
Base& operator*() const { return *(this->get()); }
private:
std::function<void (Next*, void*)> fStageCloner;
struct SK_STRUCT_ALIGN(16) Space {
char space[kSize];
};
@ -61,22 +61,22 @@ public:
class PointProcessorInterface;
class SampleProcessorInterface;
class PixelPlacerInterface;
class BlendProcessorInterface;
class DestinationInterface;
// These values were generated by the assert above in PolymorphicUnion.
using MatrixStage = PolymorphicUnion<PointProcessorInterface, 160>;
using TileStage = PolymorphicUnion<PointProcessorInterface, 160>;
using SampleStage = PolymorphicUnion<SampleProcessorInterface,100>;
using PixelStage = PolymorphicUnion<PixelPlacerInterface, 80>;
// These values were generated by the assert above in Stage::init{Sink|Stage}.
using MatrixStage = Stage<PointProcessorInterface, 160, PointProcessorInterface>;
using TileStage = Stage<PointProcessorInterface, 160, SampleProcessorInterface>;
using SampleStage = Stage<SampleProcessorInterface, 100, BlendProcessorInterface>;
using BlenderStage = Stage<BlendProcessorInterface, 80>;
private:
PointProcessorInterface* fFirstStage;
MatrixStage fMatrixStage;
TileStage fTiler;
SampleStage fSampleStage;
PixelStage fPixelStage;
DestinationInterface* fLastStage;
MatrixStage fMatrixStage;
TileStage fTileStage;
SampleStage fSampleStage;
BlenderStage fBlenderStage;
DestinationInterface* fLastStage;
};
#endif // SkLinearBitmapPipeline_DEFINED

View File

@ -52,22 +52,26 @@ template<typename SourceStrategy, typename Next>
class GeneralSampler {
public:
template<typename... Args>
GeneralSampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&& ... args)
GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&& ... args)
: fNext{next}, fStrategy{std::forward<Args>(args)...} { }
GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next,
const GeneralSampler& sampler)
: fNext{next}, fStrategy{sampler.fStrategy} { }
void VECTORCALL nearestListFew(int n, Sk4s xs, Sk4s ys) {
SkASSERT(0 < n && n < 4);
Sk4f px0, px1, px2;
fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
if (n >= 1) fNext->placePixel(px0);
if (n >= 2) fNext->placePixel(px1);
if (n >= 3) fNext->placePixel(px2);
if (n >= 1) fNext->blendPixel(px0);
if (n >= 2) fNext->blendPixel(px1);
if (n >= 3) fNext->blendPixel(px2);
}
void VECTORCALL nearestList4(Sk4s xs, Sk4s ys) {
Sk4f px0, px1, px2, px3;
fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
fNext->place4Pixels(px0, px1, px2, px3);
fNext->blend4Pixels(px0, px1, px2, px3);
}
void nearestSpan(Span span) {
@ -102,16 +106,16 @@ public:
return this->bilerNonEdgePixel(xs[index], ys[index]);
};
if (n >= 1) fNext->placePixel(bilerpPixel(0));
if (n >= 2) fNext->placePixel(bilerpPixel(1));
if (n >= 3) fNext->placePixel(bilerpPixel(2));
if (n >= 1) fNext->blendPixel(bilerpPixel(0));
if (n >= 2) fNext->blendPixel(bilerpPixel(1));
if (n >= 3) fNext->blendPixel(bilerpPixel(2));
}
void VECTORCALL bilerpList4(Sk4s xs, Sk4s ys) {
auto bilerpPixel = [&](int index) {
return this->bilerNonEdgePixel(xs[index], ys[index]);
};
fNext->place4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bilerpPixel(3));
fNext->blend4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bilerpPixel(3));
}
void VECTORCALL bilerpEdge(Sk4s sampleXs, Sk4s sampleYs) {
@ -120,7 +124,7 @@ public:
Sk4f ys = Sk4f{sampleYs[0]};
fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11);
Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
fNext->placePixel(pixel);
fNext->blendPixel(pixel);
}
void bilerpSpan(Span span) {
@ -191,11 +195,11 @@ private:
Sk4f px1 = getNextPixel();
Sk4f px2 = getNextPixel();
Sk4f px3 = getNextPixel();
next->place4Pixels(px0, px1, px2, px3);
next->blend4Pixels(px0, px1, px2, px3);
count -= 4;
}
while (count > 0) {
next->placePixel(getNextPixel());
next->blendPixel(getNextPixel());
count -= 1;
}
}
@ -214,13 +218,13 @@ private:
while (count >= 4) {
Sk4f px0, px1, px2, px3;
fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3);
next->place4Pixels(px0, px1, px2, px3);
next->blend4Pixels(px0, px1, px2, px3);
ix += 4;
count -= 4;
}
while (count > 0) {
next->placePixel(fStrategy.getPixelAt(row, ix));
next->blendPixel(fStrategy.getPixelAt(row, ix));
ix += 1;
count -= 1;
}
@ -228,13 +232,13 @@ private:
while (count >= 4) {
Sk4f px0, px1, px2, px3;
fStrategy.get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0);
next->place4Pixels(px0, px1, px2, px3);
next->blend4Pixels(px0, px1, px2, px3);
ix -= 4;
count -= 4;
}
while (count > 0) {
next->placePixel(fStrategy.getPixelAt(row, ix));
next->blendPixel(fStrategy.getPixelAt(row, ix));
ix -= 1;
count -= 1;
}
@ -272,11 +276,11 @@ private:
Sk4f filterPixel = pixelY0 * filterY0 + pixelY1 * filterY1;
int count = span.count();
while (count >= 4) {
fNext->place4Pixels(filterPixel, filterPixel, filterPixel, filterPixel);
fNext->blend4Pixels(filterPixel, filterPixel, filterPixel, filterPixel);
count -= 4;
}
while (count > 0) {
fNext->placePixel(filterPixel);
fNext->blendPixel(filterPixel);
count -= 1;
}
}
@ -341,12 +345,12 @@ private:
Sk4f fpixel2 = getNextPixel();
Sk4f fpixel3 = getNextPixel();
fNext->place4Pixels(fpixel0, fpixel1, fpixel2, fpixel3);
fNext->blend4Pixels(fpixel0, fpixel1, fpixel2, fpixel3);
count -= 4;
}
while (count > 0) {
fNext->placePixel(getNextPixel());
fNext->blendPixel(getNextPixel());
count -= 1;
}
@ -416,11 +420,7 @@ private:
Sk4f pxS3 = px30 + px31;
Sk4f px3 = lerp(pxS2, pxS3);
pxB = pxS3;
fNext->place4Pixels(
px0,
px1,
px2,
px3);
fNext->blend4Pixels(px0, px1, px2, px3);
ix0 += 4;
count -= 4;
}
@ -428,7 +428,7 @@ private:
Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix0);
Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix0);
fNext->placePixel(lerp(pixelY0, pixelY1));
fNext->blendPixel(lerp(pixelY0, pixelY1));
ix0 += 1;
count -= 1;
}
@ -448,11 +448,7 @@ private:
Sk4f pxS0 = px00 + px01;
Sk4f px3 = lerp(pxS0, pxS1);
pxB = pxS0;
fNext->place4Pixels(
px0,
px1,
px2,
px3);
fNext->blend4Pixels(px0, px1, px2, px3);
ix0 -= 4;
count -= 4;
}
@ -460,7 +456,7 @@ private:
Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix0);
Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix0);
fNext->placePixel(lerp(pixelY0, pixelY1));
fNext->blendPixel(lerp(pixelY0, pixelY1));
ix0 -= 1;
count -= 1;
}
@ -488,7 +484,7 @@ private:
fStrategy.get4Pixels(rowY0, ix, &px00, &px10, &px20, &px30);
Sk4f px01, px11, px21, px31;
fStrategy.get4Pixels(rowY1, ix, &px01, &px11, &px21, &px31);
fNext->place4Pixels(
fNext->blend4Pixels(
lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21), lerp(&px30, &px31));
ix += 4;
count -= 4;
@ -497,7 +493,7 @@ private:
Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix);
Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix);
fNext->placePixel(lerp(&pixelY0, &pixelY1));
fNext->blendPixel(lerp(&pixelY0, &pixelY1));
ix += 1;
count -= 1;
}
@ -508,7 +504,7 @@ private:
fStrategy.get4Pixels(rowY0, ix - 3, &px30, &px20, &px10, &px00);
Sk4f px01, px11, px21, px31;
fStrategy.get4Pixels(rowY1, ix - 3, &px31, &px21, &px11, &px01);
fNext->place4Pixels(
fNext->blend4Pixels(
lerp(&px00, &px01), lerp(&px10, &px11), lerp(&px20, &px21), lerp(&px30, &px31));
ix -= 4;
count -= 4;
@ -517,7 +513,7 @@ private:
Sk4f pixelY0 = fStrategy.getPixelAt(rowY0, ix);
Sk4f pixelY1 = fStrategy.getPixelAt(rowY1, ix);
fNext->placePixel(lerp(&pixelY0, &pixelY1));
fNext->blendPixel(lerp(&pixelY0, &pixelY1));
ix -= 1;
count -= 1;
}
@ -657,6 +653,15 @@ public:
}
}
PixelIndex8(const PixelIndex8& 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];
}
}
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);

View File

@ -153,7 +153,7 @@ DEF_TEST(Color4f_shader, reporter) {
SkPaint paint;
for (const auto& rec : recs) {
uint32_t storage[300];
uint32_t storage[400];
paint.setShader(rec.fFact());
// Encourage 4f context selection. At some point we may need
// to instantiate two separate contexts for optimal 4b/4f selection.