Merge "Fix some edge cases" into nyc-dev

This commit is contained in:
John Reck
2016-04-07 23:08:09 +00:00
committed by Android (Google) Code Review
17 changed files with 115 additions and 98 deletions

View File

@@ -794,8 +794,7 @@ public final class ThreadedRenderer {
} }
final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo; final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length, int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
mRootNode.mNativeRenderNode);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) { if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false); setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release(); attachInfo.mViewRootImpl.mSurface.release();
@@ -994,8 +993,7 @@ public final class ThreadedRenderer {
private static native void nSetLightCenter(long nativeProxy, private static native void nSetLightCenter(long nativeProxy,
float lightX, float lightY, float lightZ); float lightX, float lightY, float lightZ);
private static native void nSetOpaque(long nativeProxy, boolean opaque); private static native void nSetOpaque(long nativeProxy, boolean opaque);
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size, private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
long rootRenderNode);
private static native void nDestroy(long nativeProxy, long rootRenderNode); private static native void nDestroy(long nativeProxy, long rootRenderNode);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);

View File

@@ -128,9 +128,22 @@ static void android_view_RenderNode_destroyRenderNode(JNIEnv* env,
static void android_view_RenderNode_setDisplayList(JNIEnv* env, static void android_view_RenderNode_setDisplayList(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong displayListPtr) { jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
class RemovedObserver : public TreeObserver {
public:
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
maybeRemovedNodes.insert(sp<RenderNode>(node));
}
std::set< sp<RenderNode> > maybeRemovedNodes;
};
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr); DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
renderNode->setStagingDisplayList(newData); RemovedObserver observer;
renderNode->setStagingDisplayList(newData, &observer);
for (auto& node : observer.maybeRemovedNodes) {
if (node->hasParents()) continue;
onRenderNodeRemoved(env, node.get());
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -525,7 +525,7 @@ static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
UiFrameInfoBuilder(proxy->frameInfo()) UiFrameInfoBuilder(proxy->frameInfo())
.setVsync(vsync, vsync) .setVsync(vsync, vsync)
.addFlag(FrameInfoFlags::SurfaceCanvas); .addFlag(FrameInfoFlags::SurfaceCanvas);
proxy->syncAndDrawFrame(); proxy->syncAndDrawFrame(nullptr);
} }
static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) { static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {

View File

@@ -72,6 +72,31 @@ static JNIEnv* getenv(JavaVM* vm) {
return env; return env;
} }
// TODO: Clean this up, it's a bit odd to need to call over to
// rendernode's jni layer. Probably means RootRenderNode should be pulled
// into HWUI with appropriate callbacks for the various JNI hooks so
// that RenderNode's JNI layer can handle its own thing
void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
class ScopedRemovedRenderNodeObserver : public TreeObserver {
public:
ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
~ScopedRemovedRenderNodeObserver() {
for (auto& node : mMaybeRemovedNodes) {
if (node->hasParents()) continue;
onRenderNodeRemoved(mEnv, node.get());
}
}
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
mMaybeRemovedNodes.insert(sp<RenderNode>(node));
}
private:
JNIEnv* mEnv;
std::set< sp<RenderNode> > mMaybeRemovedNodes;
};
class OnFinishedEvent { class OnFinishedEvent {
public: public:
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -120,13 +145,7 @@ private:
std::string mMessage; std::string mMessage;
}; };
// TODO: Clean this up, it's a bit odd to need to call over to class RootRenderNode : public RenderNode, ErrorHandler {
// rendernode's jni layer. Probably means RootRenderNode should be pulled
// into HWUI with appropriate callbacks for the various JNI hooks so
// that RenderNode's JNI layer can handle its own thing
void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
class RootRenderNode : public RenderNode, ErrorHandler, TreeObserver {
public: public:
RootRenderNode(JNIEnv* env) : RenderNode() { RootRenderNode(JNIEnv* env) : RenderNode() {
mLooper = Looper::getForThread(); mLooper = Looper::getForThread();
@@ -143,9 +162,6 @@ public:
virtual void prepareTree(TreeInfo& info) override { virtual void prepareTree(TreeInfo& info) override {
info.errorHandler = this; info.errorHandler = this;
if (info.mode == TreeInfo::MODE_FULL) {
info.observer = this;
}
// TODO: This is hacky // TODO: This is hacky
info.windowInsetLeft = -stagingProperties().getLeft(); info.windowInsetLeft = -stagingProperties().getLeft();
info.windowInsetTop = -stagingProperties().getTop(); info.windowInsetTop = -stagingProperties().getTop();
@@ -155,7 +171,6 @@ public:
info.windowInsetLeft = 0; info.windowInsetLeft = 0;
info.windowInsetTop = 0; info.windowInsetTop = 0;
info.errorHandler = nullptr; info.errorHandler = nullptr;
info.observer = nullptr;
} }
void sendMessage(const sp<MessageHandler>& handler) { void sendMessage(const sp<MessageHandler>& handler) {
@@ -181,27 +196,10 @@ public:
mPendingAnimatingRenderNodes.clear(); mPendingAnimatingRenderNodes.clear();
} }
virtual void onMaybeRemovedFromTree(RenderNode* node) override {
mMaybeRemovedNodes.insert(sp<RenderNode>(node));
}
void processMaybeRemovedNodes(JNIEnv* env) {
// We can safely access mMaybeRemovedNodes here because
// we will only modify it in prepareTree calls that are
// MODE_FULL
for (auto& node : mMaybeRemovedNodes) {
if (node->hasParents()) continue;
onRenderNodeRemoved(env, node.get());
}
mMaybeRemovedNodes.clear();
}
private: private:
sp<Looper> mLooper; sp<Looper> mLooper;
JavaVM* mVm; JavaVM* mVm;
std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes; std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
std::set< sp<RenderNode> > mMaybeRemovedNodes;
}; };
class AnimationContextBridge : public AnimationContext { class AnimationContextBridge : public AnimationContext {
@@ -500,24 +498,23 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
} }
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz, static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize, jlong rootNodePtr) { jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE, LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
"Mismatched size expectations, given %d expected %d", "Mismatched size expectations, given %d expected %d",
frameInfoSize, UI_THREAD_FRAME_INFO_SIZE); frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); ScopedRemovedRenderNodeObserver observer(env);
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo()); env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
int ret = proxy->syncAndDrawFrame(); return proxy->syncAndDrawFrame(&observer);
rootRenderNode->processMaybeRemovedNodes(env);
return ret;
} }
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz, static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong rootNodePtr) { jlong proxyPtr, jlong rootNodePtr) {
ScopedRemovedRenderNodeObserver observer(env);
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
rootRenderNode->destroy(); rootRenderNode->destroy();
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->destroy(); proxy->destroy(&observer);
} }
static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz, static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -542,9 +539,10 @@ static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobje
static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz, static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong nodePtr) { jlong proxyPtr, jlong nodePtr) {
ScopedRemovedRenderNodeObserver observer(env);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr); RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
proxy->buildLayer(node); proxy->buildLayer(node, &observer);
} }
static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
@@ -579,8 +577,9 @@ static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobj
static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz, static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
jlong proxyPtr) { jlong proxyPtr) {
ScopedRemovedRenderNodeObserver observer(env);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->destroyHardwareResources(); proxy->destroyHardwareResources(&observer);
} }
static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz, static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
@@ -736,7 +735,7 @@ static const JNINativeMethod gMethods[] = {
{ "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup }, { "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter }, { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSyncAndDrawFrame", "(J[JIJ)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },

View File

@@ -81,14 +81,14 @@ RenderNode::~RenderNode() {
#endif #endif
} }
void RenderNode::setStagingDisplayList(DisplayList* displayList) { void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
mNeedsDisplayListSync = true; mNeedsDisplayListSync = true;
delete mStagingDisplayList; delete mStagingDisplayList;
mStagingDisplayList = displayList; mStagingDisplayList = displayList;
// If mParentCount == 0 we are the sole reference to this RenderNode, // If mParentCount == 0 we are the sole reference to this RenderNode,
// so immediately free the old display list // so immediately free the old display list
if (!mParentCount && !mStagingDisplayList) { if (!mParentCount && !mStagingDisplayList) {
deleteDisplayList(nullptr); deleteDisplayList(observer);
} }
} }

