Loading libs/hwui/HWUIProperties.sysprop +7 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,10 @@ prop { scope: Public access: Readonly } prop { api_name: "render_ahead" type: Integer prop_name: "ro.hwui.render_ahead" scope: Public access: Readonly } No newline at end of file libs/hwui/Properties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ bool Properties::debuggingEnabled = false; bool Properties::isolatedProcess = false; int Properties::contextPriority = 0; int Properties::defaultRenderAhead = 0; static int property_get_int(const char* key, int defaultValue) { char buf[PROPERTY_VALUE_MAX] = { Loading Loading @@ -129,6 +130,13 @@ bool Properties::load() { enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true); defaultRenderAhead = std::max(0, std::min(2, property_get_int(PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))); if (defaultRenderAhead && sRenderPipelineType == RenderPipelineType::SkiaVulkan) { ALOGW("hwui.render_ahead of %d ignored because pipeline is skiavk", defaultRenderAhead); } return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } Loading libs/hwui/Properties.h +4 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,8 @@ enum DebugLevel { #define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled" #define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead" /////////////////////////////////////////////////////////////////////////////// // Misc /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -251,6 +253,8 @@ public: ANDROID_API static int contextPriority; static int defaultRenderAhead; private: static ProfileType sProfileType; static bool sDisableProfileBars; Loading libs/hwui/renderthread/CanvasContext.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode->makeRoot(); mRenderNodes.emplace_back(rootRenderNode); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); setRenderAheadDepth(Properties::defaultRenderAhead); } CanvasContext::~CanvasContext() { Loading Loading @@ -159,6 +160,7 @@ void CanvasContext::setSurface(sp<Surface>&& surface) { if (hasSurface) { mHaveNewSurface = true; mSwapHistory.clear(); applyRenderAheadSettings(); } else { mRenderThread.removeFrameCallback(this); mGenerationID++; Loading Loading @@ -423,6 +425,12 @@ void CanvasContext::draw() { waitOnFences(); if (mRenderAheadDepth) { auto presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) + (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1)); native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime); } bool requireSwap = false; bool didSwap = mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap); Loading Loading @@ -636,6 +644,28 @@ bool CanvasContext::surfaceRequiresRedraw() { return width == mLastFrameWidth && height == mLastFrameHeight; } void CanvasContext::applyRenderAheadSettings() { if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { // TODO: Fix SkiaVulkan's assumptions on buffer counts. And SIGBUS crashes. mRenderAheadDepth = 0; return; } if (mNativeSurface) { native_window_set_buffer_count(mNativeSurface.get(), 3 + mRenderAheadDepth); if (!mRenderAheadDepth) { native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO); } } } void CanvasContext::setRenderAheadDepth(int renderAhead) { if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) { return; } mRenderAheadDepth = renderAhead; applyRenderAheadSettings(); } SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) { // can't rely on prior content of window if viewport size changes Loading libs/hwui/renderthread/CanvasContext.h +4 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,8 @@ public: return mUseForceDark; } void setRenderAheadDepth(int renderAhead); private: CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline); Loading @@ -217,6 +219,7 @@ private: bool isSwapChainStuffed(); bool surfaceRequiresRedraw(); void applyRenderAheadSettings(); SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); Loading @@ -235,6 +238,7 @@ private: // painted onto its surface. bool mIsDirty = false; SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default; int mRenderAheadDepth = 0; struct SwapHistory { SkRect damage; nsecs_t vsyncTime; Loading Loading
libs/hwui/HWUIProperties.sysprop +7 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,10 @@ prop { scope: Public access: Readonly } prop { api_name: "render_ahead" type: Integer prop_name: "ro.hwui.render_ahead" scope: Public access: Readonly } No newline at end of file
libs/hwui/Properties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ bool Properties::debuggingEnabled = false; bool Properties::isolatedProcess = false; int Properties::contextPriority = 0; int Properties::defaultRenderAhead = 0; static int property_get_int(const char* key, int defaultValue) { char buf[PROPERTY_VALUE_MAX] = { Loading Loading @@ -129,6 +130,13 @@ bool Properties::load() { enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true); defaultRenderAhead = std::max(0, std::min(2, property_get_int(PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))); if (defaultRenderAhead && sRenderPipelineType == RenderPipelineType::SkiaVulkan) { ALOGW("hwui.render_ahead of %d ignored because pipeline is skiavk", defaultRenderAhead); } return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw); } Loading
libs/hwui/Properties.h +4 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,8 @@ enum DebugLevel { #define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled" #define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead" /////////////////////////////////////////////////////////////////////////////// // Misc /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -251,6 +253,8 @@ public: ANDROID_API static int contextPriority; static int defaultRenderAhead; private: static ProfileType sProfileType; static bool sDisableProfileBars; Loading
libs/hwui/renderthread/CanvasContext.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode->makeRoot(); mRenderNodes.emplace_back(rootRenderNode); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); setRenderAheadDepth(Properties::defaultRenderAhead); } CanvasContext::~CanvasContext() { Loading Loading @@ -159,6 +160,7 @@ void CanvasContext::setSurface(sp<Surface>&& surface) { if (hasSurface) { mHaveNewSurface = true; mSwapHistory.clear(); applyRenderAheadSettings(); } else { mRenderThread.removeFrameCallback(this); mGenerationID++; Loading Loading @@ -423,6 +425,12 @@ void CanvasContext::draw() { waitOnFences(); if (mRenderAheadDepth) { auto presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) + (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1)); native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime); } bool requireSwap = false; bool didSwap = mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap); Loading Loading @@ -636,6 +644,28 @@ bool CanvasContext::surfaceRequiresRedraw() { return width == mLastFrameWidth && height == mLastFrameHeight; } void CanvasContext::applyRenderAheadSettings() { if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { // TODO: Fix SkiaVulkan's assumptions on buffer counts. And SIGBUS crashes. mRenderAheadDepth = 0; return; } if (mNativeSurface) { native_window_set_buffer_count(mNativeSurface.get(), 3 + mRenderAheadDepth); if (!mRenderAheadDepth) { native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO); } } } void CanvasContext::setRenderAheadDepth(int renderAhead) { if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) { return; } mRenderAheadDepth = renderAhead; applyRenderAheadSettings(); } SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) { // can't rely on prior content of window if viewport size changes Loading
libs/hwui/renderthread/CanvasContext.h +4 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,8 @@ public: return mUseForceDark; } void setRenderAheadDepth(int renderAhead); private: CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline); Loading @@ -217,6 +219,7 @@ private: bool isSwapChainStuffed(); bool surfaceRequiresRedraw(); void applyRenderAheadSettings(); SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); Loading @@ -235,6 +238,7 @@ private: // painted onto its surface. bool mIsDirty = false; SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default; int mRenderAheadDepth = 0; struct SwapHistory { SkRect damage; nsecs_t vsyncTime; Loading