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

Side by Side Diff: cc/scheduler/begin_frame_source.cc

Issue 2691453002: [cc] Track observer status in ExternalBeginFrameSource. (Closed)
Patch Set: Fix comments. Created 3 years, 10 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 unified diff | Download patch
« no previous file with comments | « cc/scheduler/begin_frame_source.h ('k') | cc/scheduler/begin_frame_source_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/scheduler/begin_frame_source.h" 5 #include "cc/scheduler/begin_frame_source.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); 233 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
234 if (!last_args.IsValid() || 234 if (!last_args.IsValid() ||
235 (current_begin_frame_args_.frame_time > 235 (current_begin_frame_args_.frame_time >
236 last_args.frame_time + 236 last_args.frame_time +
237 current_begin_frame_args_.interval / kDoubleTickDivisor)) { 237 current_begin_frame_args_.interval / kDoubleTickDivisor)) {
238 obs->OnBeginFrame(current_begin_frame_args_); 238 obs->OnBeginFrame(current_begin_frame_args_);
239 } 239 }
240 } 240 }
241 } 241 }
242 242
243 // BeginFrameObserverAckTracker -------------------------------------------
244 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker()
245 : current_source_id_(0),
246 current_sequence_number_(BeginFrameArgs::kStartingFrameNumber),
247 observers_had_damage_(false) {}
248
249 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() {}
250
251 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) {
252 if (current_source_id_ != args.source_id)
253 SourceChanged(args);
254
255 DCHECK_GE(args.sequence_number, current_sequence_number_);
256 // Reset for new BeginFrame.
257 current_sequence_number_ = args.sequence_number;
258 finished_observers_.clear();
259 observers_had_damage_ = false;
260 }
261
262 void BeginFrameObserverAckTracker::SourceChanged(const BeginFrameArgs& args) {
263 current_source_id_ = args.source_id;
264 current_sequence_number_ = args.sequence_number;
265
266 // Mark all observers invalid: We report an invalid frame until every observer
267 // has confirmed the frame.
268 for (auto& entry : latest_confirmed_sequence_numbers_)
269 entry.second = BeginFrameArgs::kInvalidFrameNumber;
270 }
271
272 void BeginFrameObserverAckTracker::OnObserverFinishedFrame(
273 BeginFrameObserver* obs,
274 const BeginFrameAck& ack) {
275 if (ack.source_id != current_source_id_)
276 return;
277
278 DCHECK_LE(ack.sequence_number, current_sequence_number_);
279 if (ack.sequence_number != current_sequence_number_)
280 return;
281
282 finished_observers_.insert(obs);
283 observers_had_damage_ |= ack.has_damage;
284
285 // We max() with the current value in |latest_confirmed_sequence_numbers_| to
286 // handle situations where an observer just started observing (again) and may
287 // acknowledge with an ancient latest_confirmed_sequence_number.
288 latest_confirmed_sequence_numbers_[obs] =
289 std::max(ack.latest_confirmed_sequence_number,
290 latest_confirmed_sequence_numbers_[obs]);
291 }
292
293 void BeginFrameObserverAckTracker::OnObserverAdded(BeginFrameObserver* obs) {
294 observers_.insert(obs);
295
296 // Since the observer didn't want BeginFrames before, we consider it
297 // up-to-date up to the last BeginFrame, except if it already handled the
298 // current BeginFrame. In which case, we consider it up-to-date up to the
299 // current one.
300 DCHECK_LT(BeginFrameArgs::kInvalidFrameNumber, current_sequence_number_);
301 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
302 if (last_args.IsValid() &&
303 last_args.sequence_number == current_sequence_number_ &&
304 last_args.source_id == current_source_id_) {
305 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_;
306 finished_observers_.insert(obs);
307 } else {
308 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_ - 1;
309 }
310 }
311
312 void BeginFrameObserverAckTracker::OnObserverRemoved(BeginFrameObserver* obs) {
313 observers_.erase(obs);
314 finished_observers_.erase(obs);
315 latest_confirmed_sequence_numbers_.erase(obs);
316 }
317
318 bool BeginFrameObserverAckTracker::AllObserversFinishedFrame() const {
319 if (finished_observers_.size() < observers_.size())
320 return false;
321 return base::STLIncludes(finished_observers_, observers_);
322 }
323
324 bool BeginFrameObserverAckTracker::AnyObserversHadDamage() const {
325 return observers_had_damage_;
326 }
327
328 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const {
329 uint64_t latest_confirmed_sequence_number = current_sequence_number_;
330 for (const auto& entry : latest_confirmed_sequence_numbers_) {
331 latest_confirmed_sequence_number =
332 std::min(latest_confirmed_sequence_number, entry.second);
333 }
334 return latest_confirmed_sequence_number;
335 }
336
243 // ExternalBeginFrameSource ----------------------------------------------- 337 // ExternalBeginFrameSource -----------------------------------------------
244 ExternalBeginFrameSource::ExternalBeginFrameSource( 338 ExternalBeginFrameSource::ExternalBeginFrameSource(
245 ExternalBeginFrameSourceClient* client) 339 ExternalBeginFrameSourceClient* client)
246 : client_(client) { 340 : client_(client) {
247 DCHECK(client_); 341 DCHECK(client_);
248 } 342 }
249 343
250 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; 344 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default;
251 345
252 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { 346 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
253 DCHECK(obs); 347 DCHECK(obs);
254 DCHECK(observers_.find(obs) == observers_.end()); 348 DCHECK(observers_.find(obs) == observers_.end());
255 349
256 bool observers_was_empty = observers_.empty(); 350 bool observers_was_empty = observers_.empty();
257 observers_.insert(obs); 351 observers_.insert(obs);
352 ack_tracker_.OnObserverAdded(obs);
258 obs->OnBeginFrameSourcePausedChanged(paused_); 353 obs->OnBeginFrameSourcePausedChanged(paused_);
259 if (observers_was_empty) 354 if (observers_was_empty)
260 client_->OnNeedsBeginFrames(true); 355 client_->OnNeedsBeginFrames(true);
261 356
262 // Send a MISSED begin frame if necessary. 357 // Send a MISSED begin frame if necessary.
263 if (missed_begin_frame_args_.IsValid()) { 358 if (missed_begin_frame_args_.IsValid()) {
264 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); 359 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
265 if (!last_args.IsValid() || 360 if (!last_args.IsValid() ||
266 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { 361 (missed_begin_frame_args_.frame_time > last_args.frame_time)) {
267 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || 362 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) ||
268 (missed_begin_frame_args_.sequence_number > 363 (missed_begin_frame_args_.sequence_number >
269 last_args.sequence_number)) 364 last_args.sequence_number))
270 << "current " << missed_begin_frame_args_.AsValue()->ToString() 365 << "current " << missed_begin_frame_args_.AsValue()->ToString()
271 << ", last " << last_args.AsValue()->ToString(); 366 << ", last " << last_args.AsValue()->ToString();
272 obs->OnBeginFrame(missed_begin_frame_args_); 367 obs->OnBeginFrame(missed_begin_frame_args_);
273 } 368 }
274 } 369 }
275 } 370 }
276 371
277 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { 372 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) {
278 DCHECK(obs); 373 DCHECK(obs);
279 DCHECK(observers_.find(obs) != observers_.end()); 374 DCHECK(observers_.find(obs) != observers_.end());
280 375
281 observers_.erase(obs); 376 observers_.erase(obs);
377 ack_tracker_.OnObserverRemoved(obs);
378 MaybeFinishFrame();
282 if (observers_.empty()) { 379 if (observers_.empty()) {
283 missed_begin_frame_args_ = BeginFrameArgs(); 380 missed_begin_frame_args_ = BeginFrameArgs();
284 client_->OnNeedsBeginFrames(false); 381 client_->OnNeedsBeginFrames(false);
285 } 382 }
286 } 383 }
287 384
385 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs,
386 const BeginFrameAck& ack) {
387 ack_tracker_.OnObserverFinishedFrame(obs, ack);
388 MaybeFinishFrame();
389 }
390
288 bool ExternalBeginFrameSource::IsThrottled() const { 391 bool ExternalBeginFrameSource::IsThrottled() const {
289 return true; 392 return true;
290 } 393 }
291 394
292 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { 395 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) {
293 if (paused_ == paused) 396 if (paused_ == paused)
294 return; 397 return;
295 paused_ = paused; 398 paused_ = paused;
296 std::unordered_set<BeginFrameObserver*> observers(observers_); 399 std::unordered_set<BeginFrameObserver*> observers(observers_);
297 for (auto* obs : observers) 400 for (auto* obs : observers)
298 obs->OnBeginFrameSourcePausedChanged(paused_); 401 obs->OnBeginFrameSourcePausedChanged(paused_);
299 } 402 }
300 403
301 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { 404 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) {
405 if (frame_active_)
406 FinishFrame();
407
408 frame_active_ = true;
302 missed_begin_frame_args_ = args; 409 missed_begin_frame_args_ = args;
303 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; 410 missed_begin_frame_args_.type = BeginFrameArgs::MISSED;
411 ack_tracker_.OnBeginFrame(args);
304 std::unordered_set<BeginFrameObserver*> observers(observers_); 412 std::unordered_set<BeginFrameObserver*> observers(observers_);
305 for (auto* obs : observers) { 413 for (auto* obs : observers) {
306 // It is possible that the source in which |args| originate changes, or that 414 // It is possible that the source in which |args| originate changes, or that
307 // our hookup to this source changes, so we have to check for continuity. 415 // our hookup to this source changes, so we have to check for continuity.
308 // See also https://crbug.com/690127 for what may happen without this check. 416 // See also https://crbug.com/690127 for what may happen without this check.
309 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); 417 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
310 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) { 418 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) {
311 DCHECK((args.source_id != last_args.source_id) || 419 DCHECK((args.source_id != last_args.source_id) ||
312 (args.sequence_number > last_args.sequence_number)) 420 (args.sequence_number > last_args.sequence_number))
313 << "current " << args.AsValue()->ToString() << ", last " 421 << "current " << args.AsValue()->ToString() << ", last "
314 << last_args.AsValue()->ToString(); 422 << last_args.AsValue()->ToString();
315 obs->OnBeginFrame(args); 423 obs->OnBeginFrame(args);
316 } 424 }
317 } 425 }
426 MaybeFinishFrame();
427 }
428
429 void ExternalBeginFrameSource::MaybeFinishFrame() {
430 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame())
431 return;
432 FinishFrame();
433 }
434
435 void ExternalBeginFrameSource::FinishFrame() {
436 frame_active_ = false;
437
438 BeginFrameAck ack(missed_begin_frame_args_.source_id,
439 missed_begin_frame_args_.sequence_number,
440 ack_tracker_.LatestConfirmedSequenceNumber(), 0,
441 ack_tracker_.AnyObserversHadDamage());
442 client_->OnDidFinishFrame(ack);
318 } 443 }
319 444
320 } // namespace cc 445 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/begin_frame_source.h ('k') | cc/scheduler/begin_frame_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698