View File

@@ -117,7 +117,7 @@ public:
void debugDumpLayers(const char* prefix); void debugDumpLayers(const char* prefix);
ANDROID_API void setStagingDisplayList(DisplayList* newData); ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
void computeOrdering(); void computeOrdering();

View File

@@ -76,15 +76,15 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
} }
CanvasContext::~CanvasContext() { CanvasContext::~CanvasContext() {
destroy(); destroy(nullptr);
mRenderThread.renderState().unregisterCanvasContext(this); mRenderThread.renderState().unregisterCanvasContext(this);
} }
void CanvasContext::destroy() { void CanvasContext::destroy(TreeObserver* observer) {
stopDrawing(); stopDrawing();
setSurface(nullptr); setSurface(nullptr);
freePrefetechedLayers(); freePrefetchedLayers(observer);
destroyHardwareResources(); destroyHardwareResources(observer);
mAnimationContext->destroy(); mAnimationContext->destroy();
#if !HWUI_NEW_OPS #if !HWUI_NEW_OPS
if (mCanvas) { if (mCanvas) {
@@ -222,7 +222,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
mAnimationContext->runRemainingAnimations(info); mAnimationContext->runRemainingAnimations(info);
GL_CHECKPOINT(MODERATE); GL_CHECKPOINT(MODERATE);
freePrefetechedLayers(); freePrefetchedLayers(info.observer);
GL_CHECKPOINT(MODERATE); GL_CHECKPOINT(MODERATE);
if (CC_UNLIKELY(!mNativeSurface.get())) { if (CC_UNLIKELY(!mNativeSurface.get())) {
@@ -569,25 +569,24 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) {
} }
void CanvasContext::markLayerInUse(RenderNode* node) { void CanvasContext::markLayerInUse(RenderNode* node) {
if (mPrefetechedLayers.erase(node)) { if (mPrefetchedLayers.erase(node)) {
node->decStrong(nullptr); node->decStrong(nullptr);
} }
} }
static void destroyPrefetechedNode(RenderNode* node) { void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName()); if (mPrefetchedLayers.size()) {
node->destroyHardwareResources(nullptr); for (auto& node : mPrefetchedLayers) {
node->decStrong(nullptr); ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
} node->getName());
node->destroyHardwareResources(observer);
void CanvasContext::freePrefetechedLayers() { node->decStrong(observer);
if (mPrefetechedLayers.size()) { }
std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode); mPrefetchedLayers.clear();
mPrefetechedLayers.clear();
} }
} }
void CanvasContext::buildLayer(RenderNode* node) { void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
ATRACE_CALL(); ATRACE_CALL();
if (!mEglManager.hasEglContext()) return; if (!mEglManager.hasEglContext()) return;
#if !HWUI_NEW_OPS #if !HWUI_NEW_OPS
@@ -599,6 +598,7 @@ void CanvasContext::buildLayer(RenderNode* node) {
TreeInfo info(TreeInfo::MODE_FULL, *this); TreeInfo info(TreeInfo::MODE_FULL, *this);
info.damageAccumulator = &mDamageAccumulator; info.damageAccumulator = &mDamageAccumulator;
info.observer = observer;
#if HWUI_NEW_OPS #if HWUI_NEW_OPS
info.layerUpdateQueue = &mLayerUpdateQueue; info.layerUpdateQueue = &mLayerUpdateQueue;
#else #else
@@ -628,7 +628,7 @@ void CanvasContext::buildLayer(RenderNode* node) {
#endif #endif
node->incStrong(nullptr); node->incStrong(nullptr);
mPrefetechedLayers.insert(node); mPrefetchedLayers.insert(node);
} }
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
@@ -636,12 +636,12 @@ bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap)
return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap); return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
} }
void CanvasContext::destroyHardwareResources() { void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
stopDrawing(); stopDrawing();
if (mEglManager.hasEglContext()) { if (mEglManager.hasEglContext()) {
freePrefetechedLayers(); freePrefetchedLayers(observer);
for (const sp<RenderNode>& node : mRenderNodes) { for (const sp<RenderNode>& node : mRenderNodes) {
node->destroyHardwareResources(nullptr); node->destroyHardwareResources(observer);
} }
Caches& caches = Caches::getInstance(); Caches& caches = Caches::getInstance();
// Make sure to release all the textures we were owning as there won't // Make sure to release all the textures we were owning as there won't

View File

@@ -92,17 +92,17 @@ public:
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
int64_t syncQueued, RenderNode* target); int64_t syncQueued, RenderNode* target);
void draw(); void draw();
void destroy(); void destroy(TreeObserver* observer);
// IFrameCallback, Choreographer-driven frame callback entry point // IFrameCallback, Choreographer-driven frame callback entry point
virtual void doFrame() override; virtual void doFrame() override;
void prepareAndDraw(RenderNode* node); void prepareAndDraw(RenderNode* node);
void buildLayer(RenderNode* node); void buildLayer(RenderNode* node, TreeObserver* observer);
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
void markLayerInUse(RenderNode* node); void markLayerInUse(RenderNode* node);
void destroyHardwareResources(); void destroyHardwareResources(TreeObserver* observer);
static void trimMemory(RenderThread& thread, int level); static void trimMemory(RenderThread& thread, int level);
static void invokeFunctor(RenderThread& thread, Functor* functor); static void invokeFunctor(RenderThread& thread, Functor* functor);
@@ -174,7 +174,7 @@ private:
void setSurface(Surface* window); void setSurface(Surface* window);
void requireSurface(); void requireSurface();
void freePrefetechedLayers(); void freePrefetchedLayers(TreeObserver* observer);
void waitOnFences(); void waitOnFences();
@@ -218,7 +218,7 @@ private:
FrameInfoVisualizer mProfiler; FrameInfoVisualizer mProfiler;
std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter; std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
std::set<RenderNode*> mPrefetechedLayers; std::set<RenderNode*> mPrefetchedLayers;
// Stores the bounds of the main content. // Stores the bounds of the main content.
Rect mContentDrawBounds; Rect mContentDrawBounds;

View File

@@ -65,11 +65,12 @@ void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
} }
} }
int DrawFrameTask::drawFrame() { int DrawFrameTask::drawFrame(TreeObserver* observer) {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = kSync_OK; mSyncResult = kSync_OK;
mSyncQueued = systemTime(CLOCK_MONOTONIC); mSyncQueued = systemTime(CLOCK_MONOTONIC);
mObserver = observer;
postAndWait(); postAndWait();
return mSyncResult; return mSyncResult;
@@ -88,6 +89,7 @@ void DrawFrameTask::run() {
bool canDrawThisFrame; bool canDrawThisFrame;
{ {
TreeInfo info(TreeInfo::MODE_FULL, *mContext); TreeInfo info(TreeInfo::MODE_FULL, *mContext);
info.observer = mObserver;
canUnblockUiThread = syncFrameState(info); canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame; canDrawThisFrame = info.out.canDrawThisFrame;
} }

View File

@@ -62,7 +62,7 @@ public:
void pushLayerUpdate(DeferredLayerUpdater* layer); void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer); void removeLayerUpdate(DeferredLayerUpdater* layer);
int drawFrame(); int drawFrame(TreeObserver* observer);
int64_t* frameInfo() { return mFrameInfo; } int64_t* frameInfo() { return mFrameInfo; }
@@ -87,6 +87,7 @@ private:
int mSyncResult; int mSyncResult;
int64_t mSyncQueued; int64_t mSyncQueued;
TreeObserver* mObserver;
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE]; int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
}; };

