Support HardwareLayers in RenderThread

 Also has a few HardwareLayer lifecycle fixes

Change-Id: I6308cb05f8f199eed72189ace768013a46815941
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 5d3d393..efb1298 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -123,27 +123,5 @@
     }
 }
 
-void DeferredLayerUpdater::applyDeferred(DeferredLayerUpdater* deferredApply) {
-    // Default assignment operator doesn't quite work, and fails due to mCaches anyway
-    deferredApply->mWidth = mWidth;
-    deferredApply->mHeight = mHeight;
-    deferredApply->mBlend = mBlend;
-    deferredApply->mAlpha = mAlpha;
-    deferredApply->mMode = mMode;
-    deferredApply->mDirtyRect.set(mDirtyRect);
-    deferredApply->mDisplayList = mDisplayList;
-    deferredApply->mSurfaceTexture = mSurfaceTexture;
-    deferredApply->mNeedsGLContextAttach = mNeedsGLContextAttach;
-    deferredApply->mUpdateTexImage = mUpdateTexImage;
-    deferredApply->setColorFilter(mColorFilter);
-    deferredApply->setTransform(mTransform);
-
-    mDisplayList = 0;
-    mDirtyRect.setEmpty();
-    mTransform = 0;
-    mNeedsGLContextAttach = false;
-    mUpdateTexImage = false;
-}
-
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 9800c2f..624db2c 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -82,7 +82,6 @@
     ANDROID_API void setColorFilter(SkColorFilter* colorFilter);
 
     ANDROID_API bool apply();
-    ANDROID_API void applyDeferred(DeferredLayerUpdater* deferredApply);
 
     ANDROID_API Layer* backingLayer() {
         return mLayer;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4e665d9..fe781bd 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -24,6 +24,8 @@
 
 #include "RenderThread.h"
 #include "../Caches.h"
+#include "../DeferredLayerUpdater.h"
+#include "../LayerRenderer.h"
 #include "../OpenGLRenderer.h"
 #include "../Stencil.h"
 
@@ -371,6 +373,17 @@
     mCanvas->setViewport(width, height);
 }
 
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
+    mGlobalContext->makeCurrent(mEglSurface);
+    for (size_t i = 0; i < layerUpdaters->size(); i++) {
+        DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
+        LOG_ALWAYS_FATAL_IF(!update->apply(), "Failed to update layer!");
+        if (update->backingLayer()->deferredUpdateScheduled) {
+            mCanvas->pushLayerUpdate(update->backingLayer());
+        }
+    }
+}
+
 void CanvasContext::drawDisplayList(DisplayList* displayList, Rect* dirty) {
     LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
             "drawDisplayList called on a context with no canvas or surface!");
@@ -462,14 +475,23 @@
     mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
 }
 
+bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+    requireGlContext();
+    layer->apply();
+    return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
+}
+
 void CanvasContext::runWithGlContext(RenderTask* task) {
+    requireGlContext();
+    task->run();
+}
+
+void CanvasContext::requireGlContext() {
     if (mEglSurface != EGL_NO_SURFACE) {
         mGlobalContext->makeCurrent(mEglSurface);
     } else {
         mGlobalContext->usePBufferSurface();
     }
-
-    task->run();
 }
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 3197df3..5fac582 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -19,7 +19,9 @@
 
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
+#include <SkBitmap.h>
 #include <utils/Functor.h>
+#include <utils/Vector.h>
 
 #include "RenderTask.h"
 
