Loading core/java/android/view/SurfaceView.java +44 −17 Original line number Diff line number Diff line Loading @@ -464,7 +464,8 @@ public class SurfaceView extends View { || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) { getLocationInWindow(mLocation); if (DEBUG) Log.i(TAG, "Changes: creating=" + creating if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged + " left=" + (mWindowSpaceLeft != mLocation[0]) Loading Loading @@ -534,7 +535,8 @@ public class SurfaceView extends View { mReportDrawNeeded = false; mDrawingStopped = !visible; if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Cur surface: " + mSurface); relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight, Loading @@ -547,7 +549,8 @@ public class SurfaceView extends View { reportDrawNeeded = true; } if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "New surface: " + mNewSurface + ", vis=" + visible + ", frame=" + mWinFrame); mSurfaceFrame.left = 0; Loading Loading @@ -581,7 +584,8 @@ public class SurfaceView extends View { if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { mSurfaceCreated = false; if (mSurface.isValid()) { if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "visibleChanged -- surfaceDestroyed"); callbacks = getSurfaceCallbacks(); for (SurfaceHolder.Callback c : callbacks) { c.surfaceDestroyed(mSurfaceHolder); Loading @@ -594,7 +598,8 @@ public class SurfaceView extends View { if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { mSurfaceCreated = true; mIsCreating = true; if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "visibleChanged -- surfaceCreated"); if (callbacks == null) { callbacks = getSurfaceCallbacks(); } Loading @@ -604,7 +609,8 @@ public class SurfaceView extends View { } if (creating || formatChanged || sizeChanged || visibleChanged || realSizeChanged) { if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "surfaceChanged -- format=" + mFormat + " w=" + myWidth + " h=" + myHeight); if (callbacks == null) { callbacks = getSurfaceCallbacks(); Loading @@ -614,7 +620,8 @@ public class SurfaceView extends View { } } if (redrawNeeded) { if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "surfaceRedrawNeeded"); if (callbacks == null) { callbacks = getSurfaceCallbacks(); } Loading @@ -629,7 +636,8 @@ public class SurfaceView extends View { } finally { mIsCreating = false; if (redrawNeeded) { if (DEBUG) Log.i(TAG, "finishedDrawing"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "finishedDrawing"); mSession.finishDrawing(mWindow); } mSession.performDeferredDestroy(mWindow); Loading Loading @@ -663,8 +671,9 @@ public class SurfaceView extends View { } try { Log.d(TAG, String.format("updateWindowPosition UI, " + "postion = [%d, %d, %d, %d]", mWinFrame.left, mWinFrame.top, Log.d(TAG, String.format("%d updateWindowPosition UI, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), mWinFrame.left, mWinFrame.top, mWinFrame.right, mWinFrame.bottom)); mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top, mWinFrame.right, mWinFrame.bottom, -1, mWinFrame); Loading Loading @@ -697,9 +706,9 @@ public class SurfaceView extends View { } try { if (DEBUG) { Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " + "postion = [%d, %d, %d, %d]", frameNumber, left, top, right, bottom)); Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), frameNumber, left, top, right, bottom)); } // Just using mRTLastReportedPosition as a dummy rect here session.repositionChild(window, left, top, right, bottom, Loading @@ -712,6 +721,25 @@ public class SurfaceView extends View { } } /** * Called by native on RenderThread to notify that the window is no longer in the * draw tree * @hide */ public final void windowPositionLostRT(long frameNumber) { if (DEBUG) { Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d", System.identityHashCode(this), frameNumber)); } // TODO: This is a bit of a hack as we don't have an API to report to WM // to hide a window with a frameNumber, so just shift the window very far into // negative space which will do effectively the same thing. // Use the last reported size to avoid influencing the size of the bufferqueue int x = -1000 - mRTLastReportedPosition.width(); int y = -1000 - mRTLastReportedPosition.height(); updateWindowPositionRT(frameNumber, x, y, -1000, -1000); } private SurfaceHolder.Callback[] getSurfaceCallbacks() { SurfaceHolder.Callback callbacks[]; synchronized (mCallbacks) { Loading Loading @@ -750,8 +778,7 @@ public class SurfaceView extends View { boolean alwaysConsumeNavBar) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (DEBUG) Log.v( "SurfaceView", surfaceView + " got resized: w=" + frame.width() if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width() + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight); surfaceView.mSurfaceLock.lock(); try { Loading Loading @@ -907,7 +934,7 @@ public class SurfaceView extends View { private final Canvas internalLockCanvas(Rect dirty) { mSurfaceLock.lock(); if (DEBUG) Log.i(TAG, "Locking canvas... stopped=" if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped=" + mDrawingStopped + ", win=" + mWindow); Canvas c = null; Loading @@ -919,7 +946,7 @@ public class SurfaceView extends View { } } if (DEBUG) Log.i(TAG, "Returned canvas: " + c); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c); if (c != null) { mLastLockTime = SystemClock.uptimeMillis(); return c; Loading core/jni/android_view_RenderNode.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -534,6 +534,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz, // ---------------------------------------------------------------------------- jmethodID gSurfaceViewPositionUpdateMethod; jmethodID gSurfaceViewPositionLostMethod; static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, jlong renderNodePtr, jobject surfaceview) { Loading Loading @@ -581,6 +582,20 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, info.canvasContext.enqueueFrameWork(std::move(functor)); } virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override { if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return; if (info) { auto functor = std::bind( std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this, (jlong) info->canvasContext.getFrameNumber()); info->canvasContext.enqueueFrameWork(std::move(functor)); } else { doNotifyPositionLost(0); } } private: JNIEnv* jnienv() { JNIEnv* env; Loading @@ -607,6 +622,21 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, env->DeleteLocalRef(localref); } void doNotifyPositionLost(jlong frameNumber) { ATRACE_NAME("SurfaceView position lost"); JNIEnv* env = jnienv(); jobject localref = env->NewLocalRef(mWeakRef); if (CC_UNLIKELY(!localref)) { jnienv()->DeleteWeakGlobalRef(mWeakRef); mWeakRef = nullptr; return; } env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber); env->DeleteLocalRef(localref); } JavaVM* mVm; jobject mWeakRef; }; Loading Loading @@ -701,6 +731,8 @@ int register_android_view_RenderNode(JNIEnv* env) { jclass clazz = FindClassOrDie(env, "android/view/SurfaceView"); gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz, "updateWindowPositionRT", "(JIIII)V"); gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz, "windowPositionLostRT", "(J)V"); clazz = FindClassOrDie(env, "android/view/RenderNode"); gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz, "onRenderNodeDetached", "()V"); Loading libs/hwui/RenderNode.cpp +13 −10 Original line number Diff line number Diff line Loading @@ -464,7 +464,7 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) { } #endif void RenderNode::syncDisplayList(TreeObserver* observer) { void RenderNode::syncDisplayList(TreeInfo* info) { // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache if (mStagingDisplayList) { Loading @@ -472,7 +472,7 @@ void RenderNode::syncDisplayList(TreeObserver* observer) { child->renderNode->incParentRefCount(); } } deleteDisplayList(observer); deleteDisplayList(info ? info->observer : nullptr, info); mDisplayList = mStagingDisplayList; mStagingDisplayList = nullptr; if (mDisplayList) { Loading @@ -491,15 +491,15 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { // Damage with the old display list first then the new one to catch any // changes in isRenderable or, in the future, bounds damageSelf(info); syncDisplayList(info.observer); syncDisplayList(&info); damageSelf(info); } } void RenderNode::deleteDisplayList(TreeObserver* observer) { void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) { if (mDisplayList) { for (auto&& child : mDisplayList->getChildren()) { child->renderNode->decParentRefCount(observer); child->renderNode->decParentRefCount(observer, info); } } delete mDisplayList; Loading Loading @@ -531,35 +531,38 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL } } void RenderNode::destroyHardwareResources(TreeObserver* observer) { void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) { if (mLayer) { destroyLayer(mLayer); mLayer = nullptr; } if (mDisplayList) { for (auto&& child : mDisplayList->getChildren()) { child->renderNode->destroyHardwareResources(observer); child->renderNode->destroyHardwareResources(observer, info); } if (mNeedsDisplayListSync) { // Next prepare tree we are going to push a new display list, so we can // drop our current one now deleteDisplayList(observer); deleteDisplayList(observer, info); } } } void RenderNode::decParentRefCount(TreeObserver* observer) { void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) { LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!"); mParentCount--; if (!mParentCount) { if (observer) { observer->onMaybeRemovedFromTree(this); } if (CC_UNLIKELY(mPositionListener.get())) { mPositionListener->onPositionLost(*this, info); } // If a child of ours is being attached to our parent then this will incorrectly // destroy its hardware resources. However, this situation is highly unlikely // and the failure is "just" that the layer is re-created, so this should // be safe enough destroyHardwareResources(observer); destroyHardwareResources(observer, info); } } Loading libs/hwui/RenderNode.h +13 −4 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ public: } ANDROID_API virtual void prepareTree(TreeInfo& info); void destroyHardwareResources(TreeObserver* observer); void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr); // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator); Loading Loading @@ -228,10 +228,19 @@ public: OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh... #endif // Note: The position callbacks are relying on the listener using // the frameNumber to appropriately batch/synchronize these transactions. // There is no other filtering/batching to ensure that only the "final" // state called once per frame. class ANDROID_API PositionListener { public: virtual ~PositionListener() {} // Called when the RenderNode's position changes virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0; // Called when the RenderNode no longer has a position. As in, it's // no longer being drawn. // Note, tree info might be null virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0; }; // Note this is not thread safe, this needs to be called Loading Loading @@ -306,7 +315,7 @@ private: void syncProperties(); void syncDisplayList(TreeObserver* observer); void syncDisplayList(TreeInfo* info); void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer); void pushStagingPropertiesChanges(TreeInfo& info); Loading @@ -317,11 +326,11 @@ private: #endif void prepareLayer(TreeInfo& info, uint32_t dirtyMask); void pushLayerUpdate(TreeInfo& info); void deleteDisplayList(TreeObserver* observer); void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr); void damageSelf(TreeInfo& info); void incParentRefCount() { mParentCount++; } void decParentRefCount(TreeObserver* observer); void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr); String8 mName; sp<VirtualLightRefBase> mUserContext; Loading Loading
core/java/android/view/SurfaceView.java +44 −17 Original line number Diff line number Diff line Loading @@ -464,7 +464,8 @@ public class SurfaceView extends View { || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) { getLocationInWindow(mLocation); if (DEBUG) Log.i(TAG, "Changes: creating=" + creating if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged + " left=" + (mWindowSpaceLeft != mLocation[0]) Loading Loading @@ -534,7 +535,8 @@ public class SurfaceView extends View { mReportDrawNeeded = false; mDrawingStopped = !visible; if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Cur surface: " + mSurface); relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight, Loading @@ -547,7 +549,8 @@ public class SurfaceView extends View { reportDrawNeeded = true; } if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "New surface: " + mNewSurface + ", vis=" + visible + ", frame=" + mWinFrame); mSurfaceFrame.left = 0; Loading Loading @@ -581,7 +584,8 @@ public class SurfaceView extends View { if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { mSurfaceCreated = false; if (mSurface.isValid()) { if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "visibleChanged -- surfaceDestroyed"); callbacks = getSurfaceCallbacks(); for (SurfaceHolder.Callback c : callbacks) { c.surfaceDestroyed(mSurfaceHolder); Loading @@ -594,7 +598,8 @@ public class SurfaceView extends View { if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { mSurfaceCreated = true; mIsCreating = true; if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "visibleChanged -- surfaceCreated"); if (callbacks == null) { callbacks = getSurfaceCallbacks(); } Loading @@ -604,7 +609,8 @@ public class SurfaceView extends View { } if (creating || formatChanged || sizeChanged || visibleChanged || realSizeChanged) { if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "surfaceChanged -- format=" + mFormat + " w=" + myWidth + " h=" + myHeight); if (callbacks == null) { callbacks = getSurfaceCallbacks(); Loading @@ -614,7 +620,8 @@ public class SurfaceView extends View { } } if (redrawNeeded) { if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "surfaceRedrawNeeded"); if (callbacks == null) { callbacks = getSurfaceCallbacks(); } Loading @@ -629,7 +636,8 @@ public class SurfaceView extends View { } finally { mIsCreating = false; if (redrawNeeded) { if (DEBUG) Log.i(TAG, "finishedDrawing"); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "finishedDrawing"); mSession.finishDrawing(mWindow); } mSession.performDeferredDestroy(mWindow); Loading Loading @@ -663,8 +671,9 @@ public class SurfaceView extends View { } try { Log.d(TAG, String.format("updateWindowPosition UI, " + "postion = [%d, %d, %d, %d]", mWinFrame.left, mWinFrame.top, Log.d(TAG, String.format("%d updateWindowPosition UI, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), mWinFrame.left, mWinFrame.top, mWinFrame.right, mWinFrame.bottom)); mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top, mWinFrame.right, mWinFrame.bottom, -1, mWinFrame); Loading Loading @@ -697,9 +706,9 @@ public class SurfaceView extends View { } try { if (DEBUG) { Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " + "postion = [%d, %d, %d, %d]", frameNumber, left, top, right, bottom)); Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), frameNumber, left, top, right, bottom)); } // Just using mRTLastReportedPosition as a dummy rect here session.repositionChild(window, left, top, right, bottom, Loading @@ -712,6 +721,25 @@ public class SurfaceView extends View { } } /** * Called by native on RenderThread to notify that the window is no longer in the * draw tree * @hide */ public final void windowPositionLostRT(long frameNumber) { if (DEBUG) { Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d", System.identityHashCode(this), frameNumber)); } // TODO: This is a bit of a hack as we don't have an API to report to WM // to hide a window with a frameNumber, so just shift the window very far into // negative space which will do effectively the same thing. // Use the last reported size to avoid influencing the size of the bufferqueue int x = -1000 - mRTLastReportedPosition.width(); int y = -1000 - mRTLastReportedPosition.height(); updateWindowPositionRT(frameNumber, x, y, -1000, -1000); } private SurfaceHolder.Callback[] getSurfaceCallbacks() { SurfaceHolder.Callback callbacks[]; synchronized (mCallbacks) { Loading Loading @@ -750,8 +778,7 @@ public class SurfaceView extends View { boolean alwaysConsumeNavBar) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (DEBUG) Log.v( "SurfaceView", surfaceView + " got resized: w=" + frame.width() if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width() + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight); surfaceView.mSurfaceLock.lock(); try { Loading Loading @@ -907,7 +934,7 @@ public class SurfaceView extends View { private final Canvas internalLockCanvas(Rect dirty) { mSurfaceLock.lock(); if (DEBUG) Log.i(TAG, "Locking canvas... stopped=" if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped=" + mDrawingStopped + ", win=" + mWindow); Canvas c = null; Loading @@ -919,7 +946,7 @@ public class SurfaceView extends View { } } if (DEBUG) Log.i(TAG, "Returned canvas: " + c); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c); if (c != null) { mLastLockTime = SystemClock.uptimeMillis(); return c; Loading
core/jni/android_view_RenderNode.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -534,6 +534,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz, // ---------------------------------------------------------------------------- jmethodID gSurfaceViewPositionUpdateMethod; jmethodID gSurfaceViewPositionLostMethod; static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, jlong renderNodePtr, jobject surfaceview) { Loading Loading @@ -581,6 +582,20 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, info.canvasContext.enqueueFrameWork(std::move(functor)); } virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override { if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return; if (info) { auto functor = std::bind( std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this, (jlong) info->canvasContext.getFrameNumber()); info->canvasContext.enqueueFrameWork(std::move(functor)); } else { doNotifyPositionLost(0); } } private: JNIEnv* jnienv() { JNIEnv* env; Loading @@ -607,6 +622,21 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, env->DeleteLocalRef(localref); } void doNotifyPositionLost(jlong frameNumber) { ATRACE_NAME("SurfaceView position lost"); JNIEnv* env = jnienv(); jobject localref = env->NewLocalRef(mWeakRef); if (CC_UNLIKELY(!localref)) { jnienv()->DeleteWeakGlobalRef(mWeakRef); mWeakRef = nullptr; return; } env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber); env->DeleteLocalRef(localref); } JavaVM* mVm; jobject mWeakRef; }; Loading Loading @@ -701,6 +731,8 @@ int register_android_view_RenderNode(JNIEnv* env) { jclass clazz = FindClassOrDie(env, "android/view/SurfaceView"); gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz, "updateWindowPositionRT", "(JIIII)V"); gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz, "windowPositionLostRT", "(J)V"); clazz = FindClassOrDie(env, "android/view/RenderNode"); gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz, "onRenderNodeDetached", "()V"); Loading
libs/hwui/RenderNode.cpp +13 −10 Original line number Diff line number Diff line Loading @@ -464,7 +464,7 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) { } #endif void RenderNode::syncDisplayList(TreeObserver* observer) { void RenderNode::syncDisplayList(TreeInfo* info) { // Make sure we inc first so that we don't fluctuate between 0 and 1, // which would thrash the layer cache if (mStagingDisplayList) { Loading @@ -472,7 +472,7 @@ void RenderNode::syncDisplayList(TreeObserver* observer) { child->renderNode->incParentRefCount(); } } deleteDisplayList(observer); deleteDisplayList(info ? info->observer : nullptr, info); mDisplayList = mStagingDisplayList; mStagingDisplayList = nullptr; if (mDisplayList) { Loading @@ -491,15 +491,15 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { // Damage with the old display list first then the new one to catch any // changes in isRenderable or, in the future, bounds damageSelf(info); syncDisplayList(info.observer); syncDisplayList(&info); damageSelf(info); } } void RenderNode::deleteDisplayList(TreeObserver* observer) { void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) { if (mDisplayList) { for (auto&& child : mDisplayList->getChildren()) { child->renderNode->decParentRefCount(observer); child->renderNode->decParentRefCount(observer, info); } } delete mDisplayList; Loading Loading @@ -531,35 +531,38 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL } } void RenderNode::destroyHardwareResources(TreeObserver* observer) { void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) { if (mLayer) { destroyLayer(mLayer); mLayer = nullptr; } if (mDisplayList) { for (auto&& child : mDisplayList->getChildren()) { child->renderNode->destroyHardwareResources(observer); child->renderNode->destroyHardwareResources(observer, info); } if (mNeedsDisplayListSync) { // Next prepare tree we are going to push a new display list, so we can // drop our current one now deleteDisplayList(observer); deleteDisplayList(observer, info); } } } void RenderNode::decParentRefCount(TreeObserver* observer) { void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) { LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!"); mParentCount--; if (!mParentCount) { if (observer) { observer->onMaybeRemovedFromTree(this); } if (CC_UNLIKELY(mPositionListener.get())) { mPositionListener->onPositionLost(*this, info); } // If a child of ours is being attached to our parent then this will incorrectly // destroy its hardware resources. However, this situation is highly unlikely // and the failure is "just" that the layer is re-created, so this should // be safe enough destroyHardwareResources(observer); destroyHardwareResources(observer, info); } } Loading
libs/hwui/RenderNode.h +13 −4 Original line number Diff line number Diff line Loading @@ -196,7 +196,7 @@ public: } ANDROID_API virtual void prepareTree(TreeInfo& info); void destroyHardwareResources(TreeObserver* observer); void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr); // UI thread only! ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator); Loading Loading @@ -228,10 +228,19 @@ public: OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh... #endif // Note: The position callbacks are relying on the listener using // the frameNumber to appropriately batch/synchronize these transactions. // There is no other filtering/batching to ensure that only the "final" // state called once per frame. class ANDROID_API PositionListener { public: virtual ~PositionListener() {} // Called when the RenderNode's position changes virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0; // Called when the RenderNode no longer has a position. As in, it's // no longer being drawn. // Note, tree info might be null virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0; }; // Note this is not thread safe, this needs to be called Loading Loading @@ -306,7 +315,7 @@ private: void syncProperties(); void syncDisplayList(TreeObserver* observer); void syncDisplayList(TreeInfo* info); void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer); void pushStagingPropertiesChanges(TreeInfo& info); Loading @@ -317,11 +326,11 @@ private: #endif void prepareLayer(TreeInfo& info, uint32_t dirtyMask); void pushLayerUpdate(TreeInfo& info); void deleteDisplayList(TreeObserver* observer); void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr); void damageSelf(TreeInfo& info); void incParentRefCount() { mParentCount++; } void decParentRefCount(TreeObserver* observer); void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr); String8 mName; sp<VirtualLightRefBase> mUserContext; Loading