1 // Copyright 2020 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/metrics/dropped_frame_counter.h"
6
7 #include "base/bind.h"
8 #include "base/trace_event/trace_event.h"
9 #include "cc/metrics/frame_sorter.h"
10 #include "cc/metrics/total_frame_counter.h"
11 #include "cc/metrics/ukm_smoothness_data.h"
12
13 namespace cc {
14
DroppedFrameCounter()15 DroppedFrameCounter::DroppedFrameCounter()
16 : frame_sorter_(base::BindRepeating(&DroppedFrameCounter::NotifyFrameResult,
17 base::Unretained(this))) {}
18 DroppedFrameCounter::~DroppedFrameCounter() = default;
19
GetAverageThroughput() const20 uint32_t DroppedFrameCounter::GetAverageThroughput() const {
21 size_t good_frames = 0;
22 for (auto it = --end(); it; --it) {
23 if (**it == kFrameStateComplete)
24 ++good_frames;
25 }
26 double throughput = 100. * good_frames / ring_buffer_.BufferSize();
27 return static_cast<uint32_t>(throughput);
28 }
29
AddGoodFrame()30 void DroppedFrameCounter::AddGoodFrame() {
31 ring_buffer_.SaveToBuffer(kFrameStateComplete);
32 ++total_frames_;
33 }
34
AddPartialFrame()35 void DroppedFrameCounter::AddPartialFrame() {
36 ring_buffer_.SaveToBuffer(kFrameStatePartial);
37 ++total_frames_;
38 ++total_partial_;
39 }
40
AddDroppedFrame()41 void DroppedFrameCounter::AddDroppedFrame() {
42 ring_buffer_.SaveToBuffer(kFrameStateDropped);
43 ++total_frames_;
44 ++total_dropped_;
45 }
46
ResetFrameSorter()47 void DroppedFrameCounter::ResetFrameSorter() {
48 frame_sorter_.Reset();
49 }
50
OnBeginFrame(const viz::BeginFrameArgs & args)51 void DroppedFrameCounter::OnBeginFrame(const viz::BeginFrameArgs& args) {
52 if (fcp_received_)
53 frame_sorter_.AddNewFrame(args);
54 }
55
OnEndFrame(const viz::BeginFrameArgs & args,bool is_dropped)56 void DroppedFrameCounter::OnEndFrame(const viz::BeginFrameArgs& args,
57 bool is_dropped) {
58 if (is_dropped) {
59 if (fcp_received_)
60 ++total_smoothness_dropped_;
61 ReportFrames();
62 }
63
64 if (fcp_received_)
65 frame_sorter_.AddFrameResult(args, is_dropped);
66 }
67
ReportFrames()68 void DroppedFrameCounter::ReportFrames() {
69 const auto total_frames =
70 total_counter_->ComputeTotalVisibleFrames(base::TimeTicks::Now());
71 TRACE_EVENT2("cc,benchmark", "SmoothnessDroppedFrame", "total", total_frames,
72 "smoothness", total_smoothness_dropped_);
73
74 if (ukm_smoothness_data_ && total_frames > 0) {
75 UkmSmoothnessData smoothness_data;
76 smoothness_data.avg_smoothness =
77 static_cast<double>(total_smoothness_dropped_) * 100 / total_frames;
78
79 ukm_smoothness_data_->seq_lock.WriteBegin();
80 device::OneWriterSeqLock::AtomicWriterMemcpy(&ukm_smoothness_data_->data,
81 &smoothness_data,
82 sizeof(UkmSmoothnessData));
83 ukm_smoothness_data_->seq_lock.WriteEnd();
84 }
85 }
86
SetUkmSmoothnessDestination(UkmSmoothnessDataShared * smoothness_data)87 void DroppedFrameCounter::SetUkmSmoothnessDestination(
88 UkmSmoothnessDataShared* smoothness_data) {
89 ukm_smoothness_data_ = smoothness_data;
90 }
91
Reset()92 void DroppedFrameCounter::Reset() {
93 total_frames_ = 0;
94 total_partial_ = 0;
95 total_dropped_ = 0;
96 total_smoothness_dropped_ = 0;
97 fcp_received_ = false;
98 ring_buffer_.Clear();
99 frame_sorter_.Reset();
100 }
101
NotifyFrameResult(const viz::BeginFrameArgs & args,bool is_dropped)102 void DroppedFrameCounter::NotifyFrameResult(const viz::BeginFrameArgs& args,
103 bool is_dropped) {
104 // TODO(crbug.com/1115141) The implementation of smoothness metrics.
105 }
106
OnFcpReceived()107 void DroppedFrameCounter::OnFcpReceived() {
108 fcp_received_ = true;
109 }
110
111 } // namespace cc
112