1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGRenderEffect.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkMaskFilter.h" 12cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 13cb93a386Sopenharmony_ci#include "src/core/SkMaskFilterBase.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cinamespace sksg { 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cisk_sp<MaskShaderEffect> MaskShaderEffect::Make(sk_sp<RenderNode> child, sk_sp<SkShader> sh) { 18cb93a386Sopenharmony_ci return child ? sk_sp<MaskShaderEffect>(new MaskShaderEffect(std::move(child), std::move(sh))) 19cb93a386Sopenharmony_ci : nullptr; 20cb93a386Sopenharmony_ci} 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciMaskShaderEffect::MaskShaderEffect(sk_sp<RenderNode> child, sk_sp<SkShader> sh) 23cb93a386Sopenharmony_ci : INHERITED(std::move(child)) 24cb93a386Sopenharmony_ci , fShader(std::move(sh)) { 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_civoid MaskShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 28cb93a386Sopenharmony_ci const auto local_ctx = ScopedRenderContext(canvas, ctx) 29cb93a386Sopenharmony_ci .modulateMaskShader(fShader, canvas->getTotalMatrix()); 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci this->INHERITED::onRender(canvas, local_ctx); 32cb93a386Sopenharmony_ci} 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_cisk_sp<ShaderEffect> ShaderEffect::Make(sk_sp<RenderNode> child, sk_sp<Shader> shader) { 35cb93a386Sopenharmony_ci return child ? sk_sp<ShaderEffect>(new ShaderEffect(std::move(child), std::move(shader))) 36cb93a386Sopenharmony_ci : nullptr; 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ciShaderEffect::ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader) 40cb93a386Sopenharmony_ci : INHERITED(std::move(child)) 41cb93a386Sopenharmony_ci , fShader(std::move(shader)) { 42cb93a386Sopenharmony_ci if (fShader) { 43cb93a386Sopenharmony_ci this->observeInval(fShader); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci} 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ciShaderEffect::~ShaderEffect() { 48cb93a386Sopenharmony_ci if (fShader) { 49cb93a386Sopenharmony_ci this->unobserveInval(fShader); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_civoid ShaderEffect::setShader(sk_sp<Shader> sh) { 54cb93a386Sopenharmony_ci if (fShader) { 55cb93a386Sopenharmony_ci this->unobserveInval(fShader); 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci fShader = std::move(sh); 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci if (fShader) { 61cb93a386Sopenharmony_ci this->observeInval(fShader); 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci} 64cb93a386Sopenharmony_ciSkRect ShaderEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { 65cb93a386Sopenharmony_ci if (fShader) { 66cb93a386Sopenharmony_ci fShader->revalidate(ic, ctm); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci return this->INHERITED::onRevalidate(ic, ctm); 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_civoid ShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 73cb93a386Sopenharmony_ci const auto local_ctx = ScopedRenderContext(canvas, ctx) 74cb93a386Sopenharmony_ci .modulateShader(fShader ? fShader->getShader() : nullptr, canvas->getTotalMatrix()); 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci this->INHERITED::onRender(canvas, local_ctx); 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ciShader::Shader() : INHERITED(kBubbleDamage_Trait) {} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciShader::~Shader() = default; 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ciSkRect Shader::onRevalidate(InvalidationController*, const SkMatrix&) { 84cb93a386Sopenharmony_ci SkASSERT(this->hasInval()); 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci fShader = this->onRevalidateShader(); 87cb93a386Sopenharmony_ci return SkRect::MakeEmpty(); 88cb93a386Sopenharmony_ci} 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_cisk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) { 91cb93a386Sopenharmony_ci return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter))) 92cb93a386Sopenharmony_ci : child; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ciImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) 96cb93a386Sopenharmony_ci // filters always override descendent damage 97cb93a386Sopenharmony_ci : INHERITED(std::move(child), kOverrideDamage_Trait) 98cb93a386Sopenharmony_ci , fImageFilter(std::move(filter)) { 99cb93a386Sopenharmony_ci this->observeInval(fImageFilter); 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ciImageFilterEffect::~ImageFilterEffect() { 103cb93a386Sopenharmony_ci this->unobserveInval(fImageFilter); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ciSkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { 107cb93a386Sopenharmony_ci // FIXME: image filter effects should replace the descendents' damage! 108cb93a386Sopenharmony_ci fImageFilter->revalidate(ic, ctm); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci const auto& filter = fImageFilter->getFilter(); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci // Would be nice for this this to stick, but canComputeFastBounds() 113cb93a386Sopenharmony_ci // appears to be conservative (false negatives). 114cb93a386Sopenharmony_ci // SkASSERT(!filter || filter->canComputeFastBounds()); 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci return filter ? filter->computeFastBounds(content_bounds) 119cb93a386Sopenharmony_ci : content_bounds; 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ciconst RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const { 123cb93a386Sopenharmony_ci // TODO: map p through the filter DAG and dispatch to descendants? 124cb93a386Sopenharmony_ci // For now, image filters occlude hit-testing. 125cb93a386Sopenharmony_ci SkASSERT(this->bounds().contains(p.x(), p.y())); 126cb93a386Sopenharmony_ci return this; 127cb93a386Sopenharmony_ci} 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_civoid ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 130cb93a386Sopenharmony_ci // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds. 131cb93a386Sopenharmony_ci const auto filter_ctx = 132cb93a386Sopenharmony_ci ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(), 133cb93a386Sopenharmony_ci canvas->getTotalMatrix(), 134cb93a386Sopenharmony_ci fImageFilter->getFilter()); 135cb93a386Sopenharmony_ci this->INHERITED::onRender(canvas, filter_ctx); 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ciImageFilter::ImageFilter(sk_sp<ImageFilter> input) 139cb93a386Sopenharmony_ci : ImageFilter(input ? std::make_unique<InputsT>(1, std::move(input)) : nullptr) {} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ciImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs) 142cb93a386Sopenharmony_ci : INHERITED(kBubbleDamage_Trait) 143cb93a386Sopenharmony_ci , fInputs(std::move(inputs)) { 144cb93a386Sopenharmony_ci if (fInputs) { 145cb93a386Sopenharmony_ci for (const auto& input : *fInputs) { 146cb93a386Sopenharmony_ci this->observeInval(input); 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ciImageFilter::~ImageFilter() { 152cb93a386Sopenharmony_ci if (fInputs) { 153cb93a386Sopenharmony_ci for (const auto& input : *fInputs) { 154cb93a386Sopenharmony_ci this->unobserveInval(input); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_cisk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const { 160cb93a386Sopenharmony_ci return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr; 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ciSkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) { 164cb93a386Sopenharmony_ci SkASSERT(this->hasInval()); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci fFilter = this->onRevalidateFilter(); 167cb93a386Sopenharmony_ci return SkRect::MakeEmpty(); 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ciExternalImageFilter:: ExternalImageFilter() = default; 171cb93a386Sopenharmony_ciExternalImageFilter::~ExternalImageFilter() = default; 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_cisk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) { 174cb93a386Sopenharmony_ci return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input))); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ciDropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input) 178cb93a386Sopenharmony_ci : INHERITED(std::move(input)) {} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ciDropShadowImageFilter::~DropShadowImageFilter() = default; 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_cisk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() { 183cb93a386Sopenharmony_ci if (fMode == Mode::kShadowOnly) { 184cb93a386Sopenharmony_ci return SkImageFilters::DropShadowOnly(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(), 185cb93a386Sopenharmony_ci fColor, this->refInput(0)); 186cb93a386Sopenharmony_ci } else { 187cb93a386Sopenharmony_ci return SkImageFilters::DropShadow(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(), 188cb93a386Sopenharmony_ci fColor, this->refInput(0)); 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci} 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_cisk_sp<BlurImageFilter> BlurImageFilter::Make(sk_sp<ImageFilter> input) { 193cb93a386Sopenharmony_ci return sk_sp<BlurImageFilter>(new BlurImageFilter(std::move(input))); 194cb93a386Sopenharmony_ci} 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ciBlurImageFilter::BlurImageFilter(sk_sp<ImageFilter> input) 197cb93a386Sopenharmony_ci : INHERITED(std::move(input)) {} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ciBlurImageFilter::~BlurImageFilter() = default; 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_cisk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() { 202cb93a386Sopenharmony_ci return SkImageFilters::Blur(fSigma.x(), fSigma.y(), fTileMode, this->refInput(0)); 203cb93a386Sopenharmony_ci} 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_cisk_sp<BlendModeEffect> BlendModeEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) { 206cb93a386Sopenharmony_ci return child ? sk_sp<BlendModeEffect>(new BlendModeEffect(std::move(child), mode)) 207cb93a386Sopenharmony_ci : nullptr; 208cb93a386Sopenharmony_ci} 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ciBlendModeEffect::BlendModeEffect(sk_sp<RenderNode> child, SkBlendMode mode) 211cb93a386Sopenharmony_ci : INHERITED(std::move(child)) 212cb93a386Sopenharmony_ci , fMode(mode) {} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ciBlendModeEffect::~BlendModeEffect() = default; 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_civoid BlendModeEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 217cb93a386Sopenharmony_ci const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlendMode(fMode); 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci this->INHERITED::onRender(canvas, local_ctx); 220cb93a386Sopenharmony_ci} 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ciconst RenderNode* BlendModeEffect::onNodeAt(const SkPoint& p) const { 223cb93a386Sopenharmony_ci // TODO: we likely need to do something more sophisticated than delegate to descendants here. 224cb93a386Sopenharmony_ci return this->INHERITED::onNodeAt(p); 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_cisk_sp<LayerEffect> LayerEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) { 228cb93a386Sopenharmony_ci return child ? sk_sp<LayerEffect>(new LayerEffect(std::move(child), mode)) 229cb93a386Sopenharmony_ci : nullptr; 230cb93a386Sopenharmony_ci} 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ciLayerEffect::LayerEffect(sk_sp<RenderNode> child, SkBlendMode mode) 233cb93a386Sopenharmony_ci : INHERITED(std::move(child)) 234cb93a386Sopenharmony_ci , fMode(mode) {} 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ciLayerEffect::~LayerEffect() = default; 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_civoid LayerEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { 239cb93a386Sopenharmony_ci SkAutoCanvasRestore acr(canvas, false); 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci // Commit any potential pending paint effects to their own layer. 242cb93a386Sopenharmony_ci const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(), 243cb93a386Sopenharmony_ci canvas->getTotalMatrix(), 244cb93a386Sopenharmony_ci true); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci SkPaint layer_paint; 247cb93a386Sopenharmony_ci if (ctx) { 248cb93a386Sopenharmony_ci // Apply all optional context overrides upfront. 249cb93a386Sopenharmony_ci ctx->modulatePaint(canvas->getTotalMatrix(), &layer_paint); 250cb93a386Sopenharmony_ci } 251cb93a386Sopenharmony_ci layer_paint.setBlendMode(fMode); 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci canvas->saveLayer(nullptr, &layer_paint); 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_ci this->INHERITED::onRender(canvas, nullptr); 256cb93a386Sopenharmony_ci} 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci} // namespace sksg 259