Start hooking shaders into SkRasterPipelineBlitter.
Here first just the simplest, constant-color shaders.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4743
Change-Id: I92c6523660e21a1e2aa353524570230282ba5dfe
Reviewed-on: https://skia-review.googlesource.com/4743
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 5e21c28..48e8419 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -18,9 +18,11 @@
class SkColorFilter;
class SkColorSpace;
+class SkFallbackAlloc;
class SkImage;
class SkPath;
class SkPicture;
+class SkRasterPipeline;
class GrContext;
class GrFragmentProcessor;
@@ -98,6 +100,12 @@
virtual bool isOpaque() const { return false; }
/**
+ * Returns true if the shader is guaranteed to produce only a single color.
+ * Subclasses can override this to allow loop-hoisting optimization.
+ */
+ virtual bool isConstant() const { return false; }
+
+ /**
* ContextRec acts as a parameter bundle for creating Contexts.
*/
struct ContextRec {
@@ -399,7 +407,7 @@
//////////////////////////////////////////////////////////////////////////
// Factory methods for stock shaders
-
+
/**
* Call this to create a new "empty" shader, that will not draw anything.
*/
@@ -467,6 +475,8 @@
SK_DEFINE_FLATTENABLE_TYPE(SkShader)
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+ bool appendStages(SkRasterPipeline*, SkColorSpace*, SkFallbackAlloc*) const;
+
protected:
void flatten(SkWriteBuffer&) const override;
@@ -498,6 +508,10 @@
return nullptr;
}
+ virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkFallbackAlloc*) const {
+ return false;
+ }
+
private:
// This is essentially const, but not officially so it can be modified in
// constructors.
diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp
index aa7adaf..a761d60 100644
--- a/src/core/SkColorShader.cpp
+++ b/src/core/SkColorShader.cpp
@@ -7,6 +7,9 @@
#include "SkColorShader.h"
#include "SkColorSpace.h"
+#include "SkFixedAlloc.h"
+#include "SkPM4fPriv.h"
+#include "SkRasterPipeline.h"
#include "SkReadBuffer.h"
#include "SkUtils.h"
@@ -305,3 +308,30 @@
bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) {
return choose_blitprocs(&fPM4f, info, state);
}
+
+// To shade a constant color:
+// 1) move the paint color to dst registers
+// 2) load the constant color into the src registers
+// 3) srcin, s' = s*da, modulating the src color by the paint alpha.
+
+bool SkColorShader::onAppendStages(SkRasterPipeline* p,
+ SkColorSpace* dst,
+ SkFallbackAlloc* scratch) const {
+ auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst));
+ p->append(SkRasterPipeline::move_src_dst);
+ p->append(SkRasterPipeline::constant_color, color);
+ // TODO: sRGB -> dst gamut correction if needed
+ p->append(SkRasterPipeline::srcin);
+ return true;
+}
+
+bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
+ SkColorSpace* dst,
+ SkFallbackAlloc* scratch) const {
+ auto color = scratch->make<SkPM4f>(fColor4.premul());
+ p->append(SkRasterPipeline::move_src_dst);
+ p->append(SkRasterPipeline::constant_color, color);
+ // TODO: fColorSpace -> dst gamut correction if needed
+ p->append(SkRasterPipeline::srcin);
+ return true;
+}
diff --git a/src/core/SkColorShader.h b/src/core/SkColorShader.h
index 0bd2702..9aee365 100644
--- a/src/core/SkColorShader.h
+++ b/src/core/SkColorShader.h
@@ -25,6 +25,7 @@
explicit SkColorShader(SkColor c);
bool isOpaque() const override;
+ bool isConstant() const override { return true; }
class ColorShaderContext : public SkShader::Context {
public:
@@ -64,6 +65,7 @@
*lum = fColor;
return true;
}
+ bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkFallbackAlloc*) const override;
private:
SkColor fColor;
@@ -78,6 +80,7 @@
bool isOpaque() const override {
return SkColorGetA(fCachedByteColor) == 255;
}
+ bool isConstant() const override { return true; }
class Color4Context : public SkShader::Context {
public:
@@ -117,12 +120,13 @@
*lum = fCachedByteColor;
return true;
}
+ bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkFallbackAlloc*) const override;
private:
sk_sp<SkColorSpace> fColorSpace;
const SkColor4f fColor4;
const SkColor fCachedByteColor;
-
+
typedef SkShader INHERITED;
};
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index d382eba..2cd84f0 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -106,19 +106,20 @@
SkColorFilter* colorFilter = paint.getColorFilter();
// TODO: all temporary
- if (!supported(dst.info()) || shader || !SkBlendMode_AppendStages(*blend)) {
+ if (!supported(dst.info()) || !SkBlendMode_AppendStages(*blend)) {
return earlyOut();
}
- bool is_opaque, is_constant;
+ bool is_opaque = paintColor->a() == 1.0f,
+ is_constant = true;
+ pipeline->append(SkRasterPipeline::constant_color, paintColor);
+
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);
+ is_opaque = is_opaque && shader->isOpaque();
+ is_constant = shader->isConstant();
+ if (!shader->appendStages(pipeline, dst.colorSpace(), &blitter->fScratchFallback)) {
+ return earlyOut();
+ }
}
if (colorFilter) {
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index c452d07..c232cf7 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -257,6 +257,12 @@
}
#endif
+bool SkShader::appendStages(SkRasterPipeline* pipeline,
+ SkColorSpace* dst,
+ SkFallbackAlloc* scratch) const {
+ return this->onAppendStages(pipeline, dst, scratch);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {