Loading libs/hwui/DeviceInfo.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -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() { Loading Loading @@ -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); } Loading libs/hwui/DeviceInfo.h +4 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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; }; Loading libs/hwui/JankTracker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading libs/hwui/renderthread/RenderThread.cpp +49 −76 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 { public: DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver, const std::function<void()>& onDisplayConfigChanged) : mDisplayEventReceiver(std::move(receiver)) , mOnDisplayConfigChanged(onDisplayConfigChanged) {} virtual void requestNextVsync() override { status_t status = mDisplayEventReceiver->requestNextVsync(); LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status); } 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; 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(); } if (n < 0) { ALOGW("Failed to get events from display event receiver, status=%d", status_t(n)); class ChoreographerSource : public VsyncSource { public: ChoreographerSource(RenderThread* renderThread) : mRenderThread(renderThread) {} virtual void requestNextVsync() override { AChoreographer_postFrameCallback64(mRenderThread->mChoreographer, RenderThread::frameCallback, mRenderThread); } 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 { Loading @@ -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; Loading Loading @@ -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); } Loading @@ -175,7 +162,7 @@ void RenderThread::initializeDisplayEventReceiver() { void RenderThread::initThreadLocals() { setupFrameInterval(); initializeDisplayEventReceiver(); initializeChoreographer(); mEglManager = new EglManager(); mRenderState = new RenderState(*this); mVkManager = new VulkanManager(); Loading @@ -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); } Loading Loading @@ -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", Loading @@ -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() { Loading Loading @@ -360,7 +333,7 @@ bool RenderThread::threadLoop() { processQueue(); if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) { drainDisplayEventQueue(); mVsyncSource->drainPendingEvents(); mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end()); mPendingRegistrationFrameCallbacks.clear(); Loading libs/hwui/renderthread/RenderThread.h +14 −3 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading Loading
libs/hwui/DeviceInfo.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -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() { Loading Loading @@ -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); } Loading
libs/hwui/DeviceInfo.h +4 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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; }; Loading
libs/hwui/JankTracker.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/hwui/renderthread/RenderThread.cpp +49 −76 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 { public: DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver, const std::function<void()>& onDisplayConfigChanged) : mDisplayEventReceiver(std::move(receiver)) , mOnDisplayConfigChanged(onDisplayConfigChanged) {} virtual void requestNextVsync() override { status_t status = mDisplayEventReceiver->requestNextVsync(); LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status); } 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; 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(); } if (n < 0) { ALOGW("Failed to get events from display event receiver, status=%d", status_t(n)); class ChoreographerSource : public VsyncSource { public: ChoreographerSource(RenderThread* renderThread) : mRenderThread(renderThread) {} virtual void requestNextVsync() override { AChoreographer_postFrameCallback64(mRenderThread->mChoreographer, RenderThread::frameCallback, mRenderThread); } 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 { Loading @@ -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; Loading Loading @@ -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); } Loading @@ -175,7 +162,7 @@ void RenderThread::initializeDisplayEventReceiver() { void RenderThread::initThreadLocals() { setupFrameInterval(); initializeDisplayEventReceiver(); initializeChoreographer(); mEglManager = new EglManager(); mRenderState = new RenderState(*this); mVkManager = new VulkanManager(); Loading @@ -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); } Loading Loading @@ -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", Loading @@ -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() { Loading Loading @@ -360,7 +333,7 @@ bool RenderThread::threadLoop() { processQueue(); if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) { drainDisplayEventQueue(); mVsyncSource->drainPendingEvents(); mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end()); mPendingRegistrationFrameCallbacks.clear(); Loading
libs/hwui/renderthread/RenderThread.h +14 −3 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading