Loading libs/hwui/Android.mk +4 −0 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,10 @@ hwui_cflags := \ -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \ -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \ -Wall -Wno-unused-parameter -Wunreachable-code -Werror -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 # GCC false-positives on this warning, and since we -Werror that's # a problem # a problem hwui_cflags += -Wno-free-nonheap-object hwui_cflags += -Wno-free-nonheap-object Loading libs/hwui/FrameInfo.cpp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -35,8 +35,14 @@ const std::string FrameInfoNames[] = { "IssueDrawCommandsStart", "IssueDrawCommandsStart", "SwapBuffers", "SwapBuffers", "FrameCompleted", "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) { void FrameInfo::importUiThreadInfo(int64_t* info) { memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); } } Loading libs/hwui/FrameInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,9 @@ enum class FrameInfoIndex { SwapBuffers, SwapBuffers, FrameCompleted, FrameCompleted, DequeueBufferDuration, QueueBufferDuration, // Must be the last value! // Must be the last value! NumIndexes NumIndexes }; }; Loading libs/hwui/JankTracker.cpp +31 −1 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "JankTracker.h" #include "JankTracker.h" #include "Properties.h" #include "Properties.h" #include "utils/TimeUtils.h" #include <algorithm> #include <algorithm> #include <cutils/ashmem.h> #include <cutils/ashmem.h> Loading Loading @@ -119,11 +120,27 @@ static uint32_t frameTimeForFrameCountIndex(uint32_t index) { return 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 // 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. // if there is shared space for it and a request comes in to do that. mData = new ProfileData; mData = new ProfileData; reset(); 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); setFrameInterval(frameIntervalNanos); } } Loading Loading @@ -213,6 +230,19 @@ void JankTracker::addFrame(const FrameInfo& frame) { mData->totalFrameCount++; mData->totalFrameCount++; // Fast-path for jank-free frames // Fast-path for jank-free frames int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted); 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); uint32_t framebucket = frameCountIndexForFrameTime(totalDuration); // Keep the fast path as fast as possible. // Keep the fast path as fast as possible. if (CC_LIKELY(totalDuration < mFrameInterval)) { if (CC_LIKELY(totalDuration < mFrameInterval)) { Loading libs/hwui/JankTracker.h +10 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "utils/RingBuffer.h" #include "utils/RingBuffer.h" #include <cutils/compiler.h> #include <cutils/compiler.h> #include <ui/DisplayInfo.h> #include <array> #include <array> #include <memory> #include <memory> Loading Loading @@ -56,7 +57,7 @@ struct ProfileData { // TODO: Replace DrawProfiler with this // TODO: Replace DrawProfiler with this class JankTracker { class JankTracker { public: public: explicit JankTracker(nsecs_t frameIntervalNanos); explicit JankTracker(const DisplayInfo& displayInfo); ~JankTracker(); ~JankTracker(); void addFrame(const FrameInfo& frame); void addFrame(const FrameInfo& frame); Loading @@ -79,6 +80,14 @@ private: std::array<int64_t, NUM_BUCKETS> mThresholds; std::array<int64_t, NUM_BUCKETS> mThresholds; int64_t mFrameInterval; 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; ProfileData* mData; bool mIsMapped = false; bool mIsMapped = false; }; }; Loading Loading
libs/hwui/Android.mk +4 −0 Original line number Original line Diff line number Diff line Loading @@ -124,6 +124,10 @@ hwui_cflags := \ -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \ -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \ -Wall -Wno-unused-parameter -Wunreachable-code -Werror -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 # GCC false-positives on this warning, and since we -Werror that's # a problem # a problem hwui_cflags += -Wno-free-nonheap-object hwui_cflags += -Wno-free-nonheap-object Loading
libs/hwui/FrameInfo.cpp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -35,8 +35,14 @@ const std::string FrameInfoNames[] = { "IssueDrawCommandsStart", "IssueDrawCommandsStart", "SwapBuffers", "SwapBuffers", "FrameCompleted", "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) { void FrameInfo::importUiThreadInfo(int64_t* info) { memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); } } Loading
libs/hwui/FrameInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,9 @@ enum class FrameInfoIndex { SwapBuffers, SwapBuffers, FrameCompleted, FrameCompleted, DequeueBufferDuration, QueueBufferDuration, // Must be the last value! // Must be the last value! NumIndexes NumIndexes }; }; Loading
libs/hwui/JankTracker.cpp +31 −1 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "JankTracker.h" #include "JankTracker.h" #include "Properties.h" #include "Properties.h" #include "utils/TimeUtils.h" #include <algorithm> #include <algorithm> #include <cutils/ashmem.h> #include <cutils/ashmem.h> Loading Loading @@ -119,11 +120,27 @@ static uint32_t frameTimeForFrameCountIndex(uint32_t index) { return 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 // 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. // if there is shared space for it and a request comes in to do that. mData = new ProfileData; mData = new ProfileData; reset(); 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); setFrameInterval(frameIntervalNanos); } } Loading Loading @@ -213,6 +230,19 @@ void JankTracker::addFrame(const FrameInfo& frame) { mData->totalFrameCount++; mData->totalFrameCount++; // Fast-path for jank-free frames // Fast-path for jank-free frames int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted); 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); uint32_t framebucket = frameCountIndexForFrameTime(totalDuration); // Keep the fast path as fast as possible. // Keep the fast path as fast as possible. if (CC_LIKELY(totalDuration < mFrameInterval)) { if (CC_LIKELY(totalDuration < mFrameInterval)) { Loading
libs/hwui/JankTracker.h +10 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "utils/RingBuffer.h" #include "utils/RingBuffer.h" #include <cutils/compiler.h> #include <cutils/compiler.h> #include <ui/DisplayInfo.h> #include <array> #include <array> #include <memory> #include <memory> Loading Loading @@ -56,7 +57,7 @@ struct ProfileData { // TODO: Replace DrawProfiler with this // TODO: Replace DrawProfiler with this class JankTracker { class JankTracker { public: public: explicit JankTracker(nsecs_t frameIntervalNanos); explicit JankTracker(const DisplayInfo& displayInfo); ~JankTracker(); ~JankTracker(); void addFrame(const FrameInfo& frame); void addFrame(const FrameInfo& frame); Loading @@ -79,6 +80,14 @@ private: std::array<int64_t, NUM_BUCKETS> mThresholds; std::array<int64_t, NUM_BUCKETS> mThresholds; int64_t mFrameInterval; 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; ProfileData* mData; bool mIsMapped = false; bool mIsMapped = false; }; }; Loading