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

Side by Side Diff: services/ui/ws/frame_generator.cc

Issue 2489003002: Convert mustash use surface references. (Closed)
Patch Set: Rewrite large bits Created 4 years, 1 month 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 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 "services/ui/ws/frame_generator.h" 5 #include "services/ui/ws/frame_generator.h"
6 6
7 #include "base/containers/adapters.h" 7 #include "base/containers/adapters.h"
8 #include "cc/output/compositor_frame.h" 8 #include "cc/output/compositor_frame.h"
9 #include "cc/quads/render_pass.h" 9 #include "cc/quads/render_pass.h"
10 #include "cc/quads/render_pass_draw_quad.h" 10 #include "cc/quads/render_pass_draw_quad.h"
11 #include "cc/quads/shared_quad_state.h" 11 #include "cc/quads/shared_quad_state.h"
12 #include "cc/quads/surface_draw_quad.h" 12 #include "cc/quads/surface_draw_quad.h"
13 #include "cc/surfaces/surface_id.h"
14 #include "gpu/ipc/client/gpu_channel_host.h" 13 #include "gpu/ipc/client/gpu_channel_host.h"
15 #include "services/ui/surfaces/display_compositor.h" 14 #include "services/ui/surfaces/display_compositor.h"
16 #include "services/ui/surfaces/surfaces_context_provider.h" 15 #include "services/ui/surfaces/surfaces_context_provider.h"
17 #include "services/ui/ws/frame_generator_delegate.h" 16 #include "services/ui/ws/frame_generator_delegate.h"
18 #include "services/ui/ws/server_window.h" 17 #include "services/ui/ws/server_window.h"
19 #include "services/ui/ws/server_window_compositor_frame_sink_manager.h" 18 #include "services/ui/ws/server_window_compositor_frame_sink_manager.h"
20 #include "services/ui/ws/server_window_delegate.h" 19 #include "services/ui/ws/server_window_delegate.h"
21 20
22 namespace ui { 21 namespace ui {
23 22
24 namespace ws { 23 namespace ws {
24 namespace {
25
26 // Walks up window tree and finds the SurfaceId for the ServerWindow embedding
27 // |window|. If |window| is a display root, then return |root_surface_id|.
28 cc::SurfaceId FindParentSurfaceId(ServerWindow* window,
29 const cc::SurfaceId& root_surface_id) {
30 if (!window->parent())
31 return root_surface_id;
32
33 ServerWindow* current = window;
34 while (current->parent()) {
Fady Samuel 2016/11/18 03:46:06 I'm worried about the correctness of this in gener
kylechar 2016/11/18 17:24:11 Done.
35 current = current->parent();
36 if (current->compositor_frame_sink_manager() &&
37 current->compositor_frame_sink_manager()->HasCompositorFrameSinkOfType(
38 mojom::CompositorFrameSinkType::DEFAULT)) {
39 return current->compositor_frame_sink_manager()->GetLatestSurfaceId(
40 mojom::CompositorFrameSinkType::DEFAULT);
41 }
42 }
43
44 NOTREACHED();
45 return cc::SurfaceId();
46 }
47
48 } // namespace
25 49
26 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate, 50 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate,
27 ServerWindow* root_window) 51 ServerWindow* root_window)
28 : delegate_(delegate), 52 : delegate_(delegate),
29 frame_sink_id_(
30 WindowIdToTransportId(root_window->id()),
31 static_cast<uint32_t>(mojom::CompositorFrameSinkType::DEFAULT)),
32 root_window_(root_window), 53 root_window_(root_window),
54 root_surface_id_(cc::FrameSinkId(),
Fady Samuel 2016/11/18 03:46:06 Why isn't the root window's FrameSinkId part of th
kylechar 2016/11/18 17:24:11 This is different from the display root. I changed
55 cc::LocalFrameId(0, base::UnguessableToken::Create())),
33 binding_(this), 56 binding_(this),
34 weak_factory_(this) { 57 weak_factory_(this) {
35 DCHECK(delegate_); 58 DCHECK(delegate_);
36 surface_sequence_generator_.set_frame_sink_id(frame_sink_id_);
37 } 59 }
38 60
39 FrameGenerator::~FrameGenerator() { 61 FrameGenerator::~FrameGenerator() {
40 ReleaseAllSurfaceReferences(); 62 RemoveDeadSurfaceReferences();
63 RemoveAllSurfaceReferences();
41 // Invalidate WeakPtrs now to avoid callbacks back into the 64 // Invalidate WeakPtrs now to avoid callbacks back into the
42 // FrameGenerator during destruction of |compositor_frame_sink_|. 65 // FrameGenerator during destruction of |compositor_frame_sink_|.
43 weak_factory_.InvalidateWeakPtrs(); 66 weak_factory_.InvalidateWeakPtrs();
44 compositor_frame_sink_.reset(); 67 compositor_frame_sink_.reset();
45 } 68 }
46 69
47 void FrameGenerator::OnGpuChannelEstablished( 70 void FrameGenerator::OnGpuChannelEstablished(
48 scoped_refptr<gpu::GpuChannelHost> channel) { 71 scoped_refptr<gpu::GpuChannelHost> channel) {
49 if (widget_ != gfx::kNullAcceleratedWidget) { 72 if (widget_ != gfx::kNullAcceleratedWidget) {
50 cc::mojom::MojoCompositorFrameSinkRequest request = 73 cc::mojom::MojoCompositorFrameSinkRequest request =
(...skipping 28 matching lines...) Expand all
79 new SurfacesContextProvider(widget_, std::move(gpu_channel_)), 102 new SurfacesContextProvider(widget_, std::move(gpu_channel_)),
80 std::move(request), binding_.CreateInterfacePtrAndBind()); 103 std::move(request), binding_.CreateInterfacePtrAndBind());
81 // TODO(fsamuel): This means we're always requesting a new BeginFrame signal 104 // TODO(fsamuel): This means we're always requesting a new BeginFrame signal
82 // even when we don't need it. Once surface ID propagation work is done, 105 // even when we don't need it. Once surface ID propagation work is done,
83 // this will not be necessary because FrameGenerator will only need a 106 // this will not be necessary because FrameGenerator will only need a
84 // BeginFrame if the window manager changes. 107 // BeginFrame if the window manager changes.
85 compositor_frame_sink_->SetNeedsBeginFrame(true); 108 compositor_frame_sink_->SetNeedsBeginFrame(true);
86 } 109 }
87 } 110 }
88 111
112 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id,
113 ServerWindow* window) {
114 DCHECK(surface_id.is_valid());
115
116 // TODO(kylechar): Adding surface references should be synchronized with
117 // SubmitCompositorFrame().
118
119 auto iter = active_references_.find(surface_id.frame_sink_id());
120 if (iter == active_references_.end()) {
121 AddFirstReference(surface_id, window);
122 return;
123 }
124
125 SurfaceReference& ref = iter->second;
126 DCHECK(surface_id.frame_sink_id() == ref.child_id.frame_sink_id());
127
128 // This shouldn't be called multiple times for the same SurfaceId.
129 DCHECK(surface_id.local_frame_id() != ref.child_id.local_frame_id());
130
131 // Add a reference from parent to new surface first.
132 GetDisplayCompositor()->AddSurfaceReference(ref.parent_id, surface_id);
133
134 // If the display root surface has changed, update all references to embedded
135 // surfaces.
136 if (!window->parent())
137 AddNewParentReferences(ref.child_id, surface_id);
Fady Samuel 2016/11/18 03:46:06 I'm confused. Aren't we supposed to remove parent
kylechar 2016/11/18 17:24:11 If something else is referencing the old parent, t
138
139 // Move the existing reference to list of references to remove after we submit
140 // the next CompositorFrame. Update local reference cache to be the new
141 // reference. If this is the display root surface then removing this reference
142 // will recursively remove any references it held.
143 dead_references_.push_back(ref);
144 ref.child_id = surface_id;
145 }
146
89 void FrameGenerator::DidReceiveCompositorFrameAck() {} 147 void FrameGenerator::DidReceiveCompositorFrameAck() {}
90 148
91 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) { 149 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) {
92 if (!root_window_->visible()) 150 if (!root_window_->visible())
93 return; 151 return;
94 152
95 // TODO(fsamuel): We should add a trace for generating a top level frame. 153 // TODO(fsamuel): We should add a trace for generating a top level frame.
96 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds())); 154 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds()));
97 if (compositor_frame_sink_) 155 if (compositor_frame_sink_) {
98 compositor_frame_sink_->SubmitCompositorFrame(std::move(frame)); 156 compositor_frame_sink_->SubmitCompositorFrame(std::move(frame));
157
158 // Remove dead references after we submit a frame. This has to happen after
159 // the frame is submitted otherwise we could end up deleting a surface that
160 // is still embedded in the last frame.
161 // TODO(kylechar): This should be synchronized with SubmitCompositorFrame().
162 RemoveDeadSurfaceReferences();
163 }
99 } 164 }
100 165
101 void FrameGenerator::ReclaimResources( 166 void FrameGenerator::ReclaimResources(
102 const cc::ReturnedResourceArray& resources) { 167 const cc::ReturnedResourceArray& resources) {
103 // Nothing to do here because FrameGenerator CompositorFrames don't reference 168 // Nothing to do here because FrameGenerator CompositorFrames don't reference
104 // any resources. 169 // any resources.
105 } 170 }
106 171
107 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( 172 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame(
108 const gfx::Rect& output_rect) { 173 const gfx::Rect& output_rect) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 const gfx::Rect bounds_at_origin(window->bounds().size()); 247 const gfx::Rect bounds_at_origin(window->bounds().size());
183 // TODO(fsamuel): These clipping and visible rects are incorrect. They need 248 // TODO(fsamuel): These clipping and visible rects are incorrect. They need
184 // to be populated from CompositorFrame structs. 249 // to be populated from CompositorFrame structs.
185 sqs->SetAll(quad_to_target_transform, 250 sqs->SetAll(quad_to_target_transform,
186 bounds_at_origin.size() /* layer_bounds */, 251 bounds_at_origin.size() /* layer_bounds */,
187 bounds_at_origin /* visible_layer_bounds */, 252 bounds_at_origin /* visible_layer_bounds */,
188 bounds_at_origin /* clip_rect */, false /* is_clipped */, 253 bounds_at_origin /* clip_rect */, false /* is_clipped */,
189 combined_opacity, SkXfermode::kSrcOver_Mode, 254 combined_opacity, SkXfermode::kSrcOver_Mode,
190 0 /* sorting-context_id */); 255 0 /* sorting-context_id */);
191 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 256 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
192 AddOrUpdateSurfaceReference(mojom::CompositorFrameSinkType::DEFAULT,
193 window);
194 quad->SetAll(sqs, bounds_at_origin /* rect */, 257 quad->SetAll(sqs, bounds_at_origin /* rect */,
195 gfx::Rect() /* opaque_rect */, 258 gfx::Rect() /* opaque_rect */,
196 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 259 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
197 default_surface_id); 260 default_surface_id);
198 } 261 }
199 if (underlay_surface_id.is_valid()) { 262 if (underlay_surface_id.is_valid()) {
200 const gfx::Rect underlay_absolute_bounds = 263 const gfx::Rect underlay_absolute_bounds =
201 absolute_bounds - window->underlay_offset(); 264 absolute_bounds - window->underlay_offset();
202 gfx::Transform quad_to_target_transform; 265 gfx::Transform quad_to_target_transform;
203 quad_to_target_transform.Translate(underlay_absolute_bounds.x(), 266 quad_to_target_transform.Translate(underlay_absolute_bounds.x(),
204 underlay_absolute_bounds.y()); 267 underlay_absolute_bounds.y());
205 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); 268 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
206 const gfx::Rect bounds_at_origin( 269 const gfx::Rect bounds_at_origin(
207 window->compositor_frame_sink_manager()->GetLatestFrameSize( 270 window->compositor_frame_sink_manager()->GetLatestFrameSize(
208 mojom::CompositorFrameSinkType::UNDERLAY)); 271 mojom::CompositorFrameSinkType::UNDERLAY));
209 sqs->SetAll(quad_to_target_transform, 272 sqs->SetAll(quad_to_target_transform,
210 bounds_at_origin.size() /* layer_bounds */, 273 bounds_at_origin.size() /* layer_bounds */,
211 bounds_at_origin /* visible_layer_bounds */, 274 bounds_at_origin /* visible_layer_bounds */,
212 bounds_at_origin /* clip_rect */, false /* is_clipped */, 275 bounds_at_origin /* clip_rect */, false /* is_clipped */,
213 combined_opacity, SkXfermode::kSrcOver_Mode, 276 combined_opacity, SkXfermode::kSrcOver_Mode,
214 0 /* sorting-context_id */); 277 0 /* sorting-context_id */);
215 278
216 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 279 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
217 AddOrUpdateSurfaceReference(mojom::CompositorFrameSinkType::UNDERLAY,
218 window);
219 quad->SetAll(sqs, bounds_at_origin /* rect */, 280 quad->SetAll(sqs, bounds_at_origin /* rect */,
220 gfx::Rect() /* opaque_rect */, 281 gfx::Rect() /* opaque_rect */,
221 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 282 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
222 underlay_surface_id); 283 underlay_surface_id);
223 } 284 }
224 } 285 }
225 286
226 void FrameGenerator::AddOrUpdateSurfaceReference( 287 void FrameGenerator::AddSurfaceReference(const cc::SurfaceId& parent_id,
227 mojom::CompositorFrameSinkType type, 288 const cc::SurfaceId& child_id) {
228 ServerWindow* window) { 289 if (parent_id == root_surface_id_)
229 cc::SurfaceId surface_id = 290 GetDisplayCompositor()->AddRootSurfaceReference(child_id);
230 window->compositor_frame_sink_manager()->GetLatestSurfaceId(type); 291 else
231 if (!surface_id.is_valid()) 292 GetDisplayCompositor()->AddSurfaceReference(parent_id, child_id);
232 return; 293
233 auto it = dependencies_.find(surface_id.frame_sink_id()); 294 // Add new reference from parent to surface, plus add reference to local
234 if (it == dependencies_.end()) { 295 // cache.
235 SurfaceDependency dependency = { 296 active_references_[child_id.frame_sink_id()] =
236 surface_id.local_frame_id(), 297 SurfaceReference({parent_id, child_id});
237 surface_sequence_generator_.CreateSurfaceSequence()}; 298 }
238 dependencies_[surface_id.frame_sink_id()] = dependency; 299
239 GetDisplayCompositor()->AddSurfaceReference(surface_id, 300 void FrameGenerator::AddFirstReference(const cc::SurfaceId& surface_id,
240 dependency.sequence); 301 ServerWindow* window) {
241 // Observe |window_surface|'s window so that we can release references when 302 cc::SurfaceId parent_id = FindParentSurfaceId(window, root_surface_id_);
242 // the window is destroyed. 303
243 Add(window); 304 if (parent_id == root_surface_id_ || parent_id.is_valid()) {
244 return; 305 AddSurfaceReference(parent_id, surface_id);
306
307 // For the first display root surface, add references to any child surfaces
308 // that were created before it.
309 if (parent_id == root_surface_id_) {
310 for (auto& child_surface_id : waiting_for_references_)
311 AddSurfaceReference(surface_id, child_surface_id);
312 waiting_for_references_.clear();
313 }
314 } else {
315 // This isn't the display root surface and display root surface hasn't
316 // submitted a CF yet. We can't add a reference to an unknown SurfaceId.
317 waiting_for_references_.push_back(surface_id);
245 } 318 }
246 319
247 // We are already holding a reference to this surface so there's no work to do 320 // Observe |window| so that we can remove references when it's destroyed.
248 // here. 321 Add(window);
249 if (surface_id.local_frame_id() == it->second.local_frame_id) 322 }
323
324 void FrameGenerator::AddNewParentReferences(
325 const cc::SurfaceId& old_surface_id,
326 const cc::SurfaceId& new_surface_id) {
327 DCHECK(old_surface_id.frame_sink_id() == new_surface_id.frame_sink_id());
328
329 DisplayCompositor* display_compositor = GetDisplayCompositor();
330 for (auto& map_entry : active_references_) {
331 SurfaceReference& ref = map_entry.second;
332 if (ref.parent_id == old_surface_id) {
333 display_compositor->AddSurfaceReference(new_surface_id, ref.child_id);
334 ref.parent_id = new_surface_id;
335 }
336 }
337 }
338
339 void FrameGenerator::RemoveDeadSurfaceReferences() {
340 if (dead_references_.empty())
250 return; 341 return;
251 342
252 // If we have have an existing reference to a surface from the given 343 DisplayCompositor* display_compositor = GetDisplayCompositor();
253 // FrameSink, then we should release the reference, and then add this new 344 for (auto& ref : dead_references_) {
254 // reference. This results in a delete and lookup in the map but simplifies 345 if (ref.parent_id == root_surface_id_)
255 // the code. 346 display_compositor->RemoveRootSurfaceReference(ref.child_id);
Fady Samuel 2016/11/18 03:46:06 That's a lot of potential IPCs in the future. I gu
kylechar 2016/11/18 17:24:11 Added TODO.
256 ReleaseFrameSinkReference(surface_id.frame_sink_id()); 347 else
257 348 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
258 // This recursion will always terminate. This line is being called because 349 }
259 // there was a stale surface reference. The stale reference has been released 350 dead_references_.clear();
260 // in the previous line and cleared from the dependencies_ map. Thus, in the
261 // recursive call, we'll enter the second if blcok because the FrameSinkId
262 // is no longer referenced in the map.
263 AddOrUpdateSurfaceReference(type, window);
264 } 351 }
265 352
266 void FrameGenerator::ReleaseFrameSinkReference( 353 void FrameGenerator::RemoveFrameSinkReference(
267 const cc::FrameSinkId& frame_sink_id) { 354 const cc::FrameSinkId& frame_sink_id) {
268 auto it = dependencies_.find(frame_sink_id); 355 auto it = active_references_.find(frame_sink_id);
269 if (it == dependencies_.end()) 356 if (it == active_references_.end())
270 return; 357 return;
271 std::vector<uint32_t> sequences; 358 dead_references_.push_back(it->second);
272 sequences.push_back(it->second.sequence.sequence); 359 active_references_.erase(it);
273 GetDisplayCompositor()->ReturnSurfaceReferences(frame_sink_id, sequences);
274 dependencies_.erase(it);
275 } 360 }
276 361
277 void FrameGenerator::ReleaseAllSurfaceReferences() { 362 void FrameGenerator::RemoveAllSurfaceReferences() {
278 std::vector<uint32_t> sequences; 363 DisplayCompositor* display_compositor = GetDisplayCompositor();
279 for (auto& dependency : dependencies_) 364 for (auto& map_entry : active_references_) {
280 sequences.push_back(dependency.second.sequence.sequence); 365 const SurfaceReference& ref = map_entry.second;
281 GetDisplayCompositor()->ReturnSurfaceReferences(frame_sink_id_, sequences); 366 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
282 dependencies_.clear(); 367 }
368 active_references_.clear();
283 } 369 }
284 370
285 ui::DisplayCompositor* FrameGenerator::GetDisplayCompositor() { 371 ui::DisplayCompositor* FrameGenerator::GetDisplayCompositor() {
286 return root_window_->delegate()->GetDisplayCompositor(); 372 return root_window_->delegate()->GetDisplayCompositor();
287 } 373 }
288 374
289 void FrameGenerator::OnWindowDestroying(ServerWindow* window) { 375 void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
290 Remove(window); 376 Remove(window);
291 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager = 377 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager =
292 window->compositor_frame_sink_manager(); 378 window->compositor_frame_sink_manager();
293 // If FrameGenerator was observing |window|, then that means it had a 379 // If FrameGenerator was observing |window|, then that means it had a
294 // CompositorFrame at some point in time and should have a 380 // CompositorFrame at some point in time and should have a
295 // ServerWindowCompositorFrameSinkManager. 381 // ServerWindowCompositorFrameSinkManager.
296 DCHECK(compositor_frame_sink_manager); 382 DCHECK(compositor_frame_sink_manager);
297 383
298 cc::SurfaceId default_surface_id = 384 cc::SurfaceId default_surface_id =
299 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 385 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
300 mojom::CompositorFrameSinkType::DEFAULT); 386 mojom::CompositorFrameSinkType::DEFAULT);
301 if (default_surface_id.is_valid()) 387 if (default_surface_id.is_valid())
302 ReleaseFrameSinkReference(default_surface_id.frame_sink_id()); 388 RemoveFrameSinkReference(default_surface_id.frame_sink_id());
303 389
304 cc::SurfaceId underlay_surface_id = 390 cc::SurfaceId underlay_surface_id =
305 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 391 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
306 mojom::CompositorFrameSinkType::UNDERLAY); 392 mojom::CompositorFrameSinkType::UNDERLAY);
307 if (underlay_surface_id.is_valid()) 393 if (underlay_surface_id.is_valid())
308 ReleaseFrameSinkReference(underlay_surface_id.frame_sink_id()); 394 RemoveFrameSinkReference(underlay_surface_id.frame_sink_id());
309 } 395 }
310 396
311 } // namespace ws 397 } // namespace ws
312 398
313 } // namespace ui 399 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698