summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2016-07-29 16:25:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-07-29 16:25:51 +0000
commit34921ac1104e155682c6e807856e3e06f756c8f3 (patch)
tree3849b0be75da60ade46611e4ac69f86294a9275b /libs
parent66e7752ad15f761d09155976b37cb94fc36937d9 (diff)
parent2d5b8d73929a38b019c6b6276d4a19542b990f0c (diff)
downloadandroid-frameworks-base-34921ac1104e155682c6e807856e3e06f756c8f3.tar.gz
android-frameworks-base-34921ac1104e155682c6e807856e3e06f756c8f3.tar.xz
Merge "Teach JankTracker about new swap behaviors" into nyc-mr1-dev
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Android.mk4
-rw-r--r--libs/hwui/FrameInfo.cpp6
-rw-r--r--libs/hwui/FrameInfo.h3
-rw-r--r--libs/hwui/JankTracker.cpp32
-rw-r--r--libs/hwui/JankTracker.h11
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp16
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp2
-rw-r--r--libs/hwui/utils/TimeUtils.h8
8 files changed, 73 insertions, 9 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index c9d4af6..366ef71 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -113,6 +113,10 @@ hwui_cflags := \
-DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \
-Wall -Wno-unused-parameter -Wunreachable-code -Werror
+ifeq ($(TARGET_USES_HWC2),true)
+ hwui_cflags += -DUSE_HWC2
+endif
+
# GCC false-positives on this warning, and since we -Werror that's
# a problem
hwui_cflags += -Wno-free-nonheap-object
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 41e2233..09b3945 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -35,8 +35,14 @@ const std::string FrameInfoNames[] = {
"IssueDrawCommandsStart",
"SwapBuffers",
"FrameCompleted",
+ "DequeueBufferDuration",
+ "QueueBufferDuration",
};
+static_assert((sizeof(FrameInfoNames)/sizeof(FrameInfoNames[0]))
+ == static_cast<int>(FrameInfoIndex::NumIndexes),
+ "size mismatch: FrameInfoNames doesn't match the enum!");
+
void FrameInfo::importUiThreadInfo(int64_t* info) {
memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
}
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 0baca39..1fe5459 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -48,6 +48,9 @@ enum class FrameInfoIndex {
SwapBuffers,
FrameCompleted,
+ DequeueBufferDuration,
+ QueueBufferDuration,
+
// Must be the last value!
NumIndexes
};
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index ebe9c42..ed6b211 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -16,6 +16,7 @@
#include "JankTracker.h"
#include "Properties.h"
+#include "utils/TimeUtils.h"
#include <algorithm>
#include <cutils/ashmem.h>
@@ -119,11 +120,27 @@ static uint32_t frameTimeForFrameCountIndex(uint32_t index) {
return index;
}
-JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
+JankTracker::JankTracker(const DisplayInfo& displayInfo) {
// By default this will use malloc memory. It may be moved later to ashmem
// if there is shared space for it and a request comes in to do that.
mData = new ProfileData;
reset();
+ nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
+#if USE_HWC2
+ nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
+ nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset;
+ // There are two different offset cases. If the offsetDelta is positive
+ // and small, then the intention is to give apps extra time by leveraging
+ // pipelining between the UI & RT threads. If the offsetDelta is large or
+ // negative, the intention is to subtract time from the total duration
+ // in which case we can't afford to wait for dequeueBuffer blockage.
+ if (offsetDelta <= 4_ms && offsetDelta >= 0) {
+ // SF will begin composition at VSYNC-app + offsetDelta. If we are triple
+ // buffered, this is the expected time at which dequeueBuffer will
+ // return due to the staggering of VSYNC-app & VSYNC-sf.
+ mDequeueTimeForgiveness = offsetDelta + 4_ms;
+ }
+#endif
setFrameInterval(frameIntervalNanos);
}
@@ -213,6 +230,19 @@ void JankTracker::addFrame(const FrameInfo& frame) {
mData->totalFrameCount++;
// Fast-path for jank-free frames
int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
+ if (mDequeueTimeForgiveness
+ && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
+ nsecs_t expectedDequeueDuration =
+ mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync]
+ - frame[FrameInfoIndex::IssueDrawCommandsStart];
+ if (expectedDequeueDuration > 0) {
+ // Forgive only up to the expected amount, but not more than
+ // the actual time spent blocked.
+ nsecs_t forgiveAmount = std::min(expectedDequeueDuration,
+ frame[FrameInfoIndex::DequeueBufferDuration]);
+ totalDuration -= forgiveAmount;
+ }
+ }
uint32_t framebucket = frameCountIndexForFrameTime(totalDuration);
// Keep the fast path as fast as possible.
if (CC_LIKELY(totalDuration < mFrameInterval)) {
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 84b8c3f..126025c 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -21,6 +21,7 @@
#include "utils/RingBuffer.h"
#include <cutils/compiler.h>
+#include <ui/DisplayInfo.h>
#include <array>
#include <memory>
@@ -56,7 +57,7 @@ struct ProfileData {
// TODO: Replace DrawProfiler with this
class JankTracker {
public:
- JankTracker(nsecs_t frameIntervalNanos);
+ JankTracker(const DisplayInfo& displayInfo);
~JankTracker();
void addFrame(const FrameInfo& frame);
@@ -79,6 +80,14 @@ private:
std::array<int64_t, NUM_BUCKETS> mThresholds;
int64_t mFrameInterval;
+ // The amount of time we will erase from the total duration to account
+ // for SF vsync offsets with HWC2 blocking dequeueBuffers.
+ // (Vsync + mDequeueBlockTolerance) is the point at which we expect
+ // SF to have released the buffer normally, so we will forgive up to that
+ // point in time by comparing to (IssueDrawCommandsStart + DequeueDuration)
+ // This is only used if we are in pipelined mode and are using HWC2,
+ // otherwise it's 0.
+ nsecs_t mDequeueTimeForgiveness = 0;
ProfileData* mData;
bool mIsMapped = false;
};
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 82684c5..d68f0e3 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -67,7 +67,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mEglManager(thread.eglManager())
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mJankTracker(thread.timeLord().frameIntervalNanos())
+ , mJankTracker(thread.mainDisplayInfo())
, mProfiler(mFrames)
, mContentDrawBounds(0, 0, 0, 0) {
mRenderNodes.emplace_back(rootRenderNode);
@@ -286,11 +286,6 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
if (CC_LIKELY(mSwapHistory.size())) {
nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
SwapHistory& lastSwap = mSwapHistory.back();
- int durationUs;
- mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
- lastSwap.dequeueDuration = us2ns(durationUs);
- mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
- lastSwap.queueDuration = us2ns(durationUs);
nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
// The slight fudge-factor is to deal with cases where
// the vsync was estimated due to being slow handling the signal.
@@ -567,6 +562,15 @@ void CanvasContext::draw() {
swap.damage = screenDirty;
swap.swapCompletedTime = systemTime(CLOCK_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
+ int durationUs;
+ mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
+ swap.dequeueDuration = us2ns(durationUs);
+ mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
+ swap.queueDuration = us2ns(durationUs);
+ mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration)
+ = swap.dequeueDuration;
+ mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration)
+ = swap.queueDuration;
mHaveNewSurface = false;
mFrameNumber = -1;
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 9fb30c9..f4b4416 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -190,7 +190,7 @@ void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState(*this);
- mJankTracker = new JankTracker(frameIntervalNanos);
+ mJankTracker = new JankTracker(mDisplayInfo);
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/utils/TimeUtils.h b/libs/hwui/utils/TimeUtils.h
index 8d42d7e..ce181b7 100644
--- a/libs/hwui/utils/TimeUtils.h
+++ b/libs/hwui/utils/TimeUtils.h
@@ -21,10 +21,18 @@
namespace android {
namespace uirenderer {
+constexpr nsecs_t operator"" _s (unsigned long long s) {
+ return seconds_to_nanoseconds(s);
+}
+
constexpr nsecs_t operator"" _ms (unsigned long long ms) {
return milliseconds_to_nanoseconds(ms);
}
+constexpr nsecs_t operator"" _us (unsigned long long us) {
+ return microseconds_to_nanoseconds(us);
+}
+
} /* namespace uirenderer */
} /* namespace android */