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

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 AddObserver once 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
« no previous file with comments | « services/ui/ws/frame_generator.h ('k') | services/ui/ws/frame_generator_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
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 if (!window_surface->window()->HasObserver(this))
262 window_surface->window()->AddObserver(this);
263 return;
264 }
265
266 // We are already holding a reference to this surface so there's no work to do
267 // here.
268 if (surface_id.local_frame_id() == it->second.local_frame_id)
269 return;
270
271 // If we have have an existing reference to a surface from the given
272 // FrameSink, then we should release the reference, and then add this new
273 // reference. This results in a delete and lookup in the map but simplifies
274 // the code.
275 ReleaseFrameSinkReference(surface_id.frame_sink_id());
276
277 // This recursion will always terminate. This line is being called because
278 // there was a stale surface reference. The stale reference has been released
279 // in the previous line and cleared from the dependencies_ map. Thus, in the
280 // recursive call, we'll enter the second if blcok because the FrameSinkId
281 // is no longer referenced in the map.
282 AddOrUpdateSurfaceReference(window_surface);
283 }
284
285 void FrameGenerator::ReleaseFrameSinkReference(
286 const cc::FrameSinkId& frame_sink_id) {
287 auto it = dependencies_.find(frame_sink_id);
288 if (it == dependencies_.end())
289 return;
290 std::vector<uint32_t> sequences;
291 sequences.push_back(it->second.sequence.sequence);
292 cc::SurfaceManager* surface_manager = display_compositor_->manager();
293 surface_manager->DidSatisfySequences(frame_sink_id_, &sequences);
294 dependencies_.erase(it);
295 }
296
297 void FrameGenerator::ReleaseAllSurfaceReferences() {
298 cc::SurfaceManager* surface_manager = display_compositor_->manager();
299 std::vector<uint32_t> sequences;
300 for (auto& dependency : dependencies_)
301 sequences.push_back(dependency.second.sequence.sequence);
302 surface_manager->DidSatisfySequences(frame_sink_id_, &sequences);
303 dependencies_.clear();
304 }
305
306 void FrameGenerator::OnWindowDestroying(ServerWindow* window) {
307 window->RemoveObserver(this);
308 ServerWindowSurfaceManager* surface_manager = window->surface_manager();
309 // If FrameGenerator was observing |window|, then that means it had a surface
310 // at some point in time and should have a ServerWindowSurfaceManager.
311 DCHECK(surface_manager);
312 ServerWindowSurface* default_surface = surface_manager->GetDefaultSurface();
313 if (default_surface)
314 ReleaseFrameSinkReference(default_surface->frame_sink_id());
315 ServerWindowSurface* underlay_surface = surface_manager->GetUnderlaySurface();
316 if (underlay_surface)
317 ReleaseFrameSinkReference(underlay_surface->frame_sink_id());
318 }
319
236 } // namespace ws 320 } // namespace ws
237 321
238 } // namespace ui 322 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/ws/frame_generator.h ('k') | services/ui/ws/frame_generator_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698