Merge "Add back render-ahead support" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
22477c4dd0
@@ -7,3 +7,10 @@ prop {
|
|||||||
scope: Public
|
scope: Public
|
||||||
access: Readonly
|
access: Readonly
|
||||||
}
|
}
|
||||||
|
prop {
|
||||||
|
api_name: "render_ahead"
|
||||||
|
type: Integer
|
||||||
|
prop_name: "ro.hwui.render_ahead"
|
||||||
|
scope: Public
|
||||||
|
access: Readonly
|
||||||
|
}
|
||||||
@@ -67,6 +67,7 @@ bool Properties::debuggingEnabled = false;
|
|||||||
bool Properties::isolatedProcess = false;
|
bool Properties::isolatedProcess = false;
|
||||||
|
|
||||||
int Properties::contextPriority = 0;
|
int Properties::contextPriority = 0;
|
||||||
|
int Properties::defaultRenderAhead = 0;
|
||||||
|
|
||||||
static int property_get_int(const char* key, int defaultValue) {
|
static int property_get_int(const char* key, int defaultValue) {
|
||||||
char buf[PROPERTY_VALUE_MAX] = {
|
char buf[PROPERTY_VALUE_MAX] = {
|
||||||
@@ -129,6 +130,13 @@ bool Properties::load() {
|
|||||||
|
|
||||||
enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true);
|
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);
|
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ enum DebugLevel {
|
|||||||
|
|
||||||
#define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled"
|
#define PROPERTY_ENABLE_FORCE_DARK "debug.hwui.force_dark_enabled"
|
||||||
|
|
||||||
|
#define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Misc
|
// Misc
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -251,6 +253,8 @@ public:
|
|||||||
|
|
||||||
ANDROID_API static int contextPriority;
|
ANDROID_API static int contextPriority;
|
||||||
|
|
||||||
|
static int defaultRenderAhead;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ProfileType sProfileType;
|
static ProfileType sProfileType;
|
||||||
static bool sDisableProfileBars;
|
static bool sDisableProfileBars;
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
|
|||||||
rootRenderNode->makeRoot();
|
rootRenderNode->makeRoot();
|
||||||
mRenderNodes.emplace_back(rootRenderNode);
|
mRenderNodes.emplace_back(rootRenderNode);
|
||||||
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
|
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
|
||||||
|
setRenderAheadDepth(Properties::defaultRenderAhead);
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasContext::~CanvasContext() {
|
CanvasContext::~CanvasContext() {
|
||||||
@@ -159,6 +160,7 @@ void CanvasContext::setSurface(sp<Surface>&& surface) {
|
|||||||
if (hasSurface) {
|
if (hasSurface) {
|
||||||
mHaveNewSurface = true;
|
mHaveNewSurface = true;
|
||||||
mSwapHistory.clear();
|
mSwapHistory.clear();
|
||||||
|
applyRenderAheadSettings();
|
||||||
} else {
|
} else {
|
||||||
mRenderThread.removeFrameCallback(this);
|
mRenderThread.removeFrameCallback(this);
|
||||||
mGenerationID++;
|
mGenerationID++;
|
||||||
@@ -423,6 +425,12 @@ void CanvasContext::draw() {
|
|||||||
|
|
||||||
waitOnFences();
|
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 requireSwap = false;
|
||||||
bool didSwap =
|
bool didSwap =
|
||||||
mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
|
mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
|
||||||
@@ -636,6 +644,28 @@ bool CanvasContext::surfaceRequiresRedraw() {
|
|||||||
return width == mLastFrameWidth && height == mLastFrameHeight;
|
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) {
|
SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
|
||||||
if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
|
if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
|
||||||
// can't rely on prior content of window if viewport size changes
|
// can't rely on prior content of window if viewport size changes
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ public:
|
|||||||
return mUseForceDark;
|
return mUseForceDark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRenderAheadDepth(int renderAhead);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
|
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
|
||||||
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
|
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
|
||||||
@@ -217,6 +219,7 @@ private:
|
|||||||
|
|
||||||
bool isSwapChainStuffed();
|
bool isSwapChainStuffed();
|
||||||
bool surfaceRequiresRedraw();
|
bool surfaceRequiresRedraw();
|
||||||
|
void applyRenderAheadSettings();
|
||||||
|
|
||||||
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
|
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
|
||||||
|
|
||||||
@@ -235,6 +238,7 @@ private:
|
|||||||
// painted onto its surface.
|
// painted onto its surface.
|
||||||
bool mIsDirty = false;
|
bool mIsDirty = false;
|
||||||
SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
|
SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
|
||||||
|
int mRenderAheadDepth = 0;
|
||||||
struct SwapHistory {
|
struct SwapHistory {
|
||||||
SkRect damage;
|
SkRect damage;
|
||||||
nsecs_t vsyncTime;
|
nsecs_t vsyncTime;
|
||||||
|
|||||||
@@ -312,6 +312,12 @@ void RenderProxy::setForceDark(bool enable) {
|
|||||||
mRenderThread.queue().post([this, enable]() { mContext->setForceDark(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,
|
int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
|
||||||
SkBitmap* bitmap) {
|
SkBitmap* bitmap) {
|
||||||
auto& thread = RenderThread::getInstance();
|
auto& thread = RenderThread::getInstance();
|
||||||
|
|||||||
@@ -123,6 +123,23 @@ public:
|
|||||||
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
|
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
|
||||||
ANDROID_API void setForceDark(bool enable);
|
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,
|
ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right,
|
||||||
int bottom, SkBitmap* bitmap);
|
int bottom, SkBitmap* bitmap);
|
||||||
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
|
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
int reportFrametimeWeight = 0;
|
int reportFrametimeWeight = 0;
|
||||||
bool renderOffscreen = true;
|
bool renderOffscreen = true;
|
||||||
|
int renderAhead = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
|
|||||||
proxy->resetProfileInfo();
|
proxy->resetProfileInfo();
|
||||||
proxy->fence();
|
proxy->fence();
|
||||||
|
|
||||||
|
if (opts.renderAhead) {
|
||||||
|
usleep(33000);
|
||||||
|
}
|
||||||
|
proxy->setRenderAheadDepth(opts.renderAhead);
|
||||||
|
|
||||||
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
|
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
|
||||||
|
|
||||||
nsecs_t start = systemTime(CLOCK_MONOTONIC);
|
nsecs_t start = systemTime(CLOCK_MONOTONIC);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ OPTIONS:
|
|||||||
are offscreen rendered
|
are offscreen rendered
|
||||||
--benchmark_format Set output format. Possible values are tabular, json, csv
|
--benchmark_format Set output format. Possible values are tabular, json, csv
|
||||||
--renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk
|
--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,
|
Onscreen,
|
||||||
Offscreen,
|
Offscreen,
|
||||||
Renderer,
|
Renderer,
|
||||||
|
RenderAhead,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +187,7 @@ static const struct option LONG_OPTIONS[] = {
|
|||||||
{"onscreen", no_argument, nullptr, LongOpts::Onscreen},
|
{"onscreen", no_argument, nullptr, LongOpts::Onscreen},
|
||||||
{"offscreen", no_argument, nullptr, LongOpts::Offscreen},
|
{"offscreen", no_argument, nullptr, LongOpts::Offscreen},
|
||||||
{"renderer", required_argument, nullptr, LongOpts::Renderer},
|
{"renderer", required_argument, nullptr, LongOpts::Renderer},
|
||||||
|
{"render-ahead", required_argument, nullptr, LongOpts::RenderAhead},
|
||||||
{0, 0, 0, 0}};
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
static const char* SHORT_OPTIONS = "c:r:h";
|
static const char* SHORT_OPTIONS = "c:r:h";
|
||||||
@@ -283,6 +286,16 @@ void parseOptions(int argc, char* argv[]) {
|
|||||||
gOpts.renderOffscreen = true;
|
gOpts.renderOffscreen = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LongOpts::RenderAhead:
|
||||||
|
if (!optarg) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
gOpts.renderAhead = atoi(optarg);
|
||||||
|
if (gOpts.renderAhead < 0 || gOpts.renderAhead > 2) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
printHelp();
|
printHelp();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
|||||||
Reference in New Issue
Block a user