View File

@@ -222,18 +222,19 @@ int64_t* RenderProxy::frameInfo() {
return mDrawFrameTask.frameInfo(); return mDrawFrameTask.frameInfo();
} }
int RenderProxy::syncAndDrawFrame() { int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
return mDrawFrameTask.drawFrame(); return mDrawFrameTask.drawFrame(observer);
} }
CREATE_BRIDGE1(destroy, CanvasContext* context) { CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
args->context->destroy(); args->context->destroy(args->observer);
return nullptr; return nullptr;
} }
void RenderProxy::destroy() { void RenderProxy::destroy(TreeObserver* observer) {
SETUP_TASK(destroy); SETUP_TASK(destroy);
args->context = mContext; args->context = mContext;
args->observer = observer;
// destroyCanvasAndSurface() needs a fence as when it returns the // destroyCanvasAndSurface() needs a fence as when it returns the
// underlying BufferQueue is going to be released from under // underlying BufferQueue is going to be released from under
// the render thread. // the render thread.
@@ -287,15 +288,16 @@ DeferredLayerUpdater* RenderProxy::createTextureLayer() {
return layer; return layer;
} }
CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) { CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
args->context->buildLayer(args->node); args->context->buildLayer(args->node, args->observer);
return nullptr; return nullptr;
} }
void RenderProxy::buildLayer(RenderNode* node) { void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
SETUP_TASK(buildLayer); SETUP_TASK(buildLayer);
args->context = mContext; args->context = mContext;
args->node = node; args->node = node;
args->observer = observer;
postAndWait(task); postAndWait(task);
} }
@@ -332,15 +334,16 @@ void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
postAndWait(task); postAndWait(task);
} }
CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) { CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
args->context->destroyHardwareResources(); args->context->destroyHardwareResources(args->observer);
return nullptr; return nullptr;
} }
void RenderProxy::destroyHardwareResources() { void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
SETUP_TASK(destroyHardwareResources); SETUP_TASK(destroyHardwareResources);
args->context = mContext; args->context = mContext;
post(task); args->observer = observer;
postAndWait(task);
} }
CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) { CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {

View File

@@ -42,6 +42,7 @@ class RenderNode;
class DisplayList; class DisplayList;
class Layer; class Layer;
class Rect; class Rect;
class TreeObserver;
namespace renderthread { namespace renderthread {
@@ -75,21 +76,21 @@ public:
ANDROID_API void setLightCenter(const Vector3& lightCenter); ANDROID_API void setLightCenter(const Vector3& lightCenter);
ANDROID_API void setOpaque(bool opaque); ANDROID_API void setOpaque(bool opaque);
ANDROID_API int64_t* frameInfo(); ANDROID_API int64_t* frameInfo();
ANDROID_API int syncAndDrawFrame(); ANDROID_API int syncAndDrawFrame(TreeObserver* observer);
ANDROID_API void destroy(); ANDROID_API void destroy(TreeObserver* observer);
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion); ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task); ANDROID_API void runWithGlContext(RenderTask* task);
ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node); ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap); ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer); ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
ANDROID_API void destroyHardwareResources(); ANDROID_API void destroyHardwareResources(TreeObserver* observer);
ANDROID_API static void trimMemory(int level); ANDROID_API static void trimMemory(int level);
ANDROID_API static void overrideProperty(const char* name, const char* value); ANDROID_API static void overrideProperty(const char* name, const char* value);

