Loading libs/hwui/RenderNode.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "protos/hwui.pb.h" #include "protos/ProtoHelpers.h" #include <SkPathOps.h> #include <algorithm> #include <sstream> #include <string> Loading Loading @@ -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 */ libs/hwui/RenderNode.h +21 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +8 −14 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
libs/hwui/RenderNode.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "protos/hwui.pb.h" #include "protos/ProtoHelpers.h" #include <SkPathOps.h> #include <algorithm> #include <sstream> #include <string> Loading Loading @@ -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 */
libs/hwui/RenderNode.h +21 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { Loading
libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +8 −14 Original line number Diff line number Diff line Loading @@ -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; Loading