diff options
| author | 2019-03-13 16:25:20 -0700 | |
|---|---|---|
| committer | 2019-04-03 14:33:04 -0700 | |
| commit | 859f98d82c1ff38f34c0495d180561121f8a1a81 (patch) | |
| tree | 5be87addae0b90b835b310dccafb786ce421a4b9 | |
| parent | a3151aa9ebb6764ed8de418c1cfc39bf284f521f (diff) | |
Add back render-ahead support
Currently only supported in the EGL path.
Vulkan support Coming Soon
Bug: 127822449
Test: trace of hwuimacro
Change-Id: Iac2b039e11d964aab5b8ca1bdf2a5430b187e2ea
| -rw-r--r-- | libs/hwui/HWUIProperties.sysprop | 7 | ||||
| -rw-r--r-- | libs/hwui/Properties.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/Properties.h | 4 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 30 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 4 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 6 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 17 | ||||
| -rw-r--r-- | libs/hwui/tests/common/TestScene.h | 1 | ||||
| -rw-r--r-- | libs/hwui/tests/macrobench/TestSceneRunner.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/tests/macrobench/main.cpp | 13 |
10 files changed, 95 insertions, 0 deletions
diff --git a/libs/hwui/HWUIProperties.sysprop b/libs/hwui/HWUIProperties.sysprop index 42191ca6f514..34aeaae867f9 100644 --- a/libs/hwui/HWUIProperties.sysprop +++ b/libs/hwui/HWUIProperties.sysprop @@ -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 diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 046ffc4da5ea..9b1f25986d56 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -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] = { @@ -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); } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 0a7f4e7eb41c..3e91c63fcbde 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -167,6 +167,8 @@ enum DebugLevel { #define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled" +#define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead" + /////////////////////////////////////////////////////////////////////////////// // Misc /////////////////////////////////////////////////////////////////////////////// @@ -251,6 +253,8 @@ public: ANDROID_API static int contextPriority; + static int defaultRenderAhead; + private: static ProfileType sProfileType; static bool sDisableProfileBars; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index baa41c1ec698..4808d68b89ab 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -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() { @@ -159,6 +160,7 @@ void CanvasContext::setSurface(sp<Surface>&& surface) { if (hasSurface) { mHaveNewSurface = true; mSwapHistory.clear(); + applyRenderAheadSettings(); } else { mRenderThread.removeFrameCallback(this); mGenerationID++; @@ -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); @@ -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 diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index abca34225f98..4a3119a55c77 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -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); @@ -217,6 +219,7 @@ private: bool isSwapChainStuffed(); bool surfaceRequiresRedraw(); + void applyRenderAheadSettings(); SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); @@ -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; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 16240b4e177b..b58bab1191ed 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -312,6 +312,12 @@ void RenderProxy::setForceDark(bool enable) { mRenderThread.queue().post([this, enable]() { mContext->setForceDark(enable); }); } +void RenderProxy::setRenderAheadDepth(int renderAhead) { + mRenderThread.queue().post([ context = mContext, renderAhead ] { + context->setRenderAheadDepth(renderAhead); + }); +} + int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap) { auto& thread = RenderThread::getInstance(); diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index a1a5551722bc..a0f08cbd26f9 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -123,6 +123,23 @@ public: ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer); ANDROID_API void setForceDark(bool enable); + /** + * Sets a render-ahead depth on the backing renderer. This will increase latency by + * <swapInterval> * renderAhead and increase memory usage by (3 + renderAhead) * <resolution>. + * In return the renderer will be less susceptible to jitter, resulting in a smoother animation. + * + * Not recommended to use in response to anything touch driven, but for canned animations + * where latency is not a concern careful use may be beneficial. + * + * Note that when increasing this there will be a frame gap of N frames where N is + * renderAhead - <current renderAhead>. When decreasing this if there are any pending + * frames they will retain their prior renderAhead value, so it will take a few frames + * for the decrease to flush through. + * + * @param renderAhead How far to render ahead, must be in the range [0..2] + */ + ANDROID_API void setRenderAheadDepth(int renderAhead); + ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap); ANDROID_API static void prepareToDraw(Bitmap& bitmap); diff --git a/libs/hwui/tests/common/TestScene.h b/libs/hwui/tests/common/TestScene.h index 91022cfe734b..74a039b3d090 100644 --- a/libs/hwui/tests/common/TestScene.h +++ b/libs/hwui/tests/common/TestScene.h @@ -38,6 +38,7 @@ public: int count = 0; int reportFrametimeWeight = 0; bool renderOffscreen = true; + int renderAhead = 0; }; template <class T> diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp index b45dbc8b832b..aa579adfb2ce 100644 --- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp +++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp @@ -154,6 +154,11 @@ void run(const TestScene::Info& info, const TestScene::Options& opts, proxy->resetProfileInfo(); proxy->fence(); + if (opts.renderAhead) { + usleep(33000); + } + proxy->setRenderAheadDepth(opts.renderAhead); + ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight); nsecs_t start = systemTime(CLOCK_MONOTONIC); diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp index 174a14080eff..88d33c315a09 100644 --- a/libs/hwui/tests/macrobench/main.cpp +++ b/libs/hwui/tests/macrobench/main.cpp @@ -69,6 +69,7 @@ OPTIONS: are offscreen rendered --benchmark_format Set output format. Possible values are tabular, json, csv --renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk + --render-ahead=NUM Sets how far to render-ahead. Must be 0 (default), 1, or 2. )"); } @@ -170,6 +171,7 @@ enum { Onscreen, Offscreen, Renderer, + RenderAhead, }; } @@ -185,6 +187,7 @@ static const struct option LONG_OPTIONS[] = { {"onscreen", no_argument, nullptr, LongOpts::Onscreen}, {"offscreen", no_argument, nullptr, LongOpts::Offscreen}, {"renderer", required_argument, nullptr, LongOpts::Renderer}, + {"render-ahead", required_argument, nullptr, LongOpts::RenderAhead}, {0, 0, 0, 0}}; static const char* SHORT_OPTIONS = "c:r:h"; @@ -283,6 +286,16 @@ void parseOptions(int argc, char* argv[]) { gOpts.renderOffscreen = true; break; + case LongOpts::RenderAhead: + if (!optarg) { + error = true; + } + gOpts.renderAhead = atoi(optarg); + if (gOpts.renderAhead < 0 || gOpts.renderAhead > 2) { + error = true; + } + break; + case 'h': printHelp(); exit(EXIT_SUCCESS); |