| Index: services/gfx/compositor/backend/vsync_scheduler.h
|
| diff --git a/services/gfx/compositor/backend/vsync_scheduler.h b/services/gfx/compositor/backend/vsync_scheduler.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..46fced82c9057e35532311382e226cce1b143bd2
|
| --- /dev/null
|
| +++ b/services/gfx/compositor/backend/vsync_scheduler.h
|
| @@ -0,0 +1,162 @@
|
| +// Copyright 2015 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 SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_
|
| +#define SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_
|
| +
|
| +#include <limits>
|
| +#include <memory>
|
| +#include <mutex>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/task_runner.h"
|
| +#include "services/gfx/compositor/backend/scheduler.h"
|
| +
|
| +namespace compositor {
|
| +
|
| +// Schedules work to coincide with vsync intervals.
|
| +//
|
| +// This object is thread-safe and it intended to be used to allow one thread
|
| +// to be scheduling work for itself while another thread concurrently updates
|
| +// timing parameters.
|
| +class VsyncScheduler : public Scheduler {
|
| + public:
|
| + // Limits on allowable parameters. (Exposed for testing.)
|
| + static constexpr int64_t kMinVsyncInterval = 1000; // 1000 Hz
|
| + static constexpr int64_t kMaxVsyncInterval = 1000000; // 1 Hz
|
| +
|
| + // Time reference. Should be MojoTimeTicksNow() except during testing.
|
| + using Clock = base::Callback<MojoTimeTicks()>;
|
| +
|
| + VsyncScheduler(const scoped_refptr<base::TaskRunner>& task_runner,
|
| + const SchedulerCallbacks& callbacks);
|
| + VsyncScheduler(const scoped_refptr<base::TaskRunner>& task_runner,
|
| + const SchedulerCallbacks& callbacks,
|
| + const Clock& clock);
|
| + ~VsyncScheduler() override;
|
| +
|
| + // Starts scheduling work and sets the scheduling parameters.
|
| + //
|
| + // |vsync_timebase| is a value in the |MojoTimeTicks| timebase which
|
| + // specifies when a recent vsync occurred and is used to determine the phase.
|
| + //
|
| + // |vsync_interval| is the number of microseconds between vsyncs which
|
| + // also determines the |FrameInfo.frame_interval| value to deliver to
|
| + // applications.
|
| + //
|
| + // |update_phase| specifies an offset relative to vsync for determining
|
| + // when updates are scheduled and the |FrameInfo.frame_time| to deliver
|
| + // to applications.
|
| + //
|
| + // |snapshot_phase| specifies an offset relative to vsync for
|
| + // determining when snapshots are scheduled and the |FrameInfo.frame_deadline|
|
| + // to deliver to applications. Must be greater than or equal to
|
| + // |update_phase|.
|
| + //
|
| + // |presentation_phase| specifies an offset relative to vsync for
|
| + // determining when frames are shown on the display output and the
|
| + // |FrameInfo.presentation_time| to deliver to applications. Must be
|
| + // greater than or equal to |snapshot_phase|.
|
| + //
|
| + // The notion of 'vsync' is somewhat abstract here. It's just a reference
|
| + // pulse but we usually interpret it as a deadline for preparing the next
|
| + // frame and submitting it to the display hardware.
|
| + //
|
| + // The phases can be positive or negative but negative offsets from vsync
|
| + // may be easier to interpret when computing deadlines. To avoid
|
| + // overflows, the values chosen for the phases should be close to 0.
|
| + //
|
| + // This function schedules an update and snapshot if not already scheduled.
|
| + //
|
| + // Returns true if the schedule was started successfully, false if the
|
| + // parameters are invalid.
|
| + bool Start(int64_t vsync_timebase,
|
| + int64_t vsync_interval,
|
| + int64_t update_phase,
|
| + int64_t snapshot_phase,
|
| + int64_t presentation_phase) {
|
| + return state_->Start(vsync_timebase, vsync_interval, update_phase,
|
| + snapshot_phase, presentation_phase);
|
| + }
|
| +
|
| + // Stops scheduling work.
|
| + //
|
| + // Previously scheduled callbacks may still be delivered.
|
| + void Stop() { state_->Stop(); }
|
| +
|
| + // |Scheduler|:
|
| + void ScheduleFrame(SchedulingMode scheduling_mode) override;
|
| +
|
| + private:
|
| + // Internal state. Held by a shared_ptr so that callbacks running on
|
| + // other threads can reference it using a weak_ptr.
|
| + class State : public std::enable_shared_from_this<State> {
|
| + public:
|
| + State(const scoped_refptr<base::TaskRunner>& task_runner,
|
| + const SchedulerCallbacks& callbacks,
|
| + const Clock& clock);
|
| + ~State();
|
| +
|
| + MojoTimeTicks GetTimeTicksNow() { return clock_.Run(); }
|
| +
|
| + bool Start(int64_t vsync_timebase,
|
| + int64_t vsync_interval,
|
| + int64_t update_phase,
|
| + int64_t snapshot_phase,
|
| + int64_t presentation_phase);
|
| + void Stop();
|
| + void ScheduleFrame(SchedulingMode scheduling_mode);
|
| +
|
| + private:
|
| + enum class Action {
|
| + kUpdate,
|
| + kEarlySnapshot,
|
| + kLateSnapshot,
|
| + };
|
| +
|
| + static void DispatchThunk(const std::weak_ptr<State>& state_weak,
|
| + int32_t generation,
|
| + Action action,
|
| + int64_t update_time);
|
| +
|
| + void ScheduleLocked(MojoTimeTicks now);
|
| + void PostDispatchLocked(int64_t now,
|
| + int64_t delivery_time,
|
| + Action action,
|
| + int64_t update_time);
|
| +
|
| + void Dispatch(int32_t generation, Action action, int64_t update_time);
|
| + void SetFrameInfoLocked(mojo::gfx::composition::FrameInfo* frame_info,
|
| + int64_t update_time);
|
| +
|
| + const scoped_refptr<base::TaskRunner> task_runner_;
|
| + const SchedulerCallbacks callbacks_;
|
| + const Clock clock_;
|
| +
|
| + // Parameters and state guarded by |mutex_|.
|
| + std::mutex mutex_;
|
| + bool running_ = false;
|
| + int32_t generation_ = 0;
|
| + int64_t vsync_timebase_ = 0;
|
| + int64_t vsync_interval_ = 0;
|
| + int64_t update_phase_ = 0;
|
| + int64_t snapshot_phase_ = 0;
|
| + int64_t presentation_phase_ = 0;
|
| + bool need_update_ = false;
|
| + bool pending_dispatch_ = false;
|
| + int64_t last_delivered_update_time_ = std::numeric_limits<int64_t>::min();
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(State);
|
| + };
|
| +
|
| + const std::shared_ptr<State> state_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(VsyncScheduler);
|
| +};
|
| +
|
| +} // namespace compositor
|
| +
|
| +#endif // SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_
|
|
|