summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread/DrawFrameTask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread/DrawFrameTask.cpp')
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp50
1 files changed, 46 insertions, 4 deletions
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e593388d063..5c4b9019b0ad 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,11 +16,13 @@
#include "DrawFrameTask.h"
+#include <gui/TraceUtils.h>
#include <utils/Log.h>
-#include <utils/Trace.h>
+#include <algorithm>
#include "../DeferredLayerUpdater.h"
#include "../DisplayList.h"
+#include "../Properties.h"
#include "../RenderNode.h"
#include "CanvasContext.h"
#include "RenderThread.h"
@@ -44,6 +46,12 @@ void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
mTargetNode = targetNode;
}
+void DrawFrameTask::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
+ std::function<void(int64_t)> reportActualWorkDuration) {
+ mUpdateTargetWorkDuration = std::move(updateTargetWorkDuration);
+ mReportActualWorkDuration = std::move(reportActualWorkDuration);
+}
+
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
LOG_ALWAYS_FATAL_IF(!mContext,
"Lifecycle violation, there's no context to pushLayerUpdate with!");
@@ -82,7 +90,9 @@ void DrawFrameTask::postAndWait() {
}
void DrawFrameTask::run() {
- ATRACE_NAME("DrawFrame");
+ const int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)];
+ ATRACE_FORMAT("DrawFrames %" PRId64, vsyncId);
+ nsecs_t syncDelayDuration = systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued;
bool canUnblockUiThread;
bool canDrawThisFrame;
@@ -101,6 +111,9 @@ void DrawFrameTask::run() {
CanvasContext* context = mContext;
std::function<void(int64_t)> callback = std::move(mFrameCallback);
mFrameCallback = 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)];
// From this point on anything in "this" is *UNSAFE TO ACCESS*
if (canUnblockUiThread) {
@@ -113,8 +126,9 @@ void DrawFrameTask::run() {
[callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
}
+ nsecs_t dequeueBufferDuration = 0;
if (CC_LIKELY(canDrawThisFrame)) {
- context->draw();
+ dequeueBufferDuration = context->draw();
} else {
// wait on fences so tasks don't overlap next frame
context->waitOnFences();
@@ -123,12 +137,40 @@ void DrawFrameTask::run() {
if (!canUnblockUiThread) {
unblockUiThread();
}
+
+ // These member callbacks are effectively const as they are set once during init, so it's safe
+ // to use these directly instead of making local copies.
+ if (mUpdateTargetWorkDuration && mReportActualWorkDuration) {
+ constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
+ constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
+ int64_t targetWorkDuration = frameDeadline - intendedVsync;
+ targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
+ if (targetWorkDuration > kSanityCheckLowerBound &&
+ targetWorkDuration < kSanityCheckUpperBound &&
+ targetWorkDuration != mLastTargetWorkDuration) {
+ mLastTargetWorkDuration = targetWorkDuration;
+ mUpdateTargetWorkDuration(targetWorkDuration);
+ }
+ int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
+ int64_t actualDuration = frameDuration -
+ (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
+ dequeueBufferDuration;
+ if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
+ mReportActualWorkDuration(actualDuration);
+ }
+ }
+ mLastDequeueBufferDuration = dequeueBufferDuration;
}
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
- mRenderThread->timeLord().vsyncReceived(vsync);
+ int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
+ int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)];
+ int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)];
+ int64_t frameInterval = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameInterval)];
+ mRenderThread->timeLord().vsyncReceived(vsync, intendedVsync, vsyncId, frameDeadline,
+ frameInterval);
bool canDraw = mContext->makeCurrent();
mContext->unpinImages();