Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2396)

Unified Diff: cc/scheduler/begin_frame_source.h

Issue 267783004: Refactoring the way begin frame sources inside scheduler work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Splitting dropped counts for normal and missed begin frame messages. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/scheduler/begin_frame_source.h
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
new file mode 100644
index 0000000000000000000000000000000000000000..36c99d240c50dd8c10b1d0cbc16a3ea1089c9b13
--- /dev/null
+++ b/cc/scheduler/begin_frame_source.h
@@ -0,0 +1,270 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_
+#define CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_
+
+#include <set>
+#include <string>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "cc/output/begin_frame_args.h"
+#include "cc/output/vsync_parameter_observer.h"
+#include "cc/scheduler/delay_based_time_source.h"
+
+namespace cc {
+
+// (Pure) Interface for observing BeginFrame messages from BeginFrameSource
+// objects.
+class CC_EXPORT BeginFrameObserver {
+ public:
+ // 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.
+ //
+ // Side effects: This function can (and most of the time *will*) change the
+ // return value of the LastUsedBeginFrameArgs method. See the documentation
+ // on that method for more information.
+ virtual void OnBeginFrame(const BeginFrameArgs& args) = 0;
+
+ // Some frame sources *may* provide the last missed begin frame when
+ // SetNeedsBeginFrames is set true (such as the SyntheticBeginFrameSource).
+ //
+ // **Don't** depend on this function ever being called.
+ virtual void OnMissedBeginFrame(const BeginFrameArgs& args) = 0;
+
+ // Returns the last BeginFrameArgs used by the observer. This method's return
+ // value is affected by the OnBeginFrame method!
+ //
+ // - Before the first call of OnBeginFrame, this method should return a
+ // BeginFrameArgs on which IsValid() returns false.
+ //
+ // - If the |args| passed to OnBeginFrame is (or *will be*) used, then
+ // LastUsedBeginFrameArgs return value should become the |args| given to
+ // OnBeginFrame.
+ //
+ // - If the |args| passed to OnBeginFrame is dropped, then
+ // LastUsedBeginFrameArgs return value should *not* change.
+ //
+ // These requirements are designed to allow chaining and nesting of
+ // BeginFrameObservers which filter the incoming BeginFrame messages while
+ // preventing "double dropping" and other bad side effects.
+ virtual const BeginFrameArgs LastUsedBeginFrameArgs() const = 0;
+
+ // Tracing support
+ virtual void AsValueInto(base::debug::TracedValue* dict) const = 0;
+};
+
+// Simple mix in which implements a BeginFrameObserver which checks the
+// incoming values meet the BeginFrameObserver requirements and implements the
+// required LastUsedBeginFrameArgs behaviour.
+//
+// Users of this mix in should;
+// - Implement the OnBeginFrameMixInDelegate function.
+// - Recommended (but not required) to call
+// BeginFrameObserverMixIn::OnValueInto in their overridden OnValueInto
+// function.
+//
+// Advance observers may also wish to override the OnMissedBeginFrame method.
simonhong 2014/09/25 06:19:46 Advance -> Advanced?
mithro-old 2014/09/25 13:32:19 Done.
+class CC_EXPORT BeginFrameObserverMixIn : public BeginFrameObserver {
+ public:
+ // BeginFrameObserver
simonhong 2014/09/25 06:19:46 wrong comment.
mithro-old 2014/09/25 13:32:19 Done.
+ BeginFrameObserverMixIn();
+
+ // Traces |args| and DCHECK |args| satisfies pre-conditions then calls
+ // OnBeginFrameMixInDelegate and updates the last_begin_frame_args_ value on
+ // true.
+ virtual void OnBeginFrame(const BeginFrameArgs& args) OVERRIDE;
+
+ // Forwards call to the OnBeginFrame callback.
+ virtual void OnMissedBeginFrame(const BeginFrameArgs& args) OVERRIDE;
+
+ virtual const BeginFrameArgs LastUsedBeginFrameArgs() const OVERRIDE;
+
+ // Outputs last_begin_frame_args_
+ virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
+
+ protected:
+ // Subclasses should override this method!
+ // Return true if the given argument is (or will be) used.
+ virtual bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) = 0;
+ virtual bool OnMissedBeginFrameMixInDelegate(const BeginFrameArgs& args);
+
+ BeginFrameArgs last_begin_frame_args_;
+ int64_t dropped_begin_frame_args_;
+ int64_t dropped_missed_begin_frame_args_;
+};
+
+// Interface for a class which produces BeginFrame calls to a
+// BeginFrameObserver.
+//
+// BeginFrame calls *normally* occur just after a vsync interrupt when input
+// processing has been finished and provide information about the time values
+// of the vsync times. *However*, these values can be heavily modified or even
+// plain made up (when no vsync signal is available or vsync throttling is
+// turned off). See the BeginFrameObserver for information about the guarantees
+// all BeginFrameSources *must* provide.
+//
+// Implementation classes should:
+// - Use the CallOn(Missed)BeginFrame method to call to the observer(s).
+// - Implement the pure virtual methods.
+// - Recommend (but not required) to call BeginFrameSource::AsValueInto in
+// their own AsValueInto implementation.
+class CC_EXPORT BeginFrameSource {
+ public:
+ virtual ~BeginFrameSource() {}
+
+ // SetNeedsBeginFrames is the on/off "switch" for the BeginFrameSource. When
+ // set to false no more BeginFrame messages should be sent to observer.
+ virtual bool NeedsBeginFrames() const = 0;
+ virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0;
+
+ // 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.
+ virtual void DidFinishFrame(size_t remaining_frames) = 0;
simonhong 2014/09/25 06:19:46 Does we really need this function? I'm not sure ex
mithro-old 2014/09/25 13:32:19 We went back and forth on this problem and eventua
+
+ // Add/Remove and observer from the source.
simonhong 2014/09/25 06:19:46 and -> an.
mithro-old 2014/09/25 13:32:19 Done.
+ // *At the moment* only a single observer can be added to the source, however
+ // in the future this may be extended to allow multiple observers.
+ // If making this change, please use base::ObserverList to do so.
+ void AddObserver(BeginFrameObserver* obs);
+ void RemoveObserver(BeginFrameObserver* obs);
+
+ // Tracing support - Recommend (but not required) to call this implementation
+ // in any override.
+ virtual void AsValueInto(base::debug::TracedValue* dict) const;
+
+ protected:
+ BeginFrameSource();
+
+ // These methods should be used by subclasses to make the call to the
+ // observers.
+ void CallOnBeginFrame(const BeginFrameArgs& args);
+ void CallOnMissedBeginFrame(const BeginFrameArgs& args);
+
+ BeginFrameObserver* observer_;
+
+ private:
+ bool inside_as_value_into_;
+};
+
+// A frame source which calls BeginFrame (at the next possible time) as soon as
+// remaining frames reaches zero.
+class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSource {
+ public:
+ static scoped_ptr<BackToBackBeginFrameSource> Create(
+ base::SingleThreadTaskRunner* task_runner);
+ virtual ~BackToBackBeginFrameSource();
+
+ // BeginFrameSource
+ virtual bool NeedsBeginFrames() const OVERRIDE;
+ virtual void SetNeedsBeginFrames(bool needs_begin_frames) OVERRIDE;
+ virtual void DidFinishFrame(size_t remaining_frames) OVERRIDE;
+
+ // Tracing
+ virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
+
+ protected:
+ explicit BackToBackBeginFrameSource(
+ base::SingleThreadTaskRunner* task_runner);
+ virtual base::TimeTicks Now(); // Now overridable for testing
+
+ base::WeakPtrFactory<BackToBackBeginFrameSource> weak_factory_;
+ base::SingleThreadTaskRunner* task_runner_;
+
+ bool needs_begin_frames_;
+ bool send_begin_frame_posted_;
+
+ void ScheduleBeginFrame();
+ void BeginFrame();
+};
+
+// A frame source which is locked to an external parameters provides from a
+// vsync source and generates BeginFrameArgs for it.
+class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSource,
+ public VSyncParameterObserver,
+ public TimeSourceClient {
+ public:
+ static scoped_ptr<SyntheticBeginFrameSource> Create(
+ base::SingleThreadTaskRunner* task_runner,
+ base::TimeTicks initial_vsync_timebase,
+ base::TimeDelta initial_vsync_interval);
+ virtual ~SyntheticBeginFrameSource();
+
+ // BeginFrameSource
+ virtual bool NeedsBeginFrames() const OVERRIDE;
+ virtual void SetNeedsBeginFrames(bool needs_begin_frames) OVERRIDE;
+ virtual void DidFinishFrame(size_t remaining_frames) OVERRIDE{};
+
+ // Tracing
+ virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
+
+ // VSyncParameterObserver
+ virtual void OnUpdateVSyncParameters(
+ base::TimeTicks new_vsync_timebase,
+ base::TimeDelta new_vsync_interval) OVERRIDE;
+
+ // TimeSourceClient
+ virtual void OnTimerTick() OVERRIDE;
+
+ protected:
+ explicit SyntheticBeginFrameSource(
+ scoped_refptr<DelayBasedTimeSource> time_source);
+
+ void SendBeginFrameFromTick(base::TimeTicks frame_time);
+
+ scoped_refptr<DelayBasedTimeSource> time_source_;
+};
+
+// A "virtual" frame source which lets you switch between multiple other frame
+// sources while making sure the BeginFrameArgs stays increasing (possibly
+// enforcing minimum boundry between BeginFrameArgs messages).
+class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSource,
+ public BeginFrameObserver {
+ public:
+ static scoped_ptr<BeginFrameSourceMultiplexer> Create();
+ virtual ~BeginFrameSourceMultiplexer();
+
+ void SetMinimumInterval(base::TimeDelta new_minimum_interval);
+
+ void AddSource(BeginFrameSource* new_source);
+ void RemoveSource(BeginFrameSource* existing_source);
+ void SetActiveSource(BeginFrameSource* new_source);
+ const BeginFrameSource* ActiveSource();
+
+ // BeginFrameObserver
+ // The mux is an BeginFrameObserver as it needs to proxy the OnBeginFrame
+ // calls to preserve the monotonicity of the BeginFrameArgs when switching
+ // sources.
+ virtual void OnBeginFrame(const BeginFrameArgs& args) OVERRIDE;
+ virtual void OnMissedBeginFrame(const BeginFrameArgs& args) OVERRIDE;
+ virtual const BeginFrameArgs LastUsedBeginFrameArgs() const OVERRIDE;
+
+ // BeginFrameSource
+ virtual bool NeedsBeginFrames() const OVERRIDE;
+ virtual void SetNeedsBeginFrames(bool needs_begin_frames) OVERRIDE;
+ virtual void DidFinishFrame(size_t remaining_frames) OVERRIDE;
+
+ // Tracing
+ virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
+
+ protected:
+ BeginFrameSourceMultiplexer();
+ explicit BeginFrameSourceMultiplexer(base::TimeDelta minimum_interval);
+
+ bool HasSource(BeginFrameSource* source);
+ bool IsIncreasing(const BeginFrameArgs& args);
+
+ base::TimeDelta minimum_interval_;
+
+ BeginFrameSource* active_source_;
+ std::set<BeginFrameSource*> source_list_;
+};
+
+} // namespace cc
+
+#endif // CC_SCHEDULER_BEGIN_FRAME_SOURCE_H_

Powered by Google App Engine
This is Rietveld 408576698