diff options
-rw-r--r-- | libs/hwui/FrameInfoVisualizer.cpp | 50 | ||||
-rw-r--r-- | libs/hwui/FrameInfoVisualizer.h | 3 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderThread.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderThread.h | 2 |
5 files changed, 37 insertions, 26 deletions
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp index b04c77430367..3a8e559f6d7e 100644 --- a/libs/hwui/FrameInfoVisualizer.cpp +++ b/libs/hwui/FrameInfoVisualizer.cpp @@ -17,6 +17,7 @@ #include "IProfileRenderer.h" #include "utils/Color.h" +#include "utils/TimeUtils.h" #include <cutils/compiler.h> #include <array> @@ -26,22 +27,24 @@ #define RETURN_IF_DISABLED() \ if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return -#define PROFILE_DRAW_WIDTH 3 -#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2 -#define PROFILE_DRAW_DP_PER_MS 7 - namespace android { namespace uirenderer { -// Must be NUM_ELEMENTS in size -static const SkColor THRESHOLD_COLOR = Color::Green_500; -static const SkColor BAR_FAST_MASK = 0x8FFFFFFF; -static const SkColor BAR_JANKY_MASK = 0xDFFFFFFF; +static constexpr auto PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2; +static constexpr auto PROFILE_DRAW_DP_PER_MS = 7; + +struct Threshold { + SkColor color; + float percentFrametime; +}; -// We could get this from TimeLord and use the actual frame interval, but -// this is good enough -#define FRAME_THRESHOLD 16 -#define FRAME_THRESHOLD_NS 16000000 +static constexpr std::array<Threshold, 3> THRESHOLDS{ + Threshold{.color = Color::Green_500, .percentFrametime = 0.8f}, + Threshold{.color = Color::Lime_500, .percentFrametime = 1.0f}, + Threshold{.color = Color::Red_500, .percentFrametime = 1.5f}, +}; +static constexpr SkColor BAR_FAST_MASK = 0x8FFFFFFF; +static constexpr SkColor BAR_JANKY_MASK = 0xDFFFFFFF; struct BarSegment { FrameInfoIndex start; @@ -64,7 +67,8 @@ static int dpToPx(int dp, float density) { return (int)(dp * density + 0.5f); } -FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) { +FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval) + : mFrameSource(source), mFrameInterval(frameInterval) { setDensity(1); consumeProperties(); } @@ -76,7 +80,10 @@ FrameInfoVisualizer::~FrameInfoVisualizer() { void FrameInfoVisualizer::setDensity(float density) { if (CC_UNLIKELY(mDensity != density)) { mDensity = density; - mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density); + // We want the vertical units to scale height relative to a baseline 16ms. + // This keeps the threshold lines consistent across varying refresh rates + mVerticalUnit = static_cast<int>(dpToPx(PROFILE_DRAW_DP_PER_MS, density) * (float)16_ms / + (float)mFrameInterval); mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density); } } @@ -148,7 +155,7 @@ void FrameInfoVisualizer::initializeRects(const int baseline, const int width) { float* rect; int ri; // Rects are LTRB - if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + if (mFrameSource[fi].totalDuration() <= mFrameInterval) { rect = mFastRects.get(); ri = fast_i; fast_i += 4; @@ -181,7 +188,7 @@ void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex en float* rect; int ri; // Rects are LTRB - if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + if (mFrameSource[fi].totalDuration() <= mFrameInterval) { rect = mFastRects.get(); ri = fast_i; fast_i -= 4; @@ -211,10 +218,13 @@ void FrameInfoVisualizer::drawGraph(IProfileRenderer& renderer) { void FrameInfoVisualizer::drawThreshold(IProfileRenderer& renderer) { SkPaint paint; - paint.setColor(THRESHOLD_COLOR); - float yLocation = renderer.getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit); - renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(), - yLocation + mThresholdStroke / 2, paint); + for (auto& t : THRESHOLDS) { + paint.setColor(t.color); + float yLocation = renderer.getViewportHeight() - + (ns2ms(mFrameInterval) * t.percentFrametime * mVerticalUnit); + renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(), + yLocation + mThresholdStroke / 2, paint); + } } bool FrameInfoVisualizer::consumeProperties() { diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h index b98f50101483..3040a77ef0d4 100644 --- a/libs/hwui/FrameInfoVisualizer.h +++ b/libs/hwui/FrameInfoVisualizer.h @@ -39,7 +39,7 @@ typedef RingBuffer<FrameInfo, 120> FrameInfoSource; class FrameInfoVisualizer { public: - explicit FrameInfoVisualizer(FrameInfoSource& source); + explicit FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval); ~FrameInfoVisualizer(); bool consumeProperties(); @@ -71,6 +71,7 @@ private: FrameInfoSource& mFrameSource; + nsecs_t mFrameInterval; int mVerticalUnit = 0; int mThresholdStroke = 0; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 091775dbe790..f5b4d9359ee9 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -103,7 +103,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* , mOpaque(!translucent) , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo()) - , mProfiler(mJankTracker.frames()) + , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos()) , mContentDrawBounds(0, 0, 0, 0) , mRenderPipeline(std::move(renderPipeline)) { rootRenderNode->makeRoot(); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 08edd20c0a0d..c784d64f820c 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -52,9 +52,6 @@ namespace renderthread { // using just a few large reads. static const size_t EVENT_BUFFER_SIZE = 100; -// Slight delay to give the UI time to push us a new frame before we replay -static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4); - static bool gHasRenderThreadInstance = false; static JVMAttachHook gOnStartHook = nullptr; @@ -171,6 +168,7 @@ void RenderThread::initThreadLocals() { mDisplayInfo = DeviceInfo::get()->displayInfo(); nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps); mTimeLord.setFrameInterval(frameIntervalNanos); + mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f); initializeDisplayEventReceiver(); mEglManager = new EglManager(); mRenderState = new RenderState(*this); @@ -311,7 +309,7 @@ void RenderThread::drainDisplayEventQueue() { if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) { ATRACE_NAME("queue mFrameCallbackTask"); mFrameCallbackTaskPending = true; - nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY); + nsecs_t runAt = (vsyncEvent + mDispatchFrameDelay); queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); }); } } diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 329b4b99c911..9298be65c5e8 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -24,6 +24,7 @@ #include "TimeLord.h" #include "thread/ThreadBase.h" #include "WebViewFunctorManager.h" +#include "utils/TimeUtils.h" #include <GrContext.h> #include <SkBitmap.h> @@ -164,6 +165,7 @@ private: bool mFrameCallbackTaskPending; TimeLord mTimeLord; + nsecs_t mDispatchFrameDelay = 4_ms; RenderState* mRenderState; EglManager* mEglManager; WebViewFunctorManager& mFunctorManager; |