summaryrefslogtreecommitdiffstats
path: root/libs/hwui/renderthread/CanvasContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread/CanvasContext.cpp')
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp46
1 files changed, 43 insertions, 3 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 6346479..80c60d9 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -48,7 +48,8 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mCanvas(nullptr)
, mHaveNewSurface(false)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mRootRenderNode(rootRenderNode) {
+ , mRootRenderNode(rootRenderNode)
+ , mCurrentFrameInfo(nullptr) {
mRenderThread.renderState().registerCanvasContext(this);
}
@@ -151,9 +152,13 @@ void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
}
}
-void CanvasContext::prepareTree(TreeInfo& info) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
mRenderThread.removeFrameCallback(this);
+ mCurrentFrameInfo = &mFrames.next();
+ mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
+ mCurrentFrameInfo->markSyncStart();
+
info.damageAccumulator = &mDamageAccumulator;
info.renderer = mCanvas;
if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
@@ -203,6 +208,7 @@ void CanvasContext::draw() {
"drawRenderNode called on a context with no canvas or surface!");
profiler().markPlaybackStart();
+ mCurrentFrameInfo->markIssueDrawCommandsStart();
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -239,12 +245,19 @@ void CanvasContext::draw() {
profiler().markPlaybackEnd();
+ // Even if we decided to cancel the frame, from the perspective of jank
+ // metrics the frame was swapped at this point
+ mCurrentFrameInfo->markSwapBuffers();
+
if (drew) {
swapBuffers();
} else {
mEglManager.cancelFrame();
}
+ // TODO: Use a fence for real completion?
+ mCurrentFrameInfo->markFrameCompleted();
+ mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
profiler().finishFrame();
}
@@ -257,9 +270,14 @@ void CanvasContext::doFrame() {
ATRACE_CALL();
profiler().startFrame();
+ int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
+ UiFrameInfoBuilder(frameInfo)
+ .addFlag(FrameInfoFlags::kRTAnimation)
+ .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
+ mRenderThread.timeLord().latestVsync());
TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
- prepareTree(info);
+ prepareTree(info, frameInfo);
if (info.out.canDrawThisFrame) {
draw();
}
@@ -372,6 +390,28 @@ void CanvasContext::setTextureAtlas(RenderThread& thread,
thread.eglManager().setTextureAtlas(buffer, map, mapSize);
}
+void CanvasContext::dumpFrames(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\n\n---PROFILEDATA---");
+ for (size_t i = 0; i < mFrames.size(); i++) {
+ FrameInfo& frame = mFrames[i];
+ if (frame[FrameInfoIndex::kSyncStart] == 0) {
+ continue;
+ }
+ fprintf(file, "\n");
+ for (int i = 0; i < FrameInfoIndex::kNumIndexes; i++) {
+ fprintf(file, "%" PRId64 ",", frame[i]);
+ }
+ }
+ fprintf(file, "\n---PROFILEDATA---\n\n");
+ fflush(file);
+}
+
+void CanvasContext::resetFrameStats() {
+ mFrames.clear();
+ mRenderThread.jankTracker().reset();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */