Loading core/java/android/view/ViewRootImpl.java +86 −48 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ import android.graphics.BLASTBufferQueue; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.FrameInfo; import android.graphics.HardwareRenderer; import android.graphics.HardwareRenderer.FrameDrawingCallback; import android.graphics.Insets; import android.graphics.Matrix; Loading Loading @@ -3810,33 +3811,20 @@ public final class ViewRootImpl implements ViewParent, } } private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; } else if (mView == null) { return; } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw; mFullRedrawNeeded = false; mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = false; boolean reportNextDraw = mReportNextDraw; // Capture the original value if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) { ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || (commitCallbacks != null && commitCallbacks.size() > 0) || mReportNextDraw; usingAsyncReport = mReportNextDraw; if (needFrameCompleteCallback) { final Handler handler = mAttachInfo.mHandler; mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> { finishBLASTSync(!mSendNextFrameToWm); /** * The callback will run on the render thread. */ private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { return frameNr -> { // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by // the render thread and mSurfaceChangedTransaction can only be accessed by the UI // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged // with mSurfaceChangedTransaction without synchronization issues. final Transaction t = new Transaction(); finishBLASTSyncOnRT(!mSendNextFrameToWm, t); handler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(t); if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); Loading @@ -3847,12 +3835,47 @@ public final class ViewRootImpl implements ViewParent, } } }); }); }; } private boolean addFrameCompleteCallbackIfNeeded() { if (mAttachInfo.mThreadedRenderer == null || !mAttachInfo.mThreadedRenderer.isEnabled()) { return false; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, commitCallbacks)); return true; } return false; } /** * The callback will run on a worker thread pool from the render thread. */ private HardwareRenderer.FrameDrawingCallback createFrameDrawingCallback() { return frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }; } private void addFrameCallbackIfNeeded() { if (!mNextDrawUseBLASTSyncTransaction) { return; } try { if (mNextDrawUseBLASTSyncTransaction) { // Frame callbacks will always occur after submitting draw requests and before // the draw actually occurs. This will ensure that we set the next transaction // for the frame that's about to get drawn and not on a previous frame that. Loading @@ -3860,21 +3883,31 @@ public final class ViewRootImpl implements ViewParent, // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the // next frame completed should be reported with the blast sync transaction. registerRtFrameCallback(frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }); registerRtFrameCallback(createFrameDrawingCallback()); mNextDrawUseBLASTSyncTransaction = false; } private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; } else if (mView == null) { return; } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw; mFullRedrawNeeded = false; mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); try { boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && !canUseAsync) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null); usingAsyncReport = false; finishBLASTSync(true /* apply */); } } finally { mIsDrawing = false; Loading Loading @@ -9839,7 +9872,12 @@ public final class ViewRootImpl implements ViewParent, mNextDrawUseBLASTSyncTransaction = true; } private void finishBLASTSync(boolean apply) { /** * This should only be called from the render thread. */ private void finishBLASTSyncOnRT(boolean apply, Transaction t) { // This is safe to modify on the render thread since the only other place it's modified // is on the UI thread when the render thread is paused. mSendNextFrameToWm = false; if (mRtNextFrameReportedConsumeWithBlast) { mRtNextFrameReportedConsumeWithBlast = false; Loading @@ -9850,7 +9888,7 @@ public final class ViewRootImpl implements ViewParent, if (apply) { mRtBLASTSyncTransaction.apply(); } else { mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); t.merge(mRtBLASTSyncTransaction); } } } Loading Loading
core/java/android/view/ViewRootImpl.java +86 −48 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ import android.graphics.BLASTBufferQueue; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.FrameInfo; import android.graphics.HardwareRenderer; import android.graphics.HardwareRenderer.FrameDrawingCallback; import android.graphics.Insets; import android.graphics.Matrix; Loading Loading @@ -3810,33 +3811,20 @@ public final class ViewRootImpl implements ViewParent, } } private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; } else if (mView == null) { return; } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw; mFullRedrawNeeded = false; mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = false; boolean reportNextDraw = mReportNextDraw; // Capture the original value if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) { ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || (commitCallbacks != null && commitCallbacks.size() > 0) || mReportNextDraw; usingAsyncReport = mReportNextDraw; if (needFrameCompleteCallback) { final Handler handler = mAttachInfo.mHandler; mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> { finishBLASTSync(!mSendNextFrameToWm); /** * The callback will run on the render thread. */ private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { return frameNr -> { // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by // the render thread and mSurfaceChangedTransaction can only be accessed by the UI // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged // with mSurfaceChangedTransaction without synchronization issues. final Transaction t = new Transaction(); finishBLASTSyncOnRT(!mSendNextFrameToWm, t); handler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(t); if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); Loading @@ -3847,12 +3835,47 @@ public final class ViewRootImpl implements ViewParent, } } }); }); }; } private boolean addFrameCompleteCallbackIfNeeded() { if (mAttachInfo.mThreadedRenderer == null || !mAttachInfo.mThreadedRenderer.isEnabled()) { return false; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, commitCallbacks)); return true; } return false; } /** * The callback will run on a worker thread pool from the render thread. */ private HardwareRenderer.FrameDrawingCallback createFrameDrawingCallback() { return frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }; } private void addFrameCallbackIfNeeded() { if (!mNextDrawUseBLASTSyncTransaction) { return; } try { if (mNextDrawUseBLASTSyncTransaction) { // Frame callbacks will always occur after submitting draw requests and before // the draw actually occurs. This will ensure that we set the next transaction // for the frame that's about to get drawn and not on a previous frame that. Loading @@ -3860,21 +3883,31 @@ public final class ViewRootImpl implements ViewParent, // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the // next frame completed should be reported with the blast sync transaction. registerRtFrameCallback(frame -> { mRtNextFrameReportedConsumeWithBlast = true; if (mBlastBufferQueue != null) { // We don't need to synchronize mRtBLASTSyncTransaction here since it's not // being modified and only sent to BlastBufferQueue. mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } }); registerRtFrameCallback(createFrameDrawingCallback()); mNextDrawUseBLASTSyncTransaction = false; } private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; } else if (mView == null) { return; } final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw; mFullRedrawNeeded = false; mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); try { boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && !canUseAsync) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null); usingAsyncReport = false; finishBLASTSync(true /* apply */); } } finally { mIsDrawing = false; Loading Loading @@ -9839,7 +9872,12 @@ public final class ViewRootImpl implements ViewParent, mNextDrawUseBLASTSyncTransaction = true; } private void finishBLASTSync(boolean apply) { /** * This should only be called from the render thread. */ private void finishBLASTSyncOnRT(boolean apply, Transaction t) { // This is safe to modify on the render thread since the only other place it's modified // is on the UI thread when the render thread is paused. mSendNextFrameToWm = false; if (mRtNextFrameReportedConsumeWithBlast) { mRtNextFrameReportedConsumeWithBlast = false; Loading @@ -9850,7 +9888,7 @@ public final class ViewRootImpl implements ViewParent, if (apply) { mRtBLASTSyncTransaction.apply(); } else { mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); t.merge(mRtBLASTSyncTransaction); } } } Loading