Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "cc/surfaces/display_begin_frame_source.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 namespace cc { | |
| 10 | |
| 11 DisplayBeginFrameSource::DisplayBeginFrameSource( | |
| 12 std::unique_ptr<BeginFrameSource> target_source) | |
| 13 : target_source_(std::move(target_source)), | |
| 14 observing_begin_frames_(false), | |
| 15 frame_active_(false), | |
| 16 current_source_id_(0), | |
| 17 oldest_incorporated_frame_(0), | |
| 18 client_(nullptr), | |
| 19 client_needs_begin_frames_(false) {} | |
| 20 | |
| 21 DisplayBeginFrameSource::~DisplayBeginFrameSource() { | |
| 22 if (target_source_ && observing_begin_frames_) | |
| 23 target_source_->RemoveObserver(this); | |
| 24 } | |
| 25 | |
| 26 void DisplayBeginFrameSource::SetClientNeedsBeginFrames( | |
| 27 bool needs_begin_frames) { | |
| 28 DCHECK(client_); | |
| 29 bool did_need_begin_frames = client_needs_begin_frames_; | |
| 30 client_needs_begin_frames_ = needs_begin_frames; | |
| 31 | |
| 32 if (client_needs_begin_frames_ && !did_need_begin_frames) { | |
| 33 if (!observing_begin_frames_) { | |
| 34 // We need to start observing, a missed BeginFrame will be triggered by | |
| 35 // the target source. | |
| 36 observing_begin_frames_ = true; | |
| 37 target_source_->AddObserver(this); | |
| 38 } else if (current_begin_frame_args_.IsValid()) { | |
| 39 // We were already observing, but the client may have missed the last | |
| 40 // BeginFrame. | |
| 41 const BeginFrameArgs& last_args = client_->LastUsedBeginFrameArgs(); | |
| 42 if (!last_args.IsValid() || (last_args.sequence_number < | |
| 43 current_begin_frame_args_.sequence_number)) { | |
| 44 BeginFrameArgs missed_args = current_begin_frame_args_; | |
| 45 missed_args.type = BeginFrameArgs::MISSED; | |
| 46 client_->OnBeginFrame(missed_args); | |
| 47 } | |
| 48 } | |
| 49 } | |
|
Sami
2016/12/06 12:41:07
Are we missing the case where the client stops nee
Eric Seckler
2016/12/06 17:34:00
You're right. Should now be covered in UpdateObser
| |
| 50 } | |
| 51 | |
| 52 void DisplayBeginFrameSource::FinishFrame(bool had_updates, | |
| 53 bool has_pending_updates) { | |
| 54 if (!frame_active_) | |
|
Sami
2016/12/06 12:41:07
Is someone calling this at a bad time?
Eric Seckler
2016/12/06 17:34:00
Shouldn't :) Changed to a DCHECK.
| |
| 55 return; | |
| 56 | |
| 57 frame_active_ = false; | |
| 58 | |
| 59 // Only update the oldest_incorporated_frame if there are no further pending | |
| 60 // updates (i.e. the Display didn't have to draw or drew successfully). | |
| 61 if (!has_pending_updates) | |
| 62 oldest_incorporated_frame_ = ack_tracker_.OldestIncorporatedFrame(); | |
| 63 | |
| 64 BeginFrameAck ack(current_begin_frame_args_.source_id, | |
| 65 current_begin_frame_args_.sequence_number, had_updates, | |
| 66 oldest_incorporated_frame_, 0); | |
| 67 if (target_source_) | |
| 68 target_source_->DidFinishFrame(this, ack); | |
| 69 } | |
| 70 | |
| 71 bool DisplayBeginFrameSource::ObserversFinishedFrame() { | |
| 72 return ack_tracker_.ObserversFinishedFrame(); | |
| 73 } | |
| 74 | |
| 75 void DisplayBeginFrameSource::SwapTargetSource( | |
| 76 std::unique_ptr<BeginFrameSource>* begin_frame_source) { | |
| 77 if (target_source_ && observing_begin_frames_) | |
| 78 target_source_->RemoveObserver(this); | |
| 79 | |
| 80 target_source_.swap(*begin_frame_source); | |
| 81 | |
| 82 if (target_source_ && observing_begin_frames_) | |
| 83 target_source_->AddObserver(this); | |
| 84 } | |
| 85 | |
| 86 void DisplayBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | |
| 87 const BeginFrameAck& ack) { | |
| 88 ack_tracker_.OnObserverFinishedFrame(obs, ack); | |
| 89 ObserverStatusChanged(); | |
| 90 } | |
| 91 | |
| 92 void DisplayBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | |
| 93 observers_.insert(obs); | |
| 94 ack_tracker_.OnObserverAdded(obs); | |
| 95 | |
| 96 if (!observing_begin_frames_) { | |
|
Sami
2016/12/06 12:41:07
Maybe fold this together with the logic in SetClie
Eric Seckler
2016/12/06 17:34:00
Extracted common bits into UpdateObservingBeginFra
| |
| 97 observing_begin_frames_ = true; | |
| 98 if (target_source_) | |
| 99 target_source_->AddObserver(this); | |
| 100 } else if (current_begin_frame_args_.IsValid()) { | |
| 101 // We were already observing, but the observer may have missed the last | |
| 102 // BeginFrame. | |
| 103 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | |
| 104 if (!last_args.IsValid() || (last_args.sequence_number < | |
| 105 current_begin_frame_args_.sequence_number)) { | |
| 106 BeginFrameArgs missed_args = current_begin_frame_args_; | |
| 107 missed_args.type = BeginFrameArgs::MISSED; | |
| 108 obs->OnBeginFrame(missed_args); | |
| 109 ack_tracker_.OnObserverBeginFrame(obs, missed_args); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 ObserverStatusChanged(); | |
| 114 } | |
| 115 | |
| 116 void DisplayBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | |
| 117 observers_.erase(obs); | |
| 118 ack_tracker_.OnObserverRemoved(obs); | |
| 119 | |
| 120 if (observers_.empty() && !client_needs_begin_frames_) { | |
| 121 DCHECK(observing_begin_frames_); | |
| 122 observing_begin_frames_ = false; | |
| 123 if (target_source_) | |
| 124 target_source_->RemoveObserver(this); | |
| 125 } | |
| 126 | |
| 127 ObserverStatusChanged(); | |
| 128 } | |
| 129 | |
| 130 bool DisplayBeginFrameSource::IsThrottled() const { | |
| 131 if (target_source_) | |
| 132 return target_source_->IsThrottled(); | |
| 133 return true; | |
| 134 } | |
| 135 | |
| 136 void DisplayBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { | |
| 137 if (client_ && client_needs_begin_frames_) | |
| 138 client_->OnBeginFrame(args); | |
| 139 | |
| 140 // Reset for the new frame. | |
| 141 frame_active_ = true; | |
| 142 ack_tracker_.OnBeginFrame(args); | |
| 143 | |
| 144 // BeginFrameObserverAckTracker will have updated the oldest incorporated | |
| 145 // frame if the target source changes. | |
| 146 if (args.source_id != current_source_id_) | |
| 147 oldest_incorporated_frame_ = ack_tracker_.OldestIncorporatedFrame(); | |
| 148 | |
| 149 current_begin_frame_args_ = args; | |
| 150 | |
| 151 // Observers may remove themselves during OnBeginFrame(), so use a copy. | |
| 152 std::set<BeginFrameObserver*> observers = observers_; | |
| 153 for (BeginFrameObserver* obs : observers) { | |
| 154 obs->OnBeginFrame(args); | |
| 155 ack_tracker_.OnObserverBeginFrame(obs, args); | |
| 156 } | |
| 157 | |
| 158 ObserverStatusChanged(); | |
| 159 } | |
| 160 | |
| 161 const BeginFrameArgs& DisplayBeginFrameSource::LastUsedBeginFrameArgs() const { | |
| 162 return current_begin_frame_args_; | |
| 163 } | |
| 164 | |
| 165 void DisplayBeginFrameSource::OnBeginFrameSourcePausedChanged(bool paused) { | |
| 166 // BeginFrameSources used as target sources do not make use of this feature. | |
| 167 DCHECK(!paused); | |
| 168 } | |
| 169 | |
| 170 void DisplayBeginFrameSource::ObserverStatusChanged() { | |
| 171 if (client_) | |
| 172 client_->BeginFrameObserverStatusChanged(); | |
| 173 } | |
| 174 | |
| 175 } // namespace cc | |
| OLD | NEW |