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
Change-Id: I24dd19ab2746be3fc33e597761abf8c5249f8b5b
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index bb0b135..0cd6ffb 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -492,10 +492,10 @@
// 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;
}
@@ -604,10 +604,10 @@
#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 2fed468..ed4a620 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -195,8 +195,8 @@
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) {
@@ -328,7 +328,7 @@
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 e7081df..94aedd0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -150,16 +150,18 @@
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 @@
}
// 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 @@
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 6a61a2b..e3ea802 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -81,7 +81,11 @@
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 @@
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 c485ce2..72d4ac5 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -326,7 +326,11 @@
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 2b5405c..6417b38 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -124,7 +124,8 @@
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);