MultiThreaded rendering of different renderNodes

This is adding the renderer side infrastructure to allow
rendering multiple render nodes with different threads.
This is a pre-step for decoupling a non client decor
resize reder from a content resize render.

Multiple render nodes can be added to be drawn, and to
prevent overdrawing, a content bounds area can be set

Bug: 22527834

Change-Id: Ie7271e20895bf38957e5a84aeefc883e282039ad
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 420f7a1..dcef142 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -108,6 +108,11 @@
     private Choreographer mChoreographer;
     private boolean mRootNodeNeedsUpdate;
 
+    // In case of multi threaded render nodes, these bounds indicate the content bounds against
+    // which the backdrop needs to be cropped against.
+    private final Rect mCurrentContentBounds = new Rect();
+    private final Rect mStagedContentBounds = new Rect();
+
     ThreadedRenderer(Context context, boolean translucent) {
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
@@ -307,6 +312,47 @@
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
     }
 
+    /**
+     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+     * rendernode of the UI thread.
+     * @param node The node to add.
+     * @param placeFront If true, the render node will be placed in front of the content node,
+     *                   otherwise behind the content node.
+     */
+    public void addRenderNode(RenderNode node, boolean placeFront) {
+        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+    }
+
+    /**
+     * Only especially added render nodes can be removed.
+     * @param node The node which was added via addRenderNode which should get removed again.
+     */
+    public void removeRenderNode(RenderNode node) {
+        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Draws a particular render node. If the node is not the content node, only the additional
+     * nodes will get drawn and the content remains untouched.
+     * @param node The node to be drawn.
+     */
+    public void drawRenderNode(RenderNode node) {
+        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+     * will be prevented to overdraw this area. It will be synchronized with the draw call.
+     * This should be updated in the content view's draw call.
+     * @param left The left side of the protected bounds.
+     * @param top The top side of the protected bounds.
+     * @param right The right side of the protected bounds.
+     * @param bottom The bottom side of the protected bounds.
+     */
+    public void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
+        mStagedContentBounds.set(left, top, right, bottom);
+    }
+
     @Override
     void invalidateRoot() {
         mRootNodeNeedsUpdate = true;
@@ -320,6 +366,14 @@
         choreographer.mFrameInfo.markDrawStart();
 
         updateRootDisplayList(view, callbacks);
+        // The main content view was updating the content bounds and we transfer them to the
+        // renderer.
+        if (!mCurrentContentBounds.equals(mStagedContentBounds)) {
+            mCurrentContentBounds.set(mStagedContentBounds);
+            nSetContentOverdrawProtectionBounds(mNativeProxy, mCurrentContentBounds.left,
+                mCurrentContentBounds.top, mCurrentContentBounds.right,
+            mCurrentContentBounds.bottom);
+        }
 
         attachInfo.mIgnoreDirtyState = false;
 
@@ -541,4 +595,11 @@
     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
             @DumpFlags int dumpFlags);
     private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
+
+    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+             boolean placeFront);
+    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+    private static native void nSetContentOverdrawProtectionBounds(long nativeProxy, int left,
+             int top, int right, int bottom);
 }