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

Side by Side Diff: cc/surfaces/surface_dependency_tracker.cc

Issue 2789163002: [cc] Acknowledge BeginFrames in SurfaceDependencyTracker. (Closed)
Patch Set: fix nits Created 3 years, 8 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/surfaces/surface_dependency_tracker.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 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/surfaces/surface_dependency_tracker.h" 5 #include "cc/surfaces/surface_dependency_tracker.h"
6 6
7 #include "cc/surfaces/surface.h" 7 #include "cc/surfaces/surface.h"
8 #include "cc/surfaces/surface_info.h" 8 #include "cc/surfaces/surface_info.h"
9 #include "cc/surfaces/surface_manager.h" 9 #include "cc/surfaces/surface_manager.h"
10 10
11 namespace cc { 11 namespace cc {
12 12
13 namespace { 13 namespace {
14 constexpr uint32_t kMaxBeginFrameCount = 4; 14 constexpr uint32_t kMaxBeginFrameCount = 4;
15 } 15 }
16 16
17 SurfaceDependencyTracker::SurfaceDependencyTracker( 17 SurfaceDependencyTracker::SurfaceDependencyTracker(
18 SurfaceManager* surface_manager, 18 SurfaceManager* surface_manager,
19 BeginFrameSource* begin_frame_source) 19 BeginFrameSource* begin_frame_source)
20 : surface_manager_(surface_manager), 20 : surface_manager_(surface_manager),
21 begin_frame_source_(begin_frame_source) { 21 begin_frame_source_(begin_frame_source) {
22 surface_manager_->AddObserver(this); 22 surface_manager_->AddObserver(this);
23 begin_frame_source_->AddObserver(this);
24 } 23 }
25 24
26 SurfaceDependencyTracker::~SurfaceDependencyTracker() { 25 SurfaceDependencyTracker::~SurfaceDependencyTracker() {
27 surface_manager_->RemoveObserver(this); 26 surface_manager_->RemoveObserver(this);
28 begin_frame_source_->RemoveObserver(this);
29 for (Surface* pending_surface : pending_surfaces_) 27 for (Surface* pending_surface : pending_surfaces_)
30 pending_surface->RemoveObserver(this); 28 pending_surface->RemoveObserver(this);
31 pending_surfaces_.clear(); 29 pending_surfaces_.clear();
30 UpdateNeedsBeginFrames(); // Stop observing the BeginFrameSource.
32 } 31 }
33 32
34 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { 33 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
35 DCHECK(surface->HasPendingFrame()); 34 DCHECK(surface->HasPendingFrame());
36 35
37 const CompositorFrame& pending_frame = surface->GetPendingFrame(); 36 const CompositorFrame& pending_frame = surface->GetPendingFrame();
38 bool needs_begin_frame = 37 bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies;
39 pending_frame.metadata.can_activate_before_dependencies;
40 38
41 // Referenced surface IDs that aren't currently known to the surface manager 39 // Referenced surface IDs that aren't currently known to the surface manager
42 // or do not have an active CompsotiorFrame block this frame. 40 // or do not have an active CompsotiorFrame block this frame.
43 for (const SurfaceId& surface_id : 41 for (const SurfaceId& surface_id :
44 pending_frame.metadata.referenced_surfaces) { 42 pending_frame.metadata.referenced_surfaces) {
45 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); 43 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id);
46 if (!surface_dependency || !surface_dependency->HasActiveFrame()) 44 if (!surface_dependency || !surface_dependency->HasActiveFrame())
47 blocked_surfaces_[surface_id].insert(surface); 45 blocked_surfaces_[surface_id].insert(surface);
48 } 46 }
49 47
50 if (!pending_surfaces_.count(surface)) { 48 if (!pending_surfaces_.count(surface)) {
51 surface->AddObserver(this); 49 surface->AddObserver(this);
52 pending_surfaces_.insert(surface); 50 pending_surfaces_.insert(surface);
53 } 51 }
54 52
55 if (needs_begin_frame && !frames_since_deadline_set_) 53 if (needs_deadline && !frames_since_deadline_set_)
56 frames_since_deadline_set_ = 0; 54 frames_since_deadline_set_ = 0;
55
56 // |pending_surfaces_| changed.
57 UpdateNeedsBeginFrames();
58 }
59
60 void SurfaceDependencyTracker::UpdateNeedsBeginFrames() {
61 // We observe while there are pending surfaces, even if we don't have a
62 // deadline set. This way, we can send BeginFrameAcks on behalf of the
63 // pending CompositorFrames.
64 bool needs_begin_frames = !pending_surfaces_.empty();
65
66 if (needs_begin_frames_ == needs_begin_frames)
67 return;
68 needs_begin_frames_ = needs_begin_frames;
69
70 if (needs_begin_frames_)
71 begin_frame_source_->AddObserver(this);
72 else
73 begin_frame_source_->RemoveObserver(this);
57 } 74 }
58 75
59 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { 76 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
77 // We only acknowledge the BeginFrame if and when all pending frames have
78 // been activated. While there are pending frames, we will not acknowledge the
79 // BeginFrame. This way, we indicate to the BeginFrameSource that we are still
80 // waiting on blockers to resolve and that the
81 // |latest_confirmed_sequence_number| of each pending frame is not integrated
82 // into any display frame produced before their activation.
83 //
84 // While we are not acknowledging, the BeginFrameSource will use the sequence
85 // number of the last BeginFrame that we did not receive as our
86 // latest_confirmed_sequence_number. This may not be completely accurate (a
87 // pending frame may include older updates), but it is as good as we can get,
88 // since we cannot retroactively unconfirm BeginFrames that we didn't receive.
89
60 // If no deadline is set then we have nothing to do. 90 // If no deadline is set then we have nothing to do.
61 if (!frames_since_deadline_set_) 91 if (!frames_since_deadline_set_)
62 return; 92 return;
63 93
94 if (args.source_id == last_begin_frame_args_.source_id &&
95 args.sequence_number == last_begin_frame_args_.sequence_number) {
96 // We've seen this BeginFrame already.
97 return;
98 }
99
64 // TODO(fsamuel, kylechar): We have a single global deadline here. We should 100 // TODO(fsamuel, kylechar): We have a single global deadline here. We should
65 // scope deadlines to surface subtrees. We cannot do that until 101 // scope deadlines to surface subtrees. We cannot do that until
66 // SurfaceReferences have been fully implemented 102 // SurfaceReferences have been fully implemented
67 // (see https://crbug.com/689719). 103 // (see https://crbug.com/689719).
68 last_begin_frame_args_ = args; 104 last_begin_frame_args_ = args;
69 // Nothing to do if we haven't hit a deadline yet. 105 // Nothing to do if we haven't hit a deadline yet.
70 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) 106 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount)
71 return; 107 return;
72 108
73 // Activate all surfaces that respect the deadline. 109 // Activate all surfaces that respect the deadline.
74 PendingSurfaceSet pending_surfaces(pending_surfaces_); 110 PendingSurfaceSet pending_surfaces(pending_surfaces_);
75 for (Surface* pending_surface : pending_surfaces) 111 for (Surface* pending_surface : pending_surfaces)
76 pending_surface->ActivatePendingFrameForDeadline(); 112 pending_surface->ActivatePendingFrameForDeadline();
77 113
78 frames_since_deadline_set_.reset(); 114 frames_since_deadline_set_.reset();
79 } 115 }
80 116
81 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { 117 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const {
82 return last_begin_frame_args_; 118 // Return invalid args, so that we receive the same BeginFrame multiple times
119 // if we start observing BeginFrames again during the same BeginFrame: Even if
120 // we already received and acknowledged a BeginFrame before, we want to
121 // acknowledge it again on behalf of any newly added pending surfaces.
122 static BeginFrameArgs args;
123 return args;
83 } 124 }
84 125
85 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} 126 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {}
86 127
128 void SurfaceDependencyTracker::AcknowledgeLastBeginFrame() {
129 DCHECK(needs_begin_frames_);
130 // TODO(eseckler): By not acking while a pending surface exist, we will
131 // prevent early deadlines in DisplayScheduler, see https://crbug.com/707513.
132 // Maybe there's a way to detect when it is unlikely/impossible for blockers
133 // to resolve during the current BeginFrame.
134 DCHECK(pending_surfaces_.empty());
135
136 // Some clients submit CompositorFrames without prior BeginFrames.
137 if (!last_begin_frame_args_.IsValid())
138 return;
139
140 begin_frame_source_->DidFinishFrame(
141 this, BeginFrameAck(last_begin_frame_args_.source_id,
142 last_begin_frame_args_.sequence_number,
143 last_begin_frame_args_.sequence_number, true));
144 }
145
87 void SurfaceDependencyTracker::OnReferencedSurfacesChanged( 146 void SurfaceDependencyTracker::OnReferencedSurfacesChanged(
88 Surface* surface, 147 Surface* surface,
89 const std::vector<SurfaceId>* active_referenced_surfaces, 148 const std::vector<SurfaceId>* active_referenced_surfaces,
90 const std::vector<SurfaceId>* pending_referenced_surfaces) {} 149 const std::vector<SurfaceId>* pending_referenced_surfaces) {}
91 150
92 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { 151 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
93 // If the surface being destroyed doesn't have a pending frame then we have 152 // If the surface being destroyed doesn't have a pending frame then we have
94 // nothing to do here. 153 // nothing to do here.
95 if (!surface->HasPendingFrame()) 154 if (!surface->HasPendingFrame())
96 return; 155 return;
(...skipping 13 matching lines...) Expand all
110 if (pending_surface_it != pending_surface_set.end()) { 169 if (pending_surface_it != pending_surface_set.end()) {
111 pending_surface_set.erase(surface); 170 pending_surface_set.erase(surface);
112 if (pending_surface_set.empty()) 171 if (pending_surface_set.empty())
113 blocked_surfaces_.erase(surface_id); 172 blocked_surfaces_.erase(surface_id);
114 } 173 }
115 } 174 }
116 175
117 if (blocked_surfaces_.empty()) 176 if (blocked_surfaces_.empty())
118 frames_since_deadline_set_.reset(); 177 frames_since_deadline_set_.reset();
119 178
120 pending_surfaces_.erase(surface); 179 DCHECK(!pending_surfaces_.empty());
180 DCHECK(pending_surfaces_.erase(surface));
121 surface->RemoveObserver(this); 181 surface->RemoveObserver(this);
122 182
183 if (pending_surfaces_.empty())
184 AcknowledgeLastBeginFrame();
185 // |pending_surfaces_| changed.
186 UpdateNeedsBeginFrames();
123 // Pretend that the discarded surface's SurfaceId is now available to unblock 187 // Pretend that the discarded surface's SurfaceId is now available to unblock
124 // dependencies because we now know the surface will never activate. 188 // dependencies because we now know the surface will never activate.
125 NotifySurfaceIdAvailable(surface->surface_id()); 189 NotifySurfaceIdAvailable(surface->surface_id());
126 } 190 }
127 191
128 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { 192 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
129 surface->RemoveObserver(this); 193 surface->RemoveObserver(this);
130 pending_surfaces_.erase(surface); 194 DCHECK(!pending_surfaces_.empty());
195 DCHECK(pending_surfaces_.erase(surface));
196
197 if (pending_surfaces_.empty())
198 AcknowledgeLastBeginFrame();
199 // |pending_surfaces_| changed.
200 UpdateNeedsBeginFrames();
131 NotifySurfaceIdAvailable(surface->surface_id()); 201 NotifySurfaceIdAvailable(surface->surface_id());
132 } 202 }
133 203
134 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( 204 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged(
135 Surface* surface, 205 Surface* surface,
136 const SurfaceDependencies& added_dependencies, 206 const SurfaceDependencies& added_dependencies,
137 const SurfaceDependencies& removed_dependencies) { 207 const SurfaceDependencies& removed_dependencies) {
138 // Update the |blocked_surfaces_| map with the changes in dependencies. 208 // Update the |blocked_surfaces_| map with the changes in dependencies.
139 for (const SurfaceId& surface_id : added_dependencies) 209 for (const SurfaceId& surface_id : added_dependencies)
140 blocked_surfaces_[surface_id].insert(surface); 210 blocked_surfaces_[surface_id].insert(surface);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 // have a deadline. 248 // have a deadline.
179 if (blocked_surfaces_.empty()) 249 if (blocked_surfaces_.empty())
180 frames_since_deadline_set_.reset(); 250 frames_since_deadline_set_.reset();
181 251
182 // Tell each surface about the availability of its blocker. 252 // Tell each surface about the availability of its blocker.
183 for (Surface* blocked_pending_surface : blocked_pending_surface_set) 253 for (Surface* blocked_pending_surface : blocked_pending_surface_set)
184 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); 254 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id);
185 } 255 }
186 256
187 } // namespace cc 257 } // namespace cc
OLDNEW
« no previous file with comments | « cc/surfaces/surface_dependency_tracker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698