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

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

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: Better unit test name 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"
kylechar 2017/02/09 15:50:31 Duplicate include.
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_before_dependencies) {
139 return;
140 }
141
142 // If a frame is being activated because of a deadline, then clear its set
143 // of blockers.
144 blocking_surfaces_.clear();
145 ActivatePendingFrame();
146 }
147
148 void Surface::ActivatePendingFrame() {
149 DCHECK(pending_frame_);
150 ActivateFrame(std::move(pending_frame_.value()));
151 pending_frame_.reset();
152 // ActiveFrame resources are now double ref-ed. Unref.
153 UnrefFrameResources(*active_frame_);
154 }
155
156 // A frame is activated if all its Surface ID dependences are active or a
157 // deadline has hit and the frame was forcibly activated by the display
158 // compositor.
159 void Surface::ActivateFrame(CompositorFrame frame) {
160 DCHECK(factory_);
161 ClearCopyRequests();
162
163 TakeLatencyInfo(&frame.metadata.latency_info);
164
165 base::Optional<CompositorFrame> previous_frame = std::move(active_frame_);
166 active_frame_ = std::move(frame);
167
168 factory_->ReceiveFromChild(active_frame_->resource_list);
169
170 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
171 // increment frame index for them.
172 if (!active_frame_->render_pass_list.empty())
173 ++frame_index_;
174
175 previous_frame_surface_id_ = surface_id();
176
177 if (previous_frame)
178 UnrefFrameResources(*previous_frame);
179
180 referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
181
182 for (auto& observer : observers_)
183 observer.OnSurfaceActivated(this);
184 }
185
186 void Surface::UpdateBlockingSurfaces(
187 const base::Optional<CompositorFrame>& previous_pending_frame,
188 const CompositorFrame& current_frame) {
189 // If there is no SurfaceDependencyTracker installed then the |current_frame|
190 // does not block on anything.
191 if (!factory_->manager()->dependency_tracker()) {
192 blocking_surfaces_.clear();
193 return;
194 }
195
196 base::flat_set<SurfaceId> new_blocking_surfaces;
kylechar 2017/02/09 15:50:31 Why mix SurfaceDependencies and base::flat_set<Sur
197
198 for (const SurfaceId& surface_id :
199 current_frame.metadata.referenced_surfaces) {
200 Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
201 // If a referenced surface does not have a corresponding active frame in the
202 // display compositor, then it blocks this frame.
203 if (!surface || !surface->HasActiveFrame())
204 new_blocking_surfaces.insert(surface_id);
205 }
206
207 // If this Surface has a previous pending frame, then we must determine the
208 // changes in dependencies so that we can update the SurfaceDependencyTracker
209 // map.
210 if (previous_pending_frame.has_value()) {
211 SurfaceDependencies removed_dependencies;
212 for (const SurfaceId& surface_id : blocking_surfaces_) {
213 if (!new_blocking_surfaces.count(surface_id))
214 removed_dependencies.insert(surface_id);
215 }
216
217 SurfaceDependencies added_dependencies;
218 for (const SurfaceId& surface_id : new_blocking_surfaces) {
219 if (!blocking_surfaces_.count(surface_id))
220 added_dependencies.insert(surface_id);
221 }
222
223 // If there is a change in the dependency set, then inform observers.
224 if (!added_dependencies.empty() || !removed_dependencies.empty()) {
225 for (auto& observer : observers_) {
226 observer.OnSurfaceDependenciesChanged(this, added_dependencies,
227 removed_dependencies);
228 }
229 }
230 }
231
232 blocking_surfaces_ = std::move(new_blocking_surfaces);
104 } 233 }
105 234
106 void Surface::TakeCopyOutputRequests( 235 void Surface::TakeCopyOutputRequests(
107 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { 236 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) {
108 DCHECK(copy_requests->empty()); 237 DCHECK(copy_requests->empty());
109 if (current_frame_) { 238 if (!active_frame_)
110 for (const auto& render_pass : current_frame_->render_pass_list) { 239 return;
111 for (auto& request : render_pass->copy_requests) { 240
112 copy_requests->insert( 241 for (const auto& render_pass : active_frame_->render_pass_list) {
113 std::make_pair(render_pass->id, std::move(request))); 242 for (auto& request : render_pass->copy_requests) {
114 } 243 copy_requests->insert(
115 render_pass->copy_requests.clear(); 244 std::make_pair(render_pass->id, std::move(request)));
116 } 245 }
117 } 246 render_pass->copy_requests.clear();
118 } 247 }
119 248 }
120 const CompositorFrame& Surface::GetEligibleFrame() const { 249
121 DCHECK(current_frame_); 250 const CompositorFrame& Surface::GetActiveFrame() const {
122 return current_frame_.value(); 251 DCHECK(active_frame_);
252 return active_frame_.value();
253 }
254
255 const CompositorFrame& Surface::GetPendingFrame() {
256 DCHECK(pending_frame_);
257 return pending_frame_.value();
123 } 258 }
124 259
125 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { 260 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
126 if (!current_frame_) 261 if (!active_frame_)
127 return; 262 return;
128 if (latency_info->empty()) { 263 if (latency_info->empty()) {
129 current_frame_->metadata.latency_info.swap(*latency_info); 264 active_frame_->metadata.latency_info.swap(*latency_info);
130 return; 265 return;
131 } 266 }
132 std::copy(current_frame_->metadata.latency_info.begin(), 267 std::copy(active_frame_->metadata.latency_info.begin(),
133 current_frame_->metadata.latency_info.end(), 268 active_frame_->metadata.latency_info.end(),
134 std::back_inserter(*latency_info)); 269 std::back_inserter(*latency_info));
135 current_frame_->metadata.latency_info.clear(); 270 active_frame_->metadata.latency_info.clear();
136 } 271 }
137 272
138 void Surface::RunDrawCallbacks() { 273 void Surface::RunDrawCallbacks() {
139 if (!draw_callback_.is_null()) { 274 if (!draw_callback_.is_null()) {
140 DrawCallback callback = draw_callback_; 275 DrawCallback callback = draw_callback_;
141 draw_callback_ = DrawCallback(); 276 draw_callback_ = DrawCallback();
142 callback.Run(); 277 callback.Run();
143 } 278 }
144 } 279 }
145 280
(...skipping 17 matching lines...) Expand all
163 void Surface::UnrefFrameResources(const CompositorFrame& frame) { 298 void Surface::UnrefFrameResources(const CompositorFrame& frame) {
164 ReturnedResourceArray resources; 299 ReturnedResourceArray resources;
165 TransferableResource::ReturnResources(frame.resource_list, &resources); 300 TransferableResource::ReturnResources(frame.resource_list, &resources);
166 // No point in returning same sync token to sender. 301 // No point in returning same sync token to sender.
167 for (auto& resource : resources) 302 for (auto& resource : resources)
168 resource.sync_token.Clear(); 303 resource.sync_token.Clear();
169 factory_->UnrefResources(resources); 304 factory_->UnrefResources(resources);
170 } 305 }
171 306
172 void Surface::ClearCopyRequests() { 307 void Surface::ClearCopyRequests() {
173 if (current_frame_) { 308 if (active_frame_) {
174 for (const auto& render_pass : current_frame_->render_pass_list) { 309 for (const auto& render_pass : active_frame_->render_pass_list) {
175 for (const auto& copy_request : render_pass->copy_requests) 310 for (const auto& copy_request : render_pass->copy_requests)
176 copy_request->SendEmptyResult(); 311 copy_request->SendEmptyResult();
177 } 312 }
178 } 313 }
179 } 314 }
180 315
181 } // namespace cc 316 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698