/* * Copyright 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_GUI_FRAMETIMESTAMPS_H #define ANDROID_GUI_FRAMETIMESTAMPS_H #include #include #include #include #include #include #include namespace android { struct FrameEvents; class FrameEventHistoryDelta; class String8; // Identifiers for all the events that may be recorded or reported. enum class FrameEvent { POSTED, REQUESTED_PRESENT, LATCH, ACQUIRE, FIRST_REFRESH_START, LAST_REFRESH_START, GPU_COMPOSITION_DONE, DISPLAY_PRESENT, DEQUEUE_READY, RELEASE, EVENT_COUNT, // Not an actual event. }; // A collection of timestamps corresponding to a single frame. struct FrameEvents { static constexpr auto EVENT_COUNT = static_cast(FrameEvent::EVENT_COUNT); static_assert(EVENT_COUNT <= 32, "Event count sanity check failed."); static constexpr nsecs_t TIMESTAMP_PENDING = -2; static inline bool isValidTimestamp(nsecs_t time) { return time != TIMESTAMP_PENDING; } 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 hasReleaseInfo() const; bool hasDequeueReadyInfo() const; void checkFencesForCompletion(); void dump(String8& outString) const; bool valid{false}; int connectId{0}; uint64_t frameNumber{0}; // Whether or not certain points in the frame's life cycle have been // encountered help us determine if timestamps aren't available because // a) we'll just never get them or b) they're not ready yet. bool addPostCompositeCalled{false}; bool addReleaseCalled{false}; nsecs_t postedTime{TIMESTAMP_PENDING}; nsecs_t requestedPresentTime{TIMESTAMP_PENDING}; nsecs_t latchTime{TIMESTAMP_PENDING}; nsecs_t firstRefreshStartTime{TIMESTAMP_PENDING}; nsecs_t lastRefreshStartTime{TIMESTAMP_PENDING}; nsecs_t dequeueReadyTime{TIMESTAMP_PENDING}; std::shared_ptr acquireFence{FenceTime::NO_FENCE}; std::shared_ptr gpuCompositionDoneFence{FenceTime::NO_FENCE}; std::shared_ptr displayPresentFence{FenceTime::NO_FENCE}; std::shared_ptr releaseFence{FenceTime::NO_FENCE}; }; struct CompositorTiming { nsecs_t deadline{0}; nsecs_t interval{16666667}; nsecs_t presentLatency{16666667}; }; // 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 mFrames; CompositorTiming mCompositorTiming; }; // The producer's interface to FrameEventHistory class ProducerFrameEventHistory : public FrameEventHistory { public: ~ProducerFrameEventHistory() override; // Public for testing. static nsecs_t snapToNextTick( nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval); nsecs_t getNextCompositeDeadline(const nsecs_t now) const; nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; } nsecs_t getCompositeToPresentLatency() const { return mCompositorTiming.presentLatency; } // virtual for testing. virtual void updateAcquireFence( uint64_t frameNumber, std::shared_ptr&& acquire); void applyDelta(const FrameEventHistoryDelta& delta); void updateSignalTimes(); protected: void applyFenceDelta(FenceTimeline* timeline, std::shared_ptr* dst, const FenceTime::Snapshot& src) const; // virtual for testing. virtual std::shared_ptr createFenceTime( const sp& fence) const; size_t mAcquireOffset{0}; // The consumer updates it's timelines in Layer and SurfaceFlinger since // they can coordinate shared timelines better. The producer doesn't have // shared timelines though, so just let it own and update all of them. FenceTimeline mAcquireTimeline; FenceTimeline mGpuCompositionDoneTimeline; FenceTimeline mPresentTimeline; FenceTimeline mReleaseTimeline; }; // 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}; nsecs_t requestedPresentTime{0}; std::shared_ptr acquireFence{FenceTime::NO_FENCE}; }; // Used by the consumer to keep track of which fields it already sent to // the producer. class FrameEventDirtyFields { public: inline void reset() { mBitset.reset(); } inline bool anyDirty() const { return mBitset.any(); } template inline void setDirty() { constexpr size_t eventIndex = static_cast(event); static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index."); mBitset.set(eventIndex); } template inline bool isDirty() const { constexpr size_t eventIndex = static_cast(event); static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index."); return mBitset[eventIndex]; } private: std::bitset mBitset; }; // The consumer's interface to FrameEventHistory class ConsumerFrameEventHistory : public FrameEventHistory { public: ~ConsumerFrameEventHistory() override; void onDisconnect(); void initializeCompositorTiming(const CompositorTiming& compositorTiming); 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, const std::shared_ptr& gpuCompositionDone, const std::shared_ptr& displayPresent, const CompositorTiming& compositorTiming); void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime, std::shared_ptr&& release); void getAndResetDelta(FrameEventHistoryDelta* delta); private: void getFrameDelta(FrameEventHistoryDelta* delta, const std::array::iterator& frame); std::array mFramesDirty; size_t mQueueOffset{0}; size_t mCompositionOffset{0}; size_t mReleaseOffset{0}; int mCurrentConnectId{0}; bool mProducerWantsEvents{false}; }; // 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 { friend class ProducerFrameEventHistory; public: FrameEventsDelta() = default; FrameEventsDelta(size_t index, const FrameEvents& frameTimestamps, const FrameEventDirtyFields& dirtyFields); // Movable. FrameEventsDelta(FrameEventsDelta&& src) = default; FrameEventsDelta& operator=(FrameEventsDelta&& src) = default; // Not copyable. FrameEventsDelta(const FrameEventsDelta& src) = delete; FrameEventsDelta& operator=(const FrameEventsDelta& src) = delete; // 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 constexpr size_t minFlattenedSize(); size_t mIndex{0}; uint64_t mFrameNumber{0}; bool mAddPostCompositeCalled{0}; bool mAddReleaseCalled{0}; nsecs_t mPostedTime{FrameEvents::TIMESTAMP_PENDING}; nsecs_t mRequestedPresentTime{FrameEvents::TIMESTAMP_PENDING}; nsecs_t mLatchTime{FrameEvents::TIMESTAMP_PENDING}; nsecs_t mFirstRefreshStartTime{FrameEvents::TIMESTAMP_PENDING}; nsecs_t mLastRefreshStartTime{FrameEvents::TIMESTAMP_PENDING}; nsecs_t mDequeueReadyTime{FrameEvents::TIMESTAMP_PENDING}; FenceTime::Snapshot mGpuCompositionDoneFence; FenceTime::Snapshot mDisplayPresentFence; FenceTime::Snapshot mReleaseFence; // This is a static method with an auto return value so we can call // it without needing const and non-const versions. template static inline auto allFences(ThisT fed) -> std::arraymReleaseFence), 3> { return {{ &fed->mGpuCompositionDoneFence, &fed->mDisplayPresentFence, &fed->mReleaseFence }}; } }; // A collection of updates from consumer to producer that can be sent // through Binder. class FrameEventHistoryDelta : public Flattenable { friend class ConsumerFrameEventHistory; friend class ProducerFrameEventHistory; public: FrameEventHistoryDelta() = default; // Movable. FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default; FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src); // Not copyable. FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete; FrameEventHistoryDelta& operator=( const FrameEventHistoryDelta& src) = delete; // 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 constexpr size_t minFlattenedSize(); std::vector mDeltas; CompositorTiming mCompositorTiming; }; } // namespace android #endif