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

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

Issue 2489003002: Convert mustash use surface references. (Closed)
Patch Set: Fixes for fsamuel. 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 {
25 24
26 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate, 25 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate,
27 ServerWindow* root_window) 26 ServerWindow* root_window)
28 : delegate_(delegate), 27 : delegate_(delegate),
29 frame_sink_id_(
30 WindowIdToTransportId(root_window->id()),
31 static_cast<uint32_t>(mojom::CompositorFrameSinkType::DEFAULT)),
32 root_window_(root_window), 28 root_window_(root_window),
29 top_level_root_(cc::FrameSinkId(0, 0),
30 cc::LocalFrameId(0, base::UnguessableToken::Create())),
33 binding_(this), 31 binding_(this),
34 weak_factory_(this) { 32 weak_factory_(this) {
35 DCHECK(delegate_); 33 DCHECK(delegate_);
36 surface_sequence_generator_.set_frame_sink_id(frame_sink_id_);
37 } 34 }
38 35
39 FrameGenerator::~FrameGenerator() { 36 FrameGenerator::~FrameGenerator() {
40 ReleaseAllSurfaceReferences(); 37 RemoveDeadSurfaceReferences();
38 RemoveAllSurfaceReferences();
41 // Invalidate WeakPtrs now to avoid callbacks back into the 39 // Invalidate WeakPtrs now to avoid callbacks back into the
42 // FrameGenerator during destruction of |compositor_frame_sink_|. 40 // FrameGenerator during destruction of |compositor_frame_sink_|.
43 weak_factory_.InvalidateWeakPtrs(); 41 weak_factory_.InvalidateWeakPtrs();
44 compositor_frame_sink_.reset(); 42 compositor_frame_sink_.reset();
45 } 43 }
46 44
47 void FrameGenerator::OnGpuChannelEstablished( 45 void FrameGenerator::OnGpuChannelEstablished(
48 scoped_refptr<gpu::GpuChannelHost> channel) { 46 scoped_refptr<gpu::GpuChannelHost> channel) {
49 if (widget_ != gfx::kNullAcceleratedWidget) { 47 if (widget_ != gfx::kNullAcceleratedWidget) {
50 cc::mojom::MojoCompositorFrameSinkRequest request = 48 cc::mojom::MojoCompositorFrameSinkRequest request =
(...skipping 28 matching lines...) Expand all
79 new SurfacesContextProvider(widget_, gpu_channel_), 77 new SurfacesContextProvider(widget_, gpu_channel_),
80 std::move(request), binding_.CreateInterfacePtrAndBind()); 78 std::move(request), binding_.CreateInterfacePtrAndBind());
81 // TODO(fsamuel): This means we're always requesting a new BeginFrame signal 79 // 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, 80 // 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 81 // this will not be necessary because FrameGenerator will only need a
84 // BeginFrame if the window manager changes. 82 // BeginFrame if the window manager changes.
85 compositor_frame_sink_->SetNeedsBeginFrame(true); 83 compositor_frame_sink_->SetNeedsBeginFrame(true);
86 } 84 }
87 } 85 }
88 86
87 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id,
88 ServerWindow* window) {
89 DCHECK(surface_id.is_valid());
90
91 // TODO(kylechar): Adding surface references should be synchronized with
92 // SubmitCompositorFrame().
93
94 auto iter = active_references_.find(surface_id.frame_sink_id());
95 if (iter == active_references_.end()) {
96 AddFirstReference(surface_id, window);
97 return;
98 }
99
100 SurfaceReference& ref = iter->second;
101 DCHECK(surface_id.frame_sink_id() == ref.child_id.frame_sink_id());
sky 2016/11/19 16:38:56 DCHECK_EQ and NE?
kylechar 2016/11/21 14:48:22 I don't think that works? Maybe I just don't under
sky 2016/11/21 16:51:48 My mistake, you are right.
kylechar 2016/11/21 16:54:20 I talked with fsamuel about this and since Surface
102
103 // This shouldn't be called multiple times for the same SurfaceId.
104 DCHECK(surface_id.local_frame_id() != ref.child_id.local_frame_id());
105
106 // Add a reference from parent to new surface first.
107 GetDisplayCompositor()->AddSurfaceReference(ref.parent_id, surface_id);
108
109 // If the display root surface has changed, update all references to embedded
110 // surfaces.
Fady Samuel 2016/11/18 22:27:24 nit: specify when this can happen.
kylechar 2016/11/21 14:48:22 Done.
111 if (!window->parent())
112 AddNewParentReferences(ref.child_id, surface_id);
113
114 // Move the existing reference to list of references to remove after we submit
115 // the next CompositorFrame. Update local reference cache to be the new
116 // reference. If this is the display root surface then removing this reference
117 // will recursively remove any references it held.
118 dead_references_.push_back(ref);
119 ref.child_id = surface_id;
120 }
121
89 void FrameGenerator::DidReceiveCompositorFrameAck() {} 122 void FrameGenerator::DidReceiveCompositorFrameAck() {}
90 123
91 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) { 124 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) {
92 if (!root_window_->visible()) 125 if (!root_window_->visible())
93 return; 126 return;
94 127
95 // TODO(fsamuel): We should add a trace for generating a top level frame. 128 // TODO(fsamuel): We should add a trace for generating a top level frame.
96 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds())); 129 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds()));
97 if (compositor_frame_sink_) 130 if (compositor_frame_sink_) {
98 compositor_frame_sink_->SubmitCompositorFrame(std::move(frame)); 131 compositor_frame_sink_->SubmitCompositorFrame(std::move(frame));
132
133 // Remove dead references after we submit a frame. This has to happen after
134 // the frame is submitted otherwise we could end up deleting a surface that
135 // is still embedded in the last frame.
136 // TODO(kylechar): This should be synchronized with SubmitCompositorFrame().
137 RemoveDeadSurfaceReferences();
138 }
99 } 139 }
100 140
101 void FrameGenerator::ReclaimResources( 141 void FrameGenerator::ReclaimResources(
102 const cc::ReturnedResourceArray& resources) { 142 const cc::ReturnedResourceArray& resources) {
103 // Nothing to do here because FrameGenerator CompositorFrames don't reference 143 // Nothing to do here because FrameGenerator CompositorFrames don't reference
104 // any resources. 144 // any resources.
105 } 145 }
106 146
107 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( 147 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame(
108 const gfx::Rect& output_rect) { 148 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()); 222 const gfx::Rect bounds_at_origin(window->bounds().size());
183 // TODO(fsamuel): These clipping and visible rects are incorrect. They need 223 // TODO(fsamuel): These clipping and visible rects are incorrect. They need
184 // to be populated from CompositorFrame structs. 224 // to be populated from CompositorFrame structs.
185 sqs->SetAll(quad_to_target_transform, 225 sqs->SetAll(quad_to_target_transform,
186 bounds_at_origin.size() /* layer_bounds */, 226 bounds_at_origin.size() /* layer_bounds */,
187 bounds_at_origin /* visible_layer_bounds */, 227 bounds_at_origin /* visible_layer_bounds */,
188 bounds_at_origin /* clip_rect */, false /* is_clipped */, 228 bounds_at_origin /* clip_rect */, false /* is_clipped */,
189 combined_opacity, SkXfermode::kSrcOver_Mode, 229 combined_opacity, SkXfermode::kSrcOver_Mode,
190 0 /* sorting-context_id */); 230 0 /* sorting-context_id */);
191 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 231 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
192 AddOrUpdateSurfaceReference(mojom::CompositorFrameSinkType::DEFAULT,
193 window);
194 quad->SetAll(sqs, bounds_at_origin /* rect */, 232 quad->SetAll(sqs, bounds_at_origin /* rect */,
195 gfx::Rect() /* opaque_rect */, 233 gfx::Rect() /* opaque_rect */,
196 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 234 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
197 default_surface_id); 235 default_surface_id);
198 } 236 }
199 if (underlay_surface_id.is_valid()) { 237 if (underlay_surface_id.is_valid()) {
200 const gfx::Rect underlay_absolute_bounds = 238 const gfx::Rect underlay_absolute_bounds =
201 absolute_bounds - window->underlay_offset(); 239 absolute_bounds - window->underlay_offset();
202 gfx::Transform quad_to_target_transform; 240 gfx::Transform quad_to_target_transform;
203 quad_to_target_transform.Translate(underlay_absolute_bounds.x(), 241 quad_to_target_transform.Translate(underlay_absolute_bounds.x(),
204 underlay_absolute_bounds.y()); 242 underlay_absolute_bounds.y());
205 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); 243 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
206 const gfx::Rect bounds_at_origin( 244 const gfx::Rect bounds_at_origin(
207 window->compositor_frame_sink_manager()->GetLatestFrameSize( 245 window->compositor_frame_sink_manager()->GetLatestFrameSize(
208 mojom::CompositorFrameSinkType::UNDERLAY)); 246 mojom::CompositorFrameSinkType::UNDERLAY));
209 sqs->SetAll(quad_to_target_transform, 247 sqs->SetAll(quad_to_target_transform,
210 bounds_at_origin.size() /* layer_bounds */, 248 bounds_at_origin.size() /* layer_bounds */,
211 bounds_at_origin /* visible_layer_bounds */, 249 bounds_at_origin /* visible_layer_bounds */,
212 bounds_at_origin /* clip_rect */, false /* is_clipped */, 250 bounds_at_origin /* clip_rect */, false /* is_clipped */,
213 combined_opacity, SkXfermode::kSrcOver_Mode, 251 combined_opacity, SkXfermode::kSrcOver_Mode,
214 0 /* sorting-context_id */); 252 0 /* sorting-context_id */);
215 253
216 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 254 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
217 AddOrUpdateSurfaceReference(mojom::CompositorFrameSinkType::UNDERLAY,
218 window);
219 quad->SetAll(sqs, bounds_at_origin /* rect */, 255 quad->SetAll(sqs, bounds_at_origin /* rect */,
220 gfx::Rect() /* opaque_rect */, 256 gfx::Rect() /* opaque_rect */,
221 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 257 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
222 underlay_surface_id); 258 underlay_surface_id);
223 } 259 }
224 } 260 }
225 261
226 void FrameGenerator::AddOrUpdateSurfaceReference( 262 cc::SurfaceId FrameGenerator::FindParentSurfaceId(ServerWindow* window) {
227 mojom::CompositorFrameSinkType type, 263 if (window == root_window_)
228 ServerWindow* window) { 264 return top_level_root_;
229 cc::SurfaceId surface_id = 265
230 window->compositor_frame_sink_manager()->GetLatestSurfaceId(type); 266 return root_window_->compositor_frame_sink_manager()->GetLatestSurfaceId(
sky 2016/11/19 16:38:56 How do you know the latest surface id corresponds
kylechar 2016/11/21 14:48:22 Added comment.
231 if (!surface_id.is_valid()) 267 mojom::CompositorFrameSinkType::DEFAULT);
232 return; 268 }
233 auto it = dependencies_.find(surface_id.frame_sink_id()); 269
234 if (it == dependencies_.end()) { 270 void FrameGenerator::AddSurfaceReference(const cc::SurfaceId& parent_id,
235 SurfaceDependency dependency = { 271 const cc::SurfaceId& child_id) {
236 surface_id.local_frame_id(), 272 if (parent_id == top_level_root_)
237 surface_sequence_generator_.CreateSurfaceSequence()}; 273 GetDisplayCompositor()->AddRootSurfaceReference(child_id);
238 dependencies_[surface_id.frame_sink_id()] = dependency; 274 else
239 GetDisplayCompositor()->AddSurfaceReference(surface_id, 275 GetDisplayCompositor()->AddSurfaceReference(parent_id, child_id);
240 dependency.sequence); 276
241 // Observe |window_surface|'s window so that we can release references when 277 // Add new reference from parent to surface, plus add reference to local
242 // the window is destroyed. 278 // cache.
243 Add(window); 279 active_references_[child_id.frame_sink_id()] =
244 return; 280 SurfaceReference({parent_id, child_id});
281 }
282
283 void FrameGenerator::AddFirstReference(const cc::SurfaceId& surface_id,
284 ServerWindow* window) {
285 cc::SurfaceId parent_id = FindParentSurfaceId(window);
286
287 if (parent_id == top_level_root_ || parent_id.is_valid()) {
288 AddSurfaceReference(parent_id, surface_id);
289
290 // For the first display root surface, add references to any child surfaces
291 // that were created before it.
292 if (parent_id == top_level_root_) {
293 for (auto& child_surface_id : waiting_for_references_)
294 AddSurfaceReference(surface_id, child_surface_id);
295 waiting_for_references_.clear();
296 }
297 } else {
298 // This isn't the display root surface and display root surface hasn't
299 // submitted a CF yet. We can't add a reference to an unknown SurfaceId.
300 waiting_for_references_.push_back(surface_id);
245 } 301 }
246 302
247 // We are already holding a reference to this surface so there's no work to do 303 // Observe |window| so that we can remove references when it's destroyed.
248 // here. 304 Add(window);
249 if (surface_id.local_frame_id() == it->second.local_frame_id) 305 }
306
307 void FrameGenerator::AddNewParentReferences(
308 const cc::SurfaceId& old_surface_id,
309 const cc::SurfaceId& new_surface_id) {
310 DCHECK(old_surface_id.frame_sink_id() == new_surface_id.frame_sink_id());
311
312 DisplayCompositor* display_compositor = GetDisplayCompositor();
313 for (auto& map_entry : active_references_) {
314 SurfaceReference& ref = map_entry.second;
315 if (ref.parent_id == old_surface_id) {
316 display_compositor->AddSurfaceReference(new_surface_id, ref.child_id);
317 ref.parent_id = new_surface_id;
318 }
319 }
320 }
321
322 void FrameGenerator::RemoveDeadSurfaceReferences() {
323 if (dead_references_.empty())
250 return; 324 return;
251 325
252 // If we have have an existing reference to a surface from the given 326 DisplayCompositor* display_compositor = GetDisplayCompositor();
253 // FrameSink, then we should release the reference, and then add this new 327 for (auto& ref : dead_references_) {
254 // reference. This results in a delete and lookup in the map but simplifies 328 if (ref.parent_id == top_level_root_)
255 // the code. 329 display_compositor->RemoveRootSurfaceReference(ref.child_id);
256 ReleaseFrameSinkReference(surface_id.frame_sink_id()); 330 else
257 331 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
258 // This recursion will always terminate. This line is being called because 332 }
259 // there was a stale surface reference. The stale reference has been released 333 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 } 334 }
265 335
266 void FrameGenerator::ReleaseFrameSinkReference( 336 void FrameGenerator::RemoveFrameSinkReference(
267 const cc::FrameSinkId& frame_sink_id) { 337 const cc::FrameSinkId& frame_sink_id) {
268 auto it = dependencies_.find(frame_sink_id); 338 auto it = active_references_.find(frame_sink_id);
269 if (it == dependencies_.end()) 339 if (it == active_references_.end())
270 return; 340 return;
271 std::vector<uint32_t> sequences; 341 dead_references_.push_back(it->second);
272 sequences.push_back(it->second.sequence.sequence); 342 active_references_.erase(it);
273 GetDisplayCompositor()->ReturnSurfaceReferences(frame_sink_id, sequences);
274 dependencies_.erase(it);
275 } 343 }
276 344
277 void FrameGenerator::ReleaseAllSurfaceReferences() { 345 void FrameGenerator::RemoveAllSurfaceReferences() {
278 std::vector<uint32_t> sequences; 346 // TODO(kylechar): Remove multiple surfaces with one IPC call.
279 for (auto& dependency : dependencies_) 347 DisplayCompositor* display_compositor = GetDisplayCompositor();
280 sequences.push_back(dependency.second.sequence.sequence); 348 for (auto& map_entry : active_references_) {
281 GetDisplayCompositor()->ReturnSurfaceReferences(frame_sink_id_, sequences); 349 const SurfaceReference& ref = map_entry.second;
282 dependencies_.clear(); 350 display_compositor->RemoveSurfaceReference(ref.parent_id, ref.child_id);
351 }
352 active_references_.clear();
283 } 353 }
284 354
285 ui::DisplayCompositor* FrameGenerator::GetDisplayCompositor() { 355 ui::DisplayCompositor* FrameGenerator::GetDisplayCompositor() {
286 return root_window_->delegate()->GetDisplayCompositor(); 356 return root_window_->delegate()->GetDisplayCompositor();
287 } 357 }
288 358
289 void FrameGenerator::OnWindowDestroying(ServerWindow* window) { 359 void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
290 Remove(window); 360 Remove(window);
291 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager = 361 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager =
292 window->compositor_frame_sink_manager(); 362 window->compositor_frame_sink_manager();
293 // If FrameGenerator was observing |window|, then that means it had a 363 // If FrameGenerator was observing |window|, then that means it had a
294 // CompositorFrame at some point in time and should have a 364 // CompositorFrame at some point in time and should have a
295 // ServerWindowCompositorFrameSinkManager. 365 // ServerWindowCompositorFrameSinkManager.
296 DCHECK(compositor_frame_sink_manager); 366 DCHECK(compositor_frame_sink_manager);
297 367
298 cc::SurfaceId default_surface_id = 368 cc::SurfaceId default_surface_id =
299 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 369 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
300 mojom::CompositorFrameSinkType::DEFAULT); 370 mojom::CompositorFrameSinkType::DEFAULT);
301 if (default_surface_id.is_valid()) 371 if (default_surface_id.is_valid())
302 ReleaseFrameSinkReference(default_surface_id.frame_sink_id()); 372 RemoveFrameSinkReference(default_surface_id.frame_sink_id());
303 373
304 cc::SurfaceId underlay_surface_id = 374 cc::SurfaceId underlay_surface_id =
305 window->compositor_frame_sink_manager()->GetLatestSurfaceId( 375 window->compositor_frame_sink_manager()->GetLatestSurfaceId(
306 mojom::CompositorFrameSinkType::UNDERLAY); 376 mojom::CompositorFrameSinkType::UNDERLAY);
307 if (underlay_surface_id.is_valid()) 377 if (underlay_surface_id.is_valid())
308 ReleaseFrameSinkReference(underlay_surface_id.frame_sink_id()); 378 RemoveFrameSinkReference(underlay_surface_id.frame_sink_id());
309 } 379 }
310 380
311 } // namespace ws 381 } // namespace ws
312 382
313 } // namespace ui 383 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698