skrpb: evaluate color filters for constant shaders once.
The simplest thing to do here is just run shader+color filter pipeline at
construction time to create a new constant color shader (replacing the paint
color).
This reduces a pipeline like:
- constant_color (paint color)
- matrix_4x5
- clamp_a
- load_d_foo, xfermode, lerp, store_foo
to
- constant_color (paint color -> matrix_4x5 -> clamp_a)
- load_d_foo, xfermode, lerp, store_foo
To implement this all, we add a new store_f32 stage that writes SkPM4f, and
finally get around to implementing Sk8f::Store4() (store while reinterlacing).
Sk4f::Store4() already exists for both SSE and NEON.
Next step: reduce simple constant_color -> store pipelines (src mode, full
coverage) into non-pipeline memsets.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2480823002
Review-Url: https://codereview.chromium.org/2480823002
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 31c188e..8f9922d 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -20,12 +20,8 @@
public:
static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocator*);
- SkRasterPipelineBlitter(SkPixmap dst,
- SkRasterPipeline shader,
- SkBlendMode blend,
- SkPM4f paintColor)
+ SkRasterPipelineBlitter(SkPixmap dst, SkBlendMode blend, SkPM4f paintColor)
: fDst(dst)
- , fShader(shader)
, fBlend(blend)
, fPaintColor(paintColor)
{}
@@ -45,9 +41,9 @@
void maybe_clamp (SkRasterPipeline*) const;
SkPixmap fDst;
- SkRasterPipeline fShader;
SkBlendMode fBlend;
SkPM4f fPaintColor;
+ SkRasterPipeline fShader;
// These functions are compiled lazily when first used.
std::function<void(size_t, size_t)> fBlitH = nullptr,
@@ -84,53 +80,70 @@
return !effect || effect->appendStages(pipeline);
}
+static SkPM4f paint_color(const SkPixmap& dst, const SkPaint& paint) {
+ auto paintColor = paint.getColor();
+ SkColor4f color;
+ if (dst.info().colorSpace()) {
+ color = SkColor4f::FromColor(paintColor);
+ // TODO: transform from sRGB to dst gamut.
+ } else {
+ swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store(&color);
+ }
+ return color.premul();
+}
SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
const SkPaint& paint,
SkTBlitterAllocator* alloc) {
- if (!supported(dst.info())) {
+ auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst,
+ paint.getBlendMode(),
+ paint_color(dst, paint));
+ SkBlendMode* blend = &blitter->fBlend;
+ SkPM4f* paintColor = &blitter->fPaintColor;
+ SkRasterPipeline* pipeline = &blitter->fShader;
+
+ SkShader* shader = paint.getShader();
+ SkColorFilter* colorFilter = paint.getColorFilter();
+
+ // TODO: all temporary
+ if (!supported(dst.info()) || shader || !SkBlendMode_AppendStages(*blend)) {
+ alloc->freeLast();
return nullptr;
}
- if (paint.getShader()) {
- return nullptr; // TODO: need to work out how shaders and their contexts work
- }
- SkBlendMode blend = paint.getBlendMode();
- if (!SkBlendMode_AppendStages(blend)) {
- return nullptr; // TODO
+
+ bool is_opaque, is_constant;
+ if (shader) {
+ is_opaque = shader->isOpaque();
+ is_constant = false; // TODO: shader->isConstant()
+ // TODO: append shader stages, of course!
+ } else {
+ is_opaque = paintColor->a() == 1.0f;
+ is_constant = true;
+ pipeline->append(SkRasterPipeline::constant_color, paintColor);
}
- uint32_t paintColor = paint.getColor();
- bool shaderIsOpaque = (paintColor >> 24) == 0xff;
-
- SkRasterPipeline shader, colorFilter;
- if (auto s = paint.getShader()) {
- shaderIsOpaque = s->isOpaque();
- }
- if (auto cf = paint.getColorFilter()) {
- if (!cf->appendStages(&colorFilter, shaderIsOpaque)) {
+ if (colorFilter) {
+ if (!colorFilter->appendStages(pipeline, is_opaque)) {
+ alloc->freeLast();
return nullptr;
}
- shaderIsOpaque = shaderIsOpaque && (cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
+ is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
}
- if (shaderIsOpaque && blend == SkBlendMode::kSrcOver) {
- blend = SkBlendMode::kSrc;
+ if (is_constant) {
+ pipeline->append(SkRasterPipeline::store_f32, &paintColor);
+ pipeline->compile()(0,1);
+
+ *pipeline = SkRasterPipeline();
+ pipeline->append(SkRasterPipeline::constant_color, paintColor);
+
+ is_opaque = paintColor->a() == 1.0f;
}
- SkColor4f color;
- if (dst.info().colorSpace()) {
- color = SkColor4f::FromColor(paintColor);
- } else {
- swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store(&color);
+ if (is_opaque && *blend == SkBlendMode::kSrcOver) {
+ *blend = SkBlendMode::kSrc;
}
- auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst, shader, blend, color.premul());
-
- if (!paint.getShader()) {
- blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor);
- }
- blitter->fShader.extend(colorFilter);
-
return blitter;
}