aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkBlitter.cpp
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-04-04 13:46:35 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-04 18:13:48 +0000
commitaf2769d00b70ca456452e4e88bdf5abecd320f68 (patch)
tree83fef5b2e2a4d66ec9de911cfc33fdc2d5ffe6dd /src/core/SkBlitter.cpp
parentbf74a460814a7912ed3d2e1af000afd2c45cd318 (diff)
Banish SkShaderBase::isRasterPipelineOnly()
Keeping related heuristics in sync with actual shader capabilities is somewhat tricky, and overall fragile. So how about this: instead of an explicit opt-in mechanism, try to instantiate a legacy shader context and fall back to raster pipeline on failure (null Context => implicit opt-in for raster pipeline). Shaders can still choose not to draw by returning both a null Context and failing appendStages(). BUG=skia:7772 Change-Id: I2e76f51af7064853a6cb851b4c30c82eba3ee828 Reviewed-on: https://skia-review.googlesource.com/118383 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkBlitter.cpp')
-rw-r--r--src/core/SkBlitter.cpp72
1 files changed, 38 insertions, 34 deletions
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 29294a989b..edd3da25e8 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -914,10 +914,6 @@ bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint&
if (matrix.hasPerspective()) {
return true;
}
- // ... or unless the shader is raster pipeline-only.
- if (paint.getShader() && as_SB(paint.getShader())->isRasterPipelineOnly(matrix)) {
- return true;
- }
// Added support only for shaders (and other constraints) for android
if (device.colorType() == kRGB_565_SkColorType) {
@@ -947,22 +943,25 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
SkBlendMode mode = origPaint.getBlendMode();
sk_sp<Sk3DShader> shader3D;
- SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
+ // We're going to tweak the original paint in two ways:
+ // 1) tweaks to `commonPaint` affect both raster pipeline and legacy pipeline
+ // 2) (later) tweaks to `legacyPaint` affect only legacy pipeline
+ SkTCopyOnFirstWrite<SkPaint> commonPaint(origPaint);
if (origPaint.getMaskFilter() != nullptr &&
as_MFB(origPaint.getMaskFilter())->getFormat() == SkMask::k3D_Format) {
shader3D = sk_make_sp<Sk3DShader>(sk_ref_sp(shader));
// we know we haven't initialized lazyPaint yet, so just do it
- paint.writable()->setShader(shader3D);
+ commonPaint.writable()->setShader(shader3D);
shader = as_SB(shader3D.get());
}
if (mode != SkBlendMode::kSrcOver) {
bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
- switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
+ switch (SkInterpretXfermode(*commonPaint, deviceIsOpaque)) {
case kSrcOver_SkXfermodeInterpretation:
mode = SkBlendMode::kSrcOver;
- paint.writable()->setBlendMode(mode);
+ commonPaint.writable()->setBlendMode(mode);
break;
case kSkipDrawing_SkXfermodeInterpretation:{
return alloc->make<SkNullBlitter>();
@@ -978,7 +977,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
* will fall into our optimizations for SRC mode.
*/
if (mode == SkBlendMode::kClear) {
- SkPaint* p = paint.writable();
+ SkPaint* p = commonPaint.writable();
p->setShader(nullptr);
shader = nullptr;
p->setColorFilter(nullptr);
@@ -989,32 +988,35 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
if (kAlpha_8_SkColorType == device.colorType() && drawCoverage) {
SkASSERT(nullptr == shader);
- SkASSERT(paint->isSrcOver());
- return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
+ SkASSERT(commonPaint->isSrcOver());
+ return alloc->make<SkA8_Coverage_Blitter>(device, *commonPaint);
}
- if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) {
+ if (commonPaint->isDither() && !SkPaintPriv::ShouldDither(*commonPaint, device.colorType())) {
// Disable dithering when not needed.
- paint.writable()->setDither(false);
+ commonPaint.writable()->setDither(false);
}
- if (UseRasterPipelineBlitter(device, *paint, matrix)) {
- auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
+ if (UseRasterPipelineBlitter(device, *commonPaint, matrix)) {
+ auto blitter = SkCreateRasterPipelineBlitter(device, *commonPaint, matrix, alloc);
SkASSERT(blitter);
return blitter;
}
+ // Used for the legacy pipeline.
+ SkTCopyOnFirstWrite<SkPaint> legacyPaint(*commonPaint);
+
if (nullptr == shader) {
if (mode != SkBlendMode::kSrcOver) {
// xfermodes (and filters) require shaders for our current blitters
- paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor()));
- paint.writable()->setAlpha(0xFF);
- shader = as_SB(paint->getShader());
+ legacyPaint.writable()->setShader(SkShader::MakeColorShader(legacyPaint->getColor()));
+ legacyPaint.writable()->setAlpha(0xFF);
+ shader = as_SB(legacyPaint->getShader());
} else if (cf) {
// if no shader && no xfermode, we just apply the colorfilter to
// our color and move on.
- SkPaint* writablePaint = paint.writable();
- writablePaint->setColor(cf->filterColor(paint->getColor()));
+ SkPaint* writablePaint = legacyPaint.writable();
+ writablePaint->setColor(cf->filterColor(legacyPaint->getColor()));
writablePaint->setColorFilter(nullptr);
cf = nullptr;
}
@@ -1022,8 +1024,8 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
if (cf) {
SkASSERT(shader);
- paint.writable()->setShader(shader->makeWithColorFilter(sk_ref_sp(cf)));
- shader = as_SB(paint->getShader());
+ legacyPaint.writable()->setShader(shader->makeWithColorFilter(sk_ref_sp(cf)));
+ shader = as_SB(legacyPaint->getShader());
// blitters should ignore the presence/absence of a filter, since
// if there is one, the shader will take care of it.
}
@@ -1033,15 +1035,17 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
*/
SkShaderBase::Context* shaderContext = nullptr;
if (shader) {
- const SkShaderBase::ContextRec rec(*paint, matrix, nullptr,
+ const SkShaderBase::ContextRec rec(*legacyPaint, matrix, nullptr,
PreferredShaderDest(device.info()),
device.colorSpace());
// Try to create the ShaderContext
shaderContext = shader->makeContext(rec, alloc);
if (!shaderContext) {
- return alloc->make<SkNullBlitter>();
+ // Fall back to raster pipeline.
+ auto blitter = SkCreateRasterPipelineBlitter(device, *commonPaint, matrix, alloc);
+ SkASSERT(blitter);
+ return blitter;
}
- SkASSERT(shaderContext);
}
SkBlitter* blitter = nullptr;
@@ -1051,20 +1055,20 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
SkASSERT(!device.colorSpace());
if (shader) {
- blitter = alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext);
- } else if (paint->getColor() == SK_ColorBLACK) {
- blitter = alloc->make<SkARGB32_Black_Blitter>(device, *paint);
- } else if (paint->getAlpha() == 0xFF) {
- blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
+ blitter = alloc->make<SkARGB32_Shader_Blitter>(device, *legacyPaint, shaderContext);
+ } else if (legacyPaint->getColor() == SK_ColorBLACK) {
+ blitter = alloc->make<SkARGB32_Black_Blitter>(device, *legacyPaint);
+ } else if (legacyPaint->getAlpha() == 0xFF) {
+ blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *legacyPaint);
} else {
- blitter = alloc->make<SkARGB32_Blitter>(device, *paint);
+ blitter = alloc->make<SkARGB32_Blitter>(device, *legacyPaint);
}
break;
case kRGB_565_SkColorType:
- if (shader && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
- blitter = alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
+ if (shader && SkRGB565_Shader_Blitter::Supports(device, *legacyPaint)) {
+ blitter = alloc->make<SkRGB565_Shader_Blitter>(device, *legacyPaint, shaderContext);
} else {
- blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc);
+ blitter = SkCreateRasterPipelineBlitter(device, *legacyPaint, matrix, alloc);
}
break;