Avoid performing the pathOp for clipped shadows if possible.
Bug: 64487466 Test: SystemUiJankTests#testRecentAppsFling Change-Id: I2ca96bd6adba299cd31e12f005b2529c559740d2
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "protos/hwui.pb.h"
|
||||
#include "protos/ProtoHelpers.h"
|
||||
|
||||
#include <SkPathOps.h>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -555,5 +556,23 @@ void RenderNode::computeOrderingImpl(
|
||||
}
|
||||
}
|
||||
|
||||
const SkPath* RenderNode::getClippedOutline(const SkRect& clipRect) const {
|
||||
const SkPath* outlinePath = properties().getOutline().getPath();
|
||||
const uint32_t outlineID = outlinePath->getGenerationID();
|
||||
|
||||
if (outlineID != mClippedOutlineCache.outlineID || clipRect != mClippedOutlineCache.clipRect) {
|
||||
// update the cache keys
|
||||
mClippedOutlineCache.outlineID = outlineID;
|
||||
mClippedOutlineCache.clipRect = clipRect;
|
||||
|
||||
// update the cache value by recomputing a new path
|
||||
SkPath clipPath;
|
||||
clipPath.addRect(clipRect);
|
||||
Op(*outlinePath, clipPath, kIntersect_SkPathOp, &mClippedOutlineCache.clippedOutline);
|
||||
|
||||
}
|
||||
return &mClippedOutlineCache.clippedOutline;
|
||||
}
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
@@ -365,6 +365,17 @@ public:
|
||||
return mSkiaLayer.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path that represents the outline of RenderNode intersected with
|
||||
* the provided rect. This call will internally cache the resulting path in
|
||||
* order to potentially return that path for subsequent calls to this method.
|
||||
* By reusing the same path we get better performance on the GPU backends since
|
||||
* those resources are cached in the hardware based on the path's genID.
|
||||
*
|
||||
* The returned path is only guaranteed to be valid until this function is called
|
||||
* again or the RenderNode's outline is mutated.
|
||||
*/
|
||||
const SkPath* getClippedOutline(const SkRect& clipRect) const;
|
||||
private:
|
||||
/**
|
||||
* If this RenderNode has been used in a previous frame then the SkiaDisplayList
|
||||
@@ -380,6 +391,16 @@ private:
|
||||
* when it has been set to draw as a LayerType::RenderLayer.
|
||||
*/
|
||||
std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
|
||||
|
||||
struct ClippedOutlineCache {
|
||||
// keys
|
||||
uint32_t outlineID = 0;
|
||||
SkRect clipRect;
|
||||
|
||||
// value
|
||||
SkPath clippedOutline;
|
||||
};
|
||||
mutable ClippedOutlineCache mClippedOutlineCache;
|
||||
}; // class RenderNode
|
||||
|
||||
class MarkAndSweepRemoved : public TreeObserver {
|
||||
|
||||
@@ -163,28 +163,22 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
|
||||
hwuiMatrix.copyTo(shadowMatrix);
|
||||
canvas->concat(shadowMatrix);
|
||||
|
||||
const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
|
||||
// holds temporary SkPath to store the result of intersections
|
||||
SkPath tmpPath;
|
||||
const SkPath* casterPath = casterOutlinePath;
|
||||
// default the shadow-casting path to the outline of the caster
|
||||
const SkPath* casterPath = casterProperties.getOutline().getPath();
|
||||
|
||||
// intersect the shadow-casting path with the clipBounds, if present
|
||||
if (clippedToBounds && !casterClipRect.contains(casterPath->getBounds())) {
|
||||
casterPath = caster->getRenderNode()->getClippedOutline(casterClipRect);
|
||||
}
|
||||
|
||||
// TODO: In to following course of code that calculates the final shape, is there an optimal
|
||||
// of doing the Op calculations?
|
||||
// intersect the shadow-casting path with the reveal, if present
|
||||
SkPath tmpPath; // holds temporary SkPath to store the result of intersections
|
||||
if (revealClipPath) {
|
||||
Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, &tmpPath);
|
||||
tmpPath.setIsVolatile(true);
|
||||
casterPath = &tmpPath;
|
||||
}
|
||||
|
||||
// intersect the shadow-casting path with the clipBounds, if present
|
||||
if (clippedToBounds) {
|
||||
SkPath clipBoundsPath;
|
||||
clipBoundsPath.addRect(casterClipRect);
|
||||
Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
|
||||
tmpPath.setIsVolatile(true);
|
||||
casterPath = &tmpPath;
|
||||
}
|
||||
const Vector3 lightPos = SkiaPipeline::getLightCenter();
|
||||
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
|
||||
SkPoint3 zParams;
|
||||
|
||||
Reference in New Issue
Block a user