| Index: cc/surfaces/display_scheduler.cc
|
| diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc
|
| index 229bc6306ccb1ecf4af4056e074b35a56ac9f429..c320ad2eaa47dfdb923e72740ad7f98f9d125075 100644
|
| --- a/cc/surfaces/display_scheduler.cc
|
| +++ b/cc/surfaces/display_scheduler.cc
|
| @@ -9,14 +9,15 @@
|
| #include "base/auto_reset.h"
|
| #include "base/stl_util.h"
|
| #include "base/trace_event/trace_event.h"
|
| +#include "cc/output/begin_frame_args.h"
|
| #include "cc/output/output_surface.h"
|
|
|
| namespace cc {
|
|
|
| -DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source,
|
| - base::SingleThreadTaskRunner* task_runner,
|
| +DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner,
|
| int max_pending_swaps)
|
| - : begin_frame_source_(begin_frame_source),
|
| + : client_(nullptr),
|
| + begin_frame_source_(nullptr),
|
| task_runner_(task_runner),
|
| inside_surface_damaged_(false),
|
| visible_(false),
|
| @@ -25,12 +26,9 @@ DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source,
|
| inside_begin_frame_deadline_interval_(false),
|
| needs_draw_(false),
|
| expecting_root_surface_damage_because_of_resize_(false),
|
| - all_active_child_surfaces_ready_to_draw_(false),
|
| pending_swaps_(0),
|
| max_pending_swaps_(max_pending_swaps),
|
| - observing_begin_frame_source_(false),
|
| - root_surface_damaged_(false),
|
| - expect_damage_from_root_surface_(false),
|
| + observing_begin_frames_(false),
|
| weak_ptr_factory_(this) {
|
| begin_frame_deadline_closure_ = base::Bind(
|
| &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
|
| @@ -44,6 +42,12 @@ void DisplayScheduler::SetClient(DisplaySchedulerClient* client) {
|
| client_ = client;
|
| }
|
|
|
| +void DisplayScheduler::SetBeginFrameSource(
|
| + DisplayBeginFrameSource* begin_frame_source) {
|
| + begin_frame_source_ = begin_frame_source;
|
| + begin_frame_source_->SetClient(this);
|
| +}
|
| +
|
| void DisplayScheduler::SetVisible(bool visible) {
|
| if (visible_ == visible)
|
| return;
|
| @@ -68,14 +72,13 @@ void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) {
|
| void DisplayScheduler::ForceImmediateSwapIfPossible() {
|
| TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
|
| bool in_begin = inside_begin_frame_deadline_interval_;
|
| - AttemptDrawAndSwap();
|
| + bool did_draw = AttemptDrawAndSwap();
|
| if (in_begin)
|
| - begin_frame_source_->DidFinishFrame(this, 0);
|
| + begin_frame_source_->FinishFrame(did_draw, needs_draw_);
|
| }
|
|
|
| void DisplayScheduler::DisplayResized() {
|
| expecting_root_surface_damage_because_of_resize_ = true;
|
| - expect_damage_from_root_surface_ = true;
|
| needs_draw_ = true;
|
| ScheduleBeginFrameDeadline();
|
| }
|
| @@ -102,16 +105,8 @@ void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) {
|
|
|
| needs_draw_ = true;
|
|
|
| - if (surface_id == root_surface_id_) {
|
| - root_surface_damaged_ = true;
|
| + if (surface_id == root_surface_id_)
|
| expecting_root_surface_damage_because_of_resize_ = false;
|
| - } else {
|
| - child_surface_ids_damaged_.insert(surface_id);
|
| -
|
| - // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts.
|
| - all_active_child_surfaces_ready_to_draw_ = base::STLIncludes(
|
| - child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_);
|
| - }
|
|
|
| StartObservingBeginFrames();
|
| ScheduleBeginFrameDeadline();
|
| @@ -123,35 +118,27 @@ void DisplayScheduler::OutputSurfaceLost() {
|
| ScheduleBeginFrameDeadline();
|
| }
|
|
|
| -void DisplayScheduler::DrawAndSwap() {
|
| +bool DisplayScheduler::DrawAndSwap() {
|
| TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
|
| DCHECK_LT(pending_swaps_, max_pending_swaps_);
|
| DCHECK(!output_surface_lost_);
|
|
|
| bool success = client_->DrawAndSwap();
|
| if (!success)
|
| - return;
|
| -
|
| - child_surface_ids_to_expect_damage_from_ =
|
| - base::STLSetIntersection<std::vector<SurfaceId>>(
|
| - child_surface_ids_damaged_, child_surface_ids_damaged_prev_);
|
| -
|
| - child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_);
|
| - child_surface_ids_damaged_.clear();
|
| + return false;
|
|
|
| needs_draw_ = false;
|
| - all_active_child_surfaces_ready_to_draw_ =
|
| - child_surface_ids_to_expect_damage_from_.empty();
|
| -
|
| - expect_damage_from_root_surface_ = root_surface_damaged_;
|
| - root_surface_damaged_ = false;
|
| + return true;
|
| }
|
|
|
| -bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
|
| +void DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) {
|
| base::TimeTicks now = base::TimeTicks::Now();
|
| TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(),
|
| "now", now);
|
|
|
| + // We always use the args, even if we post a missing_begin_frame_task.
|
| + last_used_begin_frame_args_ = args;
|
| +
|
| if (inside_surface_damaged_) {
|
| // Repost this so that we don't run a missed BeginFrame on the same
|
| // callstack. Otherwise we end up running unexpected scheduler actions
|
| @@ -160,12 +147,12 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
|
| DCHECK_EQ(args.type, BeginFrameArgs::MISSED);
|
| DCHECK(missed_begin_frame_task_.IsCancelled());
|
| missed_begin_frame_task_.Reset(base::Bind(
|
| - base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl),
|
| + base::IgnoreResult(&DisplayScheduler::OnBeginFrame),
|
| // The CancelableCallback will not run after it is destroyed, which
|
| // happens when |this| is destroyed.
|
| base::Unretained(this), args));
|
| task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
|
| - return true;
|
| + return;
|
| }
|
|
|
| // Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be
|
| @@ -189,21 +176,23 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
|
| BeginFrameArgs::DefaultEstimatedParentDrawTime();
|
| inside_begin_frame_deadline_interval_ = true;
|
| ScheduleBeginFrameDeadline();
|
| +}
|
|
|
| - return true;
|
| +const BeginFrameArgs& DisplayScheduler::LastUsedBeginFrameArgs() const {
|
| + return last_used_begin_frame_args_;
|
| }
|
|
|
| void DisplayScheduler::StartObservingBeginFrames() {
|
| - if (!observing_begin_frame_source_ && ShouldDraw()) {
|
| - begin_frame_source_->AddObserver(this);
|
| - observing_begin_frame_source_ = true;
|
| + if (!observing_begin_frames_ && ShouldDraw()) {
|
| + begin_frame_source_->SetClientNeedsBeginFrames(true);
|
| + observing_begin_frames_ = true;
|
| }
|
| }
|
|
|
| void DisplayScheduler::StopObservingBeginFrames() {
|
| - if (observing_begin_frame_source_) {
|
| - begin_frame_source_->RemoveObserver(this);
|
| - observing_begin_frame_source_ = false;
|
| + if (observing_begin_frames_) {
|
| + begin_frame_source_->SetClientNeedsBeginFrames(false);
|
| + observing_begin_frames_ = false;
|
|
|
| // A missed BeginFrame may be queued, so drop that too if we're going to
|
| // stop listening.
|
| @@ -217,11 +206,9 @@ bool DisplayScheduler::ShouldDraw() {
|
| return needs_draw_ && !output_surface_lost_ && visible_;
|
| }
|
|
|
| -void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) {
|
| - // BeginFrameSources used with DisplayScheduler do not make use of this
|
| - // feature.
|
| - if (paused)
|
| - NOTIMPLEMENTED();
|
| +void DisplayScheduler::BeginFrameObserverStatusChanged() {
|
| + // Schedules an immediate deadline if all observers have responded.
|
| + ScheduleBeginFrameDeadline();
|
| }
|
|
|
| base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
|
| @@ -236,7 +223,9 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
|
| current_begin_frame_args_.interval;
|
| }
|
|
|
| - if (!needs_draw_) {
|
| + bool observers_finished_frame = begin_frame_source_->ObserversFinishedFrame();
|
| +
|
| + if (!needs_draw_ && !observers_finished_frame) {
|
| TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD);
|
| return current_begin_frame_args_.frame_time +
|
| current_begin_frame_args_.interval;
|
| @@ -249,10 +238,8 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
|
| current_begin_frame_args_.interval;
|
| }
|
|
|
| - bool root_ready_to_draw =
|
| - !expect_damage_from_root_surface_ || root_surface_damaged_;
|
| -
|
| - if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) {
|
| + if (observers_finished_frame &&
|
| + !expecting_root_surface_damage_because_of_resize_) {
|
| TRACE_EVENT_INSTANT0("cc", "All active surfaces ready",
|
| TRACE_EVENT_SCOPE_THREAD);
|
| return base::TimeTicks();
|
| @@ -266,27 +253,6 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
|
| current_begin_frame_args_.interval;
|
| }
|
|
|
| - // Use an earlier deadline if we are only waiting for the root surface
|
| - // in case our expect_damage_from_root_surface heuristic is incorrect.
|
| - // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
|
| - // logic.
|
| - if (all_active_child_surfaces_ready_to_draw_ &&
|
| - expect_damage_from_root_surface_) {
|
| - TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface",
|
| - TRACE_EVENT_SCOPE_THREAD);
|
| - // This adjusts the deadline by DefaultEstimatedParentDrawTime for
|
| - // a second time. The first one represented the Surfaces draw to display
|
| - // latency. This one represents root surface commit+raster+draw latency.
|
| - // We treat the root surface differently since it lives on the same thread
|
| - // as Surfaces and waiting for it too long may push out the Surfaces draw.
|
| - // If we also assume the root surface is fast to start a commit after the
|
| - // beginning of a frame, it'll have a chance to lock its resources, which
|
| - // will cause us to wait for it to unlock its resources above.
|
| - // TODO(mithro): Replace hard coded estimates.
|
| - return current_begin_frame_args_.deadline -
|
| - BeginFrameArgs::DefaultEstimatedParentDrawTime();
|
| - }
|
| -
|
| TRACE_EVENT_INSTANT0("cc", "More damage expected soon",
|
| TRACE_EVENT_SCOPE_THREAD);
|
| return current_begin_frame_args_.deadline;
|
| @@ -327,31 +293,31 @@ void DisplayScheduler::ScheduleBeginFrameDeadline() {
|
| "desired_deadline", desired_deadline);
|
| }
|
|
|
| -void DisplayScheduler::AttemptDrawAndSwap() {
|
| +bool DisplayScheduler::AttemptDrawAndSwap() {
|
| inside_begin_frame_deadline_interval_ = false;
|
| begin_frame_deadline_task_.Cancel();
|
| begin_frame_deadline_task_time_ = base::TimeTicks();
|
|
|
| if (ShouldDraw()) {
|
| if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_)
|
| - DrawAndSwap();
|
| + return DrawAndSwap();
|
| } else {
|
| // We are going idle, so reset expectations.
|
| - child_surface_ids_to_expect_damage_from_.clear();
|
| - child_surface_ids_damaged_prev_.clear();
|
| - child_surface_ids_damaged_.clear();
|
| - all_active_child_surfaces_ready_to_draw_ = true;
|
| - expect_damage_from_root_surface_ = false;
|
| + // TODO(eseckler): Should we avoid going idle if
|
| + // expecting_root_surface_damage_because_of_resize_ is true?
|
| + expecting_root_surface_damage_because_of_resize_ = false;
|
|
|
| StopObservingBeginFrames();
|
| }
|
| +
|
| + return false;
|
| }
|
|
|
| void DisplayScheduler::OnBeginFrameDeadline() {
|
| TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
|
|
|
| - AttemptDrawAndSwap();
|
| - begin_frame_source_->DidFinishFrame(this, 0);
|
| + bool did_draw = AttemptDrawAndSwap();
|
| + begin_frame_source_->FinishFrame(did_draw, needs_draw_);
|
| }
|
|
|
| void DisplayScheduler::DidSwapBuffers() {
|
|
|