Merge "Merge hasFunctors & pushStaging into prepareTree"
This commit is contained in:
@@ -1317,7 +1317,7 @@ public class GLRenderer extends HardwareRenderer {
|
||||
}
|
||||
|
||||
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList");
|
||||
nPushStagingChanges(displayList.getNativeDisplayList());
|
||||
nPrepareTree(displayList.getNativeDisplayList());
|
||||
try {
|
||||
status |= canvas.drawDisplayList(displayList, mRedrawClip,
|
||||
RenderNode.FLAG_CLIP_CHILDREN);
|
||||
@@ -1476,7 +1476,7 @@ public class GLRenderer extends HardwareRenderer {
|
||||
|
||||
static native void nDestroyLayer(long layerPtr);
|
||||
|
||||
private static native void nPushStagingChanges(long displayListPtr);
|
||||
private static native void nPrepareTree(long displayListPtr);
|
||||
|
||||
class DrawPerformanceDataProvider extends GraphDataProvider {
|
||||
private final int mGraphType;
|
||||
|
||||
@@ -142,11 +142,12 @@ static void android_view_GLRenderer_destroyLayer(JNIEnv* env, jobject clazz,
|
||||
LayerRenderer::destroyLayer(layer);
|
||||
}
|
||||
|
||||
static void android_view_GLRenderer_pushStagingChanges(JNIEnv* env, jobject clazz,
|
||||
static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz,
|
||||
jlong renderNodePtr) {
|
||||
using namespace android::uirenderer;
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
renderNode->pushStagingChanges();
|
||||
TreeInfo info = {0};
|
||||
renderNode->prepareTree(info);
|
||||
}
|
||||
|
||||
static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
|
||||
@@ -187,7 +188,7 @@ static JNINativeMethod gMethods[] = {
|
||||
|
||||
{ "getSystemTime", "()J", (void*) android_view_GLRenderer_getSystemTime },
|
||||
{ "nDestroyLayer", "(J)V", (void*) android_view_GLRenderer_destroyLayer },
|
||||
{ "nPushStagingChanges", "(J)V", (void*) android_view_GLRenderer_pushStagingChanges },
|
||||
{ "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree },
|
||||
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
|
||||
#endif
|
||||
|
||||
|
||||
@@ -127,7 +127,8 @@ static void android_view_HardwareLayer_updateRenderLayer(JNIEnv* env, jobject cl
|
||||
static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
|
||||
jlong layerUpdaterPtr) {
|
||||
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
|
||||
return layer->apply();
|
||||
bool ignoredHasFunctors;
|
||||
return layer->apply(&ignoredHasFunctors);
|
||||
}
|
||||
|
||||
static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
|
||||
|
||||
@@ -62,7 +62,7 @@ void DeferredLayerUpdater::setDisplayList(RenderNode* displayList,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool DeferredLayerUpdater::apply() {
|
||||
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();
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
ANDROID_API void setPaint(const SkPaint* paint);
|
||||
|
||||
ANDROID_API bool apply();
|
||||
ANDROID_API bool apply(bool* hasFunctors);
|
||||
|
||||
ANDROID_API Layer* backingLayer() {
|
||||
return mLayer;
|
||||
|
||||
@@ -93,7 +93,18 @@ void RenderNode::output(uint32_t level) {
|
||||
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 @@ void RenderNode::pushStagingChanges() {
|
||||
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
|
||||
|
||||
@@ -65,6 +65,11 @@ class SaveOp;
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
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
|
||||
|
||||
@@ -385,11 +385,12 @@ void CanvasContext::setup(int width, int height) {
|
||||
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 @@ void CanvasContext::queueFunctorsTask(int delayMs) {
|
||||
|
||||
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
|
||||
requireGlContext();
|
||||
layer->apply();
|
||||
bool hasFunctors;
|
||||
layer->apply(&hasFunctors);
|
||||
return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
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();
|
||||
|
||||
|
||||
@@ -94,7 +94,8 @@ void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
|
||||
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 @@ void DrawFrameTask::run() {
|
||||
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::run() {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ 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 */
|
||||
|
||||
@@ -68,14 +68,10 @@ private:
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user