From cf185f5b0d30516ecb34350a585aed7f7d4e0672 Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 11 Apr 2019 16:11:24 -0700 Subject: [PATCH] Dynamically adjust renderahead Tracks refresh rate changes and adjusts renderahead based off of the active refresh rate. Default is 60hz = 0 render ahead & > 70hz is render ahead 1 Bug: 127822449 Test: systraced stuff Change-Id: I9849aa065262f21f7602d44cd1761373279dc28d --- libs/hwui/DeviceInfo.cpp | 33 ++++++++++++++++--- libs/hwui/DeviceInfo.h | 6 +++- libs/hwui/Properties.cpp | 7 ++-- libs/hwui/Properties.h | 2 +- libs/hwui/renderthread/CanvasContext.cpp | 53 +++++++++++++++++++----------- libs/hwui/renderthread/CanvasContext.h | 6 ++-- libs/hwui/renderthread/RenderThread.cpp | 29 +++++++++++----- libs/hwui/renderthread/RenderThread.h | 5 +-- libs/hwui/tests/unit/CacheManagerTests.cpp | 2 +- 9 files changed, 98 insertions(+), 45 deletions(-) diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp index cf5d7ce3f738..0a9d965d0444 100644 --- a/libs/hwui/DeviceInfo.cpp +++ b/libs/hwui/DeviceInfo.cpp @@ -45,12 +45,12 @@ static constexpr android::DisplayInfo sDummyDisplay{ 1920, // viewportH }; -const DeviceInfo* DeviceInfo::get() { +DeviceInfo* DeviceInfo::get() { static DeviceInfo sDeviceInfo; return &sDeviceInfo; } -DisplayInfo QueryDisplayInfo() { +static DisplayInfo QueryDisplayInfo() { if (Properties::isolatedProcess) { return sDummyDisplay; } @@ -65,6 +65,27 @@ DisplayInfo QueryDisplayInfo() { return displayInfo; } +static float QueryMaxRefreshRate() { + if (Properties::isolatedProcess) { + return sDummyDisplay.fps; + } + + const sp token = SurfaceComposerClient::getInternalDisplayToken(); + LOG_ALWAYS_FATAL_IF(token == nullptr, + "Failed to get display info because internal display is disconnected"); + + Vector configs; + configs.reserve(10); + status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs); + LOG_ALWAYS_FATAL_IF(status, "Failed to getDisplayConfigs, error %d", status); + LOG_ALWAYS_FATAL_IF(configs.size() == 0, "getDisplayConfigs returned 0 configs?"); + float max = 0.0f; + for (auto& info : configs) { + max = std::max(max, info.fps); + } + return max; +} + static void queryWideColorGamutPreference(sk_sp* colorSpace, SkColorType* colorType) { if (Properties::isolatedProcess) { *colorSpace = SkColorSpace::MakeSRGB(); @@ -103,7 +124,7 @@ static void queryWideColorGamutPreference(sk_sp* colorSpace, SkCol } } -DeviceInfo::DeviceInfo() { +DeviceInfo::DeviceInfo() : mMaxRefreshRate(QueryMaxRefreshRate()) { #if HWUI_NULL_GPU mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE; #else @@ -119,7 +140,11 @@ int DeviceInfo::maxTextureSize() const { } void DeviceInfo::setMaxTextureSize(int maxTextureSize) { - const_cast(DeviceInfo::get())->mMaxTextureSize = maxTextureSize; + DeviceInfo::get()->mMaxTextureSize = maxTextureSize; +} + +void DeviceInfo::onDisplayConfigChanged() { + mDisplayInfo = QueryDisplayInfo(); } } /* namespace uirenderer */ diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h index 2bab5d3596cf..0e3f11960ddc 100644 --- a/libs/hwui/DeviceInfo.h +++ b/libs/hwui/DeviceInfo.h @@ -32,7 +32,7 @@ class DeviceInfo { PREVENT_COPY_AND_ASSIGN(DeviceInfo); public: - static const DeviceInfo* get(); + static DeviceInfo* get(); // this value is only valid after the GPU has been initialized and there is a valid graphics // context or if you are using the HWUI_NULL_GPU @@ -40,6 +40,9 @@ public: const DisplayInfo& displayInfo() const { return mDisplayInfo; } sk_sp getWideColorSpace() const { return mWideColorSpace; } SkColorType getWideColorType() const { return mWideColorType; } + float getMaxRefreshRate() const { return mMaxRefreshRate; } + + void onDisplayConfigChanged(); private: friend class renderthread::RenderThread; @@ -51,6 +54,7 @@ private: DisplayInfo mDisplayInfo; sk_sp mWideColorSpace; SkColorType mWideColorType; + const float mMaxRefreshRate; }; } /* namespace uirenderer */ diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 99988542d619..19f509ce8fd7 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -67,7 +67,7 @@ bool Properties::debuggingEnabled = false; bool Properties::isolatedProcess = false; int Properties::contextPriority = 0; -uint32_t Properties::defaultRenderAhead = 0; +int Properties::defaultRenderAhead = -1; static int property_get_int(const char* key, int defaultValue) { char buf[PROPERTY_VALUE_MAX] = { @@ -130,9 +130,8 @@ bool Properties::load() { enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true); - defaultRenderAhead = - std::max(0u, std::min(2u, static_cast(property_get_int( - PROPERTY_RENDERAHEAD, render_ahead().value_or(0))))); + defaultRenderAhead = std::max(-1, std::min(2, property_get_int(PROPERTY_RENDERAHEAD, + render_ahead().value_or(0)))); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 3105e58362ec..3e91c63fcbde 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -253,7 +253,7 @@ public: ANDROID_API static int contextPriority; - static uint32_t defaultRenderAhead; + static int defaultRenderAhead; private: static ProfileType sProfileType; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 2957b143a343..f326ce8d23e9 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -105,13 +105,13 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* , mGenerationID(0) , mOpaque(!translucent) , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) - , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo()) + , mJankTracker(&thread.globalProfileData(), DeviceInfo::get()->displayInfo()) , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos()) , mContentDrawBounds(0, 0, 0, 0) , mRenderPipeline(std::move(renderPipeline)) { rootRenderNode->makeRoot(); mRenderNodes.emplace_back(rootRenderNode); - mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); + mProfiler.setDensity(DeviceInfo::get()->displayInfo().density); setRenderAheadDepth(Properties::defaultRenderAhead); } @@ -153,16 +153,23 @@ void CanvasContext::setSurface(sp&& surface) { mNativeSurface = nullptr; } + if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f) { + mFixedRenderAhead = false; + mRenderAheadCapacity = 1; + } else { + mFixedRenderAhead = true; + mRenderAheadCapacity = mRenderAheadDepth; + } + ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB; bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode, - mRenderAheadDepth); + mRenderAheadCapacity); mFrameNumber = -1; if (hasSurface) { mHaveNewSurface = true; mSwapHistory.clear(); - applyRenderAheadSettings(); } else { mRenderThread.removeFrameCallback(this); mGenerationID++; @@ -403,6 +410,23 @@ void CanvasContext::notifyFramePending() { mRenderThread.pushBackFrameCallback(this); } +void CanvasContext::setPresentTime() { + int64_t presentTime = NATIVE_WINDOW_TIMESTAMP_AUTO; + int renderAhead = 0; + const auto frameIntervalNanos = mRenderThread.timeLord().frameIntervalNanos(); + if (mFixedRenderAhead) { + renderAhead = std::min(mRenderAheadDepth, mRenderAheadCapacity); + } else if (frameIntervalNanos < 15_ms) { + renderAhead = std::min(1, static_cast(mRenderAheadCapacity)); + } + + if (renderAhead) { + presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) + + (frameIntervalNanos * (renderAhead + 1)); + } + native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime); +} + void CanvasContext::draw() { SkRect dirty; mDamageAccumulator.finish(&dirty); @@ -415,14 +439,9 @@ void CanvasContext::draw() { mCurrentFrameInfo->markIssueDrawCommandsStart(); Frame frame = mRenderPipeline->getFrame(); + setPresentTime(); SkRect windowDirty = computeDirtyRect(frame, &dirty); - if (mRenderAheadDepth) { - auto presentTime = - mCurrentFrameInfo->get(FrameInfoIndex::Vsync) + - (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1)); - native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime); - } bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue, mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes, @@ -656,18 +675,12 @@ bool CanvasContext::surfaceRequiresRedraw() { return width == mLastFrameWidth && height == mLastFrameHeight; } -void CanvasContext::applyRenderAheadSettings() { - if (mNativeSurface && !mRenderAheadDepth) { - native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO); - } -} - -void CanvasContext::setRenderAheadDepth(uint32_t renderAhead) { - if (renderAhead > 2 || renderAhead == mRenderAheadDepth || mNativeSurface) { +void CanvasContext::setRenderAheadDepth(int renderAhead) { + if (renderAhead > 2 || renderAhead < 0 || mNativeSurface) { return; } - mRenderAheadDepth = renderAhead; - applyRenderAheadSettings(); + mFixedRenderAhead = true; + mRenderAheadDepth = static_cast(renderAhead); } SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 912b1257de7b..f9de00288e65 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -204,7 +204,7 @@ public: } // Must be called before setSurface - void setRenderAheadDepth(uint32_t renderAhead); + void setRenderAheadDepth(int renderAhead); SkISize getNextFrameSize() const; @@ -221,7 +221,7 @@ private: bool isSwapChainStuffed(); bool surfaceRequiresRedraw(); - void applyRenderAheadSettings(); + void setPresentTime(); SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); @@ -240,7 +240,9 @@ private: // painted onto its surface. bool mIsDirty = false; SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default; + bool mFixedRenderAhead = false; uint32_t mRenderAheadDepth = 0; + uint32_t mRenderAheadCapacity = 0; struct SwapHistory { SkRect damage; nsecs_t vsyncTime; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index eca7d88e4e48..41cb8fdc66bd 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -60,8 +60,10 @@ static JVMAttachHook gOnStartHook = nullptr; class DisplayEventReceiverWrapper : public VsyncSource { public: - DisplayEventReceiverWrapper(std::unique_ptr&& receiver) - : mDisplayEventReceiver(std::move(receiver)) {} + DisplayEventReceiverWrapper(std::unique_ptr&& receiver, + const std::function& onDisplayConfigChanged) + : mDisplayEventReceiver(std::move(receiver)) + , mOnDisplayConfigChanged(onDisplayConfigChanged) {} virtual void requestNextVsync() override { status_t status = mDisplayEventReceiver->requestNextVsync(); @@ -79,6 +81,9 @@ public: case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: latest = ev.header.timestamp; break; + case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: + mOnDisplayConfigChanged(); + break; } } } @@ -90,6 +95,7 @@ public: private: std::unique_ptr mDisplayEventReceiver; + std::function mOnDisplayConfigChanged; }; class DummyVsyncSource : public VsyncSource { @@ -160,22 +166,29 @@ void RenderThread::initializeDisplayEventReceiver() { // Register the FD mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this); - mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver)); + mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver), [this] { + DeviceInfo::get()->onDisplayConfigChanged(); + setupFrameInterval(); + }); } else { mVsyncSource = new DummyVsyncSource(this); } } void RenderThread::initThreadLocals() { - mDisplayInfo = DeviceInfo::get()->displayInfo(); - nsecs_t frameIntervalNanos = static_cast(1000000000 / mDisplayInfo.fps); - mTimeLord.setFrameInterval(frameIntervalNanos); - mDispatchFrameDelay = static_cast(frameIntervalNanos * .25f); + setupFrameInterval(); initializeDisplayEventReceiver(); mEglManager = new EglManager(); mRenderState = new RenderState(*this); mVkManager = new VulkanManager(); - mCacheManager = new CacheManager(mDisplayInfo); + mCacheManager = new CacheManager(DeviceInfo::get()->displayInfo()); +} + +void RenderThread::setupFrameInterval() { + auto& displayInfo = DeviceInfo::get()->displayInfo(); + nsecs_t frameIntervalNanos = static_cast(1000000000 / displayInfo.fps); + mTimeLord.setFrameInterval(frameIntervalNanos); + mDispatchFrameDelay = static_cast(frameIntervalNanos * .25f); } void RenderThread::requireGlContext() { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 6bb26fd6c675..c96e284df6b4 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -102,8 +102,6 @@ public: ProfileDataContainer& globalProfileData() { return mGlobalProfileData; } Readback& readback(); - const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; } - GrContext* getGrContext() const { return mGrContext.get(); } void setGrContext(sk_sp cxt); @@ -149,13 +147,12 @@ private: void initThreadLocals(); void initializeDisplayEventReceiver(); + void setupFrameInterval(); static int displayEventReceiverCallback(int fd, int events, void* data); void drainDisplayEventQueue(); void dispatchFrameCallbacks(); void requestVsync(); - DisplayInfo mDisplayInfo; - VsyncSource* mVsyncSource; bool mVsyncRequested; std::set mFrameCallbacks; diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp index 210fced574e9..3f1ef93c878c 100644 --- a/libs/hwui/tests/unit/CacheManagerTests.cpp +++ b/libs/hwui/tests/unit/CacheManagerTests.cpp @@ -33,7 +33,7 @@ static size_t getCacheUsage(GrContext* grContext) { } RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) { - DisplayInfo displayInfo = renderThread.mainDisplayInfo(); + DisplayInfo displayInfo = DeviceInfo::get()->displayInfo(); GrContext* grContext = renderThread.getGrContext(); ASSERT_TRUE(grContext != nullptr); -- 2.11.0