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>
This commit is contained in:
Mike Klein 2016-11-12 10:29:26 -05:00 committed by Skia Commit-Bot
parent 7f6cd90f0c
commit b0d10e05f1
5 changed files with 66 additions and 11 deletions

View File

@ -18,9 +18,11 @@
class SkColorFilter;
class SkColorSpace;
class SkFallbackAlloc;
class SkImage;
class SkPath;
class SkPicture;
class SkRasterPipeline;
class GrContext;
class GrFragmentProcessor;
@ -97,6 +99,12 @@ public:
*/
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.
*/
@ -399,7 +407,7 @@ public:
//////////////////////////////////////////////////////////////////////////
// Factory methods for stock shaders
/**
* Call this to create a new "empty" shader, that will not draw anything.
*/
@ -467,6 +475,8 @@ public:
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 @@ protected:
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.

View File

@ -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 SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& inf
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;
}

View File

@ -25,6 +25,7 @@ public:
explicit SkColorShader(SkColor c);
bool isOpaque() const override;
bool isConstant() const override { return true; }
class ColorShaderContext : public SkShader::Context {
public:
@ -64,6 +65,7 @@ protected:
*lum = fColor;
return true;
}
bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkFallbackAlloc*) const override;
private:
SkColor fColor;
@ -78,6 +80,7 @@ public:
bool isOpaque() const override {
return SkColorGetA(fCachedByteColor) == 255;
}
bool isConstant() const override { return true; }
class Color4Context : public SkShader::Context {
public:
@ -117,12 +120,13 @@ protected:
*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;
};

View File

@ -106,19 +106,20 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
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) {

View File

@ -257,6 +257,12 @@ void SkShader::toString(SkString* str) const {
}
#endif
bool SkShader::appendStages(SkRasterPipeline* pipeline,
SkColorSpace* dst,
SkFallbackAlloc* scratch) const {
return this->onAppendStages(pipeline, dst, scratch);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {