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

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

Issue 2400723003: Mus+Ash: Use standard cc mechanism for surface lifetime. (Closed)
Patch Set: Only add window observer if we're adding the dependency for the first time Created 4 years, 2 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 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"
13 #include "gpu/ipc/client/gpu_channel_host.h" 14 #include "gpu/ipc/client/gpu_channel_host.h"
14 #include "services/ui/surfaces/compositor_frame_sink.h" 15 #include "services/ui/surfaces/compositor_frame_sink.h"
15 #include "services/ui/ws/frame_generator_delegate.h" 16 #include "services/ui/ws/frame_generator_delegate.h"
16 #include "services/ui/ws/server_window.h" 17 #include "services/ui/ws/server_window.h"
17 #include "services/ui/ws/server_window_surface.h" 18 #include "services/ui/ws/server_window_surface.h"
18 #include "services/ui/ws/server_window_surface_manager.h" 19 #include "services/ui/ws/server_window_surface_manager.h"
19 20
20 namespace ui { 21 namespace ui {
21 22
22 namespace ws { 23 namespace ws {
23 24
24 FrameGenerator::FrameGenerator( 25 FrameGenerator::FrameGenerator(
25 FrameGeneratorDelegate* delegate, 26 FrameGeneratorDelegate* delegate,
26 scoped_refptr<DisplayCompositor> display_compositor) 27 scoped_refptr<DisplayCompositor> display_compositor)
27 : delegate_(delegate), 28 : delegate_(delegate),
28 display_compositor_(display_compositor), 29 display_compositor_(display_compositor),
29 frame_sink_id_(0, display_compositor->GenerateNextClientId()), 30 frame_sink_id_(0, display_compositor->GenerateNextClientId()),
30 draw_timer_(false, false), 31 draw_timer_(false, false),
31 weak_factory_(this) { 32 weak_factory_(this) {
32 DCHECK(delegate_); 33 DCHECK(delegate_);
34 surface_sequence_generator_.set_frame_sink_id(frame_sink_id_);
33 } 35 }
34 36
35 FrameGenerator::~FrameGenerator() { 37 FrameGenerator::~FrameGenerator() {
38 ReleaseAllSurfaceReferences();
36 // Invalidate WeakPtrs now to avoid callbacks back into the 39 // Invalidate WeakPtrs now to avoid callbacks back into the
37 // FrameGenerator during destruction of |compositor_frame_sink_|. 40 // FrameGenerator during destruction of |compositor_frame_sink_|.
38 weak_factory_.InvalidateWeakPtrs(); 41 weak_factory_.InvalidateWeakPtrs();
39 compositor_frame_sink_.reset(); 42 compositor_frame_sink_.reset();
40 } 43 }
41 44
42 void FrameGenerator::OnGpuChannelEstablished( 45 void FrameGenerator::OnGpuChannelEstablished(
43 scoped_refptr<gpu::GpuChannelHost> channel) { 46 scoped_refptr<gpu::GpuChannelHost> channel) {
44 if (widget_ != gfx::kNullAcceleratedWidget) { 47 if (widget_ != gfx::kNullAcceleratedWidget) {
45 compositor_frame_sink_ = base::MakeUnique<surfaces::CompositorFrameSink>( 48 compositor_frame_sink_ = base::MakeUnique<surfaces::CompositorFrameSink>(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 frame_pending_ = true; 105 frame_pending_ = true;
103 compositor_frame_sink_->SubmitCompositorFrame( 106 compositor_frame_sink_->SubmitCompositorFrame(
104 std::move(frame), 107 std::move(frame),
105 base::Bind(&FrameGenerator::DidDraw, weak_factory_.GetWeakPtr())); 108 base::Bind(&FrameGenerator::DidDraw, weak_factory_.GetWeakPtr()));
106 } 109 }
107 dirty_rect_ = gfx::Rect(); 110 dirty_rect_ = gfx::Rect();
108 } 111 }
109 112
110 void FrameGenerator::DidDraw() { 113 void FrameGenerator::DidDraw() {
111 frame_pending_ = false; 114 frame_pending_ = false;
112 delegate_->OnCompositorFrameDrawn();
113 if (!dirty_rect_.IsEmpty()) 115 if (!dirty_rect_.IsEmpty())
114 WantToDraw(); 116 WantToDraw();
115 } 117 }
116 118
117 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( 119 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame(
118 const gfx::Rect& output_rect) const { 120 const gfx::Rect& output_rect) {
119 const cc::RenderPassId render_pass_id(1, 1); 121 const cc::RenderPassId render_pass_id(1, 1);
120 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); 122 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
121 render_pass->SetNew(render_pass_id, output_rect, dirty_rect_, 123 render_pass->SetNew(render_pass_id, output_rect, dirty_rect_,
122 gfx::Transform()); 124 gfx::Transform());
123 125
124 bool may_contain_video = false; 126 bool may_contain_video = false;
125 DrawWindowTree(render_pass.get(), delegate_->GetRootWindow(), gfx::Vector2d(), 127 DrawWindowTree(render_pass.get(), delegate_->GetRootWindow(), gfx::Vector2d(),
126 1.0f, &may_contain_video); 128 1.0f, &may_contain_video);
127 129
128 std::unique_ptr<cc::DelegatedFrameData> frame_data( 130 std::unique_ptr<cc::DelegatedFrameData> frame_data(
(...skipping 23 matching lines...) Expand all
152 frame.delegated_frame_data = std::move(frame_data); 154 frame.delegated_frame_data = std::move(frame_data);
153 frame.metadata.may_contain_video = may_contain_video; 155 frame.metadata.may_contain_video = may_contain_video;
154 return frame; 156 return frame;
155 } 157 }
156 158
157 void FrameGenerator::DrawWindowTree( 159 void FrameGenerator::DrawWindowTree(
158 cc::RenderPass* pass, 160 cc::RenderPass* pass,
159 ServerWindow* window, 161 ServerWindow* window,
160 const gfx::Vector2d& parent_to_root_origin_offset, 162 const gfx::Vector2d& parent_to_root_origin_offset,
161 float opacity, 163 float opacity,
162 bool* may_contain_video) const { 164 bool* may_contain_video) {
163 if (!window->visible()) 165 if (!window->visible())
164 return; 166 return;
165 167
166 ServerWindowSurface* default_surface = 168 ServerWindowSurface* default_surface =
167 window->surface_manager() ? window->surface_manager()->GetDefaultSurface() 169 window->surface_manager() ? window->surface_manager()->GetDefaultSurface()
168 : nullptr; 170 : nullptr;
169 171
170 const gfx::Rect absolute_bounds = 172 const gfx::Rect absolute_bounds =
171 window->bounds() + parent_to_root_origin_offset; 173 window->bounds() + parent_to_root_origin_offset;
172 const ServerWindow::Windows& children = window->children(); 174 const ServerWindow::Windows& children = window->children();
(...skipping 21 matching lines...) Expand all
194 const gfx::Rect bounds_at_origin(window->bounds().size()); 196 const gfx::Rect bounds_at_origin(window->bounds().size());
195 // TODO(fsamuel): These clipping and visible rects are incorrect. They need 197 // TODO(fsamuel): These clipping and visible rects are incorrect. They need
196 // to be populated from CompositorFrame structs. 198 // to be populated from CompositorFrame structs.
197 sqs->SetAll(quad_to_target_transform, 199 sqs->SetAll(quad_to_target_transform,
198 bounds_at_origin.size() /* layer_bounds */, 200 bounds_at_origin.size() /* layer_bounds */,
199 bounds_at_origin /* visible_layer_bounds */, 201 bounds_at_origin /* visible_layer_bounds */,
200 bounds_at_origin /* clip_rect */, false /* is_clipped */, 202 bounds_at_origin /* clip_rect */, false /* is_clipped */,
201 combined_opacity, SkXfermode::kSrcOver_Mode, 203 combined_opacity, SkXfermode::kSrcOver_Mode,
202 0 /* sorting-context_id */); 204 0 /* sorting-context_id */);
203 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 205 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
206 AddOrUpdateSurfaceReference(default_surface);
204 quad->SetAll(sqs, bounds_at_origin /* rect */, 207 quad->SetAll(sqs, bounds_at_origin /* rect */,
205 gfx::Rect() /* opaque_rect */, 208 gfx::Rect() /* opaque_rect */,
206 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 209 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
207 default_surface->GetSurfaceId()); 210 default_surface->GetSurfaceId());
208 if (default_surface->may_contain_video()) 211 if (default_surface->may_contain_video())
209 *may_contain_video = true; 212 *may_contain_video = true;
210 } 213 }
211 if (underlay_surface) { 214 if (underlay_surface) {
212 const gfx::Rect underlay_absolute_bounds = 215 const gfx::Rect underlay_absolute_bounds =
213 absolute_bounds - window->underlay_offset(); 216 absolute_bounds - window->underlay_offset();
214 gfx::Transform quad_to_target_transform; 217 gfx::Transform quad_to_target_transform;
215 quad_to_target_transform.Translate(underlay_absolute_bounds.x(), 218 quad_to_target_transform.Translate(underlay_absolute_bounds.x(),
216 underlay_absolute_bounds.y()); 219 underlay_absolute_bounds.y());
217 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); 220 cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
218 const gfx::Rect bounds_at_origin( 221 const gfx::Rect bounds_at_origin(
219 underlay_surface->last_submitted_frame_size()); 222 underlay_surface->last_submitted_frame_size());
220 sqs->SetAll(quad_to_target_transform, 223 sqs->SetAll(quad_to_target_transform,
221 bounds_at_origin.size() /* layer_bounds */, 224 bounds_at_origin.size() /* layer_bounds */,
222 bounds_at_origin /* visible_layer_bounds */, 225 bounds_at_origin /* visible_layer_bounds */,
223 bounds_at_origin /* clip_rect */, false /* is_clipped */, 226 bounds_at_origin /* clip_rect */, false /* is_clipped */,
224 combined_opacity, SkXfermode::kSrcOver_Mode, 227 combined_opacity, SkXfermode::kSrcOver_Mode,
225 0 /* sorting-context_id */); 228 0 /* sorting-context_id */);
226 229
227 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); 230 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
231 AddOrUpdateSurfaceReference(underlay_surface);
228 quad->SetAll(sqs, bounds_at_origin /* rect */, 232 quad->SetAll(sqs, bounds_at_origin /* rect */,
229 gfx::Rect() /* opaque_rect */, 233 gfx::Rect() /* opaque_rect */,
230 bounds_at_origin /* visible_rect */, true /* needs_blending*/, 234 bounds_at_origin /* visible_rect */, true /* needs_blending*/,
231 underlay_surface->GetSurfaceId()); 235 underlay_surface->GetSurfaceId());
232 DCHECK(!underlay_surface->may_contain_video()); 236 DCHECK(!underlay_surface->may_contain_video());
233 } 237 }
234 } 238 }
235 239
240 void FrameGenerator::AddOrUpdateSurfaceReference(
241 ServerWindowSurface* window_surface) {
242 if (!window_surface->has_frame())
243 return;
244 cc::SurfaceId surface_id = window_surface->GetSurfaceId();
245 cc::SurfaceManager* surface_manager = display_compositor_->manager();
246 auto it = dependencies_.find(surface_id.frame_sink_id());
247 if (it == dependencies_.end()) {
248 cc::Surface* surface = surface_manager->GetSurfaceForId(surface_id);
249 if (!surface) {
250 LOG(ERROR) << "Attempting to add dependency to nonexistent surface "
251 << surface_id.ToString();
252 return;
253 }
254 SurfaceDependency dependency = {
255 surface_id.local_frame_id(),
256 surface_sequence_generator_.CreateSurfaceSequence()};
257 surface->AddDestructionDependency(dependency.sequence);
rjkroege 2016/10/07 19:34:50 I think that this logic could be refactored in the
Fady Samuel 2016/10/07 20:31:33 This is going away once kylechar@ finishes his sur
rjkroege 2016/10/07 20:48:13 can you add a TODO before landing?
Fady Samuel 2016/10/07 21:04:32 Done.
258 dependencies_[surface_id.frame_sink_id()] = dependency;
259 // Observe |window_surface|'s window so that we can release references when
260 // the window is destroyed.
261 window_surface->window()->AddObserver(this);
262 return;
263 }
264
265 // We are already holding a reference to this surface so there's no work to do
266 // here.
267 if (surface_id.local_frame_id() == it->second.local_frame_id)
268 return;
269
270 // If we have have an existing reference to a surface from the given
271 // FrameSink, then we should release the reference, and then add this new
272 // reference. This results in a delete and lookup in the map but simplifies
273 // the code.
274 ReleaseFrameSinkReference(surface_id.frame_sink_id());
275
276 AddOrUpdateSurfaceReference(window_surface);
rjkroege 2016/10/07 19:34:50 What is going on with this recursion? Is this ever
Fady Samuel 2016/10/07 20:31:33 It will. The reason we got here is because we alre
rjkroege 2016/10/07 20:48:13 Please insert this something like this as a commen
Fady Samuel 2016/10/07 21:04:32 Done.
277 }
278
279 void FrameGenerator::ReleaseFrameSinkReference(
280 const cc::FrameSinkId& frame_sink_id) {
281 auto it = dependencies_.find(frame_sink_id);
282 if (it == dependencies_.end())
283 return;
284 std::vector<uint32_t> sequences;
285 sequences.push_back(it->second.sequence.sequence);
286 cc::SurfaceManager* surface_manager = display_compositor_->manager();
287 surface_manager->DidSatisfySequences(frame_sink_id_, &sequences);
288 dependencies_.erase(it);
289 }
290
291 void FrameGenerator::ReleaseAllSurfaceReferences() {
292 cc::SurfaceManager* surface_manager = display_compositor_->manager();
293 std::vector<uint32_t> sequences;
294 for (auto& dependency : dependencies_)
295 sequences.push_back(dependency.second.sequence.sequence);
296 surface_manager->DidSatisfySequences(frame_sink_id_, &sequences);
297 dependencies_.clear();
298 }
299
300 void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
301 window->RemoveObserver(this);
302 ServerWindowSurfaceManager* surface_manager = window->surface_manager();
303 // If FrameGenerator was observing |window|, then that means it had a surface
304 // at some point in time and should have a ServerWindowSurfaceManager.
305 DCHECK(surface_manager);
306 ServerWindowSurface* default_surface = surface_manager->GetDefaultSurface();
307 if (default_surface)
308 ReleaseFrameSinkReference(default_surface->frame_sink_id());
309 ServerWindowSurface* underlay_surface = surface_manager->GetUnderlaySurface();
310 if (underlay_surface)
311 ReleaseFrameSinkReference(underlay_surface->frame_sink_id());
312 }
313
236 } // namespace ws 314 } // namespace ws
237 315
238 } // namespace ui 316 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698