1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/cancelable_callback.h"
#include "base/memory/raw_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/display/display_scheduler_base.h"
#include "components/viz/service/display/pending_swap_params.h"
#include "components/viz/service/viz_service_export.h"
namespace viz {
class HintSession;
class HintSessionFactory;
class VIZ_SERVICE_EXPORT DisplayScheduler
: public DisplaySchedulerBase,
public DynamicBeginFrameDeadlineOffsetSource {
public:
// `max_pending_swaps_120hz`, if positive, is used as the number of pending
// swaps while running at 120hz. Otherwise, this will fallback to
// `max_pending_swaps`.
DisplayScheduler(BeginFrameSource* begin_frame_source,
base::SingleThreadTaskRunner* task_runner,
PendingSwapParams pending_swap_params,
HintSessionFactory* hint_session_factory = nullptr,
bool wait_for_all_surfaces_before_draw = false);
DisplayScheduler(const DisplayScheduler&) = delete;
DisplayScheduler& operator=(const DisplayScheduler&) = delete;
~DisplayScheduler() override;
// DisplaySchedulerBase implementation.
void SetDamageTracker(DisplayDamageTracker* damage_tracker) override;
void SetVisible(bool visible) override;
void ForceImmediateSwapIfPossible() override;
void SetNeedsOneBeginFrame(bool needs_draw) override;
void DidSwapBuffers() override;
void DidReceiveSwapBuffersAck() override;
void OutputSurfaceLost() override;
void ReportFrameTime(
base::TimeDelta frame_time,
base::flat_set<base::PlatformThreadId> animation_thread_ids,
base::flat_set<base::PlatformThreadId> renderer_main_thread_ids,
base::TimeTicks draw_start,
HintSession::BoostType boost_type) override;
// DisplayDamageTracker::Delegate implementation.
void OnDisplayDamaged(SurfaceId surface_id) override;
void OnRootFrameMissing(bool missing) override;
void OnPendingSurfacesChanged() override;
// DynamicBeginFrameDeadlineOffsetSource:
base::TimeDelta GetDeadlineOffset(base::TimeDelta interval) const override;
protected:
class BeginFrameObserver;
class BeginFrameRequestObserverImpl;
bool OnBeginFrame(const BeginFrameArgs& args);
void OnBeginFrameContinuation(const BeginFrameArgs& args);
int MaxPendingSwaps() const;
base::TimeTicks current_frame_display_time() const {
return current_begin_frame_args_.frame_time +
current_begin_frame_args_.interval;
}
// These values inidicate how a response to the BeginFrame should be
// scheduled.
enum class BeginFrameDeadlineMode {
// Respond immediately. This means either all clients have responded with a
// BeginFrameAck so there is nothing to wait for, or DrawAndSwap cannot
// happen anymore (for example, OutputSurface is lost) and we might as well
// respond right now.
kImmediate,
// Schedule a task at the the end of BeginFrame interval minus the estimated
// time to run DrawAndSwap. This indicates that all requirements for calling
// DrawAndSwap are met, but we just want to give clients as much time as
// possible to send CompositorFrames.
kRegular,
// Schedule a response at the end of the BeginFrame interval. This usually
// indicates that some requirements for calling DrawAndSwap are not
// currently met (for example, the previous swap is not acked yet) and
// we would like to wait as long as possible to see if DrawAndSwap becomes
// possible.
kLate,
// A response to the BeginFrame cannot be scheduled right now. This means we
// have an unlimited deadline and some clients haven't responded to the
// BeginFrame yet so we need to wait longer.
kNone
};
static base::TimeTicks DesiredBeginFrameDeadlineTime(
BeginFrameDeadlineMode deadline_mode,
BeginFrameArgs begin_frame_args);
BeginFrameDeadlineMode AdjustedBeginFrameDeadlineMode() const;
BeginFrameDeadlineMode DesiredBeginFrameDeadlineMode() const;
virtual void ScheduleBeginFrameDeadline();
bool AttemptDrawAndSwap();
void OnBeginFrameDeadline();
bool DrawAndSwap();
void MaybeStartObservingBeginFrames();
void StartObservingBeginFrames();
void StopObservingBeginFrames();
bool ShouldDraw() const;
void DidFinishFrame(bool did_draw);
// Updates |has_pending_surfaces_| and returns whether its value changed.
bool UpdateHasPendingSurfaces();
void MaybeCreateHintSessions(
base::flat_set<base::PlatformThreadId> animation_thread_ids,
base::flat_set<base::PlatformThreadId> renderer_main_thread_ids);
std::unique_ptr<BeginFrameObserver> begin_frame_observer_;
raw_ptr<BeginFrameSource> begin_frame_source_;
raw_ptr<base::SingleThreadTaskRunner> task_runner_;
BeginFrameArgs current_begin_frame_args_;
base::RepeatingClosure begin_frame_deadline_closure_;
base::DeadlineTimer begin_frame_deadline_timer_;
base::TimeTicks begin_frame_deadline_task_time_;
base::CancelableOnceClosure missed_begin_frame_task_;
bool inside_surface_damaged_;
bool visible_;
bool output_surface_lost_;
bool inside_begin_frame_deadline_interval_;
bool needs_draw_;
bool has_pending_surfaces_;
int next_swap_id_;
int pending_swaps_;
const PendingSwapParams pending_swap_params_;
bool wait_for_all_surfaces_before_draw_;
bool observing_begin_frame_source_;
const raw_ptr<HintSessionFactory> hint_session_factory_;
struct AdpfSessionState {
base::flat_set<base::PlatformThreadId> thread_ids;
std::unique_ptr<HintSession> hint_session;
bool create_session_for_current_thread_ids_failed = false;
HintSession::SessionType type;
explicit AdpfSessionState(HintSession::SessionType type);
AdpfSessionState(AdpfSessionState&&);
~AdpfSessionState();
};
std::vector<AdpfSessionState> session_states_;
base::WeakPtrFactory<DisplayScheduler> weak_ptr_factory_{this};
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_H_
|