Merge hasFunctors & pushStaging into prepareTree
Bug: 13902607
Fixes synchronous mode for WebView in HardwareLayers
Change-Id: I90de1e26dcfd9b75cc2f03bac72705fc23237b68
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 358e1af..c64c169 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -62,7 +62,7 @@
}
}
-bool DeferredLayerUpdater::apply() {
+bool DeferredLayerUpdater::apply(bool* hasFunctors) {
bool success = true;
// These properties are applied the same to both layer types
mLayer->setColorFilter(mColorFilter);
@@ -73,7 +73,11 @@
success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
}
mLayer->setBlend(mBlend);
- mDisplayList->pushStagingChanges();
+ TreeInfo info = {0};
+ mDisplayList->prepareTree(info);
+ if (info.hasFunctors) {
+ *hasFunctors = true;
+ }
mLayer->updateDeferred(mDisplayList.get(),
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
mDirtyRect.setEmpty();
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index ce08c2d..2cc9229 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,7 +77,7 @@
ANDROID_API void setPaint(const SkPaint* paint);
- ANDROID_API bool apply();
+ ANDROID_API bool apply(bool* hasFunctors);
ANDROID_API Layer* backingLayer() {
return mLayer;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 761fb84..823ae7b 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -93,7 +93,18 @@
ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string());
}
-void RenderNode::pushStagingChanges() {
+void RenderNode::prepareTree(TreeInfo& info) {
+ ATRACE_CALL();
+
+ prepareTreeImpl(info);
+}
+
+void RenderNode::prepareTreeImpl(TreeInfo& info) {
+ pushStagingChanges(info);
+ prepareSubTree(info, mDisplayListData);
+}
+
+void RenderNode::pushStagingChanges(TreeInfo& info) {
if (mNeedsPropertiesSync) {
mNeedsPropertiesSync = false;
mProperties = mStagingProperties;
@@ -102,41 +113,27 @@
mNeedsDisplayListDataSync = false;
// Do a push pass on the old tree to handle freeing DisplayListData
// that are no longer used
- pushSubTreeStagingChanges(mDisplayListData);
+ TreeInfo oldTreeInfo = {0};
+ prepareSubTree(oldTreeInfo, mDisplayListData);
+ // TODO: The damage for the old tree should be accounted for
delete mDisplayListData;
mDisplayListData = mStagingDisplayListData;
mStagingDisplayListData = 0;
}
-
- pushSubTreeStagingChanges(mDisplayListData);
}
-void RenderNode::pushSubTreeStagingChanges(DisplayListData* subtree) {
+void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
if (subtree) {
+ if (!info.hasFunctors) {
+ info.hasFunctors = subtree->functorCount;
+ }
for (size_t i = 0; i < subtree->children().size(); i++) {
RenderNode* childNode = subtree->children()[i]->mDisplayList;
- childNode->pushStagingChanges();
+ childNode->prepareTreeImpl(info);
}
}
}
-bool RenderNode::hasFunctors() {
- if (!mDisplayListData) return false;
-
- if (mDisplayListData->functorCount) {
- return true;
- }
-
- for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
- RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
- if (childNode->hasFunctors()) {
- return true;
- }
- }
-
- return false;
-}
-
/*
* For property operations, we pass a savecount of 0, since the operations aren't part of the
* displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index e5b9d7c..7853701 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -65,6 +65,11 @@
class RestoreToCountOp;
class DrawDisplayListOp;
+struct TreeInfo {
+ bool hasFunctors;
+ // TODO: Damage calculations? Flag to skip staging pushes for RT animations?
+};
+
/**
* Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
*
@@ -141,10 +146,7 @@
return properties().getHeight();
}
- ANDROID_API void pushStagingChanges();
-
- // Returns true if this RenderNode or any of its children have functors
- bool hasFunctors();
+ ANDROID_API void prepareTree(TreeInfo& info);
private:
typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
@@ -203,7 +205,9 @@
const char* mText;
};
- static void pushSubTreeStagingChanges(DisplayListData* subtree);
+ void prepareTreeImpl(TreeInfo& info);
+ void pushStagingChanges(TreeInfo& info);
+ void prepareSubTree(TreeInfo& info, DisplayListData* subtree);
String8 mName;
bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 014c7d0..c5122e2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -385,11 +385,12 @@
mCanvas->setViewport(width, height);
}
-void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+ bool* hasFunctors) {
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());
}
@@ -483,7 +484,8 @@
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
requireGlContext();
- layer->apply();
+ bool hasFunctors;
+ layer->apply(&hasFunctors);
return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4d830ba..a24162e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -65,7 +65,7 @@
void updateSurface(EGLNativeWindowType window);
void pauseSurface(EGLNativeWindowType window);
void setup(int width, int height);
- void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
+ void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, bool* hasFunctors);
void drawDisplayList(RenderNode* displayList, Rect* dirty);
void destroyCanvas();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 6e7ec9b..372d0d0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -94,7 +94,8 @@
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
- syncFrameState();
+ // canUnblockUiThread is temporary until WebView has a solution for syncing frame state
+ bool canUnblockUiThread = syncFrameState();
if (mTaskMode == MODE_STATE_ONLY) {
unblockUiThread();
@@ -106,9 +107,6 @@
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();
@@ -121,15 +119,20 @@
}
}
-void DrawFrameTask::syncFrameState() {
+bool DrawFrameTask::syncFrameState() {
ATRACE_CALL();
- mContext->processLayerUpdates(&mLayers);
+ bool hasFunctors = false;
+ mContext->processLayerUpdates(&mLayers, &hasFunctors);
// If we don't have an mRenderNode this is a state flush only
if (mRenderNode.get()) {
- mRenderNode->pushStagingChanges();
+ TreeInfo info = {0};
+ mRenderNode->prepareTree(info);
+ hasFunctors |= info.hasFunctors;
}
+
+ return !hasFunctors;
}
void DrawFrameTask::unblockUiThread() {
@@ -147,10 +150,6 @@
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 ddf756b..a512408 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -68,14 +68,10 @@
};
void postAndWait(RenderThread* renderThread, TaskMode mode);
- void syncFrameState();
+ 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;