summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorChavi Weingarten <chaviw@google.com>2021-12-28 21:17:00 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-12-28 21:17:00 +0000
commit6489e997ac4fd9761da3b54bbbedc778eec66887 (patch)
tree32cd75f28efaec78f663990e45ca917826af5b8f /core/java/android
parentcb60d919701814624f0704d837ae79a5357ed0ae (diff)
parentb680371f7703b3ae60c77efc25939cba1be78439 (diff)
Merge "Send syncStatus and return FrameCommitCallback in FrameCallback"
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/view/ThreadedRenderer.java41
-rw-r--r--core/java/android/view/ViewRootImpl.java197
2 files changed, 157 insertions, 81 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 00754af6a853..1566f9e50f66 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -478,6 +478,19 @@ public final class ThreadedRenderer extends HardwareRenderer {
}
/**
+ * Remove a frame drawing callback that was added via
+ * {@link #registerRtFrameCallback(FrameDrawingCallback)}
+ *
+ * @param callback The callback to unregister.
+ */
+ void unregisterRtFrameCallback(@NonNull FrameDrawingCallback callback) {
+ if (mNextRtFrameCallbacks == null) {
+ return;
+ }
+ mNextRtFrameCallbacks.remove(callback);
+ }
+
+ /**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
*
@@ -679,9 +692,31 @@ public final class ThreadedRenderer extends HardwareRenderer {
if (mNextRtFrameCallbacks != null) {
final ArrayList<FrameDrawingCallback> frameCallbacks = mNextRtFrameCallbacks;
mNextRtFrameCallbacks = null;
- setFrameCallback(frame -> {
- for (int i = 0; i < frameCallbacks.size(); ++i) {
- frameCallbacks.get(i).onFrameDraw(frame);
+ setFrameCallback(new FrameDrawingCallback() {
+ @Override
+ public void onFrameDraw(long frame) {
+ }
+
+ @Override
+ public FrameCommitCallback onFrameDraw(int syncResult, long frame) {
+ ArrayList<FrameCommitCallback> frameCommitCallbacks = new ArrayList<>();
+ for (int i = 0; i < frameCallbacks.size(); ++i) {
+ FrameCommitCallback frameCommitCallback = frameCallbacks.get(i)
+ .onFrameDraw(syncResult, frame);
+ if (frameCommitCallback != null) {
+ frameCommitCallbacks.add(frameCommitCallback);
+ }
+ }
+
+ if (frameCommitCallbacks.isEmpty()) {
+ return null;
+ }
+
+ return didProduceBuffer -> {
+ for (int i = 0; i < frameCommitCallbacks.size(); ++i) {
+ frameCommitCallbacks.get(i).onFrameCommit(didProduceBuffer);
+ }
+ };
}
});
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index af496dcea8e3..1fdbf0e204da 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
+import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -1392,11 +1394,20 @@ public final class ViewRootImpl implements ViewParent,
*/
public void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frame -> {
- try {
- callback.onFrameDraw(frame);
- } catch (Exception e) {
- Log.e(TAG, "Exception while executing onFrameDraw", e);
+ mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
+ @Override
+ public void onFrameDraw(long frame) {
+ }
+
+ @Override
+ public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult,
+ long frame) {
+ try {
+ return callback.onFrameDraw(syncResult, frame);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while executing onFrameDraw", e);
+ }
+ return null;
}
});
}
@@ -4020,36 +4031,49 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
}
- private boolean addFrameCompleteCallbackIfNeeded(boolean useBlastSync,
- boolean reportNextDraw) {
+ private void addFrameCommitCallbackIfNeeded() {
if (!isHardwareEnabled()) {
- return false;
+ return;
}
- if (!useBlastSync && !reportNextDraw) {
- return false;
+ ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
+ .captureFrameCommitCallbacks();
+ final boolean needFrameCommitCallback =
+ (commitCallbacks != null && commitCallbacks.size() > 0);
+ if (!needFrameCommitCallback) {
+ return;
}
- if (DEBUG_BLAST) {
- Log.d(mTag, "Creating frameCompleteCallback");
+ if (DEBUG_DRAW) {
+ Log.d(mTag, "Creating frameCommitCallback"
+ + " commitCallbacks size=" + commitCallbacks.size());
}
+ mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
+ if (DEBUG_DRAW) {
+ Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
+ }
- final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
- mBLASTDrawConsumer = null;
+ mHandler.postAtFrontOfQueue(() -> {
+ for (int i = 0; i < commitCallbacks.size(); i++) {
+ commitCallbacks.get(i).run();
+ }
+ });
+ });
+ }
- mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> {
- long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum();
+ private HardwareRenderer.FrameCommitCallback createFrameCommitCallbackForSync(
+ boolean useBlastSync, boolean reportNextDraw, Consumer<Transaction> blastSyncConsumer) {
+ return didProduceBuffer -> {
if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameCompleteCallback "
- + " lastAcquiredFrameNum=" + frameNr
- + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
+ Log.d(mTag, "Received frameCommittedCallback "
+ + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum
+ + " didProduceBuffer=" + didProduceBuffer);
}
- boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum;
// 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.
- if (frameWasNotDrawn) {
+ if (!didProduceBuffer) {
mBlastBufferQueue.setSyncTransaction(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
@@ -4059,6 +4083,11 @@ public final class ViewRootImpl implements ViewParent,
Transaction tmpTransaction = new Transaction();
tmpTransaction.merge(mRtBLASTSyncTransaction);
+ // 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 (useBlastSync) {
mSurfaceChangedTransaction.merge(tmpTransaction);
@@ -4071,85 +4100,92 @@ public final class ViewRootImpl implements ViewParent,
pendingDrawFinished();
}
});
- });
- return true;
+ };
}
- private void addFrameCommitCallbackIfNeeded() {
+ @Nullable
+ private FrameDrawingCallback createFrameDrawingCallbackIfNeeded(boolean useBlastSync,
+ boolean reportNextDraw) {
if (!isHardwareEnabled()) {
- return;
- }
-
- ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
- .captureFrameCommitCallbacks();
- final boolean needFrameCommitCallback =
- (commitCallbacks != null && commitCallbacks.size() > 0);
- if (!needFrameCommitCallback) {
- return;
- }
-
- if (DEBUG_DRAW) {
- Log.d(mTag, "Creating frameCommitCallback"
- + " commitCallbacks size=" + commitCallbacks.size());
+ return null;
}
- mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
- if (DEBUG_DRAW) {
- Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
- }
-
- mHandler.postAtFrontOfQueue(() -> {
- for (int i = 0; i < commitCallbacks.size(); i++) {
- commitCallbacks.get(i).run();
- }
- });
- });
- }
-
- private void addFrameCallbackIfNeeded(boolean useBlastSync) {
final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
- if (!useBlastSync && !needsCallbackForBlur) {
- return;
+ if (!useBlastSync && !needsCallbackForBlur && !reportNextDraw) {
+ return null;
}
+ final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer;
+ mBLASTDrawConsumer = null;
+
if (DEBUG_BLAST) {
Log.d(mTag, "Creating frameDrawingCallback"
+ " nextDrawUseBlastSync=" + useBlastSync
- + " hasBlurUpdates=" + hasBlurUpdates);
+ + " reportNextDraw=" + reportNextDraw
+ + " hasBlurUpdates=" + hasBlurUpdates
+ + " hasBlastSyncConsumer=" + (blastSyncConsumer != null));
}
+
final BackgroundBlurDrawable.BlurRegion[] blurRegionsForFrame =
needsCallbackForBlur ? mBlurRegionAggregator.getBlurRegionsCopyForRT() : null;
// The callback will run on the render thread.
- HardwareRenderer.FrameDrawingCallback frameDrawingCallback = frame -> {
- if (DEBUG_BLAST) {
- Log.d(mTag, "Received frameDrawingCallback frameNum=" + frame + "."
- + " Creating transactionCompleteCallback=" + useBlastSync);
+ return new FrameDrawingCallback() {
+ @Override
+ public void onFrameDraw(long frame) {
}
- mRtLastAttemptedDrawFrameNum = frame;
+ @Override
+ public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
+ if (DEBUG_BLAST) {
+ Log.d(mTag,
+ "Received frameDrawingCallback syncResult=" + syncResult + " frameNum="
+ + frame + ".");
+ }
- if (needsCallbackForBlur) {
- mBlurRegionAggregator
- .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
- }
+ mRtLastAttemptedDrawFrameNum = frame;
- if (mBlastBufferQueue == null) {
- return;
- }
+ if (needsCallbackForBlur) {
+ mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frame,
+ blurRegionsForFrame, hasBlurUpdates);
+ }
- 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.
+ if (mBlastBufferQueue == null) {
+ return null;
+ }
- // We don't need to synchronize mRtBLASTSyncTransaction here since it's not
- // being modified and only sent to BlastBufferQueue.
- mBlastBufferQueue.setSyncTransaction(mRtBLASTSyncTransaction);
+ if (!useBlastSync && !reportNextDraw) {
+ 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.setSyncTransaction(mRtBLASTSyncTransaction);
+ }
+
+ return createFrameCommitCallbackForSync(useBlastSync, reportNextDraw,
+ blastSyncConsumer);
}
};
- registerRtFrameCallback(frameDrawingCallback);
}
private void performDraw(boolean useBlastSync) {
@@ -4165,15 +4201,20 @@ public final class ViewRootImpl implements ViewParent,
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
- addFrameCallbackIfNeeded(useBlastSync);
+ FrameDrawingCallback frameDrawingCallback = createFrameDrawingCallbackIfNeeded(useBlastSync,
+ mReportNextDraw);
+ if (frameDrawingCallback != null) {
+ mAttachInfo.mThreadedRenderer.registerRtFrameCallback(frameDrawingCallback);
+ }
addFrameCommitCallbackIfNeeded();
- boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(useBlastSync, mReportNextDraw);
+ boolean usingAsyncReport = isHardwareEnabled() && (useBlastSync || mReportNextDraw);
try {
boolean canUseAsync = draw(fullRedrawNeeded);
if (usingAsyncReport && !canUseAsync) {
- mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
+ mAttachInfo.mThreadedRenderer.setFrameCallback(null);
usingAsyncReport = false;
+ mAttachInfo.mThreadedRenderer.unregisterRtFrameCallback(frameDrawingCallback);
}
} finally {
mIsDrawing = false;