From fca52b7583d1e5f5ff8ed06554875d2a30ef56fa Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 28 Apr 2015 11:45:59 -0700 Subject: Use path intersection instead of saveLayer+mesh to mask projected ripples bug:14297149 SaveLayer's performance cost is high, and proportional to the surface being projected onto. Since ripples (even unbounded ones) are now always projected to the arbitrary background content behind them, this cost is especially important to avoid. This removes the last semi-secret, saveLayer from the projected ripple implementation. Also fixes the HW test app to correctly demonstrate this projection masking behavior. Additionaly, alters PathTessellator to gracefully handle counter-clockwise paths, and simplifies the work done by ShadowTessellator to ensure all of its paths are counterclockwise. Change-Id: Ibe9e12812bd10a774e20b1d444a140c368cbba8c --- libs/hwui/RenderNode.cpp | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) (limited to 'libs/hwui/RenderNode.cpp') diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 9146b6831a9b..c2f72341b1c3 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -768,31 +768,9 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties(); renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY()); - // If the projection reciever has an outline, we mask each of the projected rendernodes to it - // Either with clipRect, or special saveLayer masking - if (projectionReceiverOutline != nullptr) { - const SkRect& outlineBounds = projectionReceiverOutline->getBounds(); - if (projectionReceiverOutline->isRect(nullptr)) { - // mask to the rect outline simply with clipRect - ClipRectOp* clipOp = new (alloc) ClipRectOp( - outlineBounds.left(), outlineBounds.top(), - outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op); - handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds()); - } else { - // wrap the projected RenderNodes with a SaveLayer that will mask to the outline - SaveLayerOp* op = new (alloc) SaveLayerOp( - outlineBounds.left(), outlineBounds.top(), - outlineBounds.right(), outlineBounds.bottom(), - 255, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag | SkCanvas::kARGB_ClipLayer_SaveFlag); - op->setMask(projectionReceiverOutline); - handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); - - /* TODO: add optimizations here to take advantage of placement/size of projected - * children (which may shrink saveLayer area significantly). This is dependent on - * passing actual drawing/dirtying bounds of projected content down to native. - */ - } - } + // If the projection reciever has an outline, we mask projected content to it + // (which we know, apriori, are all tessellated paths) + renderer.setProjectionPathMask(alloc, projectionReceiverOutline); // draw projected nodes for (size_t i = 0; i < mProjectedNodes.size(); i++) { @@ -807,10 +785,8 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& renderer.restoreToCount(restoreTo); } - if (projectionReceiverOutline != nullptr) { - handler(new (alloc) RestoreToCountOp(restoreTo), - PROPERTY_SAVECOUNT, properties().getClipToBounds()); - } + handler(new (alloc) RestoreToCountOp(restoreTo), + PROPERTY_SAVECOUNT, properties().getClipToBounds()); } /** -- cgit v1.2.3-59-g8ed1b