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
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2957b14..f326ce8 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -105,13 +105,13 @@
, 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 @@
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 @@
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<int>(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 @@
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 @@
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<uint32_t>(renderAhead);
}
SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 912b125..f9de002 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -204,7 +204,7 @@
}
// Must be called before setSurface
- void setRenderAheadDepth(uint32_t renderAhead);
+ void setRenderAheadDepth(int renderAhead);
SkISize getNextFrameSize() const;
@@ -221,7 +221,7 @@
bool isSwapChainStuffed();
bool surfaceRequiresRedraw();
- void applyRenderAheadSettings();
+ void setPresentTime();
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
@@ -240,7 +240,9 @@
// 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 eca7d88..41cb8fd 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -60,8 +60,10 @@
class DisplayEventReceiverWrapper : public VsyncSource {
public:
- DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
- : mDisplayEventReceiver(std::move(receiver)) {}
+ DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver,
+ const std::function<void()>& onDisplayConfigChanged)
+ : mDisplayEventReceiver(std::move(receiver))
+ , mOnDisplayConfigChanged(onDisplayConfigChanged) {}
virtual void requestNextVsync() override {
status_t status = mDisplayEventReceiver->requestNextVsync();
@@ -79,6 +81,9 @@
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
latest = ev.header.timestamp;
break;
+ case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+ mOnDisplayConfigChanged();
+ break;
}
}
}
@@ -90,6 +95,7 @@
private:
std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+ std::function<void()> mOnDisplayConfigChanged;
};
class DummyVsyncSource : public VsyncSource {
@@ -160,22 +166,29 @@
// 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<nsecs_t>(1000000000 / mDisplayInfo.fps);
- mTimeLord.setFrameInterval(frameIntervalNanos);
- mDispatchFrameDelay = static_cast<nsecs_t>(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<nsecs_t>(1000000000 / displayInfo.fps);
+ mTimeLord.setFrameInterval(frameIntervalNanos);
+ mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
}
void RenderThread::requireGlContext() {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 6bb26fd..c96e284 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -102,8 +102,6 @@
ProfileDataContainer& globalProfileData() { return mGlobalProfileData; }
Readback& readback();
- const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
-
GrContext* getGrContext() const { return mGrContext.get(); }
void setGrContext(sk_sp<GrContext> cxt);
@@ -149,13 +147,12 @@
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<IFrameCallback*> mFrameCallbacks;