diff options
author | Nader Jawad <njawad@google.com> | 2021-06-09 10:14:43 -0700 |
---|---|---|
committer | Nader Jawad <njawad@google.com> | 2021-06-10 23:03:03 -0700 |
commit | 6aff4814a73c0b87cd1ab5e92ef9547e4d20042c (patch) | |
tree | b3bd488c6ea0132402ffd7714fe5e733c478de1e /libs/hwui/RenderNode.cpp | |
parent | 466698f9afc2b4930544c07776493d4bce915f24 (diff) |
Refactor SkImageFilter usage to cache results.
If an SkImageFilter is used, create an image
snapshot with the filter applied to avoid
re-computing it on each draw invocation
Bug: 188450217
Test: Re-ran CTS tests
Change-Id: Ib790669e14ada9d4ebbfac958d699e2b5242f2d7
Diffstat (limited to 'libs/hwui/RenderNode.cpp')
-rw-r--r-- | libs/hwui/RenderNode.cpp | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 9a9e6d4b77bd..332f7e6f0eac 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -306,11 +306,17 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { info.damageAccumulator->popTransform(); syncProperties(); - const StretchEffect& stagingStretch = - mProperties.layerProperties().getStretchEffect(); + auto& layerProperties = mProperties.layerProperties(); + const StretchEffect& stagingStretch = layerProperties.getStretchEffect(); if (stagingStretch.isEmpty()) { mStretchMask.clear(); } + + if (layerProperties.getImageFilter() == nullptr) { + mSnapshotResult.snapshot = nullptr; + mTargetImageFilter = nullptr; + } + // We could try to be clever and only re-damage if the matrix changed. // However, we don't need to worry about that. The cost of over-damaging // here is only going to be a single additional map rect of this node @@ -321,6 +327,44 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { } } +std::optional<RenderNode::SnapshotResult> RenderNode::updateSnapshotIfRequired( + GrRecordingContext* context, + const SkImageFilter* imageFilter, + const SkIRect& clipBounds +) { + auto* layerSurface = getLayerSurface(); + if (layerSurface == nullptr) { + return std::nullopt; + } + + sk_sp<SkImage> snapshot = layerSurface->makeImageSnapshot(); + const auto subset = SkIRect::MakeWH(properties().getWidth(), + properties().getHeight()); + // If we don't have an ImageFilter just return the snapshot + if (imageFilter == nullptr) { + mSnapshotResult.snapshot = snapshot; + mSnapshotResult.outSubset = subset; + mSnapshotResult.outOffset = SkIPoint::Make(0.0f, 0.0f); + mImageFilterClipBounds = clipBounds; + mTargetImageFilter = nullptr; + } else if (mSnapshotResult.snapshot == nullptr || + imageFilter != mTargetImageFilter.get() || + mImageFilterClipBounds != clipBounds) { + // Otherwise create a new snapshot with the given filter and snapshot + mSnapshotResult.snapshot = + snapshot->makeWithFilter(context, + imageFilter, + subset, + clipBounds, + &mSnapshotResult.outSubset, + &mSnapshotResult.outOffset); + mTargetImageFilter = sk_ref_sp(imageFilter); + mImageFilterClipBounds = clipBounds; + } + + return mSnapshotResult; +} + void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) { // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache @@ -411,6 +455,8 @@ void RenderNode::destroyLayers() { if (hasLayer()) { this->setLayerSurface(nullptr); } + mSnapshotResult.snapshot = nullptr; + mTargetImageFilter = nullptr; if (mDisplayList) { mDisplayList.updateChildren([](RenderNode* child) { child->destroyLayers(); }); } |