Merge "Merge hasFunctors & pushStaging into prepareTree"

This commit is contained in:
John Reck
2014-04-10 00:14:10 +00:00
committed by Android (Google) Code Review
11 changed files with 61 additions and 57 deletions

View File

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

View File

@@ -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

View File

@@ -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,

View File

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

View File

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

View File

@@ -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

View File

@@ -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

View File

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

View File

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

View File

@@ -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 */

View File

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