summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Carr <racarr@google.com> 2020-02-18 09:00:03 -0800
committer Robert Carr <racarr@google.com> 2020-02-18 11:13:21 -0800
commit2bd95bf6ad6cd6e16f4b3b4f8f8ae90285dc322b (patch)
treed47de4fba2dc2782071c71d325b7b68060d58ada
parent8eb3cbe1bae057d356be4e4da0b38965d32bd2c8 (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.java36
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();
}
}