View File

@@ -146,7 +146,7 @@ public:
if (setup) { if (setup) {
TestCanvas canvas(props.getWidth(), props.getHeight()); TestCanvas canvas(props.getWidth(), props.getHeight());
setup(props, canvas); setup(props, canvas);
node->setStagingDisplayList(canvas.finishRecording()); node->setStagingDisplayList(canvas.finishRecording(), nullptr);
} }
node->setPropertyFieldsDirty(0xFFFFFFFF); node->setPropertyFieldsDirty(0xFFFFFFFF);
return node; return node;
@@ -157,7 +157,7 @@ public:
TestCanvas canvas(node.stagingProperties().getWidth(), TestCanvas canvas(node.stagingProperties().getWidth(),
node.stagingProperties().getHeight()); node.stagingProperties().getHeight());
contentCallback(canvas); contentCallback(canvas);
node.setStagingDisplayList(canvas.finishRecording()); node.setStagingDisplayList(canvas.finishRecording(), nullptr);
} }
/** /**

View File

@@ -59,6 +59,6 @@ public:
0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr); 0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr);
} }
container->setStagingDisplayList(canvas.finishRecording()); container->setStagingDisplayList(canvas.finishRecording(), nullptr);
} }
}; };

View File

@@ -76,7 +76,7 @@ public:
// draw it to parent DisplayList // draw it to parent DisplayList
canvas.drawRenderNode(cards[ci].get()); canvas.drawRenderNode(cards[ci].get());
} }
listView->setStagingDisplayList(canvas.finishRecording()); listView->setStagingDisplayList(canvas.finishRecording(), nullptr);
} }
private: private:
SkBitmap createRandomCharIcon() { SkBitmap createRandomCharIcon() {

View File

@@ -95,7 +95,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
testContext.waitForVsync(); testContext.waitForVsync();
nsecs_t vsync = systemTime(CLOCK_MONOTONIC); nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync); UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
proxy->syncAndDrawFrame(); proxy->syncAndDrawFrame(nullptr);
} }
proxy->resetProfileInfo(); proxy->resetProfileInfo();
@@ -110,7 +110,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
ATRACE_NAME("UI-Draw Frame"); ATRACE_NAME("UI-Draw Frame");
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync); UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
scene->doFrame(i); scene->doFrame(i);
proxy->syncAndDrawFrame(); proxy->syncAndDrawFrame(nullptr);
} }
if (opts.reportFrametimeWeight) { if (opts.reportFrametimeWeight) {
proxy->fence(); proxy->fence();

View File

@@ -104,8 +104,8 @@ public:
} }
void finishDrawing() { void finishDrawing() {
mRootNode->setStagingDisplayList(mCanvas->finishRecording()); mRootNode->setStagingDisplayList(mCanvas->finishRecording(), nullptr);
mProxy->syncAndDrawFrame(); mProxy->syncAndDrawFrame(nullptr);
// Surprisingly, calling mProxy->fence() here appears to make no difference to // Surprisingly, calling mProxy->fence() here appears to make no difference to
// the timings we record. // the timings we record.
} }