Merge "[HWUI] use AChoreographer in place of DisplayEventReceiver."

This commit is contained in:
TreeHugger Robot
2020-01-08 17:18:49 +00:00
committed by Android (Google) Code Review
5 changed files with 72 additions and 86 deletions

View File

@@ -52,8 +52,8 @@ void DeviceInfo::setMaxTextureSize(int maxTextureSize) {
DeviceInfo::get()->mMaxTextureSize = maxTextureSize;
}
void DeviceInfo::onDisplayConfigChanged() {
updateDisplayInfo();
void DeviceInfo::onRefreshRateChanged(int64_t vsyncPeriod) {
mVsyncPeriod = vsyncPeriod;
}
void DeviceInfo::updateDisplayInfo() {
@@ -113,10 +113,11 @@ void DeviceInfo::updateDisplayInfo() {
ADisplay* primaryDisplay = mDisplays[mPhysicalDisplayIndex];
status_t status = ADisplay_getCurrentConfig(primaryDisplay, &mCurrentConfig);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display config, error %d", status);
mWidth = ADisplayConfig_getWidth(mCurrentConfig);
mHeight = ADisplayConfig_getHeight(mCurrentConfig);
mDensity = ADisplayConfig_getDensity(mCurrentConfig);
mRefreshRate = ADisplayConfig_getFps(mCurrentConfig);
mVsyncPeriod = static_cast<int64_t>(1000000000 / ADisplayConfig_getFps(mCurrentConfig));
mCompositorOffset = ADisplayConfig_getCompositorOffsetNanos(mCurrentConfig);
mAppOffset = ADisplayConfig_getAppVsyncOffsetNanos(mCurrentConfig);
}

View File

@@ -37,7 +37,7 @@ public:
static int32_t getWidth() { return get()->mWidth; }
static int32_t getHeight() { return get()->mHeight; }
static float getDensity() { return get()->mDensity; }
static float getRefreshRate() { return get()->mRefreshRate; }
static int64_t getVsyncPeriod() { return get()->mVsyncPeriod; }
static int64_t getCompositorOffset() { return get()->mCompositorOffset; }
static int64_t getAppOffset() { return get()->mAppOffset; }
@@ -47,7 +47,8 @@ public:
sk_sp<SkColorSpace> getWideColorSpace() const { return mWideColorSpace; }
SkColorType getWideColorType() const { return mWideColorType; }
void onDisplayConfigChanged();
// This method should be called whenever the display refresh rate changes.
void onRefreshRateChanged(int64_t vsyncPeriod);
private:
friend class renderthread::RenderThread;
@@ -68,7 +69,7 @@ private:
int32_t mWidth = 1080;
int32_t mHeight = 1920;
float mDensity = 2.0;
float mRefreshRate = 60.0;
int64_t mVsyncPeriod = 16666666;
int64_t mCompositorOffset = 0;
int64_t mAppOffset = 0;
};

View File

@@ -81,7 +81,7 @@ static FrameInfoIndex sFrameStart = FrameInfoIndex::IntendedVsync;
JankTracker::JankTracker(ProfileDataContainer* globalData) {
mGlobalData = globalData;
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / DeviceInfo::getRefreshRate());
nsecs_t frameIntervalNanos = DeviceInfo::getVsyncPeriod();
nsecs_t sfOffset = DeviceInfo::getCompositorOffset();
nsecs_t offsetDelta = sfOffset - DeviceInfo::getAppOffset();
// There are two different offset cases. If the offsetDelta is positive

View File

@@ -34,7 +34,6 @@
#include <GrContextOptions.h>
#include <gl/GrGLInterface.h>
#include <gui/DisplayEventReceiver.h>
#include <sys/resource.h>
#include <utils/Condition.h>
#include <utils/Log.h>
@@ -45,53 +44,43 @@ namespace android {
namespace uirenderer {
namespace renderthread {
// Number of events to read at a time from the DisplayEventReceiver pipe.
// The value should be large enough that we can quickly drain the pipe
// using just a few large reads.
static const size_t EVENT_BUFFER_SIZE = 100;
static bool gHasRenderThreadInstance = false;
static JVMAttachHook gOnStartHook = nullptr;
class DisplayEventReceiverWrapper : public VsyncSource {
void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
RenderThread* rt = reinterpret_cast<RenderThread*>(data);
rt->mVsyncRequested = false;
if (rt->timeLord().vsyncReceived(frameTimeNanos) && !rt->mFrameCallbackTaskPending) {
ATRACE_NAME("queue mFrameCallbackTask");
rt->mFrameCallbackTaskPending = true;
nsecs_t runAt = (frameTimeNanos + rt->mDispatchFrameDelay);
rt->queue().postAt(runAt, [=]() { rt->dispatchFrameCallbacks(); });
}
}
void RenderThread::refreshRateCallback(int64_t vsyncPeriod, void* data) {
ATRACE_NAME("refreshRateCallback");
RenderThread* rt = reinterpret_cast<RenderThread*>(data);
DeviceInfo::get()->onRefreshRateChanged(vsyncPeriod);
rt->setupFrameInterval();
}
class ChoreographerSource : public VsyncSource {
public:
DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver,
const std::function<void()>& onDisplayConfigChanged)
: mDisplayEventReceiver(std::move(receiver))
, mOnDisplayConfigChanged(onDisplayConfigChanged) {}
ChoreographerSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
virtual void requestNextVsync() override {
status_t status = mDisplayEventReceiver->requestNextVsync();
LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
AChoreographer_postFrameCallback64(mRenderThread->mChoreographer,
RenderThread::frameCallback, mRenderThread);
}
virtual nsecs_t latestVsyncEvent() override {
DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
nsecs_t latest = 0;
ssize_t n;
while ((n = mDisplayEventReceiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
latest = ev.header.timestamp;
break;
case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
mOnDisplayConfigChanged();
break;
}
}
}
if (n < 0) {
ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
}
return latest;
virtual void drainPendingEvents() override {
AChoreographer_handlePendingEvents(mRenderThread->mChoreographer, mRenderThread);
}
private:
std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
std::function<void()> mOnDisplayConfigChanged;
RenderThread* mRenderThread;
};
class DummyVsyncSource : public VsyncSource {
@@ -99,11 +88,14 @@ public:
DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
virtual void requestNextVsync() override {
mRenderThread->queue().postDelayed(16_ms,
[this]() { mRenderThread->drainDisplayEventQueue(); });
mRenderThread->queue().postDelayed(16_ms, [this]() {
RenderThread::frameCallback(systemTime(SYSTEM_TIME_MONOTONIC), mRenderThread);
});
}
virtual nsecs_t latestVsyncEvent() override { return systemTime(SYSTEM_TIME_MONOTONIC); }
virtual void drainPendingEvents() override {
RenderThread::frameCallback(systemTime(SYSTEM_TIME_MONOTONIC), mRenderThread);
}
private:
RenderThread* mRenderThread;
@@ -145,29 +137,24 @@ RenderThread::RenderThread()
}
RenderThread::~RenderThread() {
// Note that if this fatal assertion is removed then member variables must
// be properly destroyed.
LOG_ALWAYS_FATAL("Can't destroy the render thread");
}
void RenderThread::initializeDisplayEventReceiver() {
LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second DisplayEventReceiver?");
void RenderThread::initializeChoreographer() {
LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second Choreographer?");
if (!Properties::isolatedProcess) {
auto receiver = std::make_unique<DisplayEventReceiver>(
ISurfaceComposer::eVsyncSourceApp,
ISurfaceComposer::eConfigChangedDispatch);
status_t status = receiver->initCheck();
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"Initialization of DisplayEventReceiver "
"failed with status: %d",
status);
mChoreographer = AChoreographer_create();
LOG_ALWAYS_FATAL_IF(mChoreographer == nullptr, "Initialization of Choreographer failed");
AChoreographer_registerRefreshRateCallback(mChoreographer,
RenderThread::refreshRateCallback, this);
// Register the FD
mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
RenderThread::displayEventReceiverCallback, this);
mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver), [this] {
DeviceInfo::get()->onDisplayConfigChanged();
setupFrameInterval();
});
mLooper->addFd(AChoreographer_getFd(mChoreographer), 0, Looper::EVENT_INPUT,
RenderThread::choreographerCallback, this);
mVsyncSource = new ChoreographerSource(this);
} else {
mVsyncSource = new DummyVsyncSource(this);
}
@@ -175,7 +162,7 @@ void RenderThread::initializeDisplayEventReceiver() {
void RenderThread::initThreadLocals() {
setupFrameInterval();
initializeDisplayEventReceiver();
initializeChoreographer();
mEglManager = new EglManager();
mRenderState = new RenderState(*this);
mVkManager = new VulkanManager();
@@ -183,7 +170,7 @@ void RenderThread::initThreadLocals() {
}
void RenderThread::setupFrameInterval() {
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / DeviceInfo::getRefreshRate());
nsecs_t frameIntervalNanos = DeviceInfo::getVsyncPeriod();
mTimeLord.setFrameInterval(frameIntervalNanos);
mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
}
@@ -288,7 +275,7 @@ void RenderThread::setGrContext(sk_sp<GrContext> context) {
}
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
int RenderThread::choreographerCallback(int fd, int events, void* data) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
"events=0x%x",
@@ -302,24 +289,10 @@ int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
events);
return 1; // keep the callback
}
RenderThread* rt = reinterpret_cast<RenderThread*>(data);
AChoreographer_handlePendingEvents(rt->mChoreographer, data);
reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
return 1; // keep the callback
}
void RenderThread::drainDisplayEventQueue() {
ATRACE_CALL();
nsecs_t vsyncEvent = mVsyncSource->latestVsyncEvent();
if (vsyncEvent > 0) {
mVsyncRequested = false;
if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
ATRACE_NAME("queue mFrameCallbackTask");
mFrameCallbackTaskPending = true;
nsecs_t runAt = (vsyncEvent + mDispatchFrameDelay);
queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
}
}
return 1;
}
void RenderThread::dispatchFrameCallbacks() {
@@ -360,7 +333,7 @@ bool RenderThread::threadLoop() {
processQueue();
if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
drainDisplayEventQueue();
mVsyncSource->drainPendingEvents();
mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
mPendingRegistrationFrameCallbacks.end());
mPendingRegistrationFrameCallbacks.clear();

View File

@@ -19,6 +19,7 @@
#include <GrContext.h>
#include <SkBitmap.h>
#include <apex/choreographer.h>
#include <cutils/compiler.h>
#include <thread/ThreadBase.h>
#include <utils/Looper.h>
@@ -73,10 +74,11 @@ protected:
struct VsyncSource {
virtual void requestNextVsync() = 0;
virtual nsecs_t latestVsyncEvent() = 0;
virtual void drainPendingEvents() = 0;
virtual ~VsyncSource() {}
};
class ChoreographerSource;
class DummyVsyncSource;
typedef void (*JVMAttachHook)(const char* name);
@@ -136,6 +138,7 @@ private:
friend class DispatchFrameCallbacks;
friend class RenderProxy;
friend class DummyVsyncSource;
friend class ChoreographerSource;
friend class android::uirenderer::AutoBackendTextureRelease;
friend class android::uirenderer::TestUtils;
friend class android::uirenderer::WebViewFunctor;
@@ -149,13 +152,21 @@ private:
static RenderThread& getInstance();
void initThreadLocals();
void initializeDisplayEventReceiver();
void initializeChoreographer();
void setupFrameInterval();
static int displayEventReceiverCallback(int fd, int events, void* data);
// Callbacks for choreographer events:
// choreographerCallback will call AChoreograper_handleEvent to call the
// corresponding callbacks for each display event type
static int choreographerCallback(int fd, int events, void* data);
// Callback that will be run on vsync ticks.
static void frameCallback(int64_t frameTimeNanos, void* data);
// Callback that will be run whenver there is a refresh rate change.
static void refreshRateCallback(int64_t vsyncPeriod, void* data);
void drainDisplayEventQueue();
void dispatchFrameCallbacks();
void requestVsync();
AChoreographer* mChoreographer;
VsyncSource* mVsyncSource;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;