summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2014-06-20 15:03:43 -0700
committerChris Craik <ccraik@google.com>2014-06-20 16:18:58 -0700
commit80d4902196899d1325cd9f52c06ae0174cf9bd4c (patch)
tree659794797f8161ca9580fc17cc5c44bbbe3c304e
parent6b2df21ecacfa6826a85cabdf8d6fe0e81fe11d9 (diff)
downloadframeworks_base-80d4902196899d1325cd9f52c06ae0174cf9bd4c.zip
frameworks_base-80d4902196899d1325cd9f52c06ae0174cf9bd4c.tar.gz
frameworks_base-80d4902196899d1325cd9f52c06ae0174cf9bd4c.tar.bz2
Wrap ViewGroup content in save/restore to protect composited children
bug:15570351 Pos Z composited children are drawn before the primary restore for a RenderNode. This means that without an additional save/restore (which wraps the content) they aren't protected from transformations/clips that happen within the ViewGroup's DisplayList. Also changes RenderNode to use OpenGLRenderer tag for displaylist dumping consistency, and simplifies the entry points into RenderNode drawing, since the distinction between tree root vs tree internal is no longer important. Change-Id: I2621eba0592c74d71f85a91a4ab3d0da2d7468d3
-rw-r--r--libs/hwui/DisplayListOp.h8
-rw-r--r--libs/hwui/Layer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp4
-rw-r--r--libs/hwui/RenderNode.cpp64
-rw-r--r--libs/hwui/RenderNode.h15
5 files changed, 55 insertions, 38 deletions
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 233f3f0..4dbebc5 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1475,19 +1475,19 @@ public:
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->deferNodeInParent(deferStruct, level + 1);
+ mDisplayList->defer(deferStruct, level + 1);
}
}
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->replayNodeInParent(replayStruct, level + 1);
+ mDisplayList->replay(replayStruct, level + 1);
}
}
- // NOT USED since replay() is overridden
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
- return DrawGlInfo::kStatusDone;
+ LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
+ return 0;
}
virtual void output(int level, uint32_t logFlags) const {
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 6a2ef2a..e59e714 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -219,7 +219,7 @@ void Layer::defer() {
dirtyRect.right, dirtyRect.bottom, !isBlend());
displayList->computeOrdering();
- displayList->deferNodeTree(deferredState);
+ displayList->defer(deferredState, 0);
deferredUpdateScheduled = false;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8f3872a..48cc3e4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1942,14 +1942,14 @@ status_t OpenGLRenderer::drawDisplayList(RenderNode* displayList, Rect& dirty,
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
status = startFrame();
ReplayStateStruct replayStruct(*this, dirty, replayFlags);
- displayList->replayNodeTree(replayStruct);
+ displayList->replay(replayStruct, 0);
return status | replayStruct.mDrawGlStatus;
}
bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
- displayList->deferNodeTree(deferStruct);
+ displayList->defer(deferStruct, 0);
flushLayers();
status = startFrame();
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 378183a..f0eca3c 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -15,7 +15,7 @@
*/
#define ATRACE_TAG ATRACE_TAG_VIEW
-#define LOG_TAG "RenderNode"
+#define LOG_TAG "OpenGLRenderer"
#include "RenderNode.h"
@@ -523,15 +523,7 @@ private:
const int mLevel;
};
-void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
- DeferOperationHandler handler(deferStruct, 0);
- if (MathUtils::isPositive(properties().getZ())) {
- issueDrawShadowOperation(Matrix4::identity(), handler);
- }
- issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
-}
-
-void RenderNode::deferNodeInParent(DeferStateStruct& deferStruct, const int level) {
+void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
DeferOperationHandler handler(deferStruct, level);
issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
}
@@ -561,15 +553,7 @@ private:
const int mLevel;
};
-void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
- ReplayOperationHandler handler(replayStruct, 0);
- if (MathUtils::isPositive(properties().getZ())) {
- issueDrawShadowOperation(Matrix4::identity(), handler);
- }
- issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
-}
-
-void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int level) {
+void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
ReplayOperationHandler handler(replayStruct, level);
issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
@@ -628,6 +612,36 @@ void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T&
handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
+template <class T>
+int RenderNode::issueOperationsOfNegZChildren(
+ const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ OpenGLRenderer& renderer, T& handler) {
+ if (zTranslatedNodes.isEmpty()) return -1;
+
+ // create a save around the body of the ViewGroup's draw method, so that
+ // matrix/clip methods don't affect composited children
+ int shadowSaveCount = renderer.getSaveCount();
+ handler(new (handler.allocator()) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
+ PROPERTY_SAVECOUNT, properties().getClipToBounds());
+
+ issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
+ return shadowSaveCount;
+}
+
+template <class T>
+void RenderNode::issueOperationsOfPosZChildren(int shadowRestoreTo,
+ const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ OpenGLRenderer& renderer, T& handler) {
+ if (zTranslatedNodes.isEmpty()) return;
+
+ LOG_ALWAYS_FATAL_IF(shadowRestoreTo < 0, "invalid save to restore to");
+ handler(new (handler.allocator()) RestoreToCountOp(shadowRestoreTo),
+ PROPERTY_SAVECOUNT, properties().getClipToBounds());
+ renderer.setOverrideLayerAlpha(1.0f);
+
+ issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
+}
+
#define SHADOW_DELTA 0.1f
template <class T>
@@ -701,8 +715,6 @@ template <class T>
void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size());
const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
- bool maskProjecteesWithPath = projectionReceiverOutline != NULL
- && !projectionReceiverOutline->isRect(NULL);
int restoreTo = renderer.getSaveCount();
// If the projection reciever has an outline, we mask each of the projected rendernodes to it
@@ -723,7 +735,7 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
SaveLayerOp* op = new (alloc) SaveLayerOp(
outlineBounds.left(), outlineBounds.top(),
outlineBounds.right(), outlineBounds.bottom(),
- 255, SkCanvas::kARGB_ClipLayer_SaveFlag);
+ 255, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag | SkCanvas::kARGB_ClipLayer_SaveFlag);
op->setMask(projectionReceiverOutline);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
@@ -812,7 +824,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
buildZSortedChildList(zTranslatedNodes);
// for 3d root, draw children with negative z values
- issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
+ int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -820,9 +832,9 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
DisplayListOp *op = mDisplayListData->displayListOps[i];
- #if DEBUG_DISPLAY_LIST
+#if DEBUG_DISPLAY_LIST
op->output(level + 1);
- #endif
+#endif
logBuffer.writeCommand(level, op->name());
handler(op, saveCountOffset, properties().getClipToBounds());
@@ -832,7 +844,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
}
// for 3d root, draw children with positive z values
- issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
+ issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index b2fe849..ec12b9f 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -113,11 +113,8 @@ public:
void computeOrdering();
- void deferNodeTree(DeferStateStruct& deferStruct);
- void deferNodeInParent(DeferStateStruct& deferStruct, const int level);
-
- void replayNodeTree(ReplayStateStruct& replayStruct);
- void replayNodeInParent(ReplayStateStruct& replayStruct, const int level);
+ void defer(DeferStateStruct& deferStruct, const int level);
+ void replay(ReplayStateStruct& replayStruct, const int level);
ANDROID_API void output(uint32_t level = 1);
ANDROID_API int getDebugSize();
@@ -226,6 +223,14 @@ private:
inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
template <class T>
+ inline int issueOperationsOfNegZChildren(
+ const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ OpenGLRenderer& renderer, T& handler);
+ template <class T>
+ inline void issueOperationsOfPosZChildren(int shadowRestoreTo,
+ const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ OpenGLRenderer& renderer, T& handler);
+ template <class T>
inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);