From 9bce5e0c048de763b9f65385fe6e81e16e5f8db5 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 14 Oct 2020 18:36:59 -0700 Subject: [PATCH] BLAST: Ensure buffers are submitted before reporting draw finished If blast sync is not enabled abut we need to report draw finished for the next frame, call setNextTransaction. Blast buffer queue will process any queued up buffers and ensure the buffer is submitted before reporting draw finished. Test: Test no flickers with blast enabled in splitscreen Change-Id: If7a36eb0a9a2914dd37adfd20abcbe2b5074b16a --- core/java/android/view/ViewRootImpl.java | 19 +++++++++++++------ .../jni/android_graphics_BLASTBufferQueue.cpp | 8 +++++++- .../android/graphics/BLASTBufferQueue.java | 5 +++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 52357402877a7..93c2787ede2e4 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3881,10 +3881,6 @@ public final class ViewRootImpl implements ViewParent, } private void addFrameCallbackIfNeeded() { - if (!mNextDrawUseBLASTSyncTransaction) { - return; - } - // 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. @@ -3892,8 +3888,19 @@ public final class ViewRootImpl implements ViewParent, // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the // next frame completed should be reported with the blast sync transaction. - registerRtFrameCallback(createFrameDrawingCallback()); - mNextDrawUseBLASTSyncTransaction = false; + if (mNextDrawUseBLASTSyncTransaction) { + registerRtFrameCallback(createFrameDrawingCallback()); + mNextDrawUseBLASTSyncTransaction = false; + } else if (mReportNextDraw) { + registerRtFrameCallback(frame -> { + if (mBlastBufferQueue != null) { + // If we need to report next draw, wait for adapter to flush its shadow queue + // by processing previously queued buffers so that we can submit the + // transaction a timely manner. + mBlastBufferQueue.flushShadowQueue(); + } + }); + } } private void performDraw() { diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index a30c37bbd11cb..b07c29307339a 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -69,13 +69,19 @@ static void nativeUpdate(JNIEnv*env, jclass clazz, jlong ptr, jlong surfaceContr queue->update(reinterpret_cast(surfaceControl), width, height); } +static void nativeFlushShadowQueue(JNIEnv* env, jclass clazz, jlong ptr) { + sp queue = reinterpret_cast(ptr); + queue->flushShadowQueue(); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ {"nativeCreate", "(Ljava/lang/String;JJJZ)J", (void*)nativeCreate}, {"nativeGetSurface", "(J)Landroid/view/Surface;", (void*)nativeGetSurface}, {"nativeDestroy", "(J)V", (void*)nativeDestroy}, {"nativeSetNextTransaction", "(JJ)V", (void*)nativeSetNextTransaction}, - {"nativeUpdate", "(JJJJ)V", (void*)nativeUpdate}}; + {"nativeUpdate", "(JJJJ)V", (void*)nativeUpdate}, + {"nativeFlushShadowQueue", "(J)V", (void*)nativeFlushShadowQueue}}; int register_android_graphics_BLASTBufferQueue(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "android/graphics/BLASTBufferQueue", diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index 4c0f890eee408..8284042c4dca8 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -32,6 +32,7 @@ public final class BLASTBufferQueue { private static native Surface nativeGetSurface(long ptr); private static native void nativeSetNextTransaction(long ptr, long transactionPtr); private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height); + private static native void nativeFlushShadowQueue(long ptr); /** Create a new connection with the surface flinger. */ public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, @@ -69,4 +70,8 @@ public final class BLASTBufferQueue { super.finalize(); } } + + public void flushShadowQueue() { + nativeFlushShadowQueue(mNativeObject); + } }