Skip to content
Snippets Groups Projects
Commit 859f98d8 authored by John Reck's avatar John Reck
Browse files

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
parent a3151aa9
No related branches found
No related tags found
No related merge requests found
......@@ -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
......@@ -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);
}
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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();
......
......@@ -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);
......
......@@ -38,6 +38,7 @@ public:
int count = 0;
int reportFrametimeWeight = 0;
bool renderOffscreen = true;
int renderAhead = 0;
};
template <class T>
......
......@@ -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);
......
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment