Merge "[HWUI] use AChoreographer in place of DisplayEventReceiver."
This commit is contained in:
committed by
Android (Google) Code Review
commit
68f7a52419
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user