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

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

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: Use base::flat_set 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
OLDNEW
(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/surface_dependency_tracker.h"
6
7 #include "cc/surfaces/surface.h"
8 #include "cc/surfaces/surface_info.h"
9 #include "cc/surfaces/surface_manager.h"
10
11 namespace cc {
12
13 namespace {
14 constexpr uint32_t kMaxBeginFrameCount = 4;
15 }
16
17 SurfaceDependencyTracker::SurfaceDependencyTracker(
18 SurfaceManager* surface_manager,
19 BeginFrameSource* begin_frame_source)
20 : surface_manager_(surface_manager),
21 begin_frame_source_(begin_frame_source) {
22 surface_manager_->AddObserver(this);
23 begin_frame_source_->AddObserver(this);
24 }
25
26 SurfaceDependencyTracker::~SurfaceDependencyTracker() {
27 surface_manager_->RemoveObserver(this);
28 begin_frame_source_->RemoveObserver(this);
29 }
30
31 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
32 DCHECK(surface->HasPendingFrame());
33
34 const CompositorFrame& pending_frame = surface->GetPendingFrame();
35 bool needs_begin_frame =
36 pending_frame.metadata.can_activate_without_dependencies;
vmpstr 2017/02/08 19:25:40 oh, maybe "can_activate_before_dependencies" :D
Fady Samuel 2017/02/08 23:39:58 Done.
37
38 // Referenced surface IDs that aren't currently known to the surface manager
39 // or do not have an active CompsotiorFrame block this frame.
40 for (const SurfaceId& surface_id :
41 pending_frame.metadata.referenced_surfaces) {
42 Surface* surface_dep = surface_manager_->GetSurfaceForId(surface_id);
vmpstr 2017/02/08 19:25:39 s/surface_dep/dependency/
Fady Samuel 2017/02/08 23:39:58 Done.
43 if (!surface_dep || !surface_dep->HasActiveFrame())
44 blocking_surfaces_[surface_id].insert(surface);
vmpstr 2017/02/08 19:25:40 this to me says if the dependency isn't satisfied,
Fady Samuel 2017/02/08 23:39:58 If the dependency isn't satisfied, then it blocks
45 }
46
47 if (!pending_surfaces_.count(surface)) {
48 surface->AddObserver(this);
49 pending_surfaces_.insert(surface);
50 }
51
52 if (needs_begin_frame) {
vmpstr 2017/02/08 19:25:40 When can RequestSurfaceResolution be called? My wo
Fady Samuel 2017/02/08 23:39:58 Done.
53 has_deadline_ = true;
54 begin_frame_count_ = 0;
55 }
56 }
57
58 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
59 // If no deadline is set then we have nothing to do.
60 if (!has_deadline_)
61 return;
62
63 // TODO(fsamuel, kylechar): We have a single global deadline here. We should
64 // scope deadlines to surface subtrees. We cannot do that until
65 // SurfaceReferences have been fully implemented
66 // (see https://crbug.com/689719).
67 last_begin_frame_args_ = args;
68 // Nothing to do if we haven't hit a deadline yet.
69 if (++begin_frame_count_ != kMaxBeginFrameCount)
70 return;
71
72 // Activate all surfaces that respect the deadline.
73 PendingSurfaceSet pending_surfaces(pending_surfaces_);
74 for (Surface* pending_surface : pending_surfaces)
75 pending_surface->ActivatePendingFrameForDeadline();
76
77 has_deadline_ = false;
78 begin_frame_count_ = 0;
vmpstr 2017/02/08 19:25:39 You might hate the idea, but having a bool and an
Fady Samuel 2017/02/08 23:39:58 added base::Optional<uint32_t> frames_since_deadli
79 }
80
81 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const {
82 return last_begin_frame_args_;
83 }
84
85 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {}
86
87 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
88 // If the surface being destroyed doesn't have a pending frame then we have
89 // nothing to do here.
90 if (!surface->HasPendingFrame())
91 return;
92
93 const CompositorFrame& pending_frame = surface->GetPendingFrame();
94
95 DCHECK(!pending_frame.metadata.referenced_surfaces.empty());
96
97 for (const SurfaceId& surface_id :
98 pending_frame.metadata.referenced_surfaces) {
99 auto it = blocking_surfaces_.find(surface_id);
100 if (it == blocking_surfaces_.end())
101 continue;
102
103 auto& pending_surface_set = it->second;
104 auto pending_surface_it = pending_surface_set.find(surface);
105 if (pending_surface_it != pending_surface_set.end()) {
106 pending_surface_set.erase(surface);
107 if (pending_surface_set.empty())
108 blocking_surfaces_.erase(surface_id);
109 }
110 }
111
112 if (blocking_surfaces_.empty()) {
113 has_deadline_ = false;
114 begin_frame_count_ = 0;
115 }
116
117 pending_surfaces_.erase(surface);
118 surface->RemoveObserver(this);
119
120 // TODO(fsamuel): We should consider removing this surface as a dependency on
121 // other surfaces. This dependency will be removed when the deadline hits
122 // anyway but maybe we should try to actiate these frames early (see
123 // https://crbug.com/689725).
124 }
125
126 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
127 surface->RemoveObserver(this);
128 pending_surfaces_.erase(surface);
129 NotifySurfaceIdAvailable(surface->surface_id());
130 }
131
132 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged(
133 Surface* surface,
134 const SurfaceDependencies& added_dependencies,
135 const SurfaceDependencies& removed_dependencies) {
136 // Update the |blocking_surfaces_| map with the changes in dependencies.
137 for (const SurfaceId& surface_id : added_dependencies)
138 blocking_surfaces_[surface_id].insert(surface);
139
140 for (const SurfaceId& surface_id : removed_dependencies) {
141 auto it = blocking_surfaces_.find(surface_id);
142 it->second.erase(surface);
143 if (it->second.empty())
144 blocking_surfaces_.erase(it);
145 }
146
147 // If there are no more dependencies to resolve then we don't need to have a
148 // deadline.
149 if (blocking_surfaces_.empty()) {
150 has_deadline_ = false;
151 begin_frame_count_ = 0;
152 }
153 }
154
155 // SurfaceObserver implementation:
156 void SurfaceDependencyTracker::OnSurfaceCreated(
157 const SurfaceInfo& surface_info) {
158 // This is called when a Surface has an activated frame for the first time.
159 // SurfaceDependencyTracker only observes Surfaces that contain pending
160 // frames. SurfaceDependencyTracker becomes aware of CompositorFrames that
161 // activate immediately go through here.
162 NotifySurfaceIdAvailable(surface_info.id());
163 }
164
165 void SurfaceDependencyTracker::OnSurfaceDamaged(const SurfaceId& surface_id,
166 bool* changed) {}
167
168 void SurfaceDependencyTracker::NotifySurfaceIdAvailable(
169 const SurfaceId& surface_id) {
170 auto it = blocking_surfaces_.find(surface_id);
171 if (it == blocking_surfaces_.end())
172 return;
173
174 // Unblock surfaces that depend on this pending surface.
175 PendingSurfaceSet blocked_pending_surface_set(it->second);
176 blocking_surfaces_.erase(it);
177 // If there are no more blockers in the system, then we no longer need to
178 // have a deadline.
179 if (blocking_surfaces_.empty()) {
180 has_deadline_ = false;
181 begin_frame_count_ = 0;
182 }
183
184 // Tell each surface about the availability of its blocker.
185 for (Surface* blocked_pending_surface : blocked_pending_surface_set)
186 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id);
187 }
188
189 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698