Chromium Code Reviews| Index: cc/scheduler/begin_frame_source.h |
| diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h |
| index bde01afd79ec6bd72a1d525c85b9d6d49bafe9d0..1208d2bc81368cfe74baff3edaf90a2820f65c43 100644 |
| --- a/cc/scheduler/begin_frame_source.h |
| +++ b/cc/scheduler/begin_frame_source.h |
| @@ -10,6 +10,7 @@ |
| #include <set> |
| #include <string> |
| +#include <unordered_set> |
| #include "base/logging.h" |
| #include "base/macros.h" |
| @@ -26,8 +27,10 @@ class CC_EXPORT BeginFrameObserver { |
| virtual ~BeginFrameObserver() {} |
| // The |args| given to OnBeginFrame is guaranteed to have |
| - // |args|.IsValid()==true and have |args|.frame_time |
| - // field be strictly greater than the previous call. |
| + // |args|.IsValid()==true. If |args|.source_id did not change between |
| + // invocations, |args|.sequence_number is guaranteed to be be strictly greater |
| + // than the previous call. Further, |args|.frame_time is guaranteed to be |
| + // greater than or equal to the previous call. |
|
brianderson
2016/12/09 01:08:11
To "Further, |args|.frame_time is guaranteed to be
Eric Seckler
2016/12/09 16:47:16
Yes, done!
|
| // |
| // Side effects: This function can (and most of the time *will*) change the |
| // return value of the LastUsedBeginFrameArgs method. See the documentation |
| @@ -99,14 +102,21 @@ class CC_EXPORT BeginFrameObserverBase : public BeginFrameObserver { |
| // all BeginFrameSources *must* provide. |
| class CC_EXPORT BeginFrameSource { |
| public: |
| + BeginFrameSource(); |
| virtual ~BeginFrameSource() {} |
| - // DidFinishFrame provides back pressure to a frame source about frame |
| - // processing (rather than toggling SetNeedsBeginFrames every frame). It is |
| - // used by systems like the BackToBackFrameSource to make sure only one frame |
| - // is pending at a time. |
| + // BeginFrameObservers use DidFinishFrame to acknowledge that they have |
| + // completed handling a BeginFrame. |
| + // |
| + // The DisplayScheduler uses these acknowledgments to trigger an early |
| + // deadline once all BeginFrameObservers have completed a frame. |
| + // |
| + // They also provide back pressure to a frame source about frame processing |
| + // (rather than toggling SetNeedsBeginFrames every frame). For example, the |
| + // BackToBackFrameSource uses them to make sure only one frame is pending at a |
| + // time. |
| virtual void DidFinishFrame(BeginFrameObserver* obs, |
| - size_t remaining_frames) = 0; |
| + const BeginFrameAck& ack) = 0; |
| // Add/Remove an observer from the source. When no observers are added the BFS |
| // should shut down its timers, disable vsync, etc. |
| @@ -116,13 +126,22 @@ class CC_EXPORT BeginFrameSource { |
| // Returns false if the begin frame source will just continue to produce |
| // begin frames without waiting. |
| virtual bool IsThrottled() const = 0; |
| + |
| + // Returns an identifier for this BeginFrameSource. Guaranteed unique within a |
| + // process, and very likely unique across processes. This is used to create |
|
brianderson
2016/12/09 01:08:11
"Guaranteed unique within a process, but not acros
Eric Seckler
2016/12/09 16:47:17
Okay. I guess the question is whether there may be
|
| + // BeginFrames that originate at this source. Note that BeginFrameSources may |
| + // pass on BeginFrames created by other sources, with different IDs. |
| + uint64_t source_id() const; |
| + |
| + private: |
| + uint64_t source_id_; |
| }; |
| // A BeginFrameSource that does nothing. |
| class CC_EXPORT StubBeginFrameSource : public BeginFrameSource { |
| public: |
| void DidFinishFrame(BeginFrameObserver* obs, |
| - size_t remaining_frames) override {} |
| + const BeginFrameAck& ack) override {} |
| void AddObserver(BeginFrameObserver* obs) override {} |
| void RemoveObserver(BeginFrameObserver* obs) override {} |
| bool IsThrottled() const override; |
| @@ -152,7 +171,7 @@ class CC_EXPORT BackToBackBeginFrameSource : public SyntheticBeginFrameSource, |
| void AddObserver(BeginFrameObserver* obs) override; |
| void RemoveObserver(BeginFrameObserver* obs) override; |
| void DidFinishFrame(BeginFrameObserver* obs, |
| - size_t remaining_frames) override; |
| + const BeginFrameAck& ack) override; |
| bool IsThrottled() const override; |
| // SyntheticBeginFrameSource implementation. |
| @@ -167,6 +186,7 @@ class CC_EXPORT BackToBackBeginFrameSource : public SyntheticBeginFrameSource, |
| std::unique_ptr<DelayBasedTimeSource> time_source_; |
| std::unordered_set<BeginFrameObserver*> observers_; |
| std::unordered_set<BeginFrameObserver*> pending_begin_frame_observers_; |
| + uint64_t next_sequence_number_; |
| base::WeakPtrFactory<BackToBackBeginFrameSource> weak_factory_; |
| DISALLOW_COPY_AND_ASSIGN(BackToBackBeginFrameSource); |
| @@ -185,7 +205,7 @@ class CC_EXPORT DelayBasedBeginFrameSource : public SyntheticBeginFrameSource, |
| void AddObserver(BeginFrameObserver* obs) override; |
| void RemoveObserver(BeginFrameObserver* obs) override; |
| void DidFinishFrame(BeginFrameObserver* obs, |
| - size_t remaining_frames) override {} |
| + const BeginFrameAck& ack) override {} |
| bool IsThrottled() const override; |
| // SyntheticBeginFrameSource implementation. |
| @@ -197,21 +217,64 @@ class CC_EXPORT DelayBasedBeginFrameSource : public SyntheticBeginFrameSource, |
| void OnTimerTick() override; |
| private: |
| - BeginFrameArgs CreateBeginFrameArgs(base::TimeTicks frame_time, |
| + BeginFrameArgs CreateBeginFrameArgs(uint64_t sequence_number, |
| + base::TimeTicks frame_time, |
| BeginFrameArgs::BeginFrameArgsType type); |
| std::unique_ptr<DelayBasedTimeSource> time_source_; |
| std::unordered_set<BeginFrameObserver*> observers_; |
| base::TimeTicks last_timebase_; |
| base::TimeDelta authoritative_interval_; |
| + BeginFrameArgs current_begin_frame_args_; |
| DISALLOW_COPY_AND_ASSIGN(DelayBasedBeginFrameSource); |
| }; |
| +// Helper class that tracks outstanding acknowledgments from |
| +// BeginFrameObservers. |
| +class CC_EXPORT BeginFrameObserverAckTracker { |
| + public: |
| + BeginFrameObserverAckTracker(); |
| + virtual ~BeginFrameObserverAckTracker(); |
| + |
| + // The BeginFrameSource uses these methods to notify us when a BeginFrame was |
| + // started and sent to a specific observer, an observer finished a frame, or |
| + // an observer was added/removed. |
| + void OnBeginFrame(const BeginFrameArgs& args); |
| + void OnObserverBeginFrame(BeginFrameObserver* obs, |
| + const BeginFrameArgs& args); |
| + void OnObserverFinishedFrame(BeginFrameObserver* obs, |
| + const BeginFrameAck& ack); |
| + void OnObserverAdded(BeginFrameObserver* obs); |
| + void OnObserverRemoved(BeginFrameObserver* obs); |
| + |
| + // Returns |true| if all the source's observers completed the current frame. |
| + bool AllObserversFinishedFrame() const; |
| + |
| + // Returns |true| if any observer had damages during the current frame. |
| + bool AnyObserversHadDamages() const; |
| + |
| + // Returns the sequence number of the latest_confirmed_frame that any of |
| + // the observers have contributed for the latest frame. |
| + uint64_t LatestConfirmedFrame() const; |
| + |
| + private: |
| + void SourceChanged(const BeginFrameArgs& args); |
| + |
| + uint64_t current_source_id_; |
| + uint64_t current_sequence_number_; |
| + std::set<BeginFrameObserver*> observers_; |
| + std::set<BeginFrameObserver*> finished_observers_; |
| + bool observers_had_damages_; |
|
brianderson
2016/12/09 01:08:11
observers_had_damage_
Eric Seckler
2016/12/09 16:47:17
Done.
Sami
2016/12/09 18:36:37
Should we do a s/damages/damage/g overall?
|
| + std::unordered_map<BeginFrameObserver*, uint64_t> latest_confirmed_frames_; |
| +}; |
| + |
| class CC_EXPORT ExternalBeginFrameSourceClient { |
| public: |
| // Only called when changed. Assumed false by default. |
| virtual void OnNeedsBeginFrames(bool needs_begin_frames) = 0; |
| + // Called when all observers have completed a frame. |
| + virtual void OnDidFinishFrame(const BeginFrameAck& ack) = 0; |
| }; |
| // A BeginFrameSource that is only ticked manually. Usually the endpoint |
| @@ -228,22 +291,45 @@ class CC_EXPORT ExternalBeginFrameSource : public BeginFrameSource { |
| void AddObserver(BeginFrameObserver* obs) override; |
| void RemoveObserver(BeginFrameObserver* obs) override; |
| void DidFinishFrame(BeginFrameObserver* obs, |
| - size_t remaining_frames) override {} |
| + const BeginFrameAck& ack) override; |
| bool IsThrottled() const override; |
| void OnSetBeginFrameSourcePaused(bool paused); |
| void OnBeginFrame(const BeginFrameArgs& args); |
| protected: |
| + void MaybeFinishFrame(); |
| + void FinishFrame(); |
| + |
| BeginFrameArgs missed_begin_frame_args_; |
| std::unordered_set<BeginFrameObserver*> observers_; |
| ExternalBeginFrameSourceClient* client_; |
| bool paused_ = false; |
| + bool frame_active_ = false; |
| + BeginFrameObserverAckTracker ack_tracker_; |
|
brianderson
2016/12/09 01:08:11
For my education, is this something that is actual
Eric Seckler
2016/12/09 16:47:17
Mus uses ExternalBeginFrameSources in WindowCompos
|
| private: |
| DISALLOW_COPY_AND_ASSIGN(ExternalBeginFrameSource); |
| }; |
| +// A BeginFrameSource that delegates to another given source. |
|
brianderson
2016/12/09 01:08:11
Can you add a comment explaining why this class is
Eric Seckler
2016/12/09 16:47:16
I think moving the ownership of the BeginFrameSour
|
| +class CC_EXPORT DelegatingBeginFrameSource : public BeginFrameSource { |
| + public: |
| + // |delegate| lifetime must be preserved past the lifetime of this class. |
| + explicit DelegatingBeginFrameSource(BeginFrameSource* delegate); |
| + ~DelegatingBeginFrameSource() override {} |
| + |
| + // BeginFrameSource implementation. |
| + void DidFinishFrame(BeginFrameObserver* obs, |
| + const BeginFrameAck& ack) override; |
| + void AddObserver(BeginFrameObserver* obs) override; |
| + void RemoveObserver(BeginFrameObserver* obs) override; |
| + bool IsThrottled() const override; |
| + |
| + private: |
| + BeginFrameSource* delegate_; // Not owned. |
| +}; |
| + |
| } // namespace cc |
| #endif // CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_ |