Attempting to fix the black flicker
Bug: 79231206
Test: Repro steps from bug
Merged-In: I4c2810c42a7a4358f64584da3ab0cdf1499e71b6
Change-Id: I4c2810c42a7a4358f64584da3ab0cdf1499e71b6
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2ddf55b..aed0620 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -46,6 +46,7 @@
#include <algorithm>
#include <cstdlib>
+#include <functional>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
@@ -383,6 +384,12 @@
info.out.canDrawThisFrame = true;
}
+ // TODO: Do we need to abort out if the backdrop is added but not ready? Should that even
+ // be an allowable combination?
+ if (mRenderNodes.size() > 2 && !mRenderNodes[1]->isRenderable()) {
+ info.out.canDrawThisFrame = false;
+ }
+
if (!info.out.canDrawThisFrame) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
}
@@ -449,6 +456,8 @@
mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
mRenderNodes, &(profiler()));
+ int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
+
waitOnFences();
bool requireSwap = false;
@@ -509,6 +518,13 @@
}
#endif
+ if (didSwap) {
+ for (auto& func : mFrameCompleteCallbacks) {
+ std::invoke(func, frameCompleteNr);
+ }
+ mFrameCompleteCallbacks.clear();
+ }
+
mJankTracker.finishFrame(*mCurrentFrameInfo);
if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e52b644..1c4e02d 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -190,6 +190,10 @@
IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
+ void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
+ mFrameCompleteCallbacks.push_back(std::move(func));
+ }
+
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
@@ -267,6 +271,8 @@
std::vector<sp<FuncTask>> mFrameFences;
sp<TaskProcessor<bool>> mFrameWorkProcessor;
std::unique_ptr<IRenderPipeline> mRenderPipeline;
+
+ std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 60df514..51eeab7 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -90,6 +90,11 @@
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
+
+ if (mFrameCompleteCallback) {
+ mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
+ mFrameCompleteCallback = nullptr;
+ }
}
// Grab a copy of everything we need
@@ -152,6 +157,9 @@
mSyncResult |= SyncResult::UIRedrawRequired;
}
}
+ if (!info.out.canDrawThisFrame) {
+ mSyncResult |= SyncResult::FrameDropped;
+ }
// If prepareTextures is false, we ran out of texture cache space
return info.prepareTextures;
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d8c43e0..2c46762f 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -46,6 +46,7 @@
UIRedrawRequired = 1 << 0,
LostSurfaceRewardIfFound = 1 << 1,
ContextIsStopped = 1 << 2,
+ FrameDropped = 1 << 3,
};
}
@@ -78,6 +79,10 @@
mFrameCallback = std::move(callback);
}
+ void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mFrameCompleteCallback = std::move(callback);
+ }
+
private:
void postAndWait();
bool syncFrameState(TreeInfo& info);
@@ -102,6 +107,7 @@
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
std::function<void(int64_t)> mFrameCallback;
+ std::function<void(int64_t)> mFrameCompleteCallback;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c6a9b55f..59048be 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -274,6 +274,10 @@
mDrawFrameTask.setFrameCallback(std::move(callback));
}
+void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
+}
+
void RenderProxy::serializeDisplayListTree() {
mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); });
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 3425c5c..ad534f0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -116,6 +116,7 @@
ANDROID_API void drawRenderNode(RenderNode* node);
ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback);
+ ANDROID_API void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);