diff options
-rw-r--r-- | libs/gui/DisplayEventDispatcher.cpp | 20 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventDispatcher.h | 15 | ||||
-rw-r--r-- | libs/nativedisplay/AChoreographer.cpp | 20 | ||||
-rw-r--r-- | libs/nativedisplay/include-private/private/android/choreographer.h | 7 | ||||
-rw-r--r-- | libs/nativedisplay/libnativedisplay.map.txt | 1 |
5 files changed, 47 insertions, 16 deletions
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 7e894b4b79..abfee61685 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -73,8 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - int64_t vsyncId; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { + VsyncEventData vsyncEventData; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp))); } @@ -117,13 +117,14 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - int64_t vsyncId; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { + VsyncEventData vsyncEventData; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d, vsyncId=%" PRId64, - this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId); + this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, + vsyncEventData.id); mWaitingForVsync = false; - dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId); + dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); } return 1; // keep the callback @@ -131,11 +132,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount, int64_t* outVsyncId) { + uint32_t* outCount, + VsyncEventData* outVsyncEventData) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; - *outVsyncId = 0; while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); for (ssize_t i = 0; i < n; i++) { @@ -148,7 +149,8 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; - *outVsyncId = ev.vsync.vsyncId; + outVsyncEventData->id = ev.vsync.vsyncId; + outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index cf598ead14..c65618b31f 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -20,6 +20,17 @@ namespace android { +struct VsyncEventData { + // The Vsync Id corresponsing to this vsync event. This will be used to + // populate ISurfaceComposer::setFrameTimelineVsync and + // SurfaceComposerClient::setFrameTimelineVsync + int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; + + // The deadline in CLOCK_MONOTONIC that the app needs to complete its + // frame by (both on the CPU and the GPU) + int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max(); +}; + class DisplayEventDispatcher : public LooperCallback { public: explicit DisplayEventDispatcher( @@ -44,7 +55,7 @@ private: bool mWaitingForVsync; virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, - int64_t vsyncId) = 0; + VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, @@ -54,6 +65,6 @@ private: virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount, int64_t* outVsyncId); + uint32_t* outCount, VsyncEventData* outVsyncEventData); }; } // namespace android diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 470f28f947..9e515cdc80 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -129,13 +129,14 @@ public: static Choreographer* getForThread(); virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getVsyncId() const; + int64_t getFrameDeadline() const; private: Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, - int64_t vsyncId) override; + VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; @@ -149,7 +150,7 @@ private: std::vector<RefreshRateCallback> mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; - int64_t mLastVsyncId = -1; + VsyncEventData mLastVsyncEventData; const sp<Looper> mLooper; const std::thread::id mThreadId; @@ -354,7 +355,8 @@ void Choreographer::handleRefreshRateUpdates() { // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for // the internal display implicitly. -void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) { +void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, + VsyncEventData vsyncEventData) { std::vector<FrameCallback> callbacks{}; { std::lock_guard<std::mutex> _l{mLock}; @@ -364,7 +366,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t mFrameCallbacks.pop(); } } - mLastVsyncId = vsyncId; + mLastVsyncEventData = vsyncEventData; for (const auto& cb : callbacks) { if (cb.callback64 != nullptr) { cb.callback64(timestamp, cb.data); @@ -410,7 +412,11 @@ void Choreographer::handleMessage(const Message& message) { } int64_t Choreographer::getVsyncId() const { - return mLastVsyncId; + return mLastVsyncEventData.id; +} + +int64_t Choreographer::getFrameDeadline() const { + return mLastVsyncEventData.deadlineTimestamp; } } // namespace android @@ -492,6 +498,10 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getVsyncId(); } +int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) { + return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline(); +} + } // namespace android /* Glue for the NDK interface */ diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 1d57c155ec..d3a4a66c18 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -35,6 +35,13 @@ void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod); // this function from anywhere else will return an undefined value. int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); +// Returns the deadline timestamp (in CLOCK_MONOTONIC) of the last frame callback. +// Client are expected to call this function from their frame callback function +// to get the deadline and use it to know whether a frame is likely to miss +// presentation. Calling this function from anywhere else will return an undefined +// value. +int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer); + // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index 5ed2e496d3..fda6a20a0b 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -30,6 +30,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_routeUnregisterRefreshRateCallback*; android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getVsyncId*; + android::AChoreographer_getFrameDeadline*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; |