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

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

Issue 2541683004: Add/remove surface references via MojoCompositorFrameSink. (Closed)
Patch Set: Created 4 years 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 <utility>
8
7 #include "base/containers/adapters.h" 9 #include "base/containers/adapters.h"
8 #include "cc/output/compositor_frame.h" 10 #include "cc/output/compositor_frame.h"
9 #include "cc/quads/render_pass.h" 11 #include "cc/quads/render_pass.h"
10 #include "cc/quads/render_pass_draw_quad.h" 12 #include "cc/quads/render_pass_draw_quad.h"
11 #include "cc/quads/shared_quad_state.h" 13 #include "cc/quads/shared_quad_state.h"
12 #include "cc/quads/surface_draw_quad.h" 14 #include "cc/quads/surface_draw_quad.h"
13 #include "cc/surfaces/surface_id.h"
14 #include "services/ui/ws/frame_generator_delegate.h" 15 #include "services/ui/ws/frame_generator_delegate.h"
15 #include "services/ui/ws/server_window.h" 16 #include "services/ui/ws/server_window.h"
16 #include "services/ui/ws/server_window_compositor_frame_sink_manager.h" 17 #include "services/ui/ws/server_window_compositor_frame_sink_manager.h"
17 #include "services/ui/ws/server_window_delegate.h" 18 #include "services/ui/ws/server_window_delegate.h"
18 19
19 namespace ui { 20 namespace ui {
20 21
21 namespace ws { 22 namespace ws {
22 23
23 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate, 24 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate,
24 ServerWindow* root_window) 25 ServerWindow* root_window)
25 : delegate_(delegate), 26 : delegate_(delegate),
26 root_window_(root_window), 27 root_window_(root_window),
27 top_level_root_surface_id_(
28 cc::FrameSinkId(0, 0),
29 cc::LocalFrameId(0, base::UnguessableToken::Create())),
30 binding_(this), 28 binding_(this),
31 weak_factory_(this) { 29 weak_factory_(this) {
32 DCHECK(delegate_); 30 DCHECK(delegate_);
33 } 31 }
34 32
35 FrameGenerator::~FrameGenerator() { 33 FrameGenerator::~FrameGenerator() {
36 RemoveDeadSurfaceReferences();
37 RemoveAllSurfaceReferences(); 34 RemoveAllSurfaceReferences();
38 // Invalidate WeakPtrs now to avoid callbacks back into the 35 // Invalidate WeakPtrs now to avoid callbacks back into the
39 // FrameGenerator during destruction of |compositor_frame_sink_|. 36 // FrameGenerator during destruction of |compositor_frame_sink_|.
40 weak_factory_.InvalidateWeakPtrs(); 37 weak_factory_.InvalidateWeakPtrs();
41 compositor_frame_sink_.reset(); 38 compositor_frame_sink_.reset();
42 } 39 }
43 40
44 void FrameGenerator::OnAcceleratedWidgetAvailable( 41 void FrameGenerator::OnAcceleratedWidgetAvailable(
45 gfx::AcceleratedWidget widget) { 42 gfx::AcceleratedWidget widget) {
46 DCHECK_NE(gfx::kNullAcceleratedWidget, widget); 43 DCHECK_NE(gfx::kNullAcceleratedWidget, widget);
47 cc::mojom::MojoCompositorFrameSinkRequest request = 44 cc::mojom::MojoCompositorFrameSinkRequest request =
48 mojo::GetProxy(&compositor_frame_sink_); 45 mojo::GetProxy(&compositor_frame_sink_);
49 root_window_->CreateCompositorFrameSink( 46 root_window_->CreateCompositorFrameSink(
50 mojom::CompositorFrameSinkType::DEFAULT, widget, std::move(request), 47 mojom::CompositorFrameSinkType::DEFAULT, widget, std::move(request),
51 binding_.CreateInterfacePtrAndBind()); 48 binding_.CreateInterfacePtrAndBind());
52 // TODO(fsamuel): This means we're always requesting a new BeginFrame signal 49 // TODO(fsamuel): This means we're always requesting a new BeginFrame signal
53 // even when we don't need it. Once surface ID propagation work is done, 50 // even when we don't need it. Once surface ID propagation work is done,
54 // this will not be necessary because FrameGenerator will only need a 51 // this will not be necessary because FrameGenerator will only need a
55 // BeginFrame if the window manager changes. 52 // BeginFrame if the window manager changes.
56 compositor_frame_sink_->SetNeedsBeginFrame(true); 53 compositor_frame_sink_->SetNeedsBeginFrame(true);
57 } 54 }
58 55
59 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id, 56 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id,
60 ServerWindow* window) { 57 ServerWindow* window) {
61 DCHECK(surface_id.is_valid()); 58 DCHECK(surface_id.is_valid());
62 59
63 // TODO(kylechar): Adding surface references should be synchronized with
64 // SubmitCompositorFrame().
65
66 auto iter = active_references_.find(surface_id.frame_sink_id()); 60 auto iter = active_references_.find(surface_id.frame_sink_id());
67 if (iter == active_references_.end()) { 61 if (iter == active_references_.end()) {
68 AddFirstReference(surface_id, window); 62 AddFirstReference(surface_id, window);
69 return; 63 return;
70 } 64 }
71 65
72 SurfaceReference& ref = iter->second; 66 cc::SurfaceReference& ref = iter->second;
73 DCHECK_EQ(surface_id.frame_sink_id(), ref.child_id.frame_sink_id());
74 67
75 // This shouldn't be called multiple times for the same SurfaceId. 68 // This shouldn't be called multiple times for the same SurfaceId.
76 DCHECK_NE(surface_id.local_frame_id(), ref.child_id.local_frame_id()); 69 DCHECK_EQ(surface_id.frame_sink_id(), ref.child_id().frame_sink_id());
70 DCHECK_NE(surface_id.local_frame_id(), ref.child_id().local_frame_id());
77 71
78 // Add a reference from parent to new surface first. 72 // Old reference will be removed when the next CompositorFrame is submitted.
79 GetDisplayCompositor()->AddSurfaceReference(ref.parent_id, surface_id); 73 dead_references_.push_back(ref);
74 cc::SurfaceId old_surface_id = ref.child_id();
75
76 // New surface reference is recorded and will be added at end of this method.
77 ref = cc::SurfaceReference(ref.parent_id(), surface_id);
78 new_references_.push_back(ref);
80 79
81 // If the display root surface has changed, update all references to embedded 80 // If the display root surface has changed, update all references to embedded
82 // surfaces. For example, this would happen when the display resolution or 81 // surfaces. For example, this would happen when the display resolution or
83 // zoom level changes. 82 // zoom level changes.
84 if (!window->parent()) 83 if (!window->parent())
85 AddNewParentReferences(ref.child_id, surface_id); 84 AddNewParentReferences(old_surface_id, surface_id);
86 85
87 // Move the existing reference to list of references to remove after we submit 86 SendAddSurfaceReferences();
88 // the next CompositorFrame. Update local reference cache to be the new
89 // reference. If this is the display root surface then removing this reference
90 // will recursively remove any references it held.
91 dead_references_.push_back(ref);
92 ref.child_id = surface_id;
93 } 87 }
94 88
95 void FrameGenerator::DidReceiveCompositorFrameAck() {} 89 void FrameGenerator::DidReceiveCompositorFrameAck() {}
96 90
97 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) { 91 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) {
98 if (!root_window_->visible()) 92 if (!root_window_->visible())
99 return; 93 return;
100 94
101 // TODO(fsamuel): We should add a trace for generating a top level frame. 95 // TODO(fsamuel): We should add a trace for generating a top level frame.
102 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds())); 96 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds()));
103 97
104 if (compositor_frame_sink_) { 98 if (compositor_frame_sink_) {
105 gfx::Size frame_size = last_submitted_frame_size_; 99 gfx::Size frame_size = last_submitted_frame_size_;
106 if (!frame.render_pass_list.empty()) 100 if (!frame.render_pass_list.empty())
107 frame_size = frame.render_pass_list[0]->output_rect.size(); 101 frame_size = frame.render_pass_list[0]->output_rect.size();
108 if (!local_frame_id_.is_valid() || frame_size != last_submitted_frame_size_) 102 if (!local_frame_id_.is_valid() || frame_size != last_submitted_frame_size_)
109 local_frame_id_ = id_allocator_.GenerateId(); 103 local_frame_id_ = id_allocator_.GenerateId();
110 compositor_frame_sink_->SubmitCompositorFrame(local_frame_id_, 104 compositor_frame_sink_->SubmitCompositorFrame(local_frame_id_,
111 std::move(frame)); 105 std::move(frame));
112 last_submitted_frame_size_ = frame_size; 106 last_submitted_frame_size_ = frame_size;
113 107
114 // Remove dead references after we submit a frame. This has to happen after 108 // Remove dead references after we submit a frame. This has to happen after
115 // the frame is submitted otherwise we could end up deleting a surface that 109 // the frame is submitted otherwise we could end up deleting a surface that
116 // is still embedded in the last frame. 110 // is still embedded in the last frame.
117 // TODO(kylechar): This should be synchronized with SubmitCompositorFrame(). 111 SendRemoveSurfaceReferences();
118 RemoveDeadSurfaceReferences();
119 } 112 }
120 } 113 }
121 114
122 void FrameGenerator::ReclaimResources( 115 void FrameGenerator::ReclaimResources(
123 const cc::ReturnedResourceArray& resources) { 116 const cc::ReturnedResourceArray& resources) {
124 // Nothing to do here because FrameGenerator CompositorFrames don't reference 117 // Nothing to do here because FrameGenerator CompositorFrames don't reference
125 // any resources. 118 // any resources.
126 } 119 }
127 120
128 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( 121 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame(
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 223 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
231 quad->SetAll(sqs, bounds_at_origin /* rect */, 224 quad->SetAll(sqs, bounds_at_origin /* rect */,
232 gfx::Rect() /* opaque_rect */, 225 gfx::Rect() /* opaque_rect */,
233 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 226 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
234 underlay_surface_id); 227 underlay_surface_id);
235 } 228 }
236 } 229 }
237 230
238 cc::SurfaceId FrameGenerator::FindParentSurfaceId(ServerWindow* window) { 231 cc::SurfaceId FrameGenerator::FindParentSurfaceId(ServerWindow* window) {
239 if (window == root_window_) 232 if (window == root_window_)
240 return top_level_root_surface_id_; 233 return root_window_->delegate()->GetRootSurfaceId();
241 234
242 // The root window holds the parent SurfaceId. This SurfaceId will have an 235 // The root window holds the parent SurfaceId. This SurfaceId will have an
243 // invalid LocalFrameId before FrameGenerator has submitted a CompositorFrame. 236 // invalid LocalFrameId before FrameGenerator has submitted a CompositorFrame.
244 // After the first frame is submitted it will always be a valid SurfaceId. 237 // After the first frame is submitted it will always be a valid SurfaceId.
245 return root_window_->compositor_frame_sink_manager()->GetLatestSurfaceId( 238 return root_window_->compositor_frame_sink_manager()->GetLatestSurfaceId(
246 mojom::CompositorFrameSinkType::DEFAULT); 239 mojom::CompositorFrameSinkType::DEFAULT);
247 } 240 }
248 241
249 void FrameGenerator::AddSurfaceReference(const cc::SurfaceId& parent_id, 242 void FrameGenerator::AddSurfaceReference(const cc::SurfaceId& parent_id,
250 const cc::SurfaceId& child_id) { 243 const cc::SurfaceId& child_id) {
251 if (parent_id == top_level_root_surface_id_) 244 DCHECK_NE(parent_id, child_id);
252 GetDisplayCompositor()->AddRootSurfaceReference(child_id);
253 else
254 GetDisplayCompositor()->AddSurfaceReference(parent_id, child_id);
255 245
256 // Add new reference from parent to surface, plus add reference to local 246 // Add new reference from parent to surface, plus add reference to local
257 // cache. 247 // cache.
258 active_references_[child_id.frame_sink_id()] = 248 cc::SurfaceReference ref(parent_id, child_id);
259 SurfaceReference({parent_id, child_id}); 249 active_references_[child_id.frame_sink_id()] = ref;
250 new_references_.push_back(ref);
260 } 251 }
261 252
262 void FrameGenerator::AddFirstReference(const cc::SurfaceId& surface_id, 253 void FrameGenerator::AddFirstReference(const cc::SurfaceId& surface_id,
263 ServerWindow* window) { 254 ServerWindow* window) {
264 cc::SurfaceId parent_id = FindParentSurfaceId(window); 255 cc::SurfaceId parent_id = FindParentSurfaceId(window);
265 256
266 if (parent_id == top_level_root_surface_id_ || parent_id.is_valid()) { 257 if (window == root_window_ || parent_id.is_valid()) {
267 AddSurfaceReference(parent_id, surface_id); 258 AddSurfaceReference(parent_id, surface_id);
268 259
269 // For the first display root surface, add references to any child surfaces 260 // For the first display root surface, add references to any child surfaces
270 // that were created before it. 261 // that were created before it.
271 if (parent_id == top_level_root_surface_id_) { 262 if (window == root_window_) {
272 for (auto& child_surface_id : waiting_for_references_) 263 for (auto& child_surface_id : waiting_for_references_)
273 AddSurfaceReference(surface_id, child_surface_id); 264 AddSurfaceReference(surface_id, child_surface_id);
274 waiting_for_references_.clear(); 265 waiting_for_references_.clear();
275 } 266 }
267
268 SendAddSurfaceReferences();
276 } else { 269 } else {
277 // This isn't the display root surface and display root surface hasn't 270 // This isn't the display root surface and display root surface hasn't
278 // submitted a CF yet. We can't add a reference to an unknown SurfaceId. 271 // submitted a CF yet. We can't add a reference to an unknown SurfaceId.
279 waiting_for_references_.push_back(surface_id); 272 waiting_for_references_.push_back(surface_id);
280 } 273 }
281 274
282 // Observe |window| so that we can remove references when it's destroyed. 275 // Observe |window| so that we can remove references when it's destroyed.
283 Add(window); 276 Add(window);
284 } 277 }
285 278
286 void FrameGenerator::AddNewParentReferences( 279 void FrameGenerator::AddNewParentReferences(
287 const cc::SurfaceId& old_surface_id, 280 const cc::SurfaceId& old_surface_id,
288 const cc::SurfaceId& new_surface_id) { 281 const cc::SurfaceId& new_surface_id) {
289 DCHECK(old_surface_id.frame_sink_id() == new_surface_id.frame_sink_id()); 282 DCHECK_EQ(old_surface_id.frame_sink_id(), new_surface_id.frame_sink_id());
290 283
291 cc::mojom::DisplayCompositor* display_compositor = GetDisplayCompositor();
292 for (auto& map_entry : active_references_) { 284 for (auto& map_entry : active_references_) {
293 SurfaceReference& ref = map_entry.second; 285 cc::SurfaceReference& ref = map_entry.second;
294 if (ref.parent_id == old_surface_id) { 286 if (ref.parent_id() == old_surface_id) {
295 display_compositor->AddSurfaceReference(new_surface_id, ref.child_id); 287 ref = cc::SurfaceReference(new_surface_id, ref.child_id());
296 ref.parent_id = new_surface_id; 288 new_references_.push_back(ref);
297 } 289 }
298 } 290 }
299 } 291 }
300 292
301 void FrameGenerator::RemoveDeadSurfaceReferences() { 293 void FrameGenerator::SendAddSurfaceReferences() {
294 if (new_references_.empty())
295 return;
296
297 compositor_frame_sink_->AddSurfaceReferences(new_references_);
298 new_references_.clear();
299 }
300
301 void FrameGenerator::SendRemoveSurfaceReferences() {
302 if (dead_references_.empty()) 302 if (dead_references_.empty())
303 return; 303 return;
304 304
305 cc::mojom::DisplayCompositor* display_compositor = GetDisplayCompositor(); 305 compositor_frame_sink_->RemoveSurfaceReferences(dead_references_);
306 for (auto& ref : dead_references_) {
307 if (ref.parent_id == top_level_root_surface_id_)
308 display_compositor->RemoveRootSurfaceReference(ref.child_id);
309 else
310 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
311 }
312 dead_references_.clear(); 306 dead_references_.clear();
313 } 307 }
314 308
315 void FrameGenerator::RemoveFrameSinkReference( 309 void FrameGenerator::RemoveFrameSinkReference(
316 const cc::FrameSinkId& frame_sink_id) { 310 const cc::FrameSinkId& frame_sink_id) {
317 auto it = active_references_.find(frame_sink_id); 311 auto it = active_references_.find(frame_sink_id);
318 if (it == active_references_.end()) 312 if (it == active_references_.end())
319 return; 313 return;
320 dead_references_.push_back(it->second); 314 dead_references_.push_back(it->second);
321 active_references_.erase(it); 315 active_references_.erase(it);
322 } 316 }
323 317
324 void FrameGenerator::RemoveAllSurfaceReferences() { 318 void FrameGenerator::RemoveAllSurfaceReferences() {
325 // TODO(kylechar): Remove multiple surfaces with one IPC call. 319 for (auto& map_entry : active_references_)
326 cc::mojom::DisplayCompositor* display_compositor = GetDisplayCompositor(); 320 dead_references_.push_back(map_entry.second);
327 for (auto& map_entry : active_references_) {
328 const SurfaceReference& ref = map_entry.second;
329 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
330 }
331 active_references_.clear(); 321 active_references_.clear();
332 } 322 SendRemoveSurfaceReferences();
333
334 cc::mojom::DisplayCompositor* FrameGenerator::GetDisplayCompositor() {
335 return root_window_->delegate()->GetDisplayCompositor();
336 } 323 }
337 324
338 void FrameGenerator::OnWindowDestroying(ServerWindow* window) { 325 void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
339 Remove(window); 326 Remove(window);
340 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager = 327 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager =
341 window->compositor_frame_sink_manager(); 328 window->compositor_frame_sink_manager();
342 // If FrameGenerator was observing |window|, then that means it had a 329 // If FrameGenerator was observing |window|, then that means it had a
343 // CompositorFrame at some point in time and should have a 330 // CompositorFrame at some point in time and should have a
344 // ServerWindowCompositorFrameSinkManager. 331 // ServerWindowCompositorFrameSinkManager.
345 DCHECK(compositor_frame_sink_manager); 332 DCHECK(compositor_frame_sink_manager);
346 333
347 cc::SurfaceId default_surface_id = 334 cc::SurfaceId default_surface_id =
348 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 335 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
349 mojom::CompositorFrameSinkType::DEFAULT); 336 mojom::CompositorFrameSinkType::DEFAULT);
350 if (default_surface_id.is_valid()) 337 if (default_surface_id.is_valid())
351 RemoveFrameSinkReference(default_surface_id.frame_sink_id()); 338 RemoveFrameSinkReference(default_surface_id.frame_sink_id());
352 339
353 cc::SurfaceId underlay_surface_id = 340 cc::SurfaceId underlay_surface_id =
354 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 341 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
355 mojom::CompositorFrameSinkType::UNDERLAY); 342 mojom::CompositorFrameSinkType::UNDERLAY);
356 if (underlay_surface_id.is_valid()) 343 if (underlay_surface_id.is_valid())
357 RemoveFrameSinkReference(underlay_surface_id.frame_sink_id()); 344 RemoveFrameSinkReference(underlay_surface_id.frame_sink_id());
358 } 345 }
359 346
360 } // namespace ws 347 } // namespace ws
361 348
362 } // namespace ui 349 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698