summaryrefslogtreecommitdiffstats
path: root/libs/hwui/renderthread
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp82
-rw-r--r--libs/hwui/renderthread/CanvasContext.h28
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp67
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h30
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp58
-rw-r--r--libs/hwui/renderthread/RenderProxy.h8
6 files changed, 61 insertions, 212 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c231f6f..3638184 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -313,14 +313,11 @@ CanvasContext::CanvasContext(bool translucent)
, mDirtyRegionsEnabled(false)
, mOpaque(!translucent)
, mCanvas(0)
- , mHaveNewSurface(false)
- , mInvokeFunctorsPending(false)
- , mInvokeFunctorsTask(this) {
+ , mHaveNewSurface(false) {
mGlobalContext = GlobalContext::get();
}
CanvasContext::~CanvasContext() {
- removeFunctorsTask();
destroyCanvas();
}
@@ -347,6 +344,7 @@ void CanvasContext::setSurface(EGLNativeWindowType window) {
if (mEglSurface != EGL_NO_SURFACE) {
mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
+ mGlobalContext->makeCurrent(mEglSurface);
mHaveNewSurface = true;
}
}
@@ -356,14 +354,15 @@ void CanvasContext::swapBuffers() {
mHaveNewSurface = false;
}
-void CanvasContext::makeCurrent() {
+void CanvasContext::requireSurface() {
+ LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
+ "requireSurface() called but no surface set!");
mGlobalContext->makeCurrent(mEglSurface);
}
bool CanvasContext::initialize(EGLNativeWindowType window) {
if (mCanvas) return false;
setSurface(window);
- makeCurrent();
mCanvas = new OpenGLRenderer();
mCanvas->initProperties();
return true;
@@ -371,7 +370,11 @@ bool CanvasContext::initialize(EGLNativeWindowType window) {
void CanvasContext::updateSurface(EGLNativeWindowType window) {
setSurface(window);
- makeCurrent();
+}
+
+void CanvasContext::pauseSurface(EGLNativeWindowType window) {
+ // TODO: For now we just need a fence, in the future suspend any animations
+ // and such to prevent from trying to render into this surface
}
void CanvasContext::setup(int width, int height) {
@@ -379,15 +382,13 @@ void CanvasContext::setup(int width, int height) {
mCanvas->setViewport(width, height);
}
-void CanvasContext::setDisplayListData(RenderNode* displayList, DisplayListData* newData) {
- displayList->setData(newData);
-}
-
-void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+ bool* hasFunctors) {
+ LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
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!");
+ LOG_ALWAYS_FATAL_IF(!update->apply(hasFunctors), "Failed to update layer!");
if (update->backingLayer()->deferredUpdateScheduled) {
mCanvas->pushLayerUpdate(update->backingLayer());
}
@@ -428,60 +429,23 @@ void CanvasContext::drawDisplayList(RenderNode* displayList, Rect* dirty) {
}
}
-void InvokeFunctorsTask::run() {
- mContext->invokeFunctors();
-}
-
-void CanvasContext::attachFunctor(Functor* functor) {
- if (!mCanvas) return;
-
- mCanvas->attachFunctor(functor);
- removeFunctorsTask();
- queueFunctorsTask(0);
-}
-
-void CanvasContext::detachFunctor(Functor* functor) {
- if (!mCanvas) return;
-
- mCanvas->detachFunctor(functor);
-}
-
void CanvasContext::invokeFunctor(Functor* functor) {
+ ATRACE_CALL();
DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
if (mGlobalContext->hasContext()) {
requireGlContext();
mode = DrawGlInfo::kModeProcess;
}
- (*functor)(mode, NULL);
-}
-
-void CanvasContext::invokeFunctors() {
- mInvokeFunctorsPending = false;
-
- if (!mCanvas) return;
-
- makeCurrent();
- Rect dirty;
- mCanvas->invokeFunctors(dirty);
-}
-
-void CanvasContext::removeFunctorsTask() {
- if (!mInvokeFunctorsPending) return;
-
- mInvokeFunctorsPending = false;
- mRenderThread.remove(&mInvokeFunctorsTask);
-}
-
-void CanvasContext::queueFunctorsTask(int delayMs) {
- if (mInvokeFunctorsPending) return;
-
- mInvokeFunctorsPending = true;
- mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
+ // TODO: Remove the dummy info in the future
+ DrawGlInfo dummyInfo;
+ memset(&dummyInfo, 0, sizeof(DrawGlInfo));
+ (*functor)(mode, &dummyInfo);
}
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
- layer->apply();
+ bool hasFunctors;
+ layer->apply(&hasFunctors);
return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
}
@@ -491,12 +455,12 @@ void CanvasContext::runWithGlContext(RenderTask* task) {
}
Layer* CanvasContext::createRenderLayer(int width, int height) {
- requireGlContext();
+ requireSurface();
return LayerRenderer::createRenderLayer(width, height);
}
Layer* CanvasContext::createTextureLayer() {
- requireGlContext();
+ requireSurface();
return LayerRenderer::createTextureLayer();
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6f1c37f..dcb5957 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -43,17 +43,6 @@ class GlobalContext;
class CanvasContext;
class RenderThread;
-class InvokeFunctorsTask : public RenderTask {
-public:
- InvokeFunctorsTask(CanvasContext* context)
- : mContext(context) {}
-
- virtual void run();
-
-private:
- CanvasContext* mContext;
-};
-
// This per-renderer class manages the bridge between the global EGL context
// and the render surface.
class CanvasContext {
@@ -63,16 +52,14 @@ public:
bool initialize(EGLNativeWindowType window);
void updateSurface(EGLNativeWindowType window);
+ void pauseSurface(EGLNativeWindowType window);
void setup(int width, int height);
- void setDisplayListData(RenderNode* displayList, DisplayListData* newData);
- void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
+ void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, bool* hasFunctors);
void drawDisplayList(RenderNode* displayList, Rect* dirty);
void destroyCanvas();
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
- void attachFunctor(Functor* functor);
- void detachFunctor(Functor* functor);
void invokeFunctor(Functor* functor);
void runWithGlContext(RenderTask* task);
@@ -83,12 +70,7 @@ public:
private:
void setSurface(EGLNativeWindowType window);
void swapBuffers();
- void makeCurrent();
-
- friend class InvokeFunctorsTask;
- void invokeFunctors();
- void removeFunctorsTask();
- void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
+ void requireSurface();
void requireGlContext();
@@ -100,10 +82,6 @@ private:
bool mOpaque;
OpenGLRenderer* mCanvas;
bool mHaveNewSurface;
-
- bool mInvokeFunctorsPending;
- InvokeFunctorsTask mInvokeFunctorsTask;
-
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 7b509a2..cf6c8db 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,19 +30,7 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-SetDisplayListData::SetDisplayListData() : mNewData(0) {}
-
-SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData)
- : mTargetNode(node), mNewData(newData) {
-}
-
-SetDisplayListData::~SetDisplayListData() {}
-
-void SetDisplayListData::apply() const {
- mTargetNode->setData(mNewData);
-}
-
-DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
+DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
}
DrawFrameTask::~DrawFrameTask() {
@@ -52,13 +40,6 @@ void DrawFrameTask::setContext(CanvasContext* context) {
mContext = context;
}
-void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
- LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!");
-
- SetDisplayListData setter(renderNode, newData);
- mDisplayListDataUpdates.push(setter);
-}
-
void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
@@ -88,23 +69,14 @@ void DrawFrameTask::drawFrame(RenderThread* renderThread) {
LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
- postAndWait(renderThread, MODE_FULL);
+ postAndWait(renderThread);
// Reset the single-frame data
mDirty.setEmpty();
mRenderNode = 0;
}
-void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
- LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
-
- postAndWait(renderThread, MODE_STATE_ONLY);
-}
-
-void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
- LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
-
- mTaskMode = mode;
+void DrawFrameTask::postAndWait(RenderThread* renderThread) {
AutoMutex _lock(mLock);
renderThread->queue(this);
mSignal.wait(mLock);
@@ -113,21 +85,14 @@ void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
- syncFrameState();
-
- if (mTaskMode == MODE_STATE_ONLY) {
- unblockUiThread();
- return;
- }
+ // canUnblockUiThread is temporary until WebView has a solution for syncing frame state
+ bool canUnblockUiThread = syncFrameState();
// Grab a copy of everything we need
Rect dirtyCopy(mDirty);
sp<RenderNode> renderNode = mRenderNode;
CanvasContext* context = mContext;
- // This is temporary until WebView has a solution for syncing frame state
- bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get());
-
// From this point on anything in "this" is *UNSAFE TO ACCESS*
if (canUnblockUiThread) {
unblockUiThread();
@@ -140,21 +105,17 @@ void DrawFrameTask::run() {
}
}
-void DrawFrameTask::syncFrameState() {
+bool DrawFrameTask::syncFrameState() {
ATRACE_CALL();
- for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
- const SetDisplayListData& setter = mDisplayListDataUpdates[i];
- setter.apply();
- }
- mDisplayListDataUpdates.clear();
+ bool hasFunctors = false;
+ mContext->processLayerUpdates(&mLayers, &hasFunctors);
- mContext->processLayerUpdates(&mLayers);
+ TreeInfo info = {0};
+ mRenderNode->prepareTree(info);
+ hasFunctors |= info.hasFunctors;
- // If we don't have an mRenderNode this is a state flush only
- if (mRenderNode.get()) {
- mRenderNode->updateProperties();
- }
+ return !hasFunctors;
}
void DrawFrameTask::unblockUiThread() {
@@ -172,10 +133,6 @@ void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNod
context->drawDisplayList(renderNode, dirty);
}
-bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) {
- return renderNode->hasFunctors();
-}
-
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 4e9b244..055d4cf 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -37,18 +37,6 @@ namespace renderthread {
class CanvasContext;
class RenderThread;
-class SetDisplayListData {
-public:
- // This ctor exists for Vector's usage
- SetDisplayListData();
- SetDisplayListData(RenderNode* node, DisplayListData* newData);
- ~SetDisplayListData();
- void apply() const;
-private:
- sp<RenderNode> mTargetNode;
- DisplayListData* mNewData;
-};
-
/*
* This is a special Super Task. It is re-used multiple times by RenderProxy,
* and contains state (such as layer updaters & new DisplayListDatas) that is
@@ -62,33 +50,21 @@ public:
void setContext(CanvasContext* context);
- void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
void addLayer(DeferredLayerUpdater* layer);
void removeLayer(DeferredLayerUpdater* layer);
void setRenderNode(RenderNode* renderNode);
void setDirty(int left, int top, int right, int bottom);
void drawFrame(RenderThread* renderThread);
- void flushStateChanges(RenderThread* renderThread);
virtual void run();
private:
- enum TaskMode {
- MODE_INVALID,
- MODE_FULL,
- MODE_STATE_ONLY,
- };
-
- void postAndWait(RenderThread* renderThread, TaskMode mode);
- void syncFrameState();
+ void postAndWait(RenderThread* renderThread);
+ bool syncFrameState();
void unblockUiThread();
static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
- // This checks to see if there are any drawGlFunctors which would require
- // a synchronous drawRenderNode()
- static bool requiresSynchronousDraw(RenderNode* renderNode);
-
Mutex mLock;
Condition mSignal;
@@ -97,10 +73,8 @@ private:
/*********************************************
* Single frame data
*********************************************/
- TaskMode mTaskMode;
sp<RenderNode> mRenderNode;
Rect mDirty;
- Vector<SetDisplayListData> mDisplayListDataUpdates;
/*********************************************
* Multi frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e817e61..b233ae9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -75,9 +75,6 @@ CREATE_BRIDGE1(destroyContext, CanvasContext* context) {
void RenderProxy::destroyContext() {
if (mContext) {
- // Flush any pending changes to ensure all garbage is destroyed
- mDrawFrameTask.flushStateChanges(&mRenderThread);
-
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
@@ -92,10 +89,10 @@ CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) {
return (void*) args->context->initialize(args->window);
}
-bool RenderProxy::initialize(EGLNativeWindowType window) {
+bool RenderProxy::initialize(const sp<ANativeWindow>& window) {
SETUP_TASK(initialize);
args->context = mContext;
- args->window = window;
+ args->window = window.get();
return (bool) postAndWait(task);
}
@@ -104,11 +101,23 @@ CREATE_BRIDGE2(updateSurface, CanvasContext* context, EGLNativeWindowType window
return NULL;
}
-void RenderProxy::updateSurface(EGLNativeWindowType window) {
+void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
SETUP_TASK(updateSurface);
args->context = mContext;
- args->window = window;
- post(task);
+ args->window = window.get();
+ postAndWait(task);
+}
+
+CREATE_BRIDGE2(pauseSurface, CanvasContext* context, EGLNativeWindowType window) {
+ args->context->pauseSurface(args->window);
+ return NULL;
+}
+
+void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
+ SETUP_TASK(pauseSurface);
+ args->context = mContext;
+ args->window = window.get();
+ postAndWait(task);
}
CREATE_BRIDGE3(setup, CanvasContext* context, int width, int height) {
@@ -124,10 +133,6 @@ void RenderProxy::setup(int width, int height) {
post(task);
}
-void RenderProxy::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
- mDrawFrameTask.setDisplayListData(renderNode, newData);
-}
-
void RenderProxy::drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
mDrawFrameTask.setRenderNode(displayList);
@@ -141,45 +146,18 @@ CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
}
void RenderProxy::destroyCanvas() {
- // If the canvas is being destroyed we won't be drawing again anytime soon
- // So flush any pending state changes to allow for resource cleanup.
- mDrawFrameTask.flushStateChanges(&mRenderThread);
-
SETUP_TASK(destroyCanvas);
args->context = mContext;
post(task);
}
-CREATE_BRIDGE2(attachFunctor, CanvasContext* context, Functor* functor) {
- args->context->attachFunctor(args->functor);
- return NULL;
-}
-
-void RenderProxy::attachFunctor(Functor* functor) {
- SETUP_TASK(attachFunctor);
- args->context = mContext;
- args->functor = functor;
- post(task);
-}
-
-CREATE_BRIDGE2(detachFunctor, CanvasContext* context, Functor* functor) {
- args->context->detachFunctor(args->functor);
- return NULL;
-}
-
-void RenderProxy::detachFunctor(Functor* functor) {
- SETUP_TASK(detachFunctor);
- args->context = mContext;
- args->functor = functor;
- post(task);
-}
-
CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
args->context->invokeFunctor(args->functor);
return NULL;
}
void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
+ ATRACE_CALL();
SETUP_TASK(invokeFunctor);
args->context = mContext;
args->functor = functor;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index c50da79..3eb8ed8 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -59,16 +59,14 @@ public:
ANDROID_API RenderProxy(bool translucent);
ANDROID_API virtual ~RenderProxy();
- ANDROID_API bool initialize(EGLNativeWindowType window);
- ANDROID_API void updateSurface(EGLNativeWindowType window);
+ ANDROID_API bool initialize(const sp<ANativeWindow>& window);
+ ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
+ ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height);
- ANDROID_API void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
ANDROID_API void drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
ANDROID_API void destroyCanvas();
- ANDROID_API void attachFunctor(Functor* functor);
- ANDROID_API void detachFunctor(Functor* functor);
ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task);