Make SkCreateRasterPipelineBlitter() not fail.

Mostly this is about extending the fallback in SkShader::appendStages()
to cover more cases, and making sure subclasses call appendStages() so
they can get the fallback, not onAppendStages() directly.

We still need to watch for SkShader::makeContext() failing in the
fallback itself, so sadly SkShader::appendStages() may still fail.

Change-Id: I2314b234a24bdcecac401a385ce050d7fdf0a83e
Reviewed-on: https://skia-review.googlesource.com/16369
Reviewed-by: Matt Sarett <msarett@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Mike Klein 2017-05-10 12:29:38 -04:00 committed by Skia Commit-Bot
parent 5ac13c2362
commit 44d3279b41
7 changed files with 34 additions and 39 deletions

View File

@ -464,8 +464,8 @@ public:
SK_DEFINE_FLATTENABLE_TYPE(SkShader)
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
bool appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
const SkMatrix& ctm, const SkPaint&) const;
bool appendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM=nullptr) const;
protected:
void flatten(SkWriteBuffer&) const override;
@ -496,10 +496,6 @@ protected:
return nullptr;
}
virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
const SkMatrix&, const SkPaint&,
const SkMatrix* /*local matrix*/) const;
/**
* Returns a shader transformed into a new color space via the |xformer|.
*/
@ -511,6 +507,9 @@ protected:
}
private:
virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
const SkMatrix&, const SkPaint&, const SkMatrix* localM) const;
// This is essentially const, but not officially so it can be modified in constructors.
SkMatrix fLocalMatrix;

View File

@ -849,9 +849,9 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
// By policy we choose not to handle legacy 8888 with SkRasterPipelineBlitter.
if (device.colorSpace() || device.colorType() != kN32_SkColorType) {
if (SkBlitter* blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc)) {
return blitter;
}
auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
SkASSERT(blitter);
return blitter;
}
if (nullptr == shader) {

View File

@ -72,9 +72,8 @@ bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p,
if (localM) {
tmp.setConcat(*localM, this->getLocalMatrix());
}
return fProxyShader->onAppendStages(p, dst, scratch, ctm, paint,
localM ? &tmp : &this->getLocalMatrix());
return fProxyShader->appendStages(p, dst, scratch, ctm, paint,
localM ? &tmp : &this->getLocalMatrix());
}
#ifndef SK_IGNORE_TO_STRING

View File

@ -111,7 +111,8 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
if (shader) {
pipeline->append(SkRasterPipeline::seed_shader, &blitter->fCurrentY);
if (!shader->appendStages(pipeline, dst.colorSpace(), alloc, ctm, paint)) {
return nullptr;
// When a shader fails to append stages, it means it has vetoed drawing entirely.
return alloc->make<SkNullBlitter>();
}
if (!is_opaque) {
pipeline->append(SkRasterPipeline::scale_1_float,

View File

@ -255,22 +255,21 @@ void SkShader::toString(SkString* str) const {
}
#endif
bool SkShader::appendStages(SkRasterPipeline* pipeline,
SkColorSpace* dst,
SkArenaAlloc* scratch,
bool SkShader::appendStages(SkRasterPipeline* p,
SkColorSpace* dstCS,
SkArenaAlloc* alloc,
const SkMatrix& ctm,
const SkPaint& paint) const {
return this->onAppendStages(pipeline, dst, scratch, ctm, paint, nullptr);
}
const SkPaint& paint,
const SkMatrix* localM) const {
SkRasterPipeline subclass;
if (this->onAppendStages(&subclass, dstCS, alloc, ctm, paint, localM)) {
p->extend(subclass);
return true;
}
bool SkShader::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dstCS,
SkArenaAlloc* alloc,
const SkMatrix& ctm,
const SkPaint& paint,
const SkMatrix* localM) const {
// Legacy shaders handle the paint opacity internally,
// but RP applies it as a separate stage.
// SkShader::Context::shadeSpan4f() handles the paint opacity internally,
// but SkRasterPipelineBlitter applies it as a separate stage.
// We skip the internal shadeSpan4f() step by forcing the paint opaque.
SkTCopyOnFirstWrite<SkPaint> opaquePaint(paint);
if (paint.getAlpha() != SK_AlphaOPAQUE) {
opaquePaint.writable()->setAlpha(SK_AlphaOPAQUE);
@ -300,6 +299,15 @@ bool SkShader::onAppendStages(SkRasterPipeline* p,
return false;
}
bool SkShader::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dstCS,
SkArenaAlloc* alloc,
const SkMatrix& ctm,
const SkPaint& paint,
const SkMatrix* localM) const {
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkFlattenable> SkEmptyShader::CreateProc(SkReadBuffer&) {

View File

@ -419,12 +419,3 @@ void SkTwoPointConicalGradient::toString(SkString* str) const {
str->append(")");
}
#endif
bool SkTwoPointConicalGradient::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dstCS,
SkArenaAlloc* alloc,
const SkMatrix& ctm,
const SkPaint& paint,
const SkMatrix* localM) const {
return SkShader::onAppendStages(p, dstCS, alloc, ctm, paint, localM);
}

View File

@ -79,9 +79,6 @@ protected:
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM) const override;
private:
SkPoint fCenter1;
SkPoint fCenter2;