diff options
author | chaviw <chaviw@google.com> | 2021-08-20 12:15:48 -0500 |
---|---|---|
committer | Rob Carr <racarr@google.com> | 2021-11-24 23:38:34 +0000 |
commit | e97e296c811d16a3169c99b2b9e14a25cc245356 (patch) | |
tree | fe269f7cb38cb43c81e8e77427568eda92c21f00 | |
parent | 27cef855be711db25d8664977de3c92a4ef8c1ea (diff) |
Rework blast sync callback model
The previous code waited for a frame complete callback from hwui before
notifying WMS that a draw had occurred. However, frame complete callback
was not guaranteed to get called since it only invokes a callback if a
draw actually occured. VRI really needs a signal that RT has completed,
since it just needs to know that a draw was possible so it can notify
WMS that the RT completed its pass.
Instead, rename frameCompleteCallback to frameCommitCallback since that
API is exposed to a public API when a frame was actually drawn.
Create a new callback, frameCompleteCallback, that is invoked when the
draw has completed, regardless if a frame was actually drawn.
When the frameCompleteCallback is invoked, VRI can check to see if a new
frame actually drew. VRI can call into BBQ to see if the frame acquired
matches the frame that was attempted to draw. If so, VRI can wait on a
transaction callback. If not, it can allow VRI to continue. In either case,
it will notify WMS that the draw has finished.
Test: Split over and over
Bug: 195262673
Bug: 193634619
Change-Id: I24dd19ab2746be3fc33e597761abf8c5249f8b5b
Merged-In: I24dd19ab2746be3fc33e597761abf8c5249f8b5b
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 145 | ||||
-rw-r--r-- | core/jni/android_graphics_BLASTBufferQueue.cpp | 8 | ||||
-rw-r--r-- | graphics/java/android/graphics/BLASTBufferQueue.java | 4 | ||||
-rw-r--r-- | graphics/java/android/graphics/HardwareRenderer.java | 33 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_HardwareRenderer.cpp | 54 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 9 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 3 |
11 files changed, 206 insertions, 92 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cdfd7bea1a82..d053def6abe2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -768,6 +768,12 @@ public final class ViewRootImpl implements ViewParent, 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 @@ -4051,73 +4057,112 @@ public final class ViewRootImpl implements ViewParent, } /** - * The callback will run on the render thread. + * Only call this on the UI Thread. */ - private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, - boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { - final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer; - mBLASTDrawConsumer = null; - return frameNr -> { + 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 + */ + public boolean isHardwareEnabled() { + return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); + } + + private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) { + if (!isHardwareEnabled()) { + return false; + } + + if (!mNextDrawUseBlastSync && !reportNextDraw) { + return false; + } + + if (DEBUG_BLAST) { + Log.d(mTag, "Creating frameCompleteCallback"); + } + + mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> { + long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum(); if (DEBUG_BLAST) { - Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); + Log.d(mTag, "Received frameCompleteCallback " + + " lastAcquiredFrameNum=" + frameNr + + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum); } - handler.postAtFrontOfQueue(() -> { + 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) { + mBlastBufferQueue.setNextTransaction(null); + mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum, + null); + } + + 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 (blastSyncConsumer != null) { - blastSyncConsumer.accept(mSurfaceChangedTransaction); + if (mBLASTDrawConsumer != null) { + mBLASTDrawConsumer.accept(mSurfaceChangedTransaction); } + mBLASTDrawConsumer = null; } if (reportNextDraw) { - // TODO: Use the frame number pendingDrawFinished(); } - if (commitCallbacks != null) { - for (int i = 0; i < commitCallbacks.size(); i++) { - commitCallbacks.get(i).run(); - } + + if (frameWasNotDrawn) { + clearBlastSync(); } }); - }; - } - - /** - * @hide - */ - public boolean isHardwareEnabled() { - return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); + }); + return true; } - private boolean addFrameCompleteCallbackIfNeeded() { + private void addFrameCommitCallbackIfNeeded() { if (!isHardwareEnabled()) { - return false; + return; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); - final boolean needFrameCompleteCallback = - mNextDrawUseBlastSync || mReportNextDraw - || (commitCallbacks != null && commitCallbacks.size() > 0); - if (needFrameCompleteCallback) { - if (DEBUG_BLAST) { - Log.d(mTag, "Creating frameCompleteCallback" - + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync - + " mReportNextDraw=" + mReportNextDraw - + " commitCallbacks size=" - + (commitCallbacks == null ? 0 : commitCallbacks.size())); - } - mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( - createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, - commitCallbacks)); - return true; + final boolean needFrameCommitCallback = + (commitCallbacks != null && commitCallbacks.size() > 0); + if (!needFrameCommitCallback) { + return; } - return false; + + 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); + } + + mHandler.postAtFrontOfQueue(() -> { + for (int i = 0; i < commitCallbacks.size(); i++) { + commitCallbacks.get(i).run(); + } + }); + }); } private void addFrameCallbackIfNeeded() { @@ -4147,6 +4192,8 @@ public final class ViewRootImpl implements ViewParent, + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } + mRtLastAttemptedDrawFrameNum = frame; + if (needsCallbackForBlur) { mBlurRegionAggregator .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates); @@ -4169,18 +4216,7 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } - mHandler.postAtFrontOfQueue(() -> { - 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(); - } - }); + mHandler.postAtFrontOfQueue(this::clearBlastSync); }); } }; @@ -4201,8 +4237,9 @@ public final class ViewRootImpl implements ViewParent, mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); - boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); + addFrameCommitCallbackIfNeeded(); + boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw); try { boolean canUseAsync = draw(fullRedrawNeeded); diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index c1587eb2c4f4..3b7328e72913 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -134,6 +134,11 @@ static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlon } } +static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + return queue->getLastAcquiredFrameNum(); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off @@ -145,7 +150,8 @@ static const JNINativeMethod gMethods[] = { {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction}, {"nativeSetTransactionCompleteCallback", "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", - (void*)nativeSetTransactionCompleteCallback} + (void*)nativeSetTransactionCompleteCallback}, + {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, // clang-format on }; diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index fca4de91a352..2393eaf32e9a 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -38,6 +38,7 @@ public final class BLASTBufferQueue { long frameNumber); private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, TransactionCompleteCallback callback); + private static native long nativeGetLastAcquiredFrameNum(long ptr); /** * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} @@ -140,4 +141,7 @@ public final class BLASTBufferQueue { nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); } + public long getLastAcquiredFrameNum() { + return nativeGetLastAcquiredFrameNum(mNativeObject); + } } diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index c3b1cd74d29b..14ad74e12618 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -388,7 +388,8 @@ public class HardwareRenderer { */ public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor, @NonNull Runnable frameCommitCallback) { - setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback)); + nSetFrameCommitCallback(mNativeProxy, + didProduceBuffer -> executor.execute(frameCommitCallback)); return this; } @@ -609,6 +610,11 @@ public class HardwareRenderer { } /** @hide */ + public void setFrameCommitCallback(FrameCommitCallback callback) { + nSetFrameCommitCallback(mNativeProxy, callback); + } + + /** @hide */ public void setFrameCompleteCallback(FrameCompleteCallback callback) { nSetFrameCompleteCallback(mNativeProxy, callback); } @@ -904,13 +910,27 @@ public class HardwareRenderer { * * @hide */ - public interface FrameCompleteCallback { + public interface FrameCommitCallback { /** - * Invoked after a frame draw + * Invoked after a new frame was drawn * - * @param frameNr The id of the frame that was drawn. + * @param didProduceBuffer The draw successfully produced a new buffer. + */ + void onFrameCommit(boolean didProduceBuffer); + } + + /** + * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't + * mean a new frame has drawn, specifically if there's nothing new to draw, but only that + * RenderThread had a chance to draw a frame. + * + * @hide + */ + public interface FrameCompleteCallback { + /** + * Invoked after a frame draw was attempted. */ - void onFrameComplete(long frameNr); + void onFrameComplete(); } /** @@ -1362,6 +1382,9 @@ public class HardwareRenderer { private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); + private static native void nSetFrameCommitCallback(long nativeProxy, + FrameCommitCallback callback); + private static native void nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback); diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 54367b8334cb..b5536ad4830d 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -73,6 +73,10 @@ struct { } gFrameDrawingCallback; struct { + jmethodID onFrameCommit; +} gFrameCommitCallback; + +struct { jmethodID onFrameComplete; } gFrameCompleteCallback; @@ -101,22 +105,21 @@ private: JavaVM* mVm; }; -class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> { +class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> { public: - explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) { + explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); } - ~FrameCompleteWrapper() { - releaseObject(); - } + ~FrameCommitWrapper() { releaseObject(); } - void onFrameComplete(int64_t frameNr) { + void onFrameCommit(bool didProduceBuffer) { if (mObject) { - ATRACE_FORMAT("frameComplete %" PRId64, frameNr); - getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr); + ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer); + getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit, + didProduceBuffer); releaseObject(); } } @@ -637,15 +640,33 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, } } +static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz, + jlong proxyPtr, jobject callback) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + if (!callback) { + proxy->setFrameCommitCallback(nullptr); + } else { + sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback}; + proxy->setFrameCommitCallback( + [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); }); + } +} + static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCompleteCallback(nullptr); } else { - sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; - proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { - wrapper->onFrameComplete(frameNr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + JavaVM* vm = nullptr; + LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); + auto globalCallbackRef = + std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback)); + proxy->setFrameCompleteCallback([globalCallbackRef]() { + JNIEnv* env = getenv(globalCallbackRef->vm()); + env->CallVoidMethod(globalCallbackRef->object(), + gFrameCompleteCallback.onFrameComplete); }); } } @@ -929,6 +950,8 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback}, {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCallback}, + {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V", + (void*)android_view_ThreadedRenderer_setFrameCommitCallback}, {"nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCompleteCallback}, @@ -994,10 +1017,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw", "(J)V"); + jclass frameCommitClass = + FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback"); + gFrameCommitCallback.onFrameCommit = + GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V"); + jclass frameCompleteClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCompleteCallback"); - gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, - "onFrameComplete", "(J)V"); + gFrameCompleteCallback.onFrameComplete = + GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V"); void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface"); diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 2f3a509831d1..a066e6f7c693 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -491,10 +491,10 @@ nsecs_t CanvasContext::draw() { // Notify the callbacks, even if there's nothing to draw so they aren't waiting // indefinitely waitOnFences(); - for (auto& func : mFrameCompleteCallbacks) { - std::invoke(func, mFrameNumber); + for (auto& func : mFrameCommitCallbacks) { + std::invoke(func, false /* didProduceBuffer */); } - mFrameCompleteCallbacks.clear(); + mFrameCommitCallbacks.clear(); return 0; } @@ -603,10 +603,10 @@ nsecs_t CanvasContext::draw() { #endif if (didSwap) { - for (auto& func : mFrameCompleteCallbacks) { - std::invoke(func, frameCompleteNr); + for (auto& func : mFrameCommitCallbacks) { + std::invoke(func, true /* didProduceBuffer */); } - mFrameCompleteCallbacks.clear(); + mFrameCommitCallbacks.clear(); } if (requireSwap) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6dbfcc349d50..9df429badd5e 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -187,8 +187,8 @@ public: IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); } - void addFrameCompleteListener(std::function<void(int64_t)>&& func) { - mFrameCompleteCallbacks.push_back(std::move(func)); + void addFrameCommitListener(std::function<void(bool)>&& func) { + mFrameCommitCallbacks.push_back(std::move(func)); } void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) { @@ -320,7 +320,7 @@ private: std::vector<std::future<void>> mFrameFences; std::unique_ptr<IRenderPipeline> mRenderPipeline; - std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks; + std::vector<std::function<void(bool)>> mFrameCommitCallbacks; // If set to true, we expect that callbacks into onSurfaceStatsAvailable bool mExpectSurfaceStats = false; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index e7081df2b558..94aedd0f43be 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -150,16 +150,18 @@ void DrawFrameTask::run() { canUnblockUiThread = syncFrameState(info); canDrawThisFrame = info.out.canDrawThisFrame; - if (mFrameCompleteCallback) { - mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback)); - mFrameCompleteCallback = nullptr; + if (mFrameCommitCallback) { + mContext->addFrameCommitListener(std::move(mFrameCommitCallback)); + mFrameCommitCallback = nullptr; } } // Grab a copy of everything we need CanvasContext* context = mContext; - std::function<void(int64_t)> callback = std::move(mFrameCallback); + std::function<void(int64_t)> frameCallback = std::move(mFrameCallback); + std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback); mFrameCallback = nullptr; + mFrameCompleteCallback = nullptr; int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)]; int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)]; int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)]; @@ -170,9 +172,9 @@ void DrawFrameTask::run() { } // Even if we aren't drawing this vsync pulse the next frame number will still be accurate - if (CC_UNLIKELY(callback)) { + if (CC_UNLIKELY(frameCallback)) { context->enqueueFrameWork( - [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); }); + [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); }); } nsecs_t dequeueBufferDuration = 0; @@ -189,6 +191,10 @@ void DrawFrameTask::run() { context->waitOnFences(); } + if (CC_UNLIKELY(frameCompleteCallback)) { + std::invoke(frameCompleteCallback); + } + if (!canUnblockUiThread) { unblockUiThread(); } diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index 6a61a2bb645f..e3ea802b07b9 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -81,7 +81,11 @@ public: mFrameCallback = std::move(callback); } - void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) { + void setFrameCommitCallback(std::function<void(bool)>&& callback) { + mFrameCommitCallback = std::move(callback); + } + + void setFrameCompleteCallback(std::function<void()>&& callback) { mFrameCompleteCallback = std::move(callback); } @@ -123,7 +127,8 @@ private: int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE]; std::function<void(int64_t)> mFrameCallback; - std::function<void(int64_t)> mFrameCompleteCallback; + std::function<void(bool)> mFrameCommitCallback; + std::function<void()> mFrameCompleteCallback; nsecs_t mLastDequeueBufferDuration = 0; nsecs_t mLastTargetWorkDuration = 0; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index c485ce2781e5..72d4ac5081e6 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -326,7 +326,11 @@ void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) { mDrawFrameTask.setFrameCallback(std::move(callback)); } -void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) { +void RenderProxy::setFrameCommitCallback(std::function<void(bool)>&& callback) { + mDrawFrameTask.setFrameCommitCallback(std::move(callback)); +} + +void RenderProxy::setFrameCompleteCallback(std::function<void()>&& callback) { mDrawFrameTask.setFrameCompleteCallback(std::move(callback)); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 2b5405c82563..6417b38df064 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -124,7 +124,8 @@ public: const std::function<bool(int64_t, int64_t, int64_t)>& callback); void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback); void setFrameCallback(std::function<void(int64_t)>&& callback); - void setFrameCompleteCallback(std::function<void(int64_t)>&& callback); + void setFrameCommitCallback(std::function<void(bool)>&& callback); + void setFrameCompleteCallback(std::function<void()>&& callback); void addFrameMetricsObserver(FrameMetricsObserver* observer); void removeFrameMetricsObserver(FrameMetricsObserver* observer); |