Even FASTER damage calculations!

 * Now with more native!
 * Less matrix math thanks to bulk-property-update support!
 * Zero JNI on the View.damageInParent() path!
 * Fully aware of RT-driven animators!
 * Likely full of new and exciting bugs!
 * But it also fixes at least 1 existing invalidate bug!

Change-Id: Ie0773f85a60850ff2668370c58defef2e8aa079f
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9ebee1d..8a5c857 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -439,6 +439,7 @@
     mRenderThread.removeFrameCallback(this);
 
     info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
+    info.damageAccumulator = &mDamageAccumulator;
     mRootRenderNode->prepareTree(info);
 
     int runningBehind = 0;
@@ -465,27 +466,30 @@
     mRenderThread.pushBackFrameCallback(this);
 }
 
-void CanvasContext::draw(Rect* dirty) {
+void CanvasContext::draw() {
     LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
             "drawDisplayList called on a context with no canvas or surface!");
 
     profiler().markPlaybackStart();
 
+    SkRect dirty;
+    mDamageAccumulator.finish(&dirty);
+
     EGLint width, height;
     mGlobalContext->beginFrame(mEglSurface, &width, &height);
     if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
         mCanvas->setViewport(width, height);
-        dirty = NULL;
+        dirty.setEmpty();
     } else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
-        dirty = NULL;
+        dirty.setEmpty();
     } else {
-        profiler().unionDirty(dirty);
+        profiler().unionDirty(&dirty);
     }
 
     status_t status;
-    if (dirty && !dirty->isEmpty()) {
-        status = mCanvas->prepareDirty(dirty->left, dirty->top,
-                dirty->right, dirty->bottom, mOpaque);
+    if (!dirty.isEmpty()) {
+        status = mCanvas->prepareDirty(dirty.fLeft, dirty.fTop,
+                dirty.fRight, dirty.fBottom, mOpaque);
     } else {
         status = mCanvas->prepare(mOpaque);
     }
@@ -516,14 +520,12 @@
 
     profiler().startFrame();
 
-    TreeInfo info;
-    info.evaluateAnimations = true;
-    info.performStagingPush = false;
+    TreeInfo info(TreeInfo::MODE_RT_ONLY);
     info.prepareTextures = false;
 
     prepareTree(info);
     if (info.out.canDrawThisFrame) {
-        draw(NULL);
+        draw();
     }
 }
 
@@ -543,7 +545,7 @@
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     requireGlContext();
-    TreeInfo info;
+    TreeInfo info(TreeInfo::MODE_FULL);
     layer->apply(info);
     return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
 }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 00c5bf0..d926b38 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -23,6 +23,7 @@
 #include <utils/Functor.h>
 #include <utils/Vector.h>
 
+#include "../DamageAccumulator.h"
 #include "../DrawProfiler.h"
 #include "../RenderNode.h"
 #include "RenderTask.h"
@@ -57,7 +58,7 @@
     void makeCurrent();
     void processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info);
     void prepareTree(TreeInfo& info);
-    void draw(Rect* dirty);
+    void draw();
     void destroyCanvasAndSurface();
 
     // IFrameCallback, Chroreographer-driven frame callback entry point
@@ -99,6 +100,7 @@
     bool mOpaque;
     OpenGLRenderer* mCanvas;
     bool mHaveNewSurface;
+    DamageAccumulator mDamageAccumulator;
 
     const sp<RenderNode> mRootRenderNode;
 
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 61d67ca..bdfdd21 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -68,10 +68,6 @@
     }
 }
 
-void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
-    mDirty.set(left, top, right, bottom);
-}
-
 int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
@@ -83,7 +79,6 @@
     // Reset the single-frame data
     mFrameTimeNanos = 0;
     mRecordDurationNanos = 0;
-    mDirty.setEmpty();
 
     return mSyncResult;
 }
@@ -103,13 +98,12 @@
     bool canUnblockUiThread;
     bool canDrawThisFrame;
     {
-        TreeInfo info;
+        TreeInfo info(TreeInfo::MODE_FULL);
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
     }
 
     // Grab a copy of everything we need
-    Rect dirty(mDirty);
     CanvasContext* context = mContext;
 
     // From this point on anything in "this" is *UNSAFE TO ACCESS*
@@ -118,7 +112,7 @@
     }
 
     if (CC_LIKELY(canDrawThisFrame)) {
-        context->draw(&dirty);
+        context->draw();
     }
 
     if (!canUnblockUiThread) {
@@ -126,18 +120,11 @@
     }
 }
 
-static void initTreeInfo(TreeInfo& info) {
-    info.prepareTextures = true;
-    info.performStagingPush = true;
-    info.evaluateAnimations = true;
-}
-
 bool DrawFrameTask::syncFrameState(TreeInfo& info) {
     ATRACE_CALL();
     mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
     mContext->makeCurrent();
     Caches::getInstance().textureCache.resetMarkInUse();
-    initTreeInfo(info);
 
     for (size_t i = 0; i < mLayers.size(); i++) {
         mContext->processLayerUpdate(mLayers[i].get(), info);
@@ -149,8 +136,6 @@
     mContext->prepareTree(info);
 
     if (info.out.hasAnimations) {
-        // TODO: dirty calculations, for now just do a full-screen inval
-        mDirty.setEmpty();
         if (info.out.requiresUiRedraw) {
             mSyncResult |= kSync_UIRedrawRequired;
         }
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d4129b6..96f0add 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -60,7 +60,6 @@
     void pushLayerUpdate(DeferredLayerUpdater* layer);
     void removeLayerUpdate(DeferredLayerUpdater* layer);
 
-    void setDirty(int left, int top, int right, int bottom);
     void setDensity(float density) { mDensity = density; }
     int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
 
@@ -80,7 +79,6 @@
     /*********************************************
      *  Single frame data
      *********************************************/
-    Rect mDirty;
     nsecs_t mFrameTimeNanos;
     nsecs_t mRecordDurationNanos;
     float mDensity;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0901963..ded10a1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -180,8 +180,7 @@
 }
 
 int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
-        float density, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
-    mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+        float density) {
     mDrawFrameTask.setDensity(density);
     return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 944ff9c..a95f8f0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -70,7 +70,7 @@
     ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
-            float density, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
+            float density);
     ANDROID_API void destroyCanvasAndSurface();
 
     ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);