@@ -28,6 +30,7 @@
 namespace android {
 namespace uirenderer {
 
+class DeferredLayerUpdater;
 class DisplayList;
 class OpenGLRenderer;
 class Rect;
@@ -59,9 +62,12 @@
     bool initialize(EGLNativeWindowType window);
     void updateSurface(EGLNativeWindowType window);
     void setup(int width, int height);
+    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
     void drawDisplayList(DisplayList* displayList, Rect* dirty);
     void destroyCanvas();
 
+    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+
     void attachFunctor(Functor* functor);
     void detachFunctor(Functor* functor);
 
@@ -78,6 +84,8 @@
     void removeFunctorsTask();
     void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
 
+    void requireGlContext();
+
     GlobalContext* mGlobalContext;
     RenderThread& mRenderThread;
     EGLSurface mEglSurface;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 34f1961..0c667fd 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -22,7 +22,9 @@
 #include "RenderTask.h"
 #include "RenderThread.h"
 
+#include "../DeferredLayerUpdater.h"
 #include "../DisplayList.h"
+#include "../LayerRenderer.h"
 #include "../Rect.h"
 
 namespace android {
@@ -31,6 +33,7 @@
 
 #define ARGS(method) method ## Args
 
+#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,)
 #define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,)
 #define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,)
 #define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,)
@@ -114,13 +117,14 @@
     post(task);
 }
 
-CREATE_BRIDGE3(drawDisplayList, CanvasContext* context, DisplayList* displayList,
-        Rect dirty) {
+CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, DisplayList* displayList,
+        Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) {
     Rect* dirty = &args->dirty;
     if (dirty->bottom == -1 && dirty->left == -1 &&
             dirty->top == -1 && dirty->right == -1) {
         dirty = 0;
     }
+    args->context->processLayerUpdates(args->layerUpdates);
     args->context->drawDisplayList(args->displayList, dirty);
     return NULL;
 }
@@ -131,6 +135,7 @@
     args->context = mContext;
     args->displayList = displayList;
     args->dirty.set(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+    args->layerUpdates = &mLayers;
     // TODO: Switch to post() once some form of thread safety strategy is in place
     postAndWait(task);
 }
@@ -182,6 +187,70 @@
     postAndWait(task);
 }
 
+CREATE_BRIDGE2(createDisplayListLayer, int width, int height) {
+    Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height);
+    if (!layer) return 0;
+
+    OpenGLRenderer* renderer = new LayerRenderer(layer);
+    renderer->initProperties();
+    return new DeferredLayerUpdater(layer, renderer);
+}
+
+DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
+    SETUP_TASK(createDisplayListLayer);
+    args->width = width;
+    args->height = height;
+    void* retval = postAndWait(task);
+    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
+    mLayers.push(layer);
+    return layer;
+}
+
+CREATE_BRIDGE0(createTextureLayer) {
+    Layer* layer = LayerRenderer::createTextureLayer();
+    if (!layer) return 0;
+    return new DeferredLayerUpdater(layer);
+}
+
+DeferredLayerUpdater* RenderProxy::createTextureLayer() {
+    SETUP_TASK(createTextureLayer);
+    void* retval = postAndWait(task);
+    DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
+    mLayers.push(layer);
+    return layer;
+}
+
+CREATE_BRIDGE1(destroyLayer, Layer* layer) {
+    LayerRenderer::destroyLayer(args->layer);
+    return NULL;
+}
+
+CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
+        SkBitmap* bitmap) {
+    bool success = args->context->copyLayerInto(args->layer, args->bitmap);
+    return (void*) success;
+}
+
+bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+    SETUP_TASK(copyLayerInto);
+    args->context = mContext;
+    args->layer = layer;
+    args->bitmap = bitmap;
+    return (bool) postAndWait(task);
+}
+
+void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) {
+    for (size_t i = 0; i < mLayers.size(); i++) {
+        if (mLayers[i] == layer) {
+            mLayers.removeAt(i);
+            break;
+        }
+    }
+    SETUP_TASK(destroyLayer);
+    args->layer = layer->detachBackingLayer();
+    post(task);
+}
+
 MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) {
     // TODO: Consider having a small pool of these to avoid alloc churn
     return new MethodInvokeRenderTask(method);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 1ad0c2d..8ff3d63 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -21,15 +21,19 @@
 
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
+#include <SkBitmap.h>
 #include <utils/Condition.h>
 #include <utils/Functor.h>
 #include <utils/Mutex.h>
 #include <utils/StrongPointer.h>
+#include <utils/Vector.h>
 
 namespace android {
 namespace uirenderer {
 
+class DeferredLayerUpdater;
 class DisplayList;
+class Layer;
 class Rect;
 
 namespace renderthread {
@@ -64,6 +68,11 @@
 
     ANDROID_API void runWithGlContext(RenderTask* task);
 
+    ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
+    ANDROID_API DeferredLayerUpdater* createTextureLayer();
+    ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+    ANDROID_API void destroyLayer(DeferredLayerUpdater* layer);
+
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
@@ -71,6 +80,8 @@
     Mutex mSyncMutex;
     Condition mSyncCondition;
 
+    Vector<DeferredLayerUpdater*> mLayers;
+
     void destroyContext();
 
     MethodInvokeRenderTask* createTask(RunnableMethod method);