Remove render ahead from hwui

As HWUI uses vsync id to send buffers to SF, SF applies the right
amount of render ahead by latching the buffers at the configured time.

Test: launch an app and observe systrace
Bug: 178148035
Change-Id: Ifd3e1a2971aad0a085cb35d33e950194046aa634
This commit is contained in:
Ady Abraham
2021-02-03 18:33:11 -08:00
parent dba0fb5580
commit 7bb70faa04
12 changed files with 8 additions and 123 deletions

View File

@@ -46,7 +46,6 @@ import java.io.File;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.stream.Stream;
@@ -1148,24 +1147,14 @@ public class HardwareRenderer {
// Default to SRGB if the display doesn't support wide color
.orElse(Dataspace.SRGB);
float maxRefreshRate =
(float) Arrays.stream(display.getSupportedModes())
.mapToDouble(Mode::getRefreshRate)
.max()
.orElseGet(() -> {
Log.i(LOG_TAG, "Failed to find the maximum display refresh rate");
// Assume that the max refresh rate is 60hz if we can't find one.
return 60.0;
});
// Grab the physical screen dimensions from the active display mode
// Strictly speaking the screen resolution may not always be constant - it is for
// sizing the font cache for the underlying rendering thread. Since it's a
// heuristic we don't need to be always 100% correct.
Mode activeMode = display.getMode();
nInitDisplayInfo(activeMode.getPhysicalWidth(), activeMode.getPhysicalHeight(),
display.getRefreshRate(), maxRefreshRate,
wideColorDataspace.mNativeDataspace, display.getAppVsyncOffsetNanos(),
display.getPresentationDeadlineNanos());
display.getRefreshRate(), wideColorDataspace.mNativeDataspace,
display.getAppVsyncOffsetNanos(), display.getPresentationDeadlineNanos());
// Defensively clear out the context
mContext = null;
@@ -1324,6 +1313,5 @@ public class HardwareRenderer {
private static native void nSetDisplayDensityDpi(int densityDpi);
private static native void nInitDisplayInfo(int width, int height, float refreshRate,
float maxRefreshRate, int wideColorDataspace, long appVsyncOffsetNanos,
long presentationDeadlineNanos);
int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos);
}

View File

