am 4c9dafbf: Merge "Put WebViews with on a HW layer if stencil/shader clipping is needed" into mnc-dev

* commit '4c9dafbfecf00ba3dca0c5de61d889676bfdc7af':
  Put WebViews with on a HW layer if stencil/shader clipping is needed
This commit is contained in:
Chris Craik
2015-06-12 22:56:03 +00:00
committed by Android Git Automerger
6 changed files with 85 additions and 19 deletions

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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()
///////////////////////////

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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;
};