Merge "Use BBQ syncing instead of blocking in VRI"

This commit is contained in:
Chavi Weingarten
2021-10-20 14:06:22 +00:00
committed by Android (Google) Code Review

View File

@@ -736,47 +736,20 @@ public final class ViewRootImpl implements ViewParent,
}
/**
* This is only used when the UI thread is paused due to {@link #mNextDrawUseBlastSync} being
* set. Specifically, it's only used when calling
* {@link BLASTBufferQueue#setNextTransaction(Transaction)} and then merged with
* {@link #mSurfaceChangedTransaction}. It doesn't need to be thread safe since it's only
* accessed when the UI thread is paused.
* This is only used on the RenderThread when handling a blast sync. Specifically, it's only
* used when calling {@link BLASTBufferQueue#setNextTransaction(Transaction)} and then merged
* with a tmp transaction on the Render Thread. The tmp transaction is then merged into
* {@link #mSurfaceChangedTransaction} on the UI Thread, avoiding any threading issues.
*/
private final SurfaceControl.Transaction mRtBLASTSyncTransaction =
new SurfaceControl.Transaction();
/**
* Keeps track of whether the WM requested to use BLAST Sync when calling relayout. When set,
* we pause the UI thread to ensure we don't get overlapping requests. We then send a
* transaction to {@link BLASTBufferQueue#setNextTransaction(Transaction)}, which is then sent
* back to WM to synchronize.
*
* This flag is set to false only after the synchronized transaction that contains the buffer
* has been sent to SurfaceFlinger.
*/
private boolean mNextDrawUseBlastSync = false;
/**
* Wait for the blast sync transaction complete callback before drawing and queuing up more
* frames. This will prevent out of order buffers submissions when WM has requested to
* synchronize with the client.
*/
private boolean mWaitForBlastSyncComplete = false;
/**
* Keeps track of the last frame number that was attempted to draw. Should only be accessed on
* the RenderThread.
*/
private long mRtLastAttemptedDrawFrameNum = 0;
/**
* Keeps track of whether a traverse was triggered while the UI thread was paused. This can
* occur when the client is waiting on another process to submit the transaction that
* contains the buffer. The UI thread needs to wait on the callback before it can submit
* another buffer.
*/
private boolean mRequestedTraverseWhilePaused = false;
private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks;
private long mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS;
@@ -1601,7 +1574,7 @@ public final class ViewRootImpl implements ViewParent,
mForceNextWindowRelayout = forceNextWindowRelayout;
mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
if (msg == MSG_RESIZED_REPORT && !mNextDrawUseBlastSync) {
if (msg == MSG_RESIZED_REPORT) {
reportNextDraw();
}
@@ -2496,23 +2469,6 @@ public final class ViewRootImpl implements ViewParent,
return;
}
// This is to ensure we don't end up queueing new frames while waiting on a previous frame
// to get latched. This can happen when there's been a sync request for this window. The
// frame could be in a transaction that's passed to different processes to ensure
// synchronization. It continues to block until ViewRootImpl receives a callback that the
// transaction containing the buffer has been sent to SurfaceFlinger. Once we receive, that
// signal, we know it's safe to start queuing new buffers.
//
// When the callback is invoked, it will trigger a traversal request if
// mRequestedTraverseWhilePaused is set so there's no need to attempt a retry here.
if (mWaitForBlastSyncComplete) {
if (DEBUG_BLAST) {
Log.w(mTag, "Can't perform draw while waiting for a transaction complete");
}
mRequestedTraverseWhilePaused = true;
return;
}
mIsInTraversal = true;
mWillDrawSoon = true;
boolean windowSizeMayChange = false;
@@ -2756,6 +2712,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
final boolean wasReportNextDraw = mReportNextDraw;
boolean useBlastSync = false;
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
@@ -2808,7 +2765,7 @@ public final class ViewRootImpl implements ViewParent,
}
reportNextDraw();
if (isHardwareEnabled()) {
mNextDrawUseBlastSync = true;
useBlastSync = true;
}
}
@@ -3282,7 +3239,7 @@ public final class ViewRootImpl implements ViewParent,
}
mPendingTransitions.clear();
}
performDraw();
performDraw(useBlastSync);
} else {
if (isViewVisible) {
// Try again
@@ -3967,22 +3924,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
/**
* Only call this on the UI Thread.
*/
void clearBlastSync() {
mNextDrawUseBlastSync = false;
mWaitForBlastSyncComplete = false;
if (DEBUG_BLAST) {
Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
+ " due to a previous skipped traversal.");
}
if (mRequestedTraverseWhilePaused) {
mRequestedTraverseWhilePaused = false;
scheduleTraversals();
}
}
/**
* @hide
*/
@@ -3990,12 +3931,13 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
}
private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) {
private boolean addFrameCompleteCallbackIfNeeded(boolean useBlastSync,
boolean reportNextDraw) {
if (!isHardwareEnabled()) {
return false;
}
if (!mNextDrawUseBlastSync && !reportNextDraw) {
if (!useBlastSync && !reportNextDraw) {
return false;
}
@@ -4017,30 +3959,22 @@ public final class ViewRootImpl implements ViewParent,
// for the current draw attempt.
if (frameWasNotDrawn) {
mBlastBufferQueue.setNextTransaction(null);
mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum,
null);
// Apply the transactions that were sent to mergeWithNextTransaction since the
// frame didn't draw on this vsync. It's possible the frame will draw later, but
// it's better to not be sync than to block on a frame that may never come.
mBlastBufferQueue.applyPendingTransactions(mRtLastAttemptedDrawFrameNum);
}
Transaction tmpTransaction = new Transaction();
tmpTransaction.merge(mRtBLASTSyncTransaction);
mHandler.postAtFrontOfQueue(() -> {
if (mNextDrawUseBlastSync) {
// We don't need to synchronize mRtBLASTSyncTransaction here since we're
// guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
// is only true when the UI thread is paused. Therefore, no one should be
// modifying this object until the next vsync.
mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction);
if (useBlastSync) {
mSurfaceChangedTransaction.merge(tmpTransaction);
}
if (reportNextDraw) {
pendingDrawFinished();
}
if (frameWasNotDrawn) {
clearBlastSync();
}
});
});
return true;
@@ -4076,21 +4010,19 @@ public final class ViewRootImpl implements ViewParent,
});
}
private void addFrameCallbackIfNeeded() {
final boolean nextDrawUseBlastSync = mNextDrawUseBlastSync;
private void addFrameCallbackIfNeeded(boolean useBlastSync) {
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
if (!nextDrawUseBlastSync && !needsCallbackForBlur) {
if (!useBlastSync && !needsCallbackForBlur) {
return;
}
if (DEBUG_BLAST) {
Log.d(mTag, "Creating frameDrawingCallback"
+ " nextDrawUseBlastSync=" + nextDrawUseBlastSync
+ " nextDrawUseBlastSync=" + useBlastSync
+ " hasBlurUpdates=" + hasBlurUpdates);
}
mWaitForBlastSyncComplete = nextDrawUseBlastSync;
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
@@ -4098,7 +4030,7 @@ public final class ViewRootImpl implements ViewParent,
HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
if (DEBUG_BLAST) {
Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
+ " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
+ " Creating transactionCompleteCallback=" + useBlastSync);
}
mRtLastAttemptedDrawFrameNum = frame;
@@ -4112,7 +4044,7 @@ public final class ViewRootImpl implements ViewParent,
return;
}
if (nextDrawUseBlastSync) {
if (useBlastSync) {
// 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.
@@ -4120,35 +4052,27 @@ public final class ViewRootImpl implements ViewParent,
// We don't need to synchronize mRtBLASTSyncTransaction here since it's not
// being modified and only sent to BlastBufferQueue.
mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
mBlastBufferQueue.setTransactionCompleteCallback(frame, frameNumber -> {
if (DEBUG_BLAST) {
Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
}
mHandler.postAtFrontOfQueue(this::clearBlastSync);
});
}
};
registerRtFrameCallback(frameDrawingCallback);
}
private void performDraw() {
private void performDraw(boolean useBlastSync) {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
} else if (mView == null) {
return;
}
final boolean fullRedrawNeeded =
mFullRedrawNeeded || mReportNextDraw || mNextDrawUseBlastSync;
final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || useBlastSync;
mFullRedrawNeeded = false;
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
addFrameCallbackIfNeeded();
addFrameCallbackIfNeeded(useBlastSync);
addFrameCommitCallbackIfNeeded();
boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw);
boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(useBlastSync, mReportNextDraw);
try {
boolean canUseAsync = draw(fullRedrawNeeded);
@@ -4393,7 +4317,7 @@ public final class ViewRootImpl implements ViewParent,
mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
boolean useAsyncReport = false;
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty || mNextDrawUseBlastSync) {
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (isHardwareEnabled()) {
// If accessibility focus moved, always invalidate the root.
boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;