@@ -35,7 +35,6 @@ class DeviceInfo {
public:
static DeviceInfo* get();
static float getMaxRefreshRate() { return get()->mMaxRefreshRate; }
static int32_t getWidth() { return get()->mWidth; }
static int32_t getHeight() { return get()->mHeight; }
// Gets the density in density-independent pixels
@@ -45,7 +44,6 @@ public:
static int64_t getAppOffset() { return get()->mAppVsyncOffsetNanos; }
// Sets the density in density-independent pixels
static void setDensity(float density) { sDensity.store(density); }
static void setMaxRefreshRate(float refreshRate) { get()->mMaxRefreshRate = refreshRate; }
static void setWidth(int32_t width) { get()->mWidth = width; }
static void setHeight(int32_t height) { get()->mHeight = height; }
static void setRefreshRate(float refreshRate) {
@@ -91,7 +89,6 @@ private:
SkColorType mWideColorType = SkColorType::kN32_SkColorType;
int mDisplaysSize = 0;
int mPhysicalDisplayIndex = -1;
float mMaxRefreshRate = 60.0;
int32_t mWidth = 1080;
int32_t mHeight = 1920;
int64_t mVsyncPeriod = 16666666;

View File

@@ -79,7 +79,6 @@ bool Properties::debuggingEnabled = false;
bool Properties::isolatedProcess = false;
int Properties::contextPriority = 0;
int Properties::defaultRenderAhead = -1;
float Properties::defaultSdrWhitePoint = 200.f;
bool Properties::load() {
@@ -129,10 +128,6 @@ bool Properties::load() {
runningInEmulator = base::GetBoolProperty(PROPERTY_QEMU_KERNEL, false);
defaultRenderAhead = std::max(
-1,
std::min(2, base::GetIntProperty(PROPERTY_RENDERAHEAD, render_ahead().value_or(-1))));
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}

View File

@@ -162,8 +162,6 @@ enum DebugLevel {
*/
#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu"
#define PROPERTY_RENDERAHEAD "debug.hwui.render_ahead"
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
@@ -247,8 +245,6 @@ public:
static int contextPriority;
static int defaultRenderAhead;
static float defaultSdrWhitePoint;
private:

View File

@@ -603,14 +603,12 @@ static void android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv*, jclass,
static void android_view_ThreadedRenderer_initDisplayInfo(JNIEnv*, jclass, jint physicalWidth,
jint physicalHeight, jfloat refreshRate,
jfloat maxRefreshRate,
jint wideColorDataspace,
jlong appVsyncOffsetNanos,
jlong presentationDeadlineNanos) {
DeviceInfo::setWidth(physicalWidth);
DeviceInfo::setHeight(physicalHeight);
DeviceInfo::setRefreshRate(refreshRate);
DeviceInfo::setMaxRefreshRate(maxRefreshRate);
DeviceInfo::setWideColorDataspace(static_cast<ADataSpace>(wideColorDataspace));
DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
@@ -735,7 +733,7 @@ static const JNINativeMethod gMethods[] = {
{"nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark},
{"nSetDisplayDensityDpi", "(I)V",
(void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
{"nInitDisplayInfo", "(IIFFIJJ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
{"nInitDisplayInfo", "(IIFIJJ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
{"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
};

View File

@@ -108,7 +108,6 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
mProfiler.setDensity(DeviceInfo::getDensity());
setRenderAheadDepth(Properties::defaultRenderAhead);
}
CanvasContext::~CanvasContext() {
@@ -157,24 +156,17 @@ static void setBufferCount(ANativeWindow* window) {
void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
ATRACE_CALL();
if (mFixedRenderAhead) {
mRenderAheadCapacity = mRenderAheadDepth;
} else {
if (DeviceInfo::get()->getMaxRefreshRate() > 66.6f) {
mRenderAheadCapacity = 1;
} else {
mRenderAheadCapacity = 0;
}
}
if (window) {
int extraBuffers = 0;
native_window_get_extra_buffer_count(window, &extraBuffers);
mNativeSurface = std::make_unique<ReliableSurface>(window);
mNativeSurface->init();
if (enableTimeout) {
// TODO: Fix error handling & re-shorten timeout
ANativeWindow_setDequeueTimeout(window, 4000_ms);
}
mNativeSurface->setExtraBufferCount(mRenderAheadCapacity);
mNativeSurface->setExtraBufferCount(extraBuffers);
} else {
mNativeSurface = nullptr;
}
@@ -441,24 +433,6 @@ void CanvasContext::notifyFramePending() {
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)) - DeviceInfo::get()->getAppOffset() +
(frameIntervalNanos / 2);
}
native_window_set_buffers_timestamp(mNativeSurface->getNativeWindow(), presentTime);
}
void CanvasContext::draw() {
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -478,8 +452,6 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markIssueDrawCommandsStart();
Frame frame = mRenderPipeline->getFrame();
setPresentTime();
SkRect windowDirty = computeDirtyRect(frame, &dirty);
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
@@ -765,19 +737,6 @@ bool CanvasContext::surfaceRequiresRedraw() {
return width != mLastFrameWidth || height != mLastFrameHeight;
}
void CanvasContext::setRenderAheadDepth(int renderAhead) {
if (renderAhead > 2 || renderAhead < -1 || mNativeSurface) {
return;
}
if (renderAhead == -1) {
mFixedRenderAhead = false;
mRenderAheadDepth = 0;
} else {
mFixedRenderAhead = true;
mRenderAheadDepth = static_cast<uint32_t>(renderAhead);
}
}
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

View File

@@ -193,9 +193,6 @@ public:
return mUseForceDark;
}
// Must be called before setSurface
void setRenderAheadDepth(int renderAhead);
SkISize getNextFrameSize() const;
private:
@@ -211,7 +208,6 @@ private:
bool isSwapChainStuffed();
bool surfaceRequiresRedraw();
void setPresentTime();
void setupPipelineSurface();
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
@@ -232,9 +228,6 @@ private:
// 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;

View File

@@ -295,11 +295,6 @@ 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(ANativeWindow* window, int left, int top, int right, int bottom,
SkBitmap* bitmap) {
auto& thread = RenderThread::getInstance();

View File

@@ -123,23 +123,6 @@ public:
void removeFrameMetricsObserver(FrameMetricsObserver* observer);
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]
*/
void setRenderAheadDepth(int renderAhead);
static int copySurfaceInto(ANativeWindow* window, int left, int top, int right,
int bottom, SkBitmap* bitmap);
static void prepareToDraw(Bitmap& bitmap);

View File

@@ -38,7 +38,6 @@ public:
int count = 0;
int reportFrametimeWeight = 0;
bool renderOffscreen = true;
int renderAhead = 0;
};
template <class T>

View File

@@ -153,11 +153,6 @@ 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(SYSTEM_TIME_MONOTONIC);

View File

@@ -69,7 +69,6 @@ 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.
)");
}
@@ -171,7 +170,6 @@ enum {
Onscreen,
Offscreen,
Renderer,
RenderAhead,
};
}
@@ -187,7 +185,6 @@ 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";
@@ -286,16 +283,6 @@ 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);