Update transform isolation to handle command chunks

bug:15570351

Prevent drawing transformations on a ViewGroup's canvas from directly
affecting the transformation of the children through the renderer,
since it's already baked into mTransformFromParent at record time.

Change-Id: I6310a2260dfe4def0bde1fd2c5b93791a645d586
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 8818510..5ff7b7f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1528,8 +1528,7 @@
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
         TessellationCache::vertexBuffer_pair_t buffers;
-        Matrix4 drawTransform;
-        renderer.getMatrix(&drawTransform);
+        Matrix4 drawTransform(*(renderer.currentTransform()));
         renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
                 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 658265d..ac02349 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -653,41 +653,12 @@
     handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
 
-template <class T>
-int RenderNode::issueOperationsOfNegZChildren(
-        const Vector<ZDrawRenderNodeOpPair>& 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<ZDrawRenderNodeOpPair>& 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>
-void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-        ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
+void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode,
+        const Matrix4& initialTransform, const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
+        OpenGLRenderer& renderer, T& handler) {
     const int size = zTranslatedNodes.size();
     if (size == 0
             || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f)
@@ -696,6 +667,11 @@
         return;
     }
 
+    // Apply the base transform of the parent of the 3d children. This isolates
+    // 3d children of the current chunk from transformations made in previous chunks.
+    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
+    renderer.setMatrix(initialTransform);
+
     /**
      * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
      * with very similar Z heights to draw together.
@@ -750,6 +726,7 @@
         renderer.restoreToCount(restoreTo);
         drawIndex++;
     }
+    renderer.restoreToCount(rootRestoreTo);
 }
 
 template <class T>
@@ -869,6 +846,8 @@
     bool quickRejected = properties().getClipToBounds()
             && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
     if (!quickRejected) {
+        Matrix4 initialTransform(*(renderer.currentTransform()));
+
         if (drawLayer) {
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
@@ -880,9 +859,9 @@
                 Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
                 buildZSortedChildList(chunk, zTranslatedNodes);
 
-                // for 3d root, draw children with negative z values
-                int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes,
-                        renderer, handler);
+                issueOperationsOf3dChildren(kNegativeZChildren,
+                        initialTransform, zTranslatedNodes, renderer, handler);
+
                 const int saveCountOffset = renderer.getSaveCount() - 1;
                 const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
 
@@ -899,8 +878,8 @@
                     }
                 }
 
-                // for 3d root, draw children with positive z values
-                issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+                issueOperationsOf3dChildren(kPositiveZChildren,
+                        initialTransform, zTranslatedNodes, renderer, handler);
             }
         }
     }
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 18402b2..30eb923 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -206,16 +206,9 @@
     inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
 
     template <class T>
-    inline int issueOperationsOfNegZChildren(
-            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
+    inline void issueOperationsOf3dChildren(ChildrenSelectMode mode,
+            const Matrix4& initialTransform, const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
             OpenGLRenderer& renderer, T& handler);
-    template <class T>
-    inline void issueOperationsOfPosZChildren(int shadowRestoreTo,
-            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-            OpenGLRenderer& renderer, T& handler);
-    template <class T>
-    inline void issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
-            ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
 
     template <class T>
     inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index bdac47b..3e1aed3 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -102,10 +102,6 @@
 // Matrix
 ///////////////////////////////////////////////////////////////////////////////
 
-void StatefulBaseRenderer::getMatrix(Matrix4* matrix) const {
-    matrix->load(*(mSnapshot->transform));
-}
-
 void StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const {
     mSnapshot->transform->copyTo(*matrix);
 }
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 3957d36..c6974b4 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -69,7 +69,6 @@
     //        int alpha, SkXfermode::Mode mode, int flags);
 
     // Matrix
-    void getMatrix(Matrix4* outMatrix) const;
     virtual void getMatrix(SkMatrix* outMatrix) const;
     virtual void translate(float dx, float dy, float dz = 0.0f);
     virtual void rotate(float degrees);
@@ -100,6 +99,10 @@
     void setClippingRoundRect(LinearAllocator& allocator,
             const Rect& rect, float radius);
 
+    inline const mat4* currentTransform() const {
+        return mSnapshot->transform;
+    }
+
 protected:
     const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
 
@@ -134,10 +137,6 @@
         return mSnapshot->clipRect;
     }
 
-    inline const mat4* currentTransform() const {
-        return mSnapshot->transform;
-    }
-
     inline const Snapshot* currentSnapshot() const {
         return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
     }