From 23b867a444d80222638922daff372f2e67d77dcc Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 22 Jan 2019 12:44:53 -0800 Subject: SF: Remove fixed-size array for VSYNC events EventThread maintains two DisplayEventReceiver::Event instances to store the latest VSYNC state for the internal and external displays, regardless of their connection status. This CL removes the (unused) latter instance, replaces the former with VSyncState, and generalizes event processing by queuing up VSYNC events along with hotplug events. The VSyncState lifetime will be tied to hotplug events in a future CL. Bug: 74619554 Test: libsurfaceflinger_unittest Test: dumpsys SurfaceFlinger --vsync Change-Id: I5fbc1d08259145387dab73596a0cfe4624c35676 --- services/surfaceflinger/Scheduler/EventThread.cpp | 86 ++++++++++------------- services/surfaceflinger/Scheduler/EventThread.h | 17 ++++- 2 files changed, 51 insertions(+), 52 deletions(-) (limited to 'services/surfaceflinger') diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 01aedf45d7..281f6b7069 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -79,6 +79,20 @@ std::string toString(const DisplayEventReceiver::Event& event) { } } +DisplayEventReceiver::Event makeHotplug(uint32_t displayId, nsecs_t timestamp, bool connected) { + DisplayEventReceiver::Event event; + event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp}; + event.hotplug.connected = connected; + return event; +} + +DisplayEventReceiver::Event makeVSync(uint32_t displayId, nsecs_t timestamp, uint32_t count) { + DisplayEventReceiver::Event event; + event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp}; + event.vsync.count = count; + return event; +} + } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, @@ -149,12 +163,6 @@ EventThread::EventThread(VSyncSource* src, std::unique_ptr uniqueSr if (src == nullptr) { mVSyncSource = mVSyncSourceUnique.get(); } - for (auto& event : mVSyncEvent) { - event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - event.header.id = 0; - event.header.timestamp = 0; - event.vsync.count = 0; - } mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock lock(mMutex); @@ -253,41 +261,32 @@ void EventThread::requestNextVsync(const sp& connection, void EventThread::onScreenReleased() { std::lock_guard lock(mMutex); - if (!mUseSoftwareVSync) { - // disable reliance on h/w vsync - mUseSoftwareVSync = true; + if (!mVSyncState.synthetic) { + mVSyncState.synthetic = true; mCondition.notify_all(); } } void EventThread::onScreenAcquired() { std::lock_guard lock(mMutex); - if (mUseSoftwareVSync) { - // resume use of h/w vsync - mUseSoftwareVSync = false; + if (mVSyncState.synthetic) { + mVSyncState.synthetic = false; mCondition.notify_all(); } } void EventThread::onVSyncEvent(nsecs_t timestamp) { std::lock_guard lock(mMutex); - mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - mVSyncEvent[0].header.id = 0; - mVSyncEvent[0].header.timestamp = timestamp; - mVSyncEvent[0].vsync.count++; + + mPendingEvents.push_back(makeVSync(mVSyncState.displayId, timestamp, ++mVSyncState.count)); mCondition.notify_all(); } void EventThread::onHotplugReceived(DisplayType displayType, bool connected) { std::lock_guard lock(mMutex); - DisplayEventReceiver::Event event; - event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG; - event.header.id = displayType == DisplayType::Primary ? 0 : 1; - event.header.timestamp = systemTime(); - event.hotplug.connected = connected; - - mPendingEvents.push_back(event); + const uint32_t displayId = displayType == DisplayType::Primary ? 0 : 1; + mPendingEvents.push_back(makeHotplug(displayId, systemTime(), connected)); mCondition.notify_all(); } @@ -301,18 +300,13 @@ void EventThread::threadMain(std::unique_lock& lock) { if (!mPendingEvents.empty()) { event = mPendingEvents.front(); mPendingEvents.pop_front(); - } else { - for (auto& vsyncEvent : mVSyncEvent) { - if (vsyncEvent.header.timestamp) { - event = vsyncEvent; - vsyncEvent.header.timestamp = 0; - - if (mInterceptVSyncsCallback) { - mInterceptVSyncsCallback(event->header.timestamp); - } - break; - } - } + } + + const bool vsyncPending = + event && event->header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC; + + if (mInterceptVSyncsCallback && vsyncPending) { + mInterceptVSyncsCallback(event->header.timestamp); } bool vsyncRequested = false; @@ -338,9 +332,6 @@ void EventThread::threadMain(std::unique_lock& lock) { consumers.clear(); } - const bool vsyncPending = - event && event->header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - // Here we figure out if we need to enable or disable vsyncs if (vsyncPending && !vsyncRequested) { // we received a VSYNC but we have no clients @@ -364,15 +355,13 @@ void EventThread::threadMain(std::unique_lock& lock) { if (vsyncRequested) { // Generate a fake VSYNC after a long timeout in case the driver stalls. When the // display is off, keep feeding clients at 60 Hz. - const bool softwareSync = mUseSoftwareVSync; - const auto timeout = softwareSync ? 16ms : 1000ms; + const auto timeout = mVSyncState.synthetic ? 16ms : 1000ms; if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) { - ALOGW_IF(!softwareSync, "Faking VSYNC due to driver stall"); + ALOGW_IF(!mVSyncState.synthetic, "Faking VSYNC due to driver stall"); - mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - mVSyncEvent[0].header.id = 0; - mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); - mVSyncEvent[0].vsync.count++; + mPendingEvents.push_back(makeVSync(mVSyncState.displayId, + systemTime(SYSTEM_TIME_MONOTONIC), + ++mVSyncState.count)); } } else { mCondition.wait(lock); @@ -425,8 +414,7 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, } void EventThread::enableVSyncLocked() { - if (!mUseSoftwareVSync) { - // never enable h/w VSYNC when screen is off + if (!mVSyncState.synthetic) { if (!mVsyncEnabled) { mVsyncEnabled = true; mVSyncSource->setCallback(this); @@ -448,8 +436,8 @@ void EventThread::dump(std::string& result) const { std::lock_guard lock(mMutex); StringAppendF(&result, "%s: VSYNC %s\n", mThreadName, mDebugVsyncEnabled ? "on" : "off"); - StringAppendF(&result, " software VSYNC: %s\n", mUseSoftwareVSync ? "on" : "off"); - StringAppendF(&result, " VSYNC count: %u\n", mVSyncEvent[0].vsync.count); + StringAppendF(&result, " VSyncState{displayId=%u, count=%u%s}\n", mVSyncState.displayId, + mVSyncState.count, mVSyncState.synthetic ? ", synthetic" : ""); StringAppendF(&result, " pending events (count=%zu):\n", mPendingEvents.size()); for (const auto& event : mPendingEvents) { diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index b622e7abc5..1a8ebb7903 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -18,7 +18,6 @@ #include -#include #include #include #include @@ -199,8 +198,20 @@ private: std::vector> mDisplayEventConnections GUARDED_BY(mMutex); std::deque mPendingEvents GUARDED_BY(mMutex); - std::array mVSyncEvent GUARDED_BY(mMutex); - bool mUseSoftwareVSync GUARDED_BY(mMutex) = false; + + // VSYNC state of connected display. + struct VSyncState { + uint32_t displayId = 0; + + // Number of VSYNC events since display was connected. + uint32_t count = 0; + + // True if VSYNC should be faked, e.g. when display is off. + bool synthetic = false; + }; + + VSyncState mVSyncState GUARDED_BY(mMutex); + bool mVsyncEnabled GUARDED_BY(mMutex) = false; bool mKeepRunning GUARDED_BY(mMutex) = true; -- cgit v1.2.3-59-g8ed1b