Merge "Revert "Replace VRI and SV sync logic with SurfaceSyncer"" into tm-dev
This commit is contained in:
@@ -401,7 +401,7 @@ public class SurfaceControlViewHost {
|
|||||||
public void relayout(WindowManager.LayoutParams attrs,
|
public void relayout(WindowManager.LayoutParams attrs,
|
||||||
WindowlessWindowManager.ResizeCompleteCallback callback) {
|
WindowlessWindowManager.ResizeCompleteCallback callback) {
|
||||||
mViewRoot.setLayoutParams(attrs, false);
|
mViewRoot.setLayoutParams(attrs, false);
|
||||||
mViewRoot.setReportNextDraw(true /* syncBuffer */);
|
mViewRoot.setReportNextDraw();
|
||||||
mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), callback);
|
mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import android.view.accessibility.IAccessibilityEmbeddedConnection;
|
|||||||
import com.android.internal.view.SurfaceCallbackHelper;
|
import com.android.internal.view.SurfaceCallbackHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -204,12 +203,19 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
|
|
||||||
private int mSurfaceFlags = SurfaceControl.HIDDEN;
|
private int mSurfaceFlags = SurfaceControl.HIDDEN;
|
||||||
|
|
||||||
|
private int mPendingReportDraws;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction that should be used from the render thread. This transaction is only thread safe
|
* Transaction that should be used from the render thread. This transaction is only thread safe
|
||||||
* with other calls directly from the render thread.
|
* with other calls directly from the render thread.
|
||||||
*/
|
*/
|
||||||
private final SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
|
private final SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used on the main thread to set the transaction that will be synced with the main window.
|
||||||
|
*/
|
||||||
|
private final Transaction mSyncTransaction = new Transaction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction that should be used whe
|
* Transaction that should be used whe
|
||||||
* {@link HardwareRenderer.FrameDrawingCallback#onFrameDraw} is invoked. All
|
* {@link HardwareRenderer.FrameDrawingCallback#onFrameDraw} is invoked. All
|
||||||
@@ -385,12 +391,31 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performDrawFinished() {
|
private void performDrawFinished(@Nullable Transaction t) {
|
||||||
mDrawFinished = true;
|
if (t != null) {
|
||||||
if (mAttachedToWindow) {
|
mSyncTransaction.merge(t);
|
||||||
mParent.requestTransparentRegion(SurfaceView.this);
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mPendingReportDraws > 0) {
|
||||||
|
mDrawFinished = true;
|
||||||
|
if (mAttachedToWindow) {
|
||||||
|
mParent.requestTransparentRegion(SurfaceView.this);
|
||||||
|
notifyDrawFinished();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, System.identityHashCode(this) + "finished drawing"
|
||||||
|
+ " but no pending report draw (extra call"
|
||||||
|
+ " to draw completion runnable?)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyDrawFinished() {
|
||||||
|
ViewRootImpl viewRoot = getViewRootImpl();
|
||||||
|
if (viewRoot != null) {
|
||||||
|
viewRoot.pendingDrawFinished(mSyncTransaction);
|
||||||
|
}
|
||||||
|
mPendingReportDraws--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -413,6 +438,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
mGlobalListenersAdded = false;
|
mGlobalListenersAdded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (mPendingReportDraws > 0) {
|
||||||
|
notifyDrawFinished();
|
||||||
|
}
|
||||||
|
|
||||||
mRequestedVisible = false;
|
mRequestedVisible = false;
|
||||||
|
|
||||||
updateSurface();
|
updateSurface();
|
||||||
@@ -964,17 +993,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean redrawNeeded = sizeChanged || creating || hintChanged
|
|
||||||
|| (mVisible && !mDrawFinished);
|
|
||||||
final TransactionCallback transactionCallback =
|
|
||||||
redrawNeeded ? new TransactionCallback() : null;
|
|
||||||
if (redrawNeeded && viewRoot.wasRelayoutRequested()) {
|
|
||||||
mBlastBufferQueue.syncNextTransaction(
|
|
||||||
false /* acquireSingleBuffer */,
|
|
||||||
transactionCallback::onTransactionReady);
|
|
||||||
}
|
|
||||||
final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
|
final boolean realSizeChanged = performSurfaceTransaction(viewRoot,
|
||||||
translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
|
translator, creating, sizeChanged, hintChanged, surfaceUpdateTransaction);
|
||||||
|
final boolean redrawNeeded = sizeChanged || creating || hintChanged
|
||||||
|
|| (mVisible && !mDrawFinished);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SurfaceHolder.Callback[] callbacks = null;
|
SurfaceHolder.Callback[] callbacks = null;
|
||||||
@@ -993,7 +1015,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
mIsCreating = true;
|
mIsCreating = true;
|
||||||
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
|
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
|
||||||
+ "visibleChanged -- surfaceCreated");
|
+ "visibleChanged -- surfaceCreated");
|
||||||
callbacks = getSurfaceCallbacks();
|
if (callbacks == null) {
|
||||||
|
callbacks = getSurfaceCallbacks();
|
||||||
|
}
|
||||||
for (SurfaceHolder.Callback c : callbacks) {
|
for (SurfaceHolder.Callback c : callbacks) {
|
||||||
c.surfaceCreated(mSurfaceHolder);
|
c.surfaceCreated(mSurfaceHolder);
|
||||||
}
|
}
|
||||||
@@ -1011,7 +1035,32 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (redrawNeeded) {
|
if (redrawNeeded) {
|
||||||
redrawNeeded(callbacks, transactionCallback);
|
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
|
||||||
|
+ "surfaceRedrawNeeded");
|
||||||
|
if (callbacks == null) {
|
||||||
|
callbacks = getSurfaceCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean wasRelayoutRequested = viewRoot.wasRelayoutRequested();
|
||||||
|
if (wasRelayoutRequested && (mBlastBufferQueue != null)) {
|
||||||
|
mBlastBufferQueue.syncNextTransaction(
|
||||||
|
false /* acquireSingleBuffer */,
|
||||||
|
this::onDrawFinished);
|
||||||
|
}
|
||||||
|
mPendingReportDraws++;
|
||||||
|
viewRoot.drawPending();
|
||||||
|
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
|
||||||
|
if (mBlastBufferQueue != null) {
|
||||||
|
mBlastBufferQueue.stopContinuousSyncTransaction();
|
||||||
|
}
|
||||||
|
// If relayout was requested, then a callback from BBQ will
|
||||||
|
// be invoked with the sync transaction. onDrawFinished will be
|
||||||
|
// called in there
|
||||||
|
if (!wasRelayoutRequested) {
|
||||||
|
onDrawFinished(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1030,64 +1079,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void redrawNeeded(SurfaceHolder.Callback[] callbacks,
|
|
||||||
@Nullable TransactionCallback transactionCallback) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.i(TAG, System.identityHashCode(this) + " surfaceRedrawNeeded");
|
|
||||||
}
|
|
||||||
final SurfaceHolder.Callback[] capturedCallbacks =
|
|
||||||
callbacks == null ? getSurfaceCallbacks() : callbacks;
|
|
||||||
|
|
||||||
ViewRootImpl viewRoot = getViewRootImpl();
|
|
||||||
boolean isVriSync = viewRoot.addToSync(syncBufferCallback ->
|
|
||||||
redrawNeededAsync(capturedCallbacks, () -> {
|
|
||||||
if (mBlastBufferQueue != null) {
|
|
||||||
mBlastBufferQueue.stopContinuousSyncTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
Transaction t = null;
|
|
||||||
if (transactionCallback != null && mBlastBufferQueue != null) {
|
|
||||||
t = transactionCallback.waitForTransaction();
|
|
||||||
}
|
|
||||||
// If relayout was requested, then a callback from BBQ will
|
|
||||||
// be invoked with the sync transaction. onDrawFinished will be
|
|
||||||
// called in there
|
|
||||||
syncBufferCallback.onBufferReady(t);
|
|
||||||
onDrawFinished();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// If isVriSync, then everything was setup in the addToSync.
|
|
||||||
if (isVriSync) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
redrawNeededAsync(capturedCallbacks, this::onDrawFinished);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void redrawNeededAsync(SurfaceHolder.Callback[] callbacks,
|
|
||||||
Runnable callbacksCollected) {
|
|
||||||
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(callbacksCollected);
|
|
||||||
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TransactionCallback {
|
|
||||||
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
|
|
||||||
private Transaction mTransaction;
|
|
||||||
|
|
||||||
Transaction waitForTransaction() {
|
|
||||||
try {
|
|
||||||
mCountDownLatch.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
return mTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onTransactionReady(Transaction t) {
|
|
||||||
mTransaction = t;
|
|
||||||
mCountDownLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the Surface from the SurfaceControl or the blast adapter.
|
* Copy the Surface from the SurfaceControl or the blast adapter.
|
||||||
*
|
*
|
||||||
@@ -1198,13 +1189,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
|
mBlastBufferQueue.update(mBlastSurfaceControl, mSurfaceWidth, mSurfaceHeight, mFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDrawFinished() {
|
private void onDrawFinished(@Nullable Transaction t) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, System.identityHashCode(this) + " "
|
Log.i(TAG, System.identityHashCode(this) + " "
|
||||||
+ "finishedDrawing");
|
+ "finishedDrawing");
|
||||||
}
|
}
|
||||||
|
|
||||||
runOnUiThread(this::performDrawFinished);
|
runOnUiThread(() -> performDrawFinished(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -582,15 +582,11 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
|
|
||||||
boolean mReportNextDraw;
|
boolean mReportNextDraw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether the draw should send the buffer to system server. When set to true, VRI will
|
* Set whether the draw should use blast sync. This is in case the draw is canceled,
|
||||||
* create a sync transaction with BBQ and send the resulting buffer to system server. If false,
|
* but will be rescheduled. We still want the next draw to be sync.
|
||||||
* VRI will not try to sync a buffer in BBQ, but still report when a draw occurred.
|
|
||||||
*
|
|
||||||
* Default is true since we normally want to sync the buffer.
|
|
||||||
*/
|
*/
|
||||||
private boolean mSyncBuffer = true;
|
boolean mNextDrawUseBlastSync;
|
||||||
|
|
||||||
boolean mFullRedrawNeeded;
|
boolean mFullRedrawNeeded;
|
||||||
boolean mNewSurfaceNeeded;
|
boolean mNewSurfaceNeeded;
|
||||||
@@ -811,10 +807,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return mHandwritingInitiator;
|
return mHandwritingInitiator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer();
|
|
||||||
private int mLastSyncId = -1;
|
|
||||||
private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of the last frame number that was attempted to draw. Should only be accessed on
|
* Keeps track of the last frame number that was attempted to draw. Should only be accessed on
|
||||||
* the RenderThread.
|
* the RenderThread.
|
||||||
@@ -2893,6 +2885,8 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
|
mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final boolean wasReportNextDraw = mReportNextDraw;
|
||||||
|
boolean useBlastSync = mNextDrawUseBlastSync;
|
||||||
|
|
||||||
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|
||||||
|| mForceNextWindowRelayout) {
|
|| mForceNextWindowRelayout) {
|
||||||
@@ -2931,6 +2925,9 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
Log.d(mTag, "Relayout called with blastSync");
|
Log.d(mTag, "Relayout called with blastSync");
|
||||||
}
|
}
|
||||||
reportNextDraw();
|
reportNextDraw();
|
||||||
|
if (isHardwareEnabled()) {
|
||||||
|
useBlastSync = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean surfaceControlChanged =
|
final boolean surfaceControlChanged =
|
||||||
@@ -3166,7 +3163,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
// done to achieve a more hermetic fix for S, but it's entirely
|
// done to achieve a more hermetic fix for S, but it's entirely
|
||||||
// possible that checking the most recent value is actually more
|
// possible that checking the most recent value is actually more
|
||||||
// correct here.
|
// correct here.
|
||||||
if (!mStopped || mReportNextDraw) {
|
if (!mStopped || wasReportNextDraw) {
|
||||||
if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()
|
if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()
|
||||||
|| dispatchApplyInsets || updatedConfiguration) {
|
|| dispatchApplyInsets || updatedConfiguration) {
|
||||||
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width,
|
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width,
|
||||||
@@ -3235,7 +3232,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
prepareSurfaces();
|
prepareSurfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
|
final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw);
|
||||||
boolean triggerGlobalLayoutListener = didLayout
|
boolean triggerGlobalLayoutListener = didLayout
|
||||||
|| mAttachInfo.mRecomputeGlobalAttributes;
|
|| mAttachInfo.mRecomputeGlobalAttributes;
|
||||||
if (didLayout) {
|
if (didLayout) {
|
||||||
@@ -3428,40 +3425,51 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);
|
mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);
|
||||||
|
|
||||||
// If we already got a request for blast sync, then we don't want to unset mSyncBuffer
|
// Remember if we must report the next draw.
|
||||||
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0
|
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
|
||||||
&& !mReportNextDraw) {
|
|
||||||
reportNextDraw();
|
reportNextDraw();
|
||||||
mSyncBuffer = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
|
boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
|
||||||
if (!cancelAndRedraw) {
|
if (mBLASTDrawConsumer != null) {
|
||||||
createSyncIfNeeded();
|
useBlastSync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isViewVisible) {
|
if (!cancelDraw) {
|
||||||
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
|
|
||||||
for (int i = 0; i < mPendingTransitions.size(); ++i) {
|
|
||||||
mPendingTransitions.get(i).endChangingAnimations();
|
|
||||||
}
|
|
||||||
mPendingTransitions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSyncBufferCallback != null) {
|
|
||||||
mSyncBufferCallback.onBufferReady(null);
|
|
||||||
}
|
|
||||||
} else if (cancelAndRedraw) {
|
|
||||||
// Try again
|
|
||||||
scheduleTraversals();
|
|
||||||
} else {
|
|
||||||
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
|
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
|
||||||
for (int i = 0; i < mPendingTransitions.size(); ++i) {
|
for (int i = 0; i < mPendingTransitions.size(); ++i) {
|
||||||
mPendingTransitions.get(i).startChangingAnimations();
|
mPendingTransitions.get(i).startChangingAnimations();
|
||||||
}
|
}
|
||||||
mPendingTransitions.clear();
|
mPendingTransitions.clear();
|
||||||
}
|
}
|
||||||
performDraw();
|
performDraw(useBlastSync);
|
||||||
|
mNextDrawUseBlastSync = false;
|
||||||
|
} else {
|
||||||
|
if (isViewVisible) {
|
||||||
|
// Try again
|
||||||
|
mNextDrawUseBlastSync = useBlastSync;
|
||||||
|
scheduleTraversals();
|
||||||
|
} else {
|
||||||
|
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
|
||||||
|
for (int i = 0; i < mPendingTransitions.size(); ++i) {
|
||||||
|
mPendingTransitions.get(i).endChangingAnimations();
|
||||||
|
}
|
||||||
|
mPendingTransitions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We may never draw since it's not visible. Report back that we're finished
|
||||||
|
// drawing.
|
||||||
|
if (!wasReportNextDraw && mReportNextDraw) {
|
||||||
|
mReportNextDraw = false;
|
||||||
|
pendingDrawFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the consumer is not waiting if the view root was just made invisible.
|
||||||
|
if (mBLASTDrawConsumer != null) {
|
||||||
|
mBLASTDrawConsumer.accept(null);
|
||||||
|
mBLASTDrawConsumer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAttachInfo.mContentCaptureEvents != null) {
|
if (mAttachInfo.mContentCaptureEvents != null) {
|
||||||
@@ -3470,46 +3478,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
|
|
||||||
mIsInTraversal = false;
|
mIsInTraversal = false;
|
||||||
mRelayoutRequested = false;
|
mRelayoutRequested = false;
|
||||||
|
|
||||||
if (!cancelAndRedraw) {
|
|
||||||
mReportNextDraw = false;
|
|
||||||
mSyncBufferCallback = null;
|
|
||||||
mSyncBuffer = true;
|
|
||||||
if (mLastSyncId != -1) {
|
|
||||||
mSurfaceSyncer.markSyncReady(mLastSyncId);
|
|
||||||
mLastSyncId = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createSyncIfNeeded() {
|
|
||||||
// Started a sync already.
|
|
||||||
if (mLastSyncId != -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Consumer<Transaction> syncConsumer = null;
|
|
||||||
if (mBLASTDrawConsumer != null) {
|
|
||||||
syncConsumer = mBLASTDrawConsumer;
|
|
||||||
mBLASTDrawConsumer = null;
|
|
||||||
} else if (mReportNextDraw) {
|
|
||||||
syncConsumer = transaction -> {
|
|
||||||
mSurfaceChangedTransaction.merge(transaction);
|
|
||||||
reportDrawFinished();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncConsumer != null) {
|
|
||||||
final Consumer<Transaction> capturedSyncConsumer = syncConsumer;
|
|
||||||
mLastSyncId = mSurfaceSyncer.setupSync(transaction -> {
|
|
||||||
// Callback will be invoked on executor thread so post to main thread.
|
|
||||||
mHandler.postAtFrontOfQueue(() -> capturedSyncConsumer.accept(transaction));
|
|
||||||
});
|
|
||||||
if (DEBUG_BLAST) {
|
|
||||||
Log.d(mTag, "Setup new sync id=" + mLastSyncId);
|
|
||||||
}
|
|
||||||
mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyContentCatpureEvents() {
|
private void notifyContentCatpureEvents() {
|
||||||
@@ -4123,10 +4091,54 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A count of the number of calls to pendingDrawFinished we
|
||||||
|
* require to notify the WM drawing is complete.
|
||||||
|
*/
|
||||||
|
int mDrawsNeededToReport = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delay notifying WM of draw finished until
|
||||||
|
* a balanced call to pendingDrawFinished.
|
||||||
|
*/
|
||||||
|
void drawPending() {
|
||||||
|
mDrawsNeededToReport++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pendingDrawFinished(Transaction t) {
|
||||||
|
if (mDrawsNeededToReport == 0) {
|
||||||
|
throw new RuntimeException("Unbalanced drawPending/pendingDrawFinished calls");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t != null) {
|
||||||
|
if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag, "Merging transaction into main window transaction");
|
||||||
|
}
|
||||||
|
mSurfaceChangedTransaction.merge(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDrawsNeededToReport--;
|
||||||
|
if (mDrawsNeededToReport == 0) {
|
||||||
|
reportDrawFinished();
|
||||||
|
} else if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag, "pendingDrawFinished. Waiting on draw reported mDrawsNeededToReport="
|
||||||
|
+ mDrawsNeededToReport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pendingDrawFinished() {
|
||||||
|
pendingDrawFinished(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postDrawFinished() {
|
||||||
|
mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
|
||||||
|
}
|
||||||
|
|
||||||
private void reportDrawFinished() {
|
private void reportDrawFinished() {
|
||||||
if (DEBUG_BLAST) {
|
if (DEBUG_BLAST) {
|
||||||
Log.d(mTag, "reportDrawFinished " + Debug.getCallers(5));
|
Log.d(mTag, "reportDrawFinished");
|
||||||
}
|
}
|
||||||
|
mDrawsNeededToReport = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
|
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
|
||||||
@@ -4145,14 +4157,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
|
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean addToSync(SurfaceSyncer.SyncTarget syncable) {
|
|
||||||
if (mLastSyncId == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mSurfaceSyncer.addToSync(mLastSyncId, syncable);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFrameCommitCallbackIfNeeded() {
|
private void addFrameCommitCallbackIfNeeded() {
|
||||||
if (!isHardwareEnabled()) {
|
if (!isHardwareEnabled()) {
|
||||||
return;
|
return;
|
||||||
@@ -4183,81 +4187,188 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
|
||||||
|
boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
|
||||||
|
return didProduceBuffer -> {
|
||||||
|
if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag, "Received frameCommittedCallback "
|
||||||
|
+ " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
|
||||||
|
+ " didProduceBuffer=" + didProduceBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If frame wasn't drawn, clear out the next transaction so it doesn't affect the next
|
||||||
|
// draw attempt. The next transaction and transaction complete callback were only set
|
||||||
|
// for the current draw attempt.
|
||||||
|
final Transaction pendingTransactions;
|
||||||
|
if (!didProduceBuffer) {
|
||||||
|
mBlastBufferQueue.syncNextTransaction(null);
|
||||||
|
// Get 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.
|
||||||
|
pendingTransactions = mBlastBufferQueue.gatherPendingTransactions(
|
||||||
|
mRtLastAttemptedDrawFrameNum);
|
||||||
|
if (!useBlastSync && !reportNextDraw) {
|
||||||
|
pendingTransactions.apply();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pendingTransactions = null;
|
||||||
|
}
|
||||||
|
// Post at front of queue so the buffer can be processed immediately and allow RT
|
||||||
|
// to continue processing new buffers. If RT tries to process buffers before the sync
|
||||||
|
// buffer is applied, the new buffers will not get acquired and could result in a
|
||||||
|
// deadlock. UI thread would wait on RT, but RT would be blocked waiting for a free
|
||||||
|
// buffer.
|
||||||
|
mHandler.postAtFrontOfQueue(() -> {
|
||||||
|
if (!didProduceBuffer && useBlastSync) {
|
||||||
|
mSurfaceChangedTransaction.merge(pendingTransactions);
|
||||||
|
if (blastSyncConsumer != null) {
|
||||||
|
blastSyncConsumer.accept(mSurfaceChangedTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is to ensure pendingDrawFinished is only called exactly one time per draw
|
||||||
|
// attempt when reportNextDraw is true. Since, we sometimes create a sync
|
||||||
|
// transaction callback, the callback will handle calling pendingDrawFinished.
|
||||||
|
// However, there are cases where the transaction callback may not be called.
|
||||||
|
// 1. If useBlastSync is false, then we know that a sync transaction callback was
|
||||||
|
// not created so we won't invoke pendingDrawFinished there.
|
||||||
|
// 2. If the draw didn't produce a frame, didProduceBuffer == false, then we know
|
||||||
|
// the sync transaction callback will not be invoked even if one was set up.
|
||||||
|
if (reportNextDraw && (!didProduceBuffer || !useBlastSync)) {
|
||||||
|
pendingDrawFinished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private void registerFrameDrawingCallbackForBlur() {
|
private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
|
||||||
|
boolean reportNextDraw) {
|
||||||
if (!isHardwareEnabled()) {
|
if (!isHardwareEnabled()) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
|
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
|
||||||
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
|
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
|
||||||
|
|
||||||
if (!needsCallbackForBlur) {
|
if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw && !mHasPendingTransactions) {
|
||||||
return;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
|
||||||
|
mBLASTDrawConsumer = null;
|
||||||
|
|
||||||
|
if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag, "Creating frameDrawingCallback"
|
||||||
|
+ " nextDrawUseBlastSync=" + useBlastSync
|
||||||
|
+ " reportNextDraw=" + reportNextDraw
|
||||||
|
+ " hasBlurUpdates=" + hasBlurUpdates
|
||||||
|
+ " hasBlastSyncConsumer=" + (blastSyncConsumer != null)
|
||||||
|
+ " mHasPendingTransactions=" + mHasPendingTransactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
|
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
|
||||||
mBlurRegionAggregator.getBlurRegionsCopyForRT();
|
needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
|
||||||
|
final boolean hasPendingTransactions = mHasPendingTransactions;
|
||||||
|
mHasPendingTransactions = false;
|
||||||
|
|
||||||
// The callback will run on the render thread.
|
// The callback will run on the render thread.
|
||||||
registerRtFrameCallback((frame) -> mBlurRegionAggregator
|
return new FrameDrawingCallback() {
|
||||||
.dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerCallbackForPendingTransactions() {
|
|
||||||
registerRtFrameCallback(new FrameDrawingCallback() {
|
|
||||||
@Override
|
|
||||||
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
|
|
||||||
if ((syncResult
|
|
||||||
& (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
|
|
||||||
mBlastBufferQueue.applyPendingTransactions(frame);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return didProduceBuffer -> {
|
|
||||||
if (!didProduceBuffer) {
|
|
||||||
mBlastBufferQueue.applyPendingTransactions(frame);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFrameDraw(long frame) {
|
public void onFrameDraw(long frame) {
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
|
||||||
|
if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag,
|
||||||
|
"Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
|
||||||
|
+ frame + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
mRtLastAttemptedDrawFrameNum = frame;
|
||||||
|
|
||||||
|
if (needsCallbackForBlur) {
|
||||||
|
mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
|
||||||
|
blurRegionsForFrame, hasBlurUpdates);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBlastBufferQueue == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useBlastSync && !reportNextDraw && !hasPendingTransactions) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
|
||||||
|
// SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
|
||||||
|
// any blast sync or commit callback, and the code should directly call
|
||||||
|
// pendingDrawFinished.
|
||||||
|
if ((syncResult
|
||||||
|
& (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
|
||||||
|
if (reportNextDraw) {
|
||||||
|
mHandler.postAtFrontOfQueue(() -> pendingDrawFinished());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_BLAST) {
|
||||||
|
Log.d(mTag, "Setting up sync and frameCommitCallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
mBlastBufferQueue.syncNextTransaction(
|
||||||
|
t -> {
|
||||||
|
mHandler.postAtFrontOfQueue(() -> {
|
||||||
|
mSurfaceChangedTransaction.merge(t);
|
||||||
|
if (blastSyncConsumer != null) {
|
||||||
|
blastSyncConsumer.accept(mSurfaceChangedTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reportNextDraw) {
|
||||||
|
pendingDrawFinished();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
|
||||||
|
blastSyncConsumer);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performDraw() {
|
private void performDraw(boolean useBlastSync) {
|
||||||
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
|
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
|
||||||
return;
|
return;
|
||||||
} else if (mView == null) {
|
} else if (mView == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean fullRedrawNeeded = mFullRedrawNeeded || mSyncBufferCallback != null;
|
final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw || useBlastSync;
|
||||||
mFullRedrawNeeded = false;
|
mFullRedrawNeeded = false;
|
||||||
|
|
||||||
mIsDrawing = true;
|
mIsDrawing = true;
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
|
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
|
||||||
|
|
||||||
registerFrameDrawingCallbackForBlur();
|
FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
|
||||||
addFrameCommitCallbackIfNeeded();
|
mReportNextDraw);
|
||||||
|
if (frameDrawingCallback != null) {
|
||||||
boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null;
|
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
|
||||||
if (usingAsyncReport) {
|
|
||||||
registerCallbacksForSync(mSyncBuffer, mSyncBufferCallback);
|
|
||||||
} else if (mHasPendingTransactions) {
|
|
||||||
// These callbacks are only needed if there's no sync involved and there were calls to
|
|
||||||
// applyTransactionOnDraw. These callbacks check if the draw failed for any reason and
|
|
||||||
// apply those transactions directly so they don't get stuck forever.
|
|
||||||
registerCallbackForPendingTransactions();
|
|
||||||
}
|
}
|
||||||
mHasPendingTransactions = false;
|
addFrameCommitCallbackIfNeeded();
|
||||||
|
boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boolean canUseAsync = draw(fullRedrawNeeded);
|
boolean canUseAsync = draw(fullRedrawNeeded);
|
||||||
if (usingAsyncReport && !canUseAsync) {
|
if (usingAsyncReport && !canUseAsync) {
|
||||||
mAttachInfo.mThreadedRenderer.setFrameCallback(null);
|
mAttachInfo.mThreadedRenderer.setFrameCallback(null);
|
||||||
usingAsyncReport = false;
|
usingAsyncReport = false;
|
||||||
|
mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mIsDrawing = false;
|
mIsDrawing = false;
|
||||||
@@ -4275,6 +4386,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mReportNextDraw) {
|
if (mReportNextDraw) {
|
||||||
|
mReportNextDraw = false;
|
||||||
|
|
||||||
// if we're using multi-thread renderer, wait for the window frame draws
|
// if we're using multi-thread renderer, wait for the window frame draws
|
||||||
if (mWindowDrawCountDown != null) {
|
if (mWindowDrawCountDown != null) {
|
||||||
@@ -4295,11 +4407,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mSurfaceHolder != null && mSurface.isValid()) {
|
if (mSurfaceHolder != null && mSurface.isValid()) {
|
||||||
final SurfaceSyncer.SyncBufferCallback syncBufferCallback = mSyncBufferCallback;
|
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::postDrawFinished);
|
||||||
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() ->
|
|
||||||
mHandler.post(() -> syncBufferCallback.onBufferReady(null)));
|
|
||||||
mSyncBufferCallback = null;
|
|
||||||
|
|
||||||
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
|
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
|
||||||
|
|
||||||
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
|
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
|
||||||
@@ -4307,11 +4415,9 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
if (mAttachInfo.mThreadedRenderer != null) {
|
if (mAttachInfo.mThreadedRenderer != null) {
|
||||||
mAttachInfo.mThreadedRenderer.fence();
|
mAttachInfo.mThreadedRenderer.fence();
|
||||||
}
|
}
|
||||||
|
pendingDrawFinished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mSyncBufferCallback != null && !usingAsyncReport) {
|
|
||||||
mSyncBufferCallback.onBufferReady(null);
|
|
||||||
}
|
|
||||||
if (mPerformContentCapture) {
|
if (mPerformContentCapture) {
|
||||||
performContentCaptureInitialReport();
|
performContentCaptureInitialReport();
|
||||||
}
|
}
|
||||||
@@ -5320,6 +5426,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
private static final int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
|
private static final int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
|
||||||
private static final int MSG_UPDATE_POINTER_ICON = 27;
|
private static final int MSG_UPDATE_POINTER_ICON = 27;
|
||||||
private static final int MSG_POINTER_CAPTURE_CHANGED = 28;
|
private static final int MSG_POINTER_CAPTURE_CHANGED = 28;
|
||||||
|
private static final int MSG_DRAW_FINISHED = 29;
|
||||||
private static final int MSG_INSETS_CHANGED = 30;
|
private static final int MSG_INSETS_CHANGED = 30;
|
||||||
private static final int MSG_INSETS_CONTROL_CHANGED = 31;
|
private static final int MSG_INSETS_CONTROL_CHANGED = 31;
|
||||||
private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
|
private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
|
||||||
@@ -5382,6 +5489,8 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return "MSG_UPDATE_POINTER_ICON";
|
return "MSG_UPDATE_POINTER_ICON";
|
||||||
case MSG_POINTER_CAPTURE_CHANGED:
|
case MSG_POINTER_CAPTURE_CHANGED:
|
||||||
return "MSG_POINTER_CAPTURE_CHANGED";
|
return "MSG_POINTER_CAPTURE_CHANGED";
|
||||||
|
case MSG_DRAW_FINISHED:
|
||||||
|
return "MSG_DRAW_FINISHED";
|
||||||
case MSG_INSETS_CHANGED:
|
case MSG_INSETS_CHANGED:
|
||||||
return "MSG_INSETS_CHANGED";
|
return "MSG_INSETS_CHANGED";
|
||||||
case MSG_INSETS_CONTROL_CHANGED:
|
case MSG_INSETS_CONTROL_CHANGED:
|
||||||
@@ -5614,6 +5723,9 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
final boolean hasCapture = msg.arg1 != 0;
|
final boolean hasCapture = msg.arg1 != 0;
|
||||||
handlePointerCaptureChanged(hasCapture);
|
handlePointerCaptureChanged(hasCapture);
|
||||||
} break;
|
} break;
|
||||||
|
case MSG_DRAW_FINISHED: {
|
||||||
|
pendingDrawFinished();
|
||||||
|
} break;
|
||||||
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: {
|
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: {
|
||||||
systemGestureExclusionChanged();
|
systemGestureExclusionChanged();
|
||||||
} break;
|
} break;
|
||||||
@@ -9795,8 +9907,8 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reportNextDraw() {
|
private void reportNextDraw() {
|
||||||
if (DEBUG_BLAST) {
|
if (mReportNextDraw == false) {
|
||||||
Log.d(mTag, "reportNextDraw " + Debug.getCallers(5));
|
drawPending();
|
||||||
}
|
}
|
||||||
mReportNextDraw = true;
|
mReportNextDraw = true;
|
||||||
}
|
}
|
||||||
@@ -9807,14 +9919,9 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
* This method is only supposed to be used to speed up the interaction from SystemUI and window
|
* This method is only supposed to be used to speed up the interaction from SystemUI and window
|
||||||
* manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
|
* manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
|
||||||
* unless you fully understand this interaction.
|
* unless you fully understand this interaction.
|
||||||
*
|
|
||||||
* @param syncBuffer If true, the transaction that contains the buffer from the draw should be
|
|
||||||
* sent to system to be synced. If false, VRI will not try to sync the buffer,
|
|
||||||
* but only report back that a buffer was drawn.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void setReportNextDraw(boolean syncBuffer) {
|
public void setReportNextDraw() {
|
||||||
mSyncBuffer = syncBuffer;
|
|
||||||
reportNextDraw();
|
reportNextDraw();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -10840,15 +10947,14 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return mWindowSession;
|
return mWindowSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCallbacksForSync(boolean syncBuffer,
|
private void registerCallbacksForSync(
|
||||||
final SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
|
final SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
|
||||||
if (!isHardwareEnabled()) {
|
if (!isHardwareEnabled()) {
|
||||||
|
// TODO: correctly handle when hardware disabled
|
||||||
|
syncBufferCallback.onBufferReady(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_BLAST) {
|
|
||||||
Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
|
|
||||||
}
|
|
||||||
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
|
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFrameDraw(long frame) {
|
public void onFrameDraw(long frame) {
|
||||||
@@ -10877,9 +10983,7 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
Log.d(mTag, "Setting up sync and frameCommitCallback");
|
Log.d(mTag, "Setting up sync and frameCommitCallback");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syncBuffer) {
|
mBlastBufferQueue.syncNextTransaction(t -> syncBufferCallback.onBufferReady(t));
|
||||||
mBlastBufferQueue.syncNextTransaction(syncBufferCallback::onBufferReady);
|
|
||||||
}
|
|
||||||
|
|
||||||
return didProduceBuffer -> {
|
return didProduceBuffer -> {
|
||||||
if (DEBUG_BLAST) {
|
if (DEBUG_BLAST) {
|
||||||
@@ -10893,40 +10997,18 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
// were only set for the current draw attempt.
|
// were only set for the current draw attempt.
|
||||||
if (!didProduceBuffer) {
|
if (!didProduceBuffer) {
|
||||||
mBlastBufferQueue.syncNextTransaction(null);
|
mBlastBufferQueue.syncNextTransaction(null);
|
||||||
|
|
||||||
// Gather the transactions that were sent to mergeWithNextTransaction
|
// Gather the transactions that were sent to mergeWithNextTransaction
|
||||||
// since the frame didn't draw on this vsync. It's possible the frame will
|
// 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
|
// draw later, but it's better to not be sync than to block on a frame that
|
||||||
// may never come.
|
// may never come.
|
||||||
syncBufferCallback.onBufferReady(
|
syncBufferCallback.onBufferReady(
|
||||||
mBlastBufferQueue.gatherPendingTransactions(frame));
|
mBlastBufferQueue.gatherPendingTransactions(frame));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't request to sync a buffer, then we won't get the
|
|
||||||
// syncNextTransaction callback. Instead, just report back to the Syncer so it
|
|
||||||
// knows that this sync request is complete.
|
|
||||||
if (!syncBuffer) {
|
|
||||||
syncBufferCallback.onBufferReady(null);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public final SurfaceSyncer.SyncTarget mSyncTarget = this::readyToSync;
|
public final SurfaceSyncer.SyncTarget mSyncTarget =
|
||||||
|
syncBufferCallback -> registerCallbacksForSync(syncBufferCallback);
|
||||||
private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) {
|
|
||||||
if (mSyncBufferCallback != null) {
|
|
||||||
Log.d(mTag, "Already set sync for the next draw.");
|
|
||||||
mSyncBufferCallback.onBufferReady(null);
|
|
||||||
}
|
|
||||||
if (DEBUG_BLAST) {
|
|
||||||
Log.d(mTag, "Setting syncFrameCallback");
|
|
||||||
}
|
|
||||||
mSyncBufferCallback = syncBufferCallback;
|
|
||||||
if (!mIsInTraversal && !mTraversalScheduled) {
|
|
||||||
scheduleTraversals();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2347,8 +2347,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
|
|||||||
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
|
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
|
||||||
// the next draw from here, so we don't have to wait for window manager to signal
|
// the next draw from here, so we don't have to wait for window manager to signal
|
||||||
// this to our ViewRootImpl.
|
// this to our ViewRootImpl.
|
||||||
mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw(
|
mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
|
||||||
false /* syncBuffer */);
|
|
||||||
mScreenOnCoordinator.setWakeAndUnlocking(false);
|
mScreenOnCoordinator.setWakeAndUnlocking(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user