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);