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

Side by Side Diff: cc/surfaces/surface.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
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) {
48 DCHECK(factory_); 56 base::Optional<CompositorFrame> previous_pending_frame =
49 ClearCopyRequests(); 57 std::move(pending_frame_);
50 58 pending_frame_.reset();
51 TakeLatencyInfo(&frame.metadata.latency_info); 59
52 60 UpdateBlockingSurfaces(previous_pending_frame, frame);
53 base::Optional<CompositorFrame> previous_frame = std::move(current_frame_); 61
54 current_frame_ = std::move(frame); 62 if (!blocking_surfaces_.empty()) {
55 63 pending_frame_ = std::move(frame);
56 if (current_frame_) { 64 if (pending_frame_) {
57 factory_->ReceiveFromChild(current_frame_->resource_list); 65 factory_->ReceiveFromChild(pending_frame_->resource_list);
58 } 66 // Ask the surface manager to inform |this| when its dependencies are
59 67 // resolved.
60 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't 68 factory_->manager()->RequestSurfaceResolution(this);
61 // increment frame index for them. 69 }
62 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 70 } else {
63 ++frame_index_; 71 // If there are no blockers, then immediately activate the frame.
64 } 72 ActivateFrame(std::move(frame));
65 73 }
66 previous_frame_surface_id_ = surface_id(); 74
67 75 // Returns resources for the previous pending frame.
68 if (previous_frame) 76 if (previous_pending_frame)
69 UnrefFrameResources(*previous_frame); 77 UnrefFrameResources(*previous_pending_frame);
70 78
71 if (!draw_callback_.is_null()) 79 if (!draw_callback_.is_null())
72 draw_callback_.Run(); 80 draw_callback_.Run();
73 draw_callback_ = callback; 81 draw_callback_ = callback;
74
75 referenced_surfaces_ = current_frame_->metadata.referenced_surfaces;
76 } 82 }
77 83
78 void Surface::EvictFrame() { 84 void Surface::EvictFrame() {
79 QueueFrame(CompositorFrame(), DrawCallback()); 85 QueueFrame(CompositorFrame(), DrawCallback());
80 current_frame_.reset(); 86 active_frame_.reset();
81 } 87 }
82 88
83 void Surface::RequestCopyOfOutput( 89 void Surface::RequestCopyOfOutput(
84 std::unique_ptr<CopyOutputRequest> copy_request) { 90 std::unique_ptr<CopyOutputRequest> copy_request) {
85 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 91 if (!active_frame_ || active_frame_->render_pass_list.empty()) {
86 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
87 current_frame_->render_pass_list.back()->copy_requests;
88
89 if (copy_request->has_source()) {
90 const base::UnguessableToken& source = copy_request->source();
91 // Remove existing CopyOutputRequests made on the Surface by the same
92 // source.
93 auto to_remove = std::remove_if(
94 copy_requests.begin(), copy_requests.end(),
95 [&source](const std::unique_ptr<CopyOutputRequest>& x) {
96 return x->has_source() && x->source() == source;
97 });
98 copy_requests.erase(to_remove, copy_requests.end());
99 }
100 copy_requests.push_back(std::move(copy_request));
101 } else {
102 copy_request->SendEmptyResult(); 92 copy_request->SendEmptyResult();
103 } 93 return;
94 }
95
96 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
97 active_frame_->render_pass_list.back()->copy_requests;
98
99 if (copy_request->has_source()) {
100 const base::UnguessableToken& source = copy_request->source();
101 // Remove existing CopyOutputRequests made on the Surface by the same
102 // source.
103 auto to_remove =
104 std::remove_if(copy_requests.begin(), copy_requests.end(),
105 [&source](const std::unique_ptr<CopyOutputRequest>& x) {
106 return x->has_source() && x->source() == source;
107 });
108 copy_requests.erase(to_remove, copy_requests.end());
109 }
110 copy_requests.push_back(std::move(copy_request));
111 }
112
113 void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) {
114 auto it = blocking_surfaces_.find(surface_id);
115 // This surface may no longer have blockers if the deadline has passed.
116 if (it == blocking_surfaces_.end())
117 return;
118
119 blocking_surfaces_.erase(it);
120
121 if (!blocking_surfaces_.empty())
122 return;
123
124 // All blockers have been cleared. The surface can be activated now.
125 ActivatePendingFrame();
126 }
127
128 void Surface::AddObserver(PendingFrameObserver* observer) {
129 observers_.AddObserver(observer);
130 }
131
132 void Surface::RemoveObserver(PendingFrameObserver* observer) {
133 observers_.RemoveObserver(observer);
134 }
135
136 void Surface::ActivatePendingFrameForDeadline() {
137 if (!pending_frame_ ||
138 !pending_frame_->metadata.can_activate_without_dependencies)
vmpstr 2017/02/08 19:25:39 nit: braces pls
Fady Samuel 2017/02/08 23:39:57 Done.
139 return;
140
141 // If a frame is being activated because of a deadline, then clear its set
142 // of blockers.
143 blocking_surfaces_.clear();
144 ActivatePendingFrame();
145 }
146
147 void Surface::ActivatePendingFrame() {
148 DCHECK(!!pending_frame_);
vmpstr 2017/02/08 19:25:39 just DCHECK(pending_frame_) is good I think? Or do
Fady Samuel 2017/02/08 23:39:57 Done.
149 ActivateFrame(std::move(pending_frame_.value()));
150 pending_frame_.reset();
151 // ActiveFrame resources are now double ref-ed. Unref.
152 UnrefFrameResources(*active_frame_);
153 }
154
155 // A frame is activated if all its Surface ID dependences are active or a
156 // deadline has hit and the frame was forcibly activated by the display
157 // compositor.
158 void Surface::ActivateFrame(CompositorFrame frame) {
159 DCHECK(factory_);
160 ClearCopyRequests();
161
162 TakeLatencyInfo(&frame.metadata.latency_info);
163
164 base::Optional<CompositorFrame> previous_frame = std::move(active_frame_);
165 active_frame_ = std::move(frame);
166
167 factory_->ReceiveFromChild(active_frame_->resource_list);
168
169 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
170 // increment frame index for them.
171 if (!active_frame_->render_pass_list.empty())
172 ++frame_index_;
173
174 previous_frame_surface_id_ = surface_id();
175
176 if (previous_frame)
177 UnrefFrameResources(*previous_frame);
178
179 referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
180
181 for (auto& observer : observers_)
182 observer.OnSurfaceActivated(this);
183 }
184
185 void Surface::UpdateBlockingSurfaces(
186 const base::Optional<CompositorFrame>& previous_pending_frame,
187 const CompositorFrame& current_frame) {
188 // If there is no SurfaceDependencyTracker installed then the |current_frame|
189 // does not block on anything.
190 if (!factory_->manager()->dependency_tracker()) {
vmpstr 2017/02/08 19:25:39 Does this also imply that there are no observers_?
Fady Samuel 2017/02/08 23:39:58 Only SurfaceDependencyTracker cares about SurfaceD
191 blocking_surfaces_.clear();
192 return;
193 }
194
195 base::flat_set<SurfaceId> new_blocking_surfaces;
196
197 for (const SurfaceId& surface_id :
198 current_frame.metadata.referenced_surfaces) {
199 Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
200 // If a referenced surface does not have a corresponding active frame in the
201 // display compositor, then it blocks this frame.
202 if (!surface || !surface->HasActiveFrame())
203 new_blocking_surfaces.insert(surface_id);
204 }
205
206 // If this Surface has a previous pending frame, then we must determine the
207 // changes in dependencies so that we can update the SurfaceDependencyTracker
208 // map.
209 if (previous_pending_frame.has_value()) {
210 SurfaceDependencies removed_dependencies;
211 for (const SurfaceId& surface_id : blocking_surfaces_) {
212 if (!new_blocking_surfaces.count(surface_id))
213 removed_dependencies.insert(surface_id);
214 }
215
216 SurfaceDependencies added_dependencies;
217 for (const SurfaceId& surface_id : new_blocking_surfaces) {
218 if (!blocking_surfaces_.count(surface_id))
219 added_dependencies.insert(surface_id);
220 }
221
222 // If there is a change in the dependency set, then inform observers.
223 if (!added_dependencies.empty() || !removed_dependencies.empty()) {
224 for (auto& observer : observers_) {
225 observer.OnSurfaceDependenciesChanged(this, added_dependencies,
226 removed_dependencies);
227 }
228 }
229 }
230
231 blocking_surfaces_ = std::move(new_blocking_surfaces);
104 } 232 }
105 233
106 void Surface::TakeCopyOutputRequests( 234 void Surface::TakeCopyOutputRequests(
107 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { 235 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) {
108 DCHECK(copy_requests->empty()); 236 DCHECK(copy_requests->empty());
109 if (current_frame_) { 237 if (!active_frame_)
110 for (const auto& render_pass : current_frame_->render_pass_list) { 238 return;
111 for (auto& request : render_pass->copy_requests) { 239
112 copy_requests->insert( 240 for (const auto& render_pass : active_frame_->render_pass_list) {
113 std::make_pair(render_pass->id, std::move(request))); 241 for (auto& request : render_pass->copy_requests) {
114 } 242 copy_requests->insert(
115 render_pass->copy_requests.clear(); 243 std::make_pair(render_pass->id, std::move(request)));
116 } 244 }
117 } 245 render_pass->copy_requests.clear();
118 } 246 }
119 247 }
120 const CompositorFrame& Surface::GetEligibleFrame() const { 248
121 DCHECK(current_frame_); 249 const CompositorFrame& Surface::GetActiveFrame() const {
122 return current_frame_.value(); 250 DCHECK(active_frame_);
251 return active_frame_.value();
252 }
253
254 const CompositorFrame& Surface::GetPendingFrame() {
255 DCHECK(pending_frame_);
256 return pending_frame_.value();
123 } 257 }
124 258
125 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { 259 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
126 if (!current_frame_) 260 if (!active_frame_)
127 return; 261 return;
128 if (latency_info->empty()) { 262 if (latency_info->empty()) {
129 current_frame_->metadata.latency_info.swap(*latency_info); 263 active_frame_->metadata.latency_info.swap(*latency_info);
130 return; 264 return;
131 } 265 }
132 std::copy(current_frame_->metadata.latency_info.begin(), 266 std::copy(active_frame_->metadata.latency_info.begin(),
133 current_frame_->metadata.latency_info.end(), 267 active_frame_->metadata.latency_info.end(),
134 std::back_inserter(*latency_info)); 268 std::back_inserter(*latency_info));
135 current_frame_->metadata.latency_info.clear(); 269 active_frame_->metadata.latency_info.clear();
136 } 270 }
137 271
138 void Surface::RunDrawCallbacks() { 272 void Surface::RunDrawCallbacks() {
139 if (!draw_callback_.is_null()) { 273 if (!draw_callback_.is_null()) {
140 DrawCallback callback = draw_callback_; 274 DrawCallback callback = draw_callback_;
141 draw_callback_ = DrawCallback(); 275 draw_callback_ = DrawCallback();
142 callback.Run(); 276 callback.Run();
143 } 277 }
144 } 278 }
145 279
(...skipping 17 matching lines...) Expand all
163 void Surface::UnrefFrameResources(const CompositorFrame& frame) { 297 void Surface::UnrefFrameResources(const CompositorFrame& frame) {
164 ReturnedResourceArray resources; 298 ReturnedResourceArray resources;
165 TransferableResource::ReturnResources(frame.resource_list, &resources); 299 TransferableResource::ReturnResources(frame.resource_list, &resources);
166 // No point in returning same sync token to sender. 300 // No point in returning same sync token to sender.
167 for (auto& resource : resources) 301 for (auto& resource : resources)
168 resource.sync_token.Clear(); 302 resource.sync_token.Clear();
169 factory_->UnrefResources(resources); 303 factory_->UnrefResources(resources);
170 } 304 }
171 305
172 void Surface::ClearCopyRequests() { 306 void Surface::ClearCopyRequests() {
173 if (current_frame_) { 307 if (active_frame_) {
174 for (const auto& render_pass : current_frame_->render_pass_list) { 308 for (const auto& render_pass : active_frame_->render_pass_list) {
175 for (const auto& copy_request : render_pass->copy_requests) 309 for (const auto& copy_request : render_pass->copy_requests)
176 copy_request->SendEmptyResult(); 310 copy_request->SendEmptyResult();
177 } 311 }
178 } 312 }
179 } 313 }
180 314
181 } // namespace cc 315 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698