diff options
| author | 2020-02-18 09:00:03 -0800 | |
|---|---|---|
| committer | 2020-02-18 11:13:21 -0800 | |
| commit | 2bd95bf6ad6cd6e16f4b3b4f8f8ae90285dc322b (patch) | |
| tree | d47de4fba2dc2782071c71d325b7b68060d58ada | |
| parent | 8eb3cbe1bae057d356be4e4da0b38965d32bd2c8 (diff) | |
ViewRootImpl: Fix overlapping BLAST Sync issues.
Currently we aren't well equipped to handle overlapping synchronization.
That is to say where a second BLAST Sync begins before the first one finishes.
We track enabling this in b/149747443. In the mean-time we take a few steps
to prevent overlap:
1. Call finishBLASTSync directly from the RT callback rather than posting
to the UI thread.
2. Before consuming "mNextDrawUseBLASTSync" fence the threaded renderer to make sure
any previous draw has finished and emitted its callback.
3. Use seperate variable for tracking whether the BLAST transaction has been applied
so that an earlier draw finishing inbetween us calling setNextDrawUseBLASTSync
and calling performDraw, will not lear the value of mNextDrawUseBlastSync.
Test: Flip the flag, play with youtube.
Bug: 149747443
Bug: 146598493
Bug: 149251083
Bug: 149315421
Change-Id: I6cfd976cd72345acc814fc99d182b50456014a0e
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 857bc5058d60..b32ebe9e4ffd 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -664,7 +664,22 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } + // If set, ViewRootImpl will call BLASTBufferQueue::setNextTransaction with + // mRtBLASTSyncTransaction, prior to invoking draw. This provides a way + // to redirect the buffers in to transactions. private boolean mNextDrawUseBLASTSyncTransaction; + // Set when calling setNextTransaction, we can't just reuse mNextDrawUseBLASTSyncTransaction + // because, imagine this scenario: + // 1. First draw is using BLAST, mNextDrawUseBLAST = true + // 2. We call perform draw and are waiting on the callback + // 3. After the first perform draw but before the first callback and the + // second perform draw, a second draw sets mNextDrawUseBLAST = true (it already was) + // 4. At this point the callback fires and we set mNextDrawUseBLAST = false; + // 5. We get to performDraw and fail to sync as we intended because mNextDrawUseBLAST + // is now false. + // This is why we use a two-step latch with the two booleans, one consumed from + // performDraw and one consumed from finishBLASTSync() + private boolean mNextReportConsumeBLAST; // Be very careful with the threading here. This is used from the render thread while // the UI thread is paused and then applied and cleared from the UI thread right after // draw returns. @@ -3694,9 +3709,9 @@ public final class ViewRootImpl implements ViewParent, usingAsyncReport = mReportNextDraw; if (needFrameCompleteCallback) { final Handler handler = mAttachInfo.mHandler; - mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> + mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> { + finishBLASTSync(); handler.postAtFrontOfQueue(() -> { - finishBLASTSync(); if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); @@ -3706,12 +3721,23 @@ public final class ViewRootImpl implements ViewParent, commitCallbacks.get(i).run(); } } - })); + });}); } } try { if (mNextDrawUseBLASTSyncTransaction) { + // TODO(b/149747443) + // We aren't prepared to handle overlapping use of mRtBLASTSyncTransaction + // so if we are BLAST syncing we make sure the previous draw has + // totally finished. + if (mAttachInfo.mThreadedRenderer != null) { + mAttachInfo.mThreadedRenderer.fence(); + } + + mNextReportConsumeBLAST = true; + mNextDrawUseBLASTSyncTransaction = false; + mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); } boolean canUseAsync = draw(fullRedrawNeeded); @@ -9551,8 +9577,8 @@ public final class ViewRootImpl implements ViewParent, } private void finishBLASTSync() { - if (mNextDrawUseBLASTSyncTransaction) { - mNextDrawUseBLASTSyncTransaction = false; + if (mNextReportConsumeBLAST) { + mNextReportConsumeBLAST = false; mRtBLASTSyncTransaction.apply(); } } |