Synchronize SV buffers with main window when config changes
When the main window gets a configuration change, the new buffer for the SV will get applied in the same transaction as the main window. This will allow apps to implement seamless rotation without a frame or more of black where the SV was resized, but the buffer was not yet updated. This also includes an optimization where if only SV change occurs, but there was no request from WMS to report drawing, VRI can apply the transaction immediately without reporting to WMS. Test: SV with seamless rotation enabled Bug: 200284684 Change-Id: I5569d815eef92acf3bf9d7f753bd5ab94a332cfe
This commit is contained in:
@@ -227,6 +227,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
*/
|
||||
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
|
||||
* {@link HardwareRenderer.FrameDrawingCallback#onFrameDraw} is invoked. All
|
||||
@@ -496,7 +501,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
}
|
||||
}
|
||||
|
||||
private void performDrawFinished() {
|
||||
private void performDrawFinished(Transaction t) {
|
||||
mSyncTransaction.merge(t);
|
||||
if (mDeferredDestroySurfaceControl != null) {
|
||||
synchronized (mSurfaceControlLock) {
|
||||
mTmpTransaction.remove(mDeferredDestroySurfaceControl).apply();
|
||||
@@ -521,7 +527,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
void notifyDrawFinished() {
|
||||
ViewRootImpl viewRoot = getViewRootImpl();
|
||||
if (viewRoot != null) {
|
||||
viewRoot.pendingDrawFinished();
|
||||
viewRoot.pendingDrawFinished(mSyncTransaction);
|
||||
}
|
||||
mPendingReportDraws--;
|
||||
}
|
||||
@@ -1202,10 +1208,17 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
callbacks = getSurfaceCallbacks();
|
||||
}
|
||||
|
||||
final Transaction t = new Transaction();
|
||||
if (viewRoot.wasRelayoutRequested()) {
|
||||
mBlastBufferQueue.setSyncTransaction(t,
|
||||
false /* acquireSingleBuffer */);
|
||||
}
|
||||
mPendingReportDraws++;
|
||||
viewRoot.drawPending();
|
||||
SurfaceCallbackHelper sch =
|
||||
new SurfaceCallbackHelper(this::onDrawFinished);
|
||||
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
|
||||
mBlastBufferQueue.setSyncTransaction(null);
|
||||
onDrawFinished(t);
|
||||
});
|
||||
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
|
||||
}
|
||||
}
|
||||
@@ -1367,13 +1380,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
mSurfaceHeight, mFormat);
|
||||
}
|
||||
|
||||
private void onDrawFinished() {
|
||||
private void onDrawFinished(Transaction t) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, System.identityHashCode(this) + " "
|
||||
+ "finishedDrawing");
|
||||
}
|
||||
|
||||
runOnUiThread(this::performDrawFinished);
|
||||
runOnUiThread(() -> performDrawFinished(t));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -532,6 +532,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
boolean mPerformContentCapture;
|
||||
|
||||
boolean mReportNextDraw;
|
||||
/**
|
||||
* Set if the reportDraw was requested from WM. If just a local report draw was invoked, there's
|
||||
* no need to report back to system server and can just apply immediately on the client.
|
||||
*/
|
||||
boolean mReportDrawToWm;
|
||||
boolean mFullRedrawNeeded;
|
||||
boolean mNewSurfaceNeeded;
|
||||
boolean mForceNextWindowRelayout;
|
||||
@@ -754,6 +759,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
*/
|
||||
private int mSurfaceSequenceId = 0;
|
||||
|
||||
private boolean mRelayoutRequested;
|
||||
|
||||
private String mTag = TAG;
|
||||
|
||||
public ViewRootImpl(Context context, Display display) {
|
||||
@@ -3311,6 +3318,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
|
||||
mIsInTraversal = false;
|
||||
mRelayoutRequested = false;
|
||||
}
|
||||
|
||||
private void notifyContentCatpureEvents() {
|
||||
@@ -3941,10 +3949,18 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mDrawsNeededToReport++;
|
||||
}
|
||||
|
||||
void pendingDrawFinished() {
|
||||
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();
|
||||
@@ -3954,17 +3970,31 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
void pendingDrawFinished() {
|
||||
pendingDrawFinished(null);
|
||||
}
|
||||
|
||||
private void postDrawFinished() {
|
||||
mHandler.sendEmptyMessage(MSG_DRAW_FINISHED);
|
||||
}
|
||||
|
||||
private void reportDrawFinished() {
|
||||
try {
|
||||
if (DEBUG_BLAST) {
|
||||
Log.d(mTag, "reportDrawFinished");
|
||||
}
|
||||
mDrawsNeededToReport = 0;
|
||||
|
||||
if (!mReportDrawToWm) {
|
||||
if (DEBUG_BLAST) {
|
||||
Log.d(mTag, "reportDrawFinished");
|
||||
Log.d(mTag, "No need to report finishDrawing. Apply immediately");
|
||||
}
|
||||
mDrawsNeededToReport = 0;
|
||||
mSurfaceChangedTransaction.apply();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
|
||||
mReportDrawToWm = false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(mTag, "Unable to report draw finished", e);
|
||||
mSurfaceChangedTransaction.apply();
|
||||
@@ -7756,6 +7786,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
|
||||
boolean insetsPending) throws RemoteException {
|
||||
|
||||
mRelayoutRequested = true;
|
||||
float appScale = mAttachInfo.mApplicationScale;
|
||||
boolean restore = false;
|
||||
if (params != null && mTranslator != null) {
|
||||
@@ -9573,6 +9604,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if (mReportNextDraw == false) {
|
||||
drawPending();
|
||||
}
|
||||
mReportDrawToWm = true;
|
||||
mReportNextDraw = true;
|
||||
}
|
||||
|
||||
@@ -10501,4 +10533,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mBLASTDrawConsumer = consume;
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean wasRelayoutRequested() {
|
||||
return mRelayoutRequested;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,11 @@ static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
|
||||
queue->getSurface(includeSurfaceControlHandle));
|
||||
}
|
||||
|
||||
static void nativeSetSyncTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) {
|
||||
static void nativeSetSyncTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr,
|
||||
jboolean acquireSingleBuffer) {
|
||||
sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
|
||||
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr);
|
||||
queue->setSyncTransaction(transaction);
|
||||
queue->setSyncTransaction(transaction, acquireSingleBuffer);
|
||||
}
|
||||
|
||||
static void nativeUpdate(JNIEnv* env, jclass clazz, jlong ptr, jlong surfaceControl, jlong width,
|
||||
@@ -98,7 +99,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nativeCreate", "(Ljava/lang/String;JJJI)J", (void*)nativeCreate},
|
||||
{"nativeGetSurface", "(JZ)Landroid/view/Surface;", (void*)nativeGetSurface},
|
||||
{"nativeDestroy", "(J)V", (void*)nativeDestroy},
|
||||
{"nativeSetSyncTransaction", "(JJ)V", (void*)nativeSetSyncTransaction},
|
||||
{"nativeSetSyncTransaction", "(JJZ)V", (void*)nativeSetSyncTransaction},
|
||||
{"nativeUpdate", "(JJJJIJ)V", (void*)nativeUpdate},
|
||||
{"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
|
||||
{"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
|
||||
|
||||
@@ -31,7 +31,8 @@ public final class BLASTBufferQueue {
|
||||
long height, int format);
|
||||
private static native void nativeDestroy(long ptr);
|
||||
private static native Surface nativeGetSurface(long ptr, boolean includeSurfaceControlHandle);
|
||||
private static native void nativeSetSyncTransaction(long ptr, long transactionPtr);
|
||||
private static native void nativeSetSyncTransaction(long ptr, long transactionPtr,
|
||||
boolean acquireSingleBuffer);
|
||||
private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height,
|
||||
int format, long transactionPtr);
|
||||
private static native void nativeMergeWithNextTransaction(long ptr, long transactionPtr,
|
||||
@@ -66,12 +67,25 @@ public final class BLASTBufferQueue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the transaction to BBQ so the next frame can be added and not applied immediately.
|
||||
* This gives the caller a chance to apply the transaction when it's ready.
|
||||
* @param t The transaction to add the frame to. This can be null to clear the transaction.
|
||||
* Send the transaction to BBQ so the next frame can be added and not applied immediately. This
|
||||
* gives the caller a chance to apply the transaction when it's ready.
|
||||
*
|
||||
* @param t The transaction to add the frame to. This can be null to clear the
|
||||
* transaction.
|
||||
* @param acquireSingleBuffer If true, only acquire a single buffer when processing frames. The
|
||||
* transaction will be cleared once a single buffer has been
|
||||
* acquired. If false, continue to acquire all buffers into the
|
||||
* transaction until setSyncTransaction is called again with a null
|
||||
* transaction.
|
||||
*/
|
||||
public void setSyncTransaction(@Nullable SurfaceControl.Transaction t,
|
||||
boolean acquireSingleBuffer) {
|
||||
nativeSetSyncTransaction(mNativeObject, t == null ? 0 : t.mNativeObject,
|
||||
acquireSingleBuffer);
|
||||
}
|
||||
|
||||
public void setSyncTransaction(@Nullable SurfaceControl.Transaction t) {
|
||||
nativeSetSyncTransaction(mNativeObject, t == null ? 0 : t.mNativeObject);
|
||||
setSyncTransaction(t, true /* acquireSingleBuffer */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user