diff options
author | 2016-07-25 12:48:08 -0700 | |
---|---|---|
committer | 2016-11-17 11:44:27 -0800 | |
commit | 3890c3995c4a52439844faeb80b5503d42b977d8 (patch) | |
tree | 180b19a3ef1f44ca611b0feb2808379d175c6fc1 | |
parent | d6927fb1143398370c0885844bfb58923ef740b7 (diff) |
Cache frame event history producer-side.
* Producer maintains a recent history of frames.
* Producer only does a binder call if requested
informatiVon doesn't exist in the cache.
* Consumer sends fences to the producer, which
can be queried for timestamps without a
binder call.
Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*
Change-Id: I8a64579407cc2935f5c659462cb227b07ba27e43
22 files changed, 683 insertions, 220 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 8cf8b67149..a523cd80bf 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -66,9 +66,9 @@ public: virtual void onFrameReplaced(const BufferItem& item) override; virtual void onBuffersReleased() override; virtual void onSidebandStreamChanged() override; - virtual bool addAndGetFrameTimestamps( + virtual void addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps) override; + FrameEventHistoryDelta* outDelta) override; private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 9cfb3835dc..e6ee6c6b68 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -177,8 +177,7 @@ public: sp<Fence>* outFence, float outTransformMatrix[16]) override; // See IGraphicBufferProducer::getFrameTimestamps - virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) override; + virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override; // See IGraphicBufferProducer::getUniqueId virtual status_t getUniqueId(uint64_t* outId) const override; @@ -195,9 +194,8 @@ private: // BufferQueueCore::INVALID_BUFFER_SLOT otherwise int getFreeSlotLocked() const; - bool addAndGetFrameTimestamps( - const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps); + void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, + FrameEventHistoryDelta* outDelta); // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may // block if there are no available slots and we are not in non-blocking diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h index 6d3bd6ca23..50765978cb 100644 --- a/include/gui/FrameTimestamps.h +++ b/include/gui/FrameTimestamps.h @@ -23,47 +23,52 @@ #include <utils/Timers.h> #include <array> +#include <bitset> +#include <vector> namespace android { struct FrameEvents; +class FrameEventHistoryDelta; class String8; -enum class SupportableFrameTimestamps { +enum class FrameEvent { + POSTED, REQUESTED_PRESENT, + LATCH, ACQUIRE, - REFRESH_START, - GL_COMPOSITION_DONE_TIME, - DISPLAY_PRESENT_TIME, - DISPLAY_RETIRE_TIME, - RELEASE_TIME, -}; - - -// The timestamps the consumer sends to the producer over binder. -struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> { - FrameTimestamps() = default; - explicit FrameTimestamps(const FrameEvents& fences); - - uint64_t frameNumber{0}; - nsecs_t postedTime{0}; - nsecs_t requestedPresentTime{0}; - nsecs_t acquireTime{0}; - nsecs_t refreshStartTime{0}; - nsecs_t glCompositionDoneTime{0}; - nsecs_t displayPresentTime{0}; - nsecs_t displayRetireTime{0}; - nsecs_t releaseTime{0}; + FIRST_REFRESH_START, + LAST_REFRESH_START, + GL_COMPOSITION_DONE, + DISPLAY_PRESENT, + DISPLAY_RETIRE, + RELEASE, + EVENT_COUNT, // Not an actual event. }; // A collection of timestamps corresponding to a single frame. struct FrameEvents { + bool hasPostedInfo() const; + bool hasRequestedPresentInfo() const; + bool hasLatchInfo() const; + bool hasFirstRefreshStartInfo() const; + bool hasLastRefreshStartInfo() const; + bool hasAcquireInfo() const; + bool hasGpuCompositionDoneInfo() const; + bool hasDisplayPresentInfo() const; + bool hasDisplayRetireInfo() const; + bool hasReleaseInfo() const; + void checkFencesForCompletion(); void dump(String8& outString) const; + static constexpr size_t EVENT_COUNT = + static_cast<size_t>(FrameEvent::EVENT_COUNT); + static_assert(EVENT_COUNT <= 32, "Event count sanity check failed."); + bool valid{false}; uint64_t frameNumber{0}; @@ -72,6 +77,7 @@ struct FrameEvents { // a) we'll just never get them or b) they're not ready yet. bool addPostCompositeCalled{false}; bool addRetireCalled{false}; + bool addReleaseCalled{false}; nsecs_t postedTime{0}; nsecs_t requestedPresentTime{0}; @@ -93,6 +99,39 @@ struct FrameEvents { }; +// A short history of frames that are synchronized between the consumer and +// producer via deltas. +class FrameEventHistory { +public: + virtual ~FrameEventHistory(); + + FrameEvents* getFrame(uint64_t frameNumber); + FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint); + void checkFencesForCompletion(); + void dump(String8& outString) const; + + static constexpr size_t MAX_FRAME_HISTORY = 8; + +protected: + std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames; +}; + + +// The producer's interface to FrameEventHistory +class ProducerFrameEventHistory : public FrameEventHistory { +public: + ~ProducerFrameEventHistory() override; + + void updateAcquireFence(uint64_t frameNumber, sp<Fence> acquire); + void applyDelta(const FrameEventHistoryDelta& delta); + +private: + size_t mAcquireOffset{0}; +}; + + +// Used by the consumer to create a new frame event record that is +// partially complete. struct NewFrameEventsEntry { uint64_t frameNumber{0}; nsecs_t postedTime{0}; @@ -101,14 +140,38 @@ struct NewFrameEventsEntry { }; -class FrameEventHistory { +// Used by the consumer to keep track of which fields it already sent to +// the producer. +class FrameEventDirtyFields { public: - FrameEvents* getFrame(uint64_t frameNumber); - FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint); - void checkFencesForCompletion(); - void dump(String8& outString) const; + inline void reset() { mBitset.reset(); } + inline bool anyDirty() const { return mBitset.any(); } + + template <FrameEvent event> + inline void setDirty() { + constexpr size_t eventIndex = static_cast<size_t>(event); + static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index."); + mBitset.set(eventIndex); + } + + template <FrameEvent event> + inline bool isDirty() const { + constexpr size_t eventIndex = static_cast<size_t>(event); + static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index."); + return mBitset[eventIndex]; + } + +private: + std::bitset<FrameEvents::EVENT_COUNT> mBitset; +}; + - void addQueue(const NewFrameEventsEntry& newFrameEntry); +// The consumer's interface to FrameEventHistory +class ConsumerFrameEventHistory : public FrameEventHistory { +public: + ~ConsumerFrameEventHistory() override; + + void addQueue(const NewFrameEventsEntry& newEntry); void addLatch(uint64_t frameNumber, nsecs_t latchTime); void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime); void addPostComposition(uint64_t frameNumber, @@ -116,14 +179,96 @@ public: void addRetire(uint64_t frameNumber, sp<Fence> displayRetire); void addRelease(uint64_t frameNumber, sp<Fence> release); + void getAndResetDelta(FrameEventHistoryDelta* delta); + private: - static constexpr size_t MAX_FRAME_HISTORY = 8; - std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames; + std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty; size_t mQueueOffset{0}; size_t mCompositionOffset{0}; size_t mRetireOffset{0}; size_t mReleaseOffset{0}; }; + +// A single frame update from the consumer to producer that can be sent +// through Binder. +// Although this may be sent multiple times for the same frame as new +// timestamps are set, Fences only need to be sent once. +class FrameEventsDelta : public Flattenable<FrameEventsDelta> { +friend class ProducerFrameEventHistory; +public: + FrameEventsDelta() = default; + FrameEventsDelta(size_t index, + const FrameEvents& frameTimestamps, + const FrameEventDirtyFields& dirtyFields); + + // Flattenable implementation + size_t getFlattenedSize() const; + size_t getFdCount() const; + status_t flatten(void*& buffer, size_t& size, int*& fds, + size_t& count) const; + status_t unflatten(void const*& buffer, size_t& size, int const*& fds, + size_t& count); + +private: + static size_t minFlattenedSize(); + + size_t mIndex{0}; + uint64_t mFrameNumber{0}; + + bool mAddPostCompositeCalled{0}; + bool mAddRetireCalled{0}; + bool mAddReleaseCalled{0}; + + nsecs_t mPostedTime{0}; + nsecs_t mRequestedPresentTime{0}; + nsecs_t mLatchTime{0}; + nsecs_t mFirstRefreshStartTime{0}; + nsecs_t mLastRefreshStartTime{0}; + + sp<Fence> mAcquireFence{Fence::NO_FENCE}; + sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE}; + sp<Fence> mDisplayPresentFence{Fence::NO_FENCE}; + sp<Fence> mDisplayRetireFence{Fence::NO_FENCE}; + sp<Fence> mReleaseFence{Fence::NO_FENCE}; + + // This is a static method with an auto return value so we can call + // it without needing const and non-const versions. + template <typename ThisType> + static inline auto allFences(ThisType fed) -> + std::array<decltype(&fed->mAcquireFence), 5> { + return {{ + &fed->mAcquireFence, &fed->mGpuCompositionDoneFence, + &fed->mDisplayPresentFence, &fed->mDisplayRetireFence, + &fed->mReleaseFence + }}; + } +}; + + +// A collection of updates from consumer to producer that can be sent +// through Binder. +class FrameEventHistoryDelta + : public Flattenable<FrameEventHistoryDelta> { + +friend class ConsumerFrameEventHistory; +friend class ProducerFrameEventHistory; + +public: + // Flattenable implementation. + size_t getFlattenedSize() const; + size_t getFdCount() const; + status_t flatten(void*& buffer, size_t& size, int*& fds, + size_t& count) const; + status_t unflatten(void const*& buffer, size_t& size, int const*& fds, + size_t& count); + +private: + static size_t minFlattenedSize(); + + std::vector<FrameEventsDelta> mDeltas; +}; + + } // namespace android #endif diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h index 8eab3c5618..93dd4acf96 100644 --- a/include/gui/IConsumerListener.h +++ b/include/gui/IConsumerListener.h @@ -82,13 +82,11 @@ public: // different stream. virtual void onSidebandStreamChanged() = 0; /* Asynchronous */ - // Notifies the consumer of any new producer-side events and then queries - // the consumer timestamps - virtual bool addAndGetFrameTimestamps( + // Notifies the consumer of any new producer-side timestamps and + // returns the combined frame history that hasn't already been retrieved. + virtual void addAndGetFrameTimestamps( const NewFrameEventsEntry* /*newTimestamps*/, - uint64_t /*frameNumber*/, FrameTimestamps* /*outTimestamps*/) { - return false; - } + FrameEventHistoryDelta* /*outDelta*/) {} }; diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 493143a9bf..612a9024c3 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -588,13 +588,8 @@ public: virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, float outTransformMatrix[16]) = 0; - // Attempts to retrieve timestamp information for the given frame number. - // If information for the given frame number is not found, returns false. - // Returns true otherwise. - // - // If a fence has not yet signaled the timestamp returned will be 0; - virtual bool getFrameTimestamps(uint64_t /*frameNumber*/, - FrameTimestamps* /*outTimestamps*/) { return false; } + // Gets the frame events that haven't already been retrieved. + virtual void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {} // Returns a unique id for this BufferQueue virtual status_t getUniqueId(uint64_t* outId) const = 0; diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index bc36970ac4..824e5c4dea 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -45,7 +45,7 @@ class HdrCapabilities; class IDisplayEventConnection; class IMemoryHeap; class Rect; -enum class SupportableFrameTimestamps; +enum class FrameEvent; /* * This class defines the Binder IPC interface for accessing various @@ -118,7 +118,7 @@ public: /* Returns the frame timestamps supported by SurfaceFlinger. */ virtual status_t getSupportedFrameTimestamps( - std::vector<SupportableFrameTimestamps>* outSupported) const = 0; + std::vector<FrameEvent>* outSupported) const = 0; /* set display power mode. depending on the mode, it can either trigger * screen on, off or low power mode and wait for it to complete. diff --git a/include/gui/Surface.h b/include/gui/Surface.h index aa5657fe78..c12d452c05 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -388,6 +388,9 @@ private: mutable bool mQueriedSupportedTimestamps; mutable bool mFrameTimestampsSupportsPresent; mutable bool mFrameTimestampsSupportsRetire; + + // A cached copy of the FrameEventHistory maintained by the consumer. + ProducerFrameEventHistory mFrameEventHistory; }; namespace view { diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 6d4335e460..f76a282af6 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -61,15 +61,13 @@ void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { } } -bool BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps( +void BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps) { + FrameEventHistoryDelta* outDelta) { sp<ConsumerListener> listener(mConsumerListener.promote()); - if (listener == nullptr) { - return false; + if (listener != nullptr) { + listener->addAndGetFrameTimestamps(newTimestamps, outDelta); } - return listener->addAndGetFrameTimestamps( - newTimestamps, frameNumber, outTimestamps); } void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 6bd1cfdb0a..e27fd7a836 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -975,7 +975,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, requestedPresentTimestamp, acquireFence }; - addAndGetFrameTimestamps(&newFrameEventsEntry, 0, nullptr); + addAndGetFrameTimestamps(&newFrameEventsEntry, nullptr); return NO_ERROR; } @@ -1464,16 +1464,15 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, return NO_ERROR; } -bool BufferQueueProducer::getFrameTimestamps( - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - return addAndGetFrameTimestamps(nullptr, frameNumber, outTimestamps); +void BufferQueueProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) { + addAndGetFrameTimestamps(nullptr, outDelta); } -bool BufferQueueProducer::addAndGetFrameTimestamps( +void BufferQueueProducer::addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - if (newTimestamps == nullptr && outTimestamps == nullptr) { - return false; + FrameEventHistoryDelta* outDelta) { + if (newTimestamps == nullptr && outDelta == nullptr) { + return; } ATRACE_CALL(); @@ -1484,10 +1483,8 @@ bool BufferQueueProducer::addAndGetFrameTimestamps( listener = mCore->mConsumerListener; } if (listener != NULL) { - return listener->addAndGetFrameTimestamps( - newTimestamps, frameNumber, outTimestamps); + listener->addAndGetFrameTimestamps(newTimestamps, outDelta); } - return false; } void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp index a919911988..4b98cff615 100644 --- a/libs/gui/FrameTimestamps.cpp +++ b/libs/gui/FrameTimestamps.cpp @@ -21,6 +21,7 @@ #include <algorithm> #include <limits> +#include <numeric> namespace android { @@ -29,24 +30,55 @@ static inline bool isValidTimestamp(nsecs_t time) { } // ============================================================================ -// FrameTimestamps +// FrameEvents // ============================================================================ -FrameTimestamps::FrameTimestamps(const FrameEvents& events) : - frameNumber(events.frameNumber), - postedTime(events.postedTime), - requestedPresentTime(events.requestedPresentTime), - acquireTime(events.acquireTime), - refreshStartTime(events.firstRefreshStartTime), - glCompositionDoneTime(events.gpuCompositionDoneTime), - displayPresentTime(events.displayPresentTime), - displayRetireTime(events.displayRetireTime), - releaseTime(events.releaseTime) {} +bool FrameEvents::hasPostedInfo() const { + return isValidTimestamp(postedTime); +} +bool FrameEvents::hasRequestedPresentInfo() const { + return isValidTimestamp(requestedPresentTime); +} -// ============================================================================ -// FrameEvents -// ============================================================================ +bool FrameEvents::hasLatchInfo() const { + return isValidTimestamp(latchTime); +} + +bool FrameEvents::hasFirstRefreshStartInfo() const { + return isValidTimestamp(firstRefreshStartTime); +} + +bool FrameEvents::hasLastRefreshStartInfo() const { + // The last refresh start time may continue to update until a new frame + // is latched. We know we have the final value once the release or retire + // info is set. See ConsumerFrameEventHistory::addRetire/Release. + return addRetireCalled || addReleaseCalled; +} + +bool FrameEvents::hasAcquireInfo() const { + return isValidTimestamp(acquireTime) || acquireFence->isValid(); +} + +bool FrameEvents::hasGpuCompositionDoneInfo() const { + // We may not get a gpuCompositionDone in addPostComposite if + // client/gles compositing isn't needed. + return addPostCompositeCalled; +} + +bool FrameEvents::hasDisplayPresentInfo() const { + // We may not get a displayPresent in addPostComposite for HWC1. + return addPostCompositeCalled; +} + +bool FrameEvents::hasDisplayRetireInfo() const { + // We may not get a displayRetire in addRetire for HWC2. + return addRetireCalled; +} + +bool FrameEvents::hasReleaseInfo() const { + return addReleaseCalled; +} static void checkFenceForCompletion(sp<Fence>* fence, nsecs_t* dstTime) { if ((*fence)->isValid()) { @@ -156,6 +188,7 @@ struct FrameNumberEqual { } // namespace +FrameEventHistory::~FrameEventHistory() = default; FrameEvents* FrameEventHistory::getFrame(uint64_t frameNumber) { auto frame = std::find_if( @@ -209,82 +242,407 @@ void FrameEventHistory::dump(String8& outString) const { } } -void FrameEventHistory::addQueue(const NewFrameEventsEntry& newFrameEntry) { + +// ============================================================================ +// ProducerFrameEventHistory +// ============================================================================ + +ProducerFrameEventHistory::~ProducerFrameEventHistory() = default; + +void ProducerFrameEventHistory::updateAcquireFence( + uint64_t frameNumber, sp<Fence> acquire) { + FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset); + if (frame == nullptr) { + ALOGE("ProducerFrameEventHistory::updateAcquireFence: " + "Did not find frame."); + return; + } + + if (acquire->isValid()) { + frame->acquireFence = acquire; + } else { + // If there isn't an acquire fence, assume that buffer was + // ready for the consumer when posted. + frame->acquireTime = frame->postedTime; + } +} + +static void applyFenceDelta(sp<Fence>* dst, const sp<Fence>& src) { + if (src->isValid()) { + if ((*dst)->isValid()) { + ALOGE("applyFenceDelta: Unexpected fence."); + } + *dst = src; + } +} + +void ProducerFrameEventHistory::applyDelta( + const FrameEventHistoryDelta& delta) { + for (auto& d : delta.mDeltas) { + // Avoid out-of-bounds access. + if (d.mIndex >= mFrames.size()) { + ALOGE("ProducerFrameEventHistory::applyDelta: Bad index."); + return; + } + + FrameEvents& frame = mFrames[d.mIndex]; + + frame.addPostCompositeCalled = d.mAddPostCompositeCalled != 0; + frame.addRetireCalled = d.mAddRetireCalled != 0; + frame.addReleaseCalled = d.mAddReleaseCalled != 0; + + frame.postedTime = d.mPostedTime; + frame.requestedPresentTime = d.mRequestedPresentTime; + frame.latchTime = d.mLatchTime; + frame.firstRefreshStartTime = d.mFirstRefreshStartTime; + frame.lastRefreshStartTime = d.mLastRefreshStartTime; + + if (frame.frameNumber == d.mFrameNumber) { + // Existing frame. Merge. + // Consumer never sends timestamps of fences, only the fences + // themselves, so we never need to update the fence timestamps here. + applyFenceDelta(&frame.acquireFence, d.mAcquireFence); + applyFenceDelta( + &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence); + applyFenceDelta(&frame.displayPresentFence, d.mDisplayPresentFence); + applyFenceDelta(&frame.displayRetireFence, d.mDisplayRetireFence); + applyFenceDelta(&frame.releaseFence, d.mReleaseFence); + } else { + // New frame. Overwrite. + frame.frameNumber = d.mFrameNumber; + + frame.gpuCompositionDoneFence = d.mGpuCompositionDoneFence; + frame.displayPresentFence = d.mDisplayPresentFence; + frame.displayRetireFence = d.mDisplayRetireFence; + frame.releaseFence = d.mReleaseFence; + + // Set aquire fence and time at this point. + frame.acquireTime = 0; + frame.acquireFence = d.mAcquireFence; + + // Reset fence-related timestamps + frame.gpuCompositionDoneTime = 0; + frame.displayPresentTime = 0; + frame.displayRetireTime = 0; + frame.releaseTime = 0; + + // The consumer only sends valid frames. + frame.valid = true; + } + } +} + + +// ============================================================================ +// ConsumerFrameEventHistory +// ============================================================================ + +ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default; + +void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) { // Overwrite all fields of the frame with default values unless set here. FrameEvents newTimestamps; - newTimestamps.frameNumber = newFrameEntry.frameNumber; - newTimestamps.postedTime = newFrameEntry.postedTime; - newTimestamps.requestedPresentTime = newFrameEntry.requestedPresentTime; - newTimestamps.acquireFence = newFrameEntry.acquireFence; + newTimestamps.frameNumber = newEntry.frameNumber; + newTimestamps.postedTime = newEntry.postedTime; + newTimestamps.requestedPresentTime = newEntry.requestedPresentTime; + newTimestamps.acquireFence = newEntry.acquireFence; newTimestamps.valid = true; mFrames[mQueueOffset] = newTimestamps; + mFramesDirty[mQueueOffset].setDirty<FrameEvent::POSTED>(); + mFramesDirty[mQueueOffset].setDirty<FrameEvent::ACQUIRE>(); - mQueueOffset = mQueueOffset + 1; - if (mQueueOffset >= mFrames.size()) { - mQueueOffset = 0; - } + mQueueOffset = (mQueueOffset + 1) % mFrames.size(); } -void FrameEventHistory::addLatch(uint64_t frameNumber, nsecs_t latchTime) { +void ConsumerFrameEventHistory::addLatch( + uint64_t frameNumber, nsecs_t latchTime) { FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); if (frame == nullptr) { - ALOGE("FrameEventHistory::addLatch: Did not find frame."); + ALOGE("ConsumerFrameEventHistory::addLatch: Did not find frame."); return; } frame->latchTime = latchTime; - return; + mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LATCH>(); } -void FrameEventHistory::addPreComposition( +void ConsumerFrameEventHistory::addPreComposition( uint64_t frameNumber, nsecs_t refreshStartTime) { FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); if (frame == nullptr) { - ALOGE("FrameEventHistory::addPreComposition: Did not find frame."); + ALOGE("ConsumerFrameEventHistory::addPreComposition: " + "Did not find frame."); return; } frame->lastRefreshStartTime = refreshStartTime; + mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>(); if (!isValidTimestamp(frame->firstRefreshStartTime)) { frame->firstRefreshStartTime = refreshStartTime; + mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>(); } } -void FrameEventHistory::addPostComposition(uint64_t frameNumber, +void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber, sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) { FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset); if (frame == nullptr) { - ALOGE("FrameEventHistory::addPostComposition: Did not find frame."); + ALOGE("ConsumerFrameEventHistory::addPostComposition: " + "Did not find frame."); return; } - // Only get GPU and present info for the first composite. if (!frame->addPostCompositeCalled) { frame->addPostCompositeCalled = true; frame->gpuCompositionDoneFence = gpuCompositionDone; + mFramesDirty[mCompositionOffset].setDirty<FrameEvent::GL_COMPOSITION_DONE>(); if (!frame->displayPresentFence->isValid()) { frame->displayPresentFence = displayPresent; + mFramesDirty[mCompositionOffset].setDirty<FrameEvent::DISPLAY_PRESENT>(); } } } -void FrameEventHistory::addRetire( +void ConsumerFrameEventHistory::addRetire( uint64_t frameNumber, sp<Fence> displayRetire) { FrameEvents* frame = getFrame(frameNumber, &mRetireOffset); if (frame == nullptr) { - ALOGE("FrameEventHistory::addRetire: Did not find frame."); + ALOGE("ConsumerFrameEventHistory::addRetire: Did not find frame."); return; } frame->addRetireCalled = true; frame->displayRetireFence = displayRetire; + mFramesDirty[mRetireOffset].setDirty<FrameEvent::DISPLAY_RETIRE>(); } -void FrameEventHistory::addRelease( +void ConsumerFrameEventHistory::addRelease( uint64_t frameNumber, sp<Fence> release) { FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset); if (frame == nullptr) { - ALOGE("FrameEventHistory::addRelease: Did not find frame."); + ALOGE("ConsumerFrameEventHistory::addRelease: Did not find frame."); return; } + frame->addReleaseCalled = true; frame->releaseFence = release; + mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>(); +} + +void ConsumerFrameEventHistory::getAndResetDelta( + FrameEventHistoryDelta* delta) { + delta->mDeltas.reserve(mFramesDirty.size()); + for (size_t i = 0; i < mFramesDirty.size(); i++) { + if (mFramesDirty[i].anyDirty()) { + delta->mDeltas.push_back( + FrameEventsDelta(i, mFrames[i], mFramesDirty[i])); + mFramesDirty[i].reset(); + } + } +} + + +// ============================================================================ +// FrameEventsDelta +// ============================================================================ + +FrameEventsDelta::FrameEventsDelta( + size_t index, + const FrameEvents& frameTimestamps, + const FrameEventDirtyFields& dirtyFields) + : mIndex(index), + mFrameNumber(frameTimestamps.frameNumber), + mAddPostCompositeCalled(frameTimestamps.addPostCompositeCalled), + mAddRetireCalled(frameTimestamps.addRetireCalled), + mAddReleaseCalled(frameTimestamps.addReleaseCalled), + mPostedTime(frameTimestamps.postedTime), + mRequestedPresentTime(frameTimestamps.requestedPresentTime), + mLatchTime(frameTimestamps.latchTime), + mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime), + mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) { + mAcquireFence = dirtyFields.isDirty<FrameEvent::ACQUIRE>() ? + frameTimestamps.acquireFence : Fence::NO_FENCE; + mGpuCompositionDoneFence = + dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>() ? + frameTimestamps.gpuCompositionDoneFence : Fence::NO_FENCE; + mDisplayPresentFence = dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>() ? + frameTimestamps.displayPresentFence : Fence::NO_FENCE; + mDisplayRetireFence = dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>() ? + frameTimestamps.displayRetireFence : Fence::NO_FENCE; + mReleaseFence = dirtyFields.isDirty<FrameEvent::RELEASE>() ? + frameTimestamps.releaseFence : Fence::NO_FENCE; +} + +size_t FrameEventsDelta::minFlattenedSize() { + constexpr size_t min = + sizeof(FrameEventsDelta::mFrameNumber) + + sizeof(uint8_t) + // mIndex + sizeof(uint8_t) + // mAddPostCompositeCalled + sizeof(uint8_t) + // mAddRetireCalled + sizeof(uint8_t) + // mAddReleaseCalled + sizeof(FrameEventsDelta::mPostedTime) + + sizeof(FrameEventsDelta::mRequestedPresentTime) + + sizeof(FrameEventsDelta::mLatchTime) + + sizeof(FrameEventsDelta::mFirstRefreshStartTime) + + sizeof(FrameEventsDelta::mLastRefreshStartTime); + return min; +} + +// Flattenable implementation +size_t FrameEventsDelta::getFlattenedSize() const { + auto fences = allFences(this); + return minFlattenedSize() + + std::accumulate(fences.begin(), fences.end(), size_t(0), + [](size_t a, const sp<Fence>* fence) { + return a + (*fence)->getFlattenedSize(); + }); +} + +size_t FrameEventsDelta::getFdCount() const { + auto fences = allFences(this); + return std::accumulate(fences.begin(), fences.end(), size_t(0), + [](size_t a, const sp<Fence>* fence) { + return a + (*fence)->getFdCount(); + }); +} + +status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds, + size_t& count) const { + if (size < getFlattenedSize() || count < getFdCount()) { + return NO_MEMORY; + } + + if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY || + mIndex > std::numeric_limits<uint8_t>::max()) { + return BAD_VALUE; + } + + FlattenableUtils::write(buffer, size, mFrameNumber); + + // These are static_cast to uint8_t for alignment. + FlattenableUtils::write(buffer, size, static_cast<uint8_t>(mIndex)); + FlattenableUtils::write( + buffer, size, static_cast<uint8_t>(mAddPostCompositeCalled)); + FlattenableUtils::write( + buffer, size, static_cast<uint8_t>(mAddRetireCalled)); + FlattenableUtils::write( + buffer, size, static_cast<uint8_t>(mAddReleaseCalled)); + + FlattenableUtils::write(buffer, size, mPostedTime); + FlattenableUtils::write(buffer, size, mRequestedPresentTime); + FlattenableUtils::write(buffer, size, mLatchTime); + FlattenableUtils::write(buffer, size, mFirstRefreshStartTime); + FlattenableUtils::write(buffer, size, mLastRefreshStartTime); + + // Fences + for (auto fence : allFences(this)) { + status_t status = (*fence)->flatten(buffer, size, fds, count); + if (status != NO_ERROR) { + return status; + } + } + return NO_ERROR; +} + +status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size, + int const*& fds, size_t& count) { + if (size < minFlattenedSize()) { + return NO_MEMORY; + } + + FlattenableUtils::read(buffer, size, mFrameNumber); + + // These were written as uint8_t for alignment. + uint8_t temp = 0; + FlattenableUtils::read(buffer, size, temp); + mIndex = temp; + if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY) { + return BAD_VALUE; + } + FlattenableUtils::read(buffer, size, temp); + mAddPostCompositeCalled = static_cast<bool>(temp); + FlattenableUtils::read(buffer, size, temp); + mAddRetireCalled = static_cast<bool>(temp); + FlattenableUtils::read(buffer, size, temp); + mAddReleaseCalled = static_cast<bool>(temp); + + FlattenableUtils::read(buffer, size, mPostedTime); + FlattenableUtils::read(buffer, size, mRequestedPresentTime); + FlattenableUtils::read(buffer, size, mLatchTime); + FlattenableUtils::read(buffer, size, mFirstRefreshStartTime); + FlattenableUtils::read(buffer, size, mLastRefreshStartTime); + + // Fences + for (auto fence : allFences(this)) { + *fence = new Fence; + status_t status = (*fence)->unflatten(buffer, size, fds, count); + if (status != NO_ERROR) { + return status; + } + } + return NO_ERROR; +} + + +// ============================================================================ +// FrameEventHistoryDelta +// ============================================================================ + +size_t FrameEventHistoryDelta::minFlattenedSize() { + return sizeof(uint32_t); +} + +size_t FrameEventHistoryDelta::getFlattenedSize() const { + return minFlattenedSize() + + std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0), + [](size_t a, const FrameEventsDelta& delta) { + return a + delta.getFlattenedSize(); + }); } +size_t FrameEventHistoryDelta::getFdCount() const { + return std::accumulate(mDeltas.begin(), mDeltas.end(), size_t(0), + [](size_t a, const FrameEventsDelta& delta) { + return a + delta.getFdCount(); + }); +} + +status_t FrameEventHistoryDelta::flatten( + void*& buffer, size_t& size, int*& fds, size_t& count) const { + if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) { + return BAD_VALUE; + } + if (size < getFlattenedSize()) { + return NO_MEMORY; + } + + FlattenableUtils::write( + buffer, size, static_cast<uint32_t>(mDeltas.size())); + for (auto& d : mDeltas) { + status_t status = d.flatten(buffer, size, fds, count); + if (status != NO_ERROR) { + return status; + } + } + return NO_ERROR; +} + +status_t FrameEventHistoryDelta::unflatten( + void const*& buffer, size_t& size, int const*& fds, size_t& count) { + if (size < minFlattenedSize()) { + return NO_MEMORY; + } + + uint32_t deltaCount = 0; + FlattenableUtils::read(buffer, size, deltaCount); + if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) { + return BAD_VALUE; + } + mDeltas.resize(deltaCount); + for (auto& d : mDeltas) { + status_t status = d.unflatten(buffer, size, fds, count); + if (status != NO_ERROR) { + return status; + } + } + return NO_ERROR; +} + + } // namespace android diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index a4de7eb99a..bed7d53872 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -429,40 +429,24 @@ public: return result; } - virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) { + virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) { Parcel data, reply; status_t result = data.writeInterfaceToken( IGraphicBufferProducer::getInterfaceDescriptor()); if (result != NO_ERROR) { - ALOGE("getFrameTimestamps failed to write token: %d", result); - return false; - } - result = data.writeUint64(frameNumber); - if (result != NO_ERROR) { - ALOGE("getFrameTimestamps failed to write: %d", result); - return false; + ALOGE("IGBP::getFrameTimestamps failed to write token: %d", result); + return; } result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply); if (result != NO_ERROR) { - ALOGE("getFrameTimestamps failed to transact: %d", result); - return false; + ALOGE("IGBP::getFrameTimestamps failed to transact: %d", result); + return; } - bool found = false; - result = reply.readBool(&found); + result = reply.read(*outDelta); if (result != NO_ERROR) { - ALOGE("getFrameTimestamps failed to read: %d", result); - return false; + ALOGE("IGBP::getFrameTimestamps failed to read timestamps: %d", + result); } - if (found) { - result = reply.read(*outTimestamps); - if (result != NO_ERROR) { - ALOGE("getFrameTimestamps failed to read timestamps: %d", - result); - return false; - } - } - return found; } virtual status_t getUniqueId(uint64_t* outId) const { @@ -722,26 +706,14 @@ status_t BnGraphicBufferProducer::onTransact( } case GET_FRAME_TIMESTAMPS: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); - uint64_t frameNumber = 0; - status_t result = data.readUint64(&frameNumber); - if (result != NO_ERROR) { - ALOGE("onTransact failed to read: %d", result); - return result; - } - FrameTimestamps timestamps; - bool found = getFrameTimestamps(frameNumber, ×tamps); - result = reply->writeBool(found); + FrameEventHistoryDelta frameTimestamps; + getFrameTimestamps(&frameTimestamps); + status_t result = reply->write(frameTimestamps); if (result != NO_ERROR) { - ALOGE("onTransact failed to write: %d", result); + ALOGE("BnGBP::GET_FRAME_TIMESTAMPS failed to write buffer: %d", + result); return result; } - if (found) { - result = reply->write(timestamps); - if (result != NO_ERROR) { - ALOGE("onTransact failed to write timestamps: %d", result); - return result; - } - } return NO_ERROR; } case GET_UNIQUE_ID: { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index b5fe266c2e..fa2f59abb0 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -159,7 +159,7 @@ public: } virtual status_t getSupportedFrameTimestamps( - std::vector<SupportableFrameTimestamps>* outSupported) const { + std::vector<FrameEvent>* outSupported) const { if (!outSupported) { return UNEXPECTED_NULL; } @@ -197,7 +197,7 @@ public: outSupported->reserve(supported.size()); for (int32_t s : supported) { - outSupported->push_back(static_cast<SupportableFrameTimestamps>(s)); + outSupported->push_back(static_cast<FrameEvent>(s)); } return NO_ERROR; } @@ -566,7 +566,7 @@ status_t BnSurfaceComposer::onTransact( } case GET_SUPPORTED_FRAME_TIMESTAMPS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - std::vector<SupportableFrameTimestamps> supportedTimestamps; + std::vector<FrameEvent> supportedTimestamps; status_t result = getSupportedFrameTimestamps(&supportedTimestamps); status_t err = reply->writeInt32(result); if (err != NO_ERROR) { @@ -578,7 +578,7 @@ status_t BnSurfaceComposer::onTransact( std::vector<int32_t> supported; supported.reserve(supportedTimestamps.size()); - for (SupportableFrameTimestamps s : supportedTimestamps) { + for (FrameEvent s : supportedTimestamps) { supported.push_back(static_cast<int32_t>(s)); } return reply->writeInt32Vector(supported); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 5203cce205..c29101e4a0 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -145,47 +145,61 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber, nsecs_t* outReleaseTime) { ATRACE_CALL(); - { - Mutex::Autolock lock(mMutex); + Mutex::Autolock lock(mMutex); - // Verify the requested timestamps are supported. - querySupportedTimestampsLocked(); - if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) { - return BAD_VALUE; - } - if (outDisplayRetireTime != nullptr && !mFrameTimestampsSupportsRetire) { - return BAD_VALUE; - } + // Verify the requested timestamps are supported. + querySupportedTimestampsLocked(); + if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) { + return BAD_VALUE; + } + if (outDisplayRetireTime != nullptr && !mFrameTimestampsSupportsRetire) { + return BAD_VALUE; } - FrameTimestamps timestamps; - bool found = mGraphicBufferProducer->getFrameTimestamps(frameNumber, - ×tamps); + FrameEvents* events = mFrameEventHistory.getFrame(frameNumber); - if (!found) { + // Update our cache of events if the requested events are not available. + if (events == nullptr || + (outRequestedPresentTime && !events->hasRequestedPresentInfo()) || + (outAcquireTime && !events->hasAcquireInfo()) || + (outRefreshStartTime && !events->hasFirstRefreshStartInfo()) || + (outGlCompositionDoneTime && !events->hasGpuCompositionDoneInfo()) || + (outDisplayPresentTime && !events->hasDisplayPresentInfo()) || + (outDisplayRetireTime && !events->hasDisplayRetireInfo()) || + (outReleaseTime && !events->hasReleaseInfo())) { + FrameEventHistoryDelta delta; + mGraphicBufferProducer->getFrameTimestamps(&delta); + mFrameEventHistory.applyDelta(delta); + events = mFrameEventHistory.getFrame(frameNumber); + } + + // A record for the requested frame does not exist. + if (events == nullptr) { return NAME_NOT_FOUND; } + events->checkFencesForCompletion(); + if (outRequestedPresentTime) { - *outRequestedPresentTime = timestamps.requestedPresentTime; + *outRequestedPresentTime = events->requestedPresentTime; } if (outAcquireTime) { - *outAcquireTime = timestamps.acquireTime; + *outAcquireTime = events->acquireTime; } if (outRefreshStartTime) { - *outRefreshStartTime = timestamps.refreshStartTime; + *outRefreshStartTime = events->firstRefreshStartTime; } if (outGlCompositionDoneTime) { - *outGlCompositionDoneTime = timestamps.glCompositionDoneTime; + *outGlCompositionDoneTime = events->gpuCompositionDoneTime; } if (outDisplayPresentTime) { - *outDisplayPresentTime = timestamps.displayPresentTime; + *outDisplayPresentTime = events->displayPresentTime; } if (outDisplayRetireTime) { - *outDisplayRetireTime = timestamps.displayRetireTime; + *outDisplayRetireTime = events->displayRetireTime; } if (outReleaseTime) { - *outReleaseTime = timestamps.releaseTime; + *outReleaseTime = events->releaseTime; } return NO_ERROR; @@ -564,7 +578,7 @@ void Surface::querySupportedTimestampsLocked() const { } mQueriedSupportedTimestamps = true; - std::vector<SupportableFrameTimestamps> supportedFrameTimestamps; + std::vector<FrameEvent> supportedFrameTimestamps; sp<ISurfaceComposer> composer(ComposerService::getComposerService()); status_t err = composer->getSupportedFrameTimestamps( &supportedFrameTimestamps); @@ -574,9 +588,9 @@ void Surface::querySupportedTimestampsLocked() const { } for (auto sft : supportedFrameTimestamps) { - if (sft == SupportableFrameTimestamps::DISPLAY_PRESENT_TIME) { + if (sft == FrameEvent::DISPLAY_PRESENT) { mFrameTimestampsSupportsPresent = true; - } else if (sft == SupportableFrameTimestamps::DISPLAY_RETIRE_TIME) { + } else if (sft == FrameEvent::DISPLAY_RETIRE) { mFrameTimestampsSupportsRetire = true; } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c16af59ad2..2334e47b54 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2215,24 +2215,16 @@ void Layer::dumpFrameEvents(String8& result) { mFrameEventHistory.dump(result); } -bool Layer::addAndGetFrameTimestamps( - const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps *outTimestamps) { +void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, + FrameEventHistoryDelta *outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { mFrameEventHistory.addQueue(*newTimestamps); } - if (outTimestamps) { - FrameEvents* frameEvents = mFrameEventHistory.getFrame(frameNumber); - if (frameEvents) { - frameEvents->checkFencesForCompletion(); - *outTimestamps = FrameTimestamps(*frameEvents); - return true; - } + if (outDelta) { + mFrameEventHistory.getAndResetDelta(outDelta); } - - return false; } std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory( diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 98ea053162..b4d86857b9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -407,12 +407,10 @@ public: void logFrameStats(); void getFrameStats(FrameStats* outStats) const; - std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush); - bool addAndGetFrameTimestamps( - const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps); + void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry, + FrameEventHistoryDelta* outDelta); bool getTransformToDisplayInverse() const; @@ -587,7 +585,7 @@ private: // Timestamp history for the consumer to query. // Accessed by both consumer and producer on main and binder threads. Mutex mFrameEventHistoryMutex; - FrameEventHistory mFrameEventHistory; + ConsumerFrameEventHistory mFrameEventHistory; // main thread sp<GraphicBuffer> mActiveBuffer; diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 4604e01a5f..a2cc531d5e 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -145,9 +145,8 @@ status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, outTransformMatrix); } -bool MonitoredProducer::getFrameTimestamps( - uint64_t frameNumber, FrameTimestamps* outTimestamps) { - return mProducer->getFrameTimestamps(frameNumber, outTimestamps); +void MonitoredProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) { + mProducer->getFrameTimestamps(outDelta); } status_t MonitoredProducer::getUniqueId(uint64_t* outId) const { diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 5a2351f0be..3e64cae985 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -63,8 +63,7 @@ public: virtual IBinder* onAsBinder(); virtual status_t setSharedBufferMode(bool sharedBufferMode) override; virtual status_t setAutoRefresh(bool autoRefresh) override; - virtual bool getFrameTimestamps(uint64_t frameNumber, - FrameTimestamps* outTimestamps) override; + virtual void getFrameTimestamps(FrameEventHistoryDelta *outDelta) override; virtual status_t getUniqueId(uint64_t* outId) const override; private: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8400136507..45d1477ff0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -567,16 +567,15 @@ bool SurfaceFlinger::authenticateSurfaceTexture( } status_t SurfaceFlinger::getSupportedFrameTimestamps( - std::vector<SupportableFrameTimestamps>* outSupported) const { + std::vector<FrameEvent>* outSupported) const { *outSupported = { - SupportableFrameTimestamps::REQUESTED_PRESENT, - SupportableFrameTimestamps::ACQUIRE, - SupportableFrameTimestamps::REFRESH_START, - SupportableFrameTimestamps::GL_COMPOSITION_DONE_TIME, + FrameEvent::REQUESTED_PRESENT, + FrameEvent::ACQUIRE, + FrameEvent::FIRST_REFRESH_START, + FrameEvent::GL_COMPOSITION_DONE, getHwComposer().retireFenceRepresentsStartOfScanout() ? - SupportableFrameTimestamps::DISPLAY_PRESENT_TIME : - SupportableFrameTimestamps::DISPLAY_RETIRE_TIME, - SupportableFrameTimestamps::RELEASE_TIME, + FrameEvent::DISPLAY_PRESENT : FrameEvent::DISPLAY_RETIRE, + FrameEvent::RELEASE, }; return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5b216ddd9c..5bf989b4ea 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -200,7 +200,7 @@ private: virtual bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const; virtual status_t getSupportedFrameTimestamps( - std::vector<SupportableFrameTimestamps>* outSupported) const; + std::vector<FrameEvent>* outSupported) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection(); virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 1ef7065a28..029937a7e0 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -248,15 +248,13 @@ void SurfaceFlingerConsumer::onSidebandStreamChanged() { } } -bool SurfaceFlingerConsumer::addAndGetFrameTimestamps( +void SurfaceFlingerConsumer::addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps *outTimestamps) { + FrameEventHistoryDelta *outDelta) { sp<Layer> l = mLayer.promote(); - if (!l.get()) { - return false; + if (l.get()) { + l->addAndGetFrameTimestamps(newTimestamps, outDelta); } - return l->addAndGetFrameTimestamps( - newTimestamps, frameNumber, outTimestamps); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 0f46ddc797..d3f0070ad6 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -84,9 +84,9 @@ public: void releasePendingBuffer(); #endif - virtual bool addAndGetFrameTimestamps( + virtual void addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, - uint64_t frameNumber, FrameTimestamps* outTimestamps) override; + FrameEventHistoryDelta* outDelta) override; private: virtual void onSidebandStreamChanged(); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 3bdb0214f1..66a3c42753 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -600,14 +600,14 @@ bool SurfaceFlinger::authenticateSurfaceTexture( } status_t SurfaceFlinger::getSupportedFrameTimestamps( - std::vector<SupportableFrameTimestamps>* outSupported) const { + std::vector<FrameEvent>* outSupported) const { *outSupported = { - SupportableFrameTimestamps::REQUESTED_PRESENT, - SupportableFrameTimestamps::ACQUIRE, - SupportableFrameTimestamps::REFRESH_START, - SupportableFrameTimestamps::GL_COMPOSITION_DONE_TIME, - SupportableFrameTimestamps::DISPLAY_RETIRE_TIME, - SupportableFrameTimestamps::RELEASE_TIME, + FrameEvent::REQUESTED_PRESENT, + FrameEvent::ACQUIRE, + FrameEvent::FIRST_REFRESH_START, + FrameEvent::GL_COMPOSITION_DONE, + FrameEvent::DISPLAY_RETIRE, + FrameEvent::RELEASE, }; return NO_ERROR; } |