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

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

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: DisplayCompositorLockManager => SurfaceDependencyTracker. Added More 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
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/surfaces/surface.h" 5 #include "cc/surfaces/surface.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 11
12 #include "cc/base/container_util.h" 12 #include "cc/base/container_util.h"
13 #include "cc/output/compositor_frame.h" 13 #include "cc/output/compositor_frame.h"
14 #include "cc/output/copy_output_request.h" 14 #include "cc/output/copy_output_request.h"
15 #include "cc/surfaces/pending_frame_observer.h"
15 #include "cc/surfaces/surface_factory.h" 16 #include "cc/surfaces/surface_factory.h"
16 #include "cc/surfaces/surface_id_allocator.h" 17 #include "cc/surfaces/surface_id_allocator.h"
17 #include "cc/surfaces/surface_manager.h" 18 #include "cc/surfaces/surface_manager.h"
18 19
19 namespace cc { 20 namespace cc {
20 21
21 // The frame index starts at 2 so that empty frames will be treated as 22 // The frame index starts at 2 so that empty frames will be treated as
22 // completely damaged the first time they're drawn from. 23 // completely damaged the first time they're drawn from.
23 static const int kFrameIndexStart = 2; 24 static const int kFrameIndexStart = 2;
24 25
25 Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory) 26 Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory)
26 : surface_id_(id), 27 : surface_id_(id),
27 previous_frame_surface_id_(id), 28 previous_frame_surface_id_(id),
28 factory_(factory), 29 factory_(factory),
29 frame_index_(kFrameIndexStart), 30 frame_index_(kFrameIndexStart),
30 destroyed_(false) {} 31 destroyed_(false) {}
31 32
32 Surface::~Surface() { 33 Surface::~Surface() {
33 ClearCopyRequests(); 34 ClearCopyRequests();
34 if (current_frame_ && factory_) { 35 if (factory_) {
35 UnrefFrameResources(*current_frame_); 36 if (pending_frame_)
37 UnrefFrameResources(*pending_frame_);
38 if (active_frame_)
39 UnrefFrameResources(*active_frame_);
36 } 40 }
37 if (!draw_callback_.is_null()) 41 if (!draw_callback_.is_null())
38 draw_callback_.Run(); 42 draw_callback_.Run();
43
44 for (auto& observer : observers_)
45 observer.OnSurfaceDiscarded(this);
46 observers_.Clear();
39 } 47 }
40 48
41 void Surface::SetPreviousFrameSurface(Surface* surface) { 49 void Surface::SetPreviousFrameSurface(Surface* surface) {
42 DCHECK(surface); 50 DCHECK(surface);
43 frame_index_ = surface->frame_index() + 1; 51 frame_index_ = surface->frame_index() + 1;
44 previous_frame_surface_id_ = surface->surface_id(); 52 previous_frame_surface_id_ = surface->surface_id();
45 } 53 }
46 54
47 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { 55 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) {
vmpstr 2017/02/07 22:46:19 Can you extract the code between lines 60 and 96 t
Fady Samuel 2017/02/08 00:52:49 Done.
48 DCHECK(factory_); 56 base::Optional<CompositorFrame> previous_pending_frame =
49 ClearCopyRequests(); 57 std::move(pending_frame_);
58 pending_frame_.reset();
50 59
51 TakeLatencyInfo(&frame.metadata.latency_info); 60 std::unordered_set<SurfaceId, SurfaceIdHash> new_blocked_on_surfaces;
52 61
53 base::Optional<CompositorFrame> previous_frame = std::move(current_frame_); 62 for (const SurfaceId& surface_id : frame.metadata.referenced_surfaces) {
54 current_frame_ = std::move(frame); 63 Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
55 64 // If a referenced surface does not have a corresponding active frame in the
56 if (current_frame_) { 65 // display compositor, then it blocks this frame.
57 factory_->ReceiveFromChild(current_frame_->resource_list); 66 if (!surface || !surface->HasActiveFrame())
67 new_blocked_on_surfaces.insert(surface_id);
58 } 68 }
59 69
60 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't 70 // If this Surface has a previous pending frame, then we must determine the
61 // increment frame index for them. 71 // changes in dependencies so that we can update the
62 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 72 // DisplayCompositorLockManager map.
63 ++frame_index_; 73 if (previous_pending_frame.has_value()) {
74 SurfaceDependencies added_dependencies;
vmpstr 2017/02/07 22:46:19 move this to right before the second for loop plea
Fady Samuel 2017/02/08 00:52:49 Done.
75 SurfaceDependencies removed_dependencies;
76
77 for (const SurfaceId& surface_id : blocked_on_surfaces_) {
vmpstr 2017/02/07 22:46:19 If you use flat_sets which are ordered, then I thi
Fady Samuel 2017/02/08 00:52:49 I'll leave it as is for now.
78 if (!new_blocked_on_surfaces.count(surface_id))
79 removed_dependencies.insert(surface_id);
80 }
81
82 for (const SurfaceId& surface_id : new_blocked_on_surfaces) {
83 if (!blocked_on_surfaces_.count(surface_id))
84 added_dependencies.insert(surface_id);
85 }
86
87 // If there is a change in the dependency set, then inform observers.
88 if (!added_dependencies.empty() || !removed_dependencies.empty()) {
89 for (auto& observer : observers_) {
90 observer.OnSurfaceChanged(this, added_dependencies,
91 removed_dependencies);
92 }
93 }
64 } 94 }
65 95
66 previous_frame_surface_id_ = surface_id(); 96 blocked_on_surfaces_ = std::move(new_blocked_on_surfaces);
67 97
68 if (previous_frame) 98 if (!blocked_on_surfaces_.empty()) {
69 UnrefFrameResources(*previous_frame); 99 pending_frame_ = std::move(frame);
100 if (pending_frame_) {
101 factory_->ReceiveFromChild(pending_frame_->resource_list);
102 // Ask the surface manager to inform |this| when its dependencies are
103 // resolved.
104 factory_->manager()->RequestSurfaceResolution(this);
105 }
106 } else {
107 // If there are no blockers, then immediately activate the frame.
108 ActivateFrame(std::move(frame));
109 }
110
111 // Returns resources for the previous pending frame.
112 if (previous_pending_frame)
113 UnrefFrameResources(*previous_pending_frame);
70 114
71 if (!draw_callback_.is_null()) 115 if (!draw_callback_.is_null())
72 draw_callback_.Run(); 116 draw_callback_.Run();
73 draw_callback_ = callback; 117 draw_callback_ = callback;
74
75 referenced_surfaces_ = current_frame_->metadata.referenced_surfaces;
76 } 118 }
77 119
78 void Surface::EvictFrame() { 120 void Surface::EvictFrame() {
79 QueueFrame(CompositorFrame(), DrawCallback()); 121 QueueFrame(CompositorFrame(), DrawCallback());
80 current_frame_.reset(); 122 active_frame_.reset();
81 } 123 }
82 124
83 void Surface::RequestCopyOfOutput( 125 void Surface::RequestCopyOfOutput(
84 std::unique_ptr<CopyOutputRequest> copy_request) { 126 std::unique_ptr<CopyOutputRequest> copy_request) {
85 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 127 if (active_frame_ && !active_frame_->render_pass_list.empty()) {
vmpstr 2017/02/07 22:46:19 minor nit: while here, I think this would read bet
Fady Samuel 2017/02/08 00:52:49 Done.
86 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = 128 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
87 current_frame_->render_pass_list.back()->copy_requests; 129 active_frame_->render_pass_list.back()->copy_requests;
88 130
89 if (copy_request->has_source()) { 131 if (copy_request->has_source()) {
90 const base::UnguessableToken& source = copy_request->source(); 132 const base::UnguessableToken& source = copy_request->source();
91 // Remove existing CopyOutputRequests made on the Surface by the same 133 // Remove existing CopyOutputRequests made on the Surface by the same
92 // source. 134 // source.
93 auto to_remove = std::remove_if( 135 auto to_remove = std::remove_if(
94 copy_requests.begin(), copy_requests.end(), 136 copy_requests.begin(), copy_requests.end(),
95 [&source](const std::unique_ptr<CopyOutputRequest>& x) { 137 [&source](const std::unique_ptr<CopyOutputRequest>& x) {
96 return x->has_source() && x->source() == source; 138 return x->has_source() && x->source() == source;
97 }); 139 });
98 copy_requests.erase(to_remove, copy_requests.end()); 140 copy_requests.erase(to_remove, copy_requests.end());
99 } 141 }
100 copy_requests.push_back(std::move(copy_request)); 142 copy_requests.push_back(std::move(copy_request));
101 } else { 143 } else {
102 copy_request->SendEmptyResult(); 144 copy_request->SendEmptyResult();
103 } 145 }
104 } 146 }
105 147
148 void Surface::ReportSurfaceIdAvailable(const SurfaceId& surface_id) {
149 auto it = blocked_on_surfaces_.find(surface_id);
150 // This surface may no longer have blockers if the deadline has passed.
151 if (it == blocked_on_surfaces_.end())
152 return;
153
154 blocked_on_surfaces_.erase(it);
155
156 if (!blocked_on_surfaces_.empty())
157 return;
158
159 // All blockers have been cleared. The surface can be activated now.
160 ActivatePendingFrame();
vmpstr 2017/02/07 22:46:19 Are we guaranteed to have a pending frame at this
Fady Samuel 2017/02/08 00:52:49 We got this far, which means we had a blocker (and
161 }
162
163 void Surface::AddObserver(PendingFrameObserver* observer) {
164 observers_.AddObserver(observer);
165 }
166
167 void Surface::RemoveObserver(PendingFrameObserver* observer) {
168 observers_.RemoveObserver(observer);
169 }
170
171 void Surface::ActivatePendingFrameForDeadline() {
172 if (!pending_frame_ || !pending_frame_->metadata.respect_deadline)
173 return;
174
175 // If a frame is being activated because of a deadline, then clear its set
176 // of blockers.
177 blocked_on_surfaces_.clear();
178 ActivatePendingFrame();
179 }
180
181 void Surface::ActivatePendingFrame() {
182 ActivateFrame(std::move(pending_frame_.value()));
183 pending_frame_.reset();
184 // ActiveFrame resources are now double ref-ed. Unref.
185 UnrefFrameResources(*active_frame_);
186 }
187
188 void Surface::ActivateFrame(CompositorFrame frame) {
vmpstr 2017/02/07 22:46:19 Can you add a comment at the top of the function t
Fady Samuel 2017/02/08 00:52:49 Done.
189 DCHECK(factory_);
190 ClearCopyRequests();
191
192 TakeLatencyInfo(&frame.metadata.latency_info);
193
194 base::Optional<CompositorFrame> previous_frame = std::move(active_frame_);
195 active_frame_ = std::move(frame);
196
197 if (active_frame_)
vmpstr 2017/02/07 22:46:19 In what situations can we not have an active_frame
Fady Samuel 2017/02/08 00:52:49 Heh, We just set the active_frame_ so we should ha
198 factory_->ReceiveFromChild(active_frame_->resource_list);
199
200 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
201 // increment frame index for them.
202 if (active_frame_ && !active_frame_->render_pass_list.empty())
203 ++frame_index_;
204
205 previous_frame_surface_id_ = surface_id();
206
207 if (previous_frame)
208 UnrefFrameResources(*previous_frame);
209
210 referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
211
212 for (auto& observer : observers_)
213 observer.OnSurfaceActivated(this);
214 }
215
106 void Surface::TakeCopyOutputRequests( 216 void Surface::TakeCopyOutputRequests(
107 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { 217 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) {
108 DCHECK(copy_requests->empty()); 218 DCHECK(copy_requests->empty());
109 if (current_frame_) { 219 if (active_frame_) {
vmpstr 2017/02/07 22:46:19 nit: if (!active_frame_) return; ...
Fady Samuel 2017/02/08 00:52:49 Done.
110 for (const auto& render_pass : current_frame_->render_pass_list) { 220 for (const auto& render_pass : active_frame_->render_pass_list) {
111 for (auto& request : render_pass->copy_requests) { 221 for (auto& request : render_pass->copy_requests) {
112 copy_requests->insert( 222 copy_requests->insert(
113 std::make_pair(render_pass->id, std::move(request))); 223 std::make_pair(render_pass->id, std::move(request)));
114 } 224 }
115 render_pass->copy_requests.clear(); 225 render_pass->copy_requests.clear();
116 } 226 }
117 } 227 }
118 } 228 }
119 229
120 const CompositorFrame& Surface::GetEligibleFrame() const { 230 const CompositorFrame& Surface::GetActiveFrame() const {
121 DCHECK(current_frame_); 231 DCHECK(active_frame_);
122 return current_frame_.value(); 232 return active_frame_.value();
233 }
234
235 const CompositorFrame& Surface::GetPendingFrame() {
236 DCHECK(pending_frame_);
237 return pending_frame_.value();
123 } 238 }
124 239
125 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { 240 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
126 if (!current_frame_) 241 if (!active_frame_)
127 return; 242 return;
128 if (latency_info->empty()) { 243 if (latency_info->empty()) {
129 current_frame_->metadata.latency_info.swap(*latency_info); 244 active_frame_->metadata.latency_info.swap(*latency_info);
130 return; 245 return;
131 } 246 }
132 std::copy(current_frame_->metadata.latency_info.begin(), 247 std::copy(active_frame_->metadata.latency_info.begin(),
133 current_frame_->metadata.latency_info.end(), 248 active_frame_->metadata.latency_info.end(),
134 std::back_inserter(*latency_info)); 249 std::back_inserter(*latency_info));
135 current_frame_->metadata.latency_info.clear(); 250 active_frame_->metadata.latency_info.clear();
136 } 251 }
137 252
138 void Surface::RunDrawCallbacks() { 253 void Surface::RunDrawCallbacks() {
139 if (!draw_callback_.is_null()) { 254 if (!draw_callback_.is_null()) {
140 DrawCallback callback = draw_callback_; 255 DrawCallback callback = draw_callback_;
141 draw_callback_ = DrawCallback(); 256 draw_callback_ = DrawCallback();
142 callback.Run(); 257 callback.Run();
143 } 258 }
144 } 259 }
145 260
(...skipping 17 matching lines...) Expand all
163 void Surface::UnrefFrameResources(const CompositorFrame& frame) { 278 void Surface::UnrefFrameResources(const CompositorFrame& frame) {
164 ReturnedResourceArray resources; 279 ReturnedResourceArray resources;
165 TransferableResource::ReturnResources(frame.resource_list, &resources); 280 TransferableResource::ReturnResources(frame.resource_list, &resources);
166 // No point in returning same sync token to sender. 281 // No point in returning same sync token to sender.
167 for (auto& resource : resources) 282 for (auto& resource : resources)
168 resource.sync_token.Clear(); 283 resource.sync_token.Clear();
169 factory_->UnrefResources(resources); 284 factory_->UnrefResources(resources);
170 } 285 }
171 286
172 void Surface::ClearCopyRequests() { 287 void Surface::ClearCopyRequests() {
173 if (current_frame_) { 288 if (active_frame_) {
174 for (const auto& render_pass : current_frame_->render_pass_list) { 289 for (const auto& render_pass : active_frame_->render_pass_list) {
175 for (const auto& copy_request : render_pass->copy_requests) 290 for (const auto& copy_request : render_pass->copy_requests)
176 copy_request->SendEmptyResult(); 291 copy_request->SendEmptyResult();
177 } 292 }
178 } 293 }
179 } 294 }
180 295
181 } // namespace cc 296 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698