summaryrefslogtreecommitdiff
path: root/libs/hwui/RenderNode.cpp
diff options
context:
space:
mode:
authorNader Jawad <njawad@google.com>2021-06-09 10:14:43 -0700
committerNader Jawad <njawad@google.com>2021-06-10 23:03:03 -0700
commit6aff4814a73c0b87cd1ab5e92ef9547e4d20042c (patch)
treeb3bd488c6ea0132402ffd7714fe5e733c478de1e /libs/hwui/RenderNode.cpp
parent466698f9afc2b4930544c07776493d4bce915f24 (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.cpp50
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(); });
}