diff options
author | Chris Craik <ccraik@google.com> | 2015-06-12 22:46:19 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-12 22:46:21 +0000 |
commit | 4c9dafbfecf00ba3dca0c5de61d889676bfdc7af (patch) | |
tree | 263d7d69e9728c60441e202abc338746088caf06 /libs/hwui | |
parent | 1a3048f3677680823b52d3b0d538917d08da8495 (diff) | |
parent | a766cb2bce5db9108c0266fbebea6aa18d5713ff (diff) | |
download | frameworks_base-4c9dafbfecf00ba3dca0c5de61d889676bfdc7af.zip frameworks_base-4c9dafbfecf00ba3dca0c5de61d889676bfdc7af.tar.gz frameworks_base-4c9dafbfecf00ba3dca0c5de61d889676bfdc7af.tar.bz2 |
Merge "Put WebViews with on a HW layer if stencil/shader clipping is needed" into mnc-dev
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/CanvasState.h | 5 | ||||
-rw-r--r-- | libs/hwui/DisplayListCanvas.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 17 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 30 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 4 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.h | 40 |
6 files changed, 85 insertions, 19 deletions
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h index 9354e94..b35db28 100644 --- a/libs/hwui/CanvasState.h +++ b/libs/hwui/CanvasState.h @@ -155,8 +155,9 @@ public: inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); } int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); } int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); } - int getWidth() { return mWidth; } - int getHeight() { return mHeight; } + int getWidth() const { return mWidth; } + int getHeight() const { return mHeight; } + bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); } inline const Snapshot* currentSnapshot() const { return mSnapshot != nullptr ? mSnapshot.get() : mFirstSnapshot.get(); diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index 900a621..843c412 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -203,10 +203,10 @@ bool DisplayListCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { void DisplayListCanvas::drawRenderNode(RenderNode* renderNode) { LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode"); - - // dirty is an out parameter and should not be recorded, - // it matters only when replaying the display list - DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, *mState.currentTransform()); + DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp( + renderNode, + *mState.currentTransform(), + mState.clipIsSimple()); addRenderNodeOp(op); } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index e9d6ebc..fb2852a 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1398,9 +1398,10 @@ class DrawRenderNodeOp : public DrawBoundedOp { friend class RenderNode; // grant RenderNode access to info of child friend class DisplayListData; // grant DisplayListData access to info of child public: - DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent) + DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple) : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr) , mRenderNode(renderNode) + , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple()) , mTransformFromParent(transformFromParent) , mSkipInOrderDraw(false) {} @@ -1436,6 +1437,20 @@ public: private: RenderNode* mRenderNode; + /** + * This RenderNode was drawn into a DisplayList with the canvas in a state that will likely + * require rendering with stencil clipping. Either: + * + * 1) A path clip or rotated rect clip was in effect on the canvas at record time + * 2) The RenderNode was recorded with a non-simple canvas transform (e.g. rotation) + * + * Note: even if this is false, non-rect clipping may still be applied applied either due to + * property-driven rotation (either in this RenderNode, or any ancestor), or record time + * clipping in an ancestor. These are handled in RenderNode::prepareTreeImpl since they are + * dynamic (relative to a static DisplayList of a parent), and don't affect this flag. + */ + bool mRecordedWithPotentialStencilClip; + /////////////////////////// // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations() /////////////////////////// diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 75e700a..b4cbc36 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -120,7 +120,10 @@ void RenderNode::prepareTree(TreeInfo& info) { ATRACE_CALL(); LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing"); - prepareTreeImpl(info); + // Functors don't correctly handle stencil usage of overdraw debugging - shove 'em in a layer. + bool functorsNeedLayer = Properties::debugOverdraw; + + prepareTreeImpl(info, functorsNeedLayer); } void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) { @@ -219,7 +222,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { } } -void RenderNode::prepareTreeImpl(TreeInfo& info) { +/** + * Traverse down the the draw tree to prepare for a frame. + * + * MODE_FULL = UI Thread-driven (thus properties must be synced), otherwise RT driven + * + * While traversing down the tree, functorsNeedLayer flag is set to true if anything that uses the + * stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer. + */ +void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) { info.damageAccumulator->pushTransform(this); if (info.mode == TreeInfo::MODE_FULL) { @@ -229,11 +240,17 @@ void RenderNode::prepareTreeImpl(TreeInfo& info) { if (CC_LIKELY(info.runAnimations)) { animatorDirtyMask = mAnimatorManager.animate(info); } + + bool willHaveFunctor = info.mode == TreeInfo::MODE_FULL && mStagingDisplayListData + ? !mStagingDisplayListData->functors.isEmpty() : !mDisplayListData->functors.isEmpty(); + bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence( + willHaveFunctor, functorsNeedLayer); + prepareLayer(info, animatorDirtyMask); if (info.mode == TreeInfo::MODE_FULL) { pushStagingDisplayListChanges(info); } - prepareSubTree(info, mDisplayListData); + prepareSubTree(info, childFunctorsNeedLayer, mDisplayListData); pushLayerUpdate(info); info.damageAccumulator->popTransform(); @@ -313,7 +330,7 @@ void RenderNode::deleteDisplayListData() { mDisplayListData = nullptr; } -void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { +void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayListData* subtree) { if (subtree) { TextureCache& cache = Caches::getInstance().textureCache; info.out.hasFunctors |= subtree->functors.size(); @@ -324,7 +341,10 @@ void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) { DrawRenderNodeOp* op = subtree->children()[i]; RenderNode* childNode = op->mRenderNode; info.damageAccumulator->pushTransform(&op->mTransformFromParent); - childNode->prepareTreeImpl(info); + bool childFunctorsNeedLayer = functorsNeedLayer + // Recorded with non-rect clip, or canvas-rotated by parent + || op->mRecordedWithPotentialStencilClip; + childNode->prepareTreeImpl(info, childFunctorsNeedLayer); info.damageAccumulator->popTransform(); } } diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index d0d81d9..025a4a4 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -235,10 +235,10 @@ private: const char* mText; }; - void prepareTreeImpl(TreeInfo& info); + void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer); void pushStagingPropertiesChanges(TreeInfo& info); void pushStagingDisplayListChanges(TreeInfo& info); - void prepareSubTree(TreeInfo& info, DisplayListData* subtree); + void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayListData* subtree); void applyLayerPropertiesToLayer(TreeInfo& info); void prepareLayer(TreeInfo& info, uint32_t dirtyMask); void pushLayerUpdate(TreeInfo& info); diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 65c1c4a..81cf2df 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -158,6 +158,32 @@ public: } } + /** + * Set internal layer state based on whether this layer + * + * Additionally, returns true if child RenderNodes with functors will need to use a layer + * to support clipping. + */ + bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) { + // parent may have already dictated that a descendant layer is needed + bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer + + // Round rect clipping forces layer for functors + || CC_UNLIKELY(getOutline().willClip()) + || CC_UNLIKELY(getRevealClip().willClip()) + + // Complex matrices forces layer, due to stencil clipping + || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate()) + || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate()) + || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate()); + + mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer); + + // If on a layer, will have consumed the need for isolating functors from stencil. + // Thus, it's safe to reset the flag until some descendent sets it. + return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer; + } + RenderProperties& operator=(const RenderProperties& other); bool setClipToBounds(bool clipToBounds) { @@ -580,15 +606,16 @@ public: bool promotedToLayer() const { const int maxTextureSize = Caches::getInstance().maxTextureSize; return mLayerProperties.mType == LayerType::None - && !MathUtils::isZero(mPrimitiveFields.mAlpha) - && mPrimitiveFields.mAlpha < 1 - && mPrimitiveFields.mHasOverlappingRendering && mPrimitiveFields.mWidth <= maxTextureSize - && mPrimitiveFields.mHeight <= maxTextureSize; + && mPrimitiveFields.mHeight <= maxTextureSize + && (mComputedFields.mNeedLayerForFunctors + || (!MathUtils::isZero(mPrimitiveFields.mAlpha) + && mPrimitiveFields.mAlpha < 1 + && mPrimitiveFields.mHasOverlappingRendering)); } LayerType effectiveLayerType() const { - return promotedToLayer() ? LayerType::RenderLayer : mLayerProperties.mType; + return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType; } private: @@ -636,6 +663,9 @@ private: SkMatrix* mTransformMatrix; Sk3DView mTransformCamera; + + // Force layer on for functors to enable render features they don't yet support (clipping) + bool mNeedLayerForFunctors = false; } mComputedFields; }; |