Merge "Rework blast sync callback model" into sc-v2-dev

This commit is contained in:
Rob Carr
2021-11-29 18:43:00 +00:00
committed by Android (Google) Code Review
11 changed files with 215 additions and 101 deletions

View File

@@ -767,6 +767,12 @@ public final class ViewRootImpl implements ViewParent,
*/ */
private boolean mWaitForBlastSyncComplete = false; 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 * 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 * occur when the client is waiting on another process to submit the transaction that
@@ -4051,40 +4057,19 @@ 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, void clearBlastSync() {
boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { mNextDrawUseBlastSync = false;
final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer; mWaitForBlastSyncComplete = false;
mBLASTDrawConsumer = null; if (DEBUG_BLAST) {
return frameNr -> { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
if (DEBUG_BLAST) { + " due to a previous skipped traversal.");
Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); }
} if (mRequestedTraverseWhilePaused) {
mRequestedTraverseWhilePaused = false;
handler.postAtFrontOfQueue(() -> { scheduleTraversals();
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 (reportNextDraw) {
// TODO: Use the frame number
pendingDrawFinished();
}
if (commitCallbacks != null) {
for (int i = 0; i < commitCallbacks.size(); i++) {
commitCallbacks.get(i).run();
}
}
});
};
} }
/** /**
@@ -4094,30 +4079,90 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
} }
private boolean addFrameCompleteCallbackIfNeeded() { private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) {
if (!isHardwareEnabled()) { if (!isHardwareEnabled()) {
return false; 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 "
+ " lastAcquiredFrameNum=" + frameNr
+ " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
}
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 (mBLASTDrawConsumer != null) {
mBLASTDrawConsumer.accept(mSurfaceChangedTransaction);
}
mBLASTDrawConsumer = null;
}
if (reportNextDraw) {
pendingDrawFinished();
}
if (frameWasNotDrawn) {
clearBlastSync();
}
});
});
return true;
}
private void addFrameCommitCallbackIfNeeded() {
if (!isHardwareEnabled()) {
return;
}
ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
.captureFrameCommitCallbacks(); .captureFrameCommitCallbacks();
final boolean needFrameCompleteCallback = final boolean needFrameCommitCallback =
mNextDrawUseBlastSync || mReportNextDraw (commitCallbacks != null && commitCallbacks.size() > 0);
|| (commitCallbacks != null && commitCallbacks.size() > 0); if (!needFrameCommitCallback) {
if (needFrameCompleteCallback) { return;
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;
} }
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() { private void addFrameCallbackIfNeeded() {
@@ -4147,6 +4192,8 @@ public final class ViewRootImpl implements ViewParent,
+ " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
} }
mRtLastAttemptedDrawFrameNum = frame;
if (needsCallbackForBlur) { if (needsCallbackForBlur) {
mBlurRegionAggregator mBlurRegionAggregator
.dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates); .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
@@ -4169,18 +4216,7 @@ public final class ViewRootImpl implements ViewParent,
if (DEBUG_BLAST) { if (DEBUG_BLAST) {
Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
} }
mHandler.postAtFrontOfQueue(() -> { mHandler.postAtFrontOfQueue(this::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();
}
});
}); });
} }
}; };
@@ -4201,8 +4237,9 @@ public final class ViewRootImpl implements ViewParent,
mIsDrawing = true; mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded();
addFrameCallbackIfNeeded(); addFrameCallbackIfNeeded();
addFrameCommitCallbackIfNeeded();
boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw);
try { try {
boolean canUseAsync = draw(fullRedrawNeeded); boolean canUseAsync = draw(fullRedrawNeeded);

View File

@@ -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[] = { static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */ /* name, signature, funcPtr */
// clang-format off // clang-format off
@@ -145,7 +150,8 @@ static const JNINativeMethod gMethods[] = {
{"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction}, {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
{"nativeSetTransactionCompleteCallback", {"nativeSetTransactionCompleteCallback",
"(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
(void*)nativeSetTransactionCompleteCallback} (void*)nativeSetTransactionCompleteCallback},
{"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
// clang-format on // clang-format on
}; };

View File

@@ -38,6 +38,7 @@ public final class BLASTBufferQueue {
long frameNumber); long frameNumber);
private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber,
TransactionCompleteCallback callback); TransactionCompleteCallback callback);
private static native long nativeGetLastAcquiredFrameNum(long ptr);
/** /**
* Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)}
@@ -140,4 +141,7 @@ public final class BLASTBufferQueue {
nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber);
} }
public long getLastAcquiredFrameNum() {
return nativeGetLastAcquiredFrameNum(mNativeObject);
}
} }

View File

@@ -388,7 +388,8 @@ public class HardwareRenderer {
*/ */
public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor, public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
@NonNull Runnable frameCommitCallback) { @NonNull Runnable frameCommitCallback) {
setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback)); nSetFrameCommitCallback(mNativeProxy,
didProduceBuffer -> executor.execute(frameCommitCallback));
return this; return this;
} }
@@ -608,6 +609,11 @@ public class HardwareRenderer {
return mOpaque; return mOpaque;
} }
/** @hide */
public void setFrameCommitCallback(FrameCommitCallback callback) {
nSetFrameCommitCallback(mNativeProxy, callback);
}
/** @hide */ /** @hide */
public void setFrameCompleteCallback(FrameCompleteCallback callback) { public void setFrameCompleteCallback(FrameCompleteCallback callback) {
nSetFrameCompleteCallback(mNativeProxy, callback); nSetFrameCompleteCallback(mNativeProxy, callback);
@@ -904,13 +910,27 @@ public class HardwareRenderer {
* *
* @hide * @hide
*/ */
public interface FrameCommitCallback {
/**
* Invoked after a new frame 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 { public interface FrameCompleteCallback {
/** /**
* Invoked after a frame draw * Invoked after a frame draw was attempted.
*
* @param frameNr The id of the frame that was drawn.
*/ */
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 nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
private static native void nSetFrameCommitCallback(long nativeProxy,
FrameCommitCallback callback);
private static native void nSetFrameCompleteCallback(long nativeProxy, private static native void nSetFrameCompleteCallback(long nativeProxy,
FrameCompleteCallback callback); FrameCompleteCallback callback);

View File

@@ -72,6 +72,10 @@ struct {
jmethodID onFrameDraw; jmethodID onFrameDraw;
} gFrameDrawingCallback; } gFrameDrawingCallback;
struct {
jmethodID onFrameCommit;
} gFrameCommitCallback;
struct { struct {
jmethodID onFrameComplete; jmethodID onFrameComplete;
} gFrameCompleteCallback; } gFrameCompleteCallback;
@@ -101,22 +105,21 @@ private:
JavaVM* mVm; JavaVM* mVm;
}; };
class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> { class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
public: public:
explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) { explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
env->GetJavaVM(&mVm); env->GetJavaVM(&mVm);
mObject = env->NewGlobalRef(jobject); mObject = env->NewGlobalRef(jobject);
LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
} }
~FrameCompleteWrapper() { ~FrameCommitWrapper() { releaseObject(); }
releaseObject();
}
void onFrameComplete(int64_t frameNr) { void onFrameCommit(bool didProduceBuffer) {
if (mObject) { if (mObject) {
ATRACE_FORMAT("frameComplete %" PRId64, frameNr); ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr); getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
didProduceBuffer);
releaseObject(); 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, static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
jobject clazz, jlong proxyPtr, jobject callback) { jobject clazz, jlong proxyPtr, jobject callback) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
if (!callback) { if (!callback) {
proxy->setFrameCompleteCallback(nullptr); proxy->setFrameCompleteCallback(nullptr);
} else { } else {
sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { JavaVM* vm = nullptr;
wrapper->onFrameComplete(frameNr); 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}, (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
{"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCallback}, (void*)android_view_ThreadedRenderer_setFrameCallback},
{"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCommitCallback},
{"nSetFrameCompleteCallback", {"nSetFrameCompleteCallback",
"(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCompleteCallback}, (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
@@ -994,10 +1017,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {
gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
"onFrameDraw", "(J)V"); "onFrameDraw", "(J)V");
jclass frameCommitClass =
FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
gFrameCommitCallback.onFrameCommit =
GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");
jclass frameCompleteClass = FindClassOrDie(env, jclass frameCompleteClass = FindClassOrDie(env,
"android/graphics/HardwareRenderer$FrameCompleteCallback"); "android/graphics/HardwareRenderer$FrameCompleteCallback");
gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, gFrameCompleteCallback.onFrameComplete =
"onFrameComplete", "(J)V"); GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");
void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface"); fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");

View File

@@ -491,10 +491,10 @@ nsecs_t CanvasContext::draw() {
// Notify the callbacks, even if there's nothing to draw so they aren't waiting // Notify the callbacks, even if there's nothing to draw so they aren't waiting
// indefinitely // indefinitely
waitOnFences(); waitOnFences();
for (auto& func : mFrameCompleteCallbacks) { for (auto& func : mFrameCommitCallbacks) {
std::invoke(func, mFrameNumber); std::invoke(func, false /* didProduceBuffer */);
} }
mFrameCompleteCallbacks.clear(); mFrameCommitCallbacks.clear();
return 0; return 0;
} }
@@ -603,10 +603,10 @@ nsecs_t CanvasContext::draw() {
#endif #endif
if (didSwap) { if (didSwap) {
for (auto& func : mFrameCompleteCallbacks) { for (auto& func : mFrameCommitCallbacks) {
std::invoke(func, frameCompleteNr); std::invoke(func, true /* didProduceBuffer */);
} }
mFrameCompleteCallbacks.clear(); mFrameCommitCallbacks.clear();
} }
if (requireSwap) { if (requireSwap) {

View File

@@ -187,8 +187,8 @@ public:
IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); } IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
void addFrameCompleteListener(std::function<void(int64_t)>&& func) { void addFrameCommitListener(std::function<void(bool)>&& func) {
mFrameCompleteCallbacks.push_back(std::move(func)); mFrameCommitCallbacks.push_back(std::move(func));
} }
void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) { void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) {
@@ -320,7 +320,7 @@ private:
std::vector<std::future<void>> mFrameFences; std::vector<std::future<void>> mFrameFences;
std::unique_ptr<IRenderPipeline> mRenderPipeline; 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 // If set to true, we expect that callbacks into onSurfaceStatsAvailable
bool mExpectSurfaceStats = false; bool mExpectSurfaceStats = false;

View File

@@ -150,16 +150,18 @@ void DrawFrameTask::run() {
canUnblockUiThread = syncFrameState(info); canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame; canDrawThisFrame = info.out.canDrawThisFrame;
if (mFrameCompleteCallback) { if (mFrameCommitCallback) {
mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback)); mContext->addFrameCommitListener(std::move(mFrameCommitCallback));
mFrameCompleteCallback = nullptr; mFrameCommitCallback = nullptr;
} }
} }
// Grab a copy of everything we need // Grab a copy of everything we need
CanvasContext* context = mContext; 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; mFrameCallback = nullptr;
mFrameCompleteCallback = nullptr;
int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)]; int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)]; int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)];
int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)]; 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 // 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( context->enqueueFrameWork(
[callback, frameNr = context->getFrameNumber()]() { callback(frameNr); }); [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); });
} }
nsecs_t dequeueBufferDuration = 0; nsecs_t dequeueBufferDuration = 0;
@@ -189,6 +191,10 @@ void DrawFrameTask::run() {
context->waitOnFences(); context->waitOnFences();
} }
if (CC_UNLIKELY(frameCompleteCallback)) {
std::invoke(frameCompleteCallback);
}
if (!canUnblockUiThread) { if (!canUnblockUiThread) {
unblockUiThread(); unblockUiThread();
} }

View File

@@ -81,7 +81,11 @@ public:
mFrameCallback = std::move(callback); 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); mFrameCompleteCallback = std::move(callback);
} }
@@ -123,7 +127,8 @@ private:
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE]; int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
std::function<void(int64_t)> mFrameCallback; 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 mLastDequeueBufferDuration = 0;
nsecs_t mLastTargetWorkDuration = 0; nsecs_t mLastTargetWorkDuration = 0;

View File

@@ -326,7 +326,11 @@ void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
mDrawFrameTask.setFrameCallback(std::move(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)); mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
} }

View File

@@ -124,7 +124,8 @@ public:
const std::function<bool(int64_t, int64_t, int64_t)>& callback); const std::function<bool(int64_t, int64_t, int64_t)>& callback);
void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback); void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback);
void setFrameCallback(std::function<void(int64_t)>&& 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 addFrameMetricsObserver(FrameMetricsObserver* observer);
void removeFrameMetricsObserver(FrameMetricsObserver* observer); void removeFrameMetricsObserver(FrameMetricsObserver* observer);