| OLD | NEW |
| 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> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/containers/adapters.h" | 10 #include "base/containers/adapters.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate, | 25 FrameGenerator::FrameGenerator(FrameGeneratorDelegate* delegate, |
| 26 ServerWindow* root_window) | 26 ServerWindow* root_window) |
| 27 : delegate_(delegate), | 27 : delegate_(delegate), |
| 28 root_window_(root_window), | 28 root_window_(root_window), |
| 29 binding_(this), | 29 binding_(this), |
| 30 weak_factory_(this) { | 30 weak_factory_(this) { |
| 31 DCHECK(delegate_); | 31 DCHECK(delegate_); |
| 32 } | 32 } |
| 33 | 33 |
| 34 FrameGenerator::~FrameGenerator() { | 34 FrameGenerator::~FrameGenerator() { |
| 35 // Remove reference from top level root to the display root surface, if one | |
| 36 // exists. This will make everything referenced by the display surface | |
| 37 // unreachable so it can be garbage collected. | |
| 38 if (surface_tracker_.HasValidSurfaceId()) { | |
| 39 compositor_frame_sink_->RemoveSurfaceReferences( | |
| 40 std::vector<cc::SurfaceReference>{ | |
| 41 cc::SurfaceReference(root_window_->delegate()->GetRootSurfaceId(), | |
| 42 surface_tracker_.current_surface_id())}); | |
| 43 } | |
| 44 | |
| 45 // Invalidate WeakPtrs now to avoid callbacks back into the | 35 // Invalidate WeakPtrs now to avoid callbacks back into the |
| 46 // FrameGenerator during destruction of |compositor_frame_sink_|. | 36 // FrameGenerator during destruction of |compositor_frame_sink_|. |
| 47 weak_factory_.InvalidateWeakPtrs(); | 37 weak_factory_.InvalidateWeakPtrs(); |
| 48 compositor_frame_sink_.reset(); | 38 compositor_frame_sink_.reset(); |
| 49 } | 39 } |
| 50 | 40 |
| 51 void FrameGenerator::OnAcceleratedWidgetAvailable( | 41 void FrameGenerator::OnAcceleratedWidgetAvailable( |
| 52 gfx::AcceleratedWidget widget) { | 42 gfx::AcceleratedWidget widget) { |
| 53 DCHECK_NE(gfx::kNullAcceleratedWidget, widget); | 43 DCHECK_NE(gfx::kNullAcceleratedWidget, widget); |
| 54 cc::mojom::MojoCompositorFrameSinkRequest request(&compositor_frame_sink_); | 44 cc::mojom::MojoCompositorFrameSinkRequest request(&compositor_frame_sink_); |
| 55 cc::mojom::DisplayPrivateRequest display_private_request(&display_private_); | 45 cc::mojom::DisplayPrivateRequest display_private_request(&display_private_); |
| 56 root_window_->CreateDisplayCompositorFrameSink( | 46 root_window_->CreateDisplayCompositorFrameSink( |
| 57 widget, std::move(request), binding_.CreateInterfacePtrAndBind(), | 47 widget, std::move(request), binding_.CreateInterfacePtrAndBind(), |
| 58 std::move(display_private_request)); | 48 std::move(display_private_request)); |
| 59 // 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 |
| 60 // 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, |
| 61 // this will not be necessary because FrameGenerator will only need a | 51 // this will not be necessary because FrameGenerator will only need a |
| 62 // BeginFrame if the window manager changes. | 52 // BeginFrame if the window manager changes. |
| 63 compositor_frame_sink_->SetNeedsBeginFrame(true); | 53 compositor_frame_sink_->SetNeedsBeginFrame(true); |
| 64 } | 54 } |
| 65 | 55 |
| 66 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id, | 56 void FrameGenerator::OnSurfaceCreated(const cc::SurfaceId& surface_id, |
| 67 ServerWindow* window) { | 57 ServerWindow* window) { |
| 68 DCHECK(surface_id.is_valid()); | 58 DCHECK(surface_id.is_valid()); |
| 69 | 59 |
| 70 // TODO(samans): Clients are actually embedded in the WM and only the WM is | |
| 71 // embedded here. This needs to be fixed. | |
| 72 | |
| 73 // Only handle embedded surfaces changing here. The display root surface | 60 // Only handle embedded surfaces changing here. The display root surface |
| 74 // changing is handled immediately after the CompositorFrame is submitted. | 61 // changing is handled immediately after the CompositorFrame is submitted. |
| 75 if (window != root_window_) { | 62 // TODO(samans): Only tell FrameGenerator about WM surface instead of all |
| 76 // Add observer for window the first time it's seen. | 63 // all surfaces. |
| 77 if (surface_tracker_.EmbedSurface(surface_id)) | 64 if (window == delegate_->GetActiveRootWindow()) |
| 78 Add(window); | 65 window_manager_surface_id_ = surface_id; |
| 79 } | |
| 80 } | 66 } |
| 81 | 67 |
| 82 void FrameGenerator::DidReceiveCompositorFrameAck() {} | 68 void FrameGenerator::DidReceiveCompositorFrameAck() {} |
| 83 | 69 |
| 84 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) { | 70 void FrameGenerator::OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) { |
| 85 if (!root_window_->visible()) | 71 if (!root_window_->visible()) |
| 86 return; | 72 return; |
| 87 | 73 |
| 88 // TODO(fsamuel): We should add a trace for generating a top level frame. | 74 // TODO(fsamuel): We should add a trace for generating a top level frame. |
| 89 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds())); | 75 cc::CompositorFrame frame(GenerateCompositorFrame(root_window_->bounds())); |
| 90 | 76 |
| 91 if (compositor_frame_sink_) { | 77 if (compositor_frame_sink_) { |
| 92 gfx::Size frame_size = last_submitted_frame_size_; | 78 gfx::Size frame_size = last_submitted_frame_size_; |
| 93 if (!frame.render_pass_list.empty()) | 79 if (!frame.render_pass_list.empty()) |
| 94 frame_size = frame.render_pass_list[0]->output_rect.size(); | 80 frame_size = frame.render_pass_list[0]->output_rect.size(); |
| 95 | 81 |
| 96 bool display_surface_changed = false; | 82 if (!local_frame_id_.is_valid() || frame_size != last_submitted_frame_size_) |
| 97 if (!local_frame_id_.is_valid() || | |
| 98 frame_size != last_submitted_frame_size_) { | |
| 99 local_frame_id_ = id_allocator_.GenerateId(); | 83 local_frame_id_ = id_allocator_.GenerateId(); |
| 100 display_surface_changed = true; | |
| 101 } else { | |
| 102 // If the display surface is changing then we shouldn't add references | |
| 103 // from the old display surface. We want to add references from the new | |
| 104 // display surface, this happens after we submit the first CompositorFrame | |
| 105 // so the new display surface exists. | |
| 106 if (surface_tracker_.HasReferencesToAdd()) { | |
| 107 compositor_frame_sink_->AddSurfaceReferences( | |
| 108 surface_tracker_.GetReferencesToAdd()); | |
| 109 } | |
| 110 } | |
| 111 | 84 |
| 112 compositor_frame_sink_->SubmitCompositorFrame(local_frame_id_, | 85 compositor_frame_sink_->SubmitCompositorFrame(local_frame_id_, |
| 113 std::move(frame)); | 86 std::move(frame)); |
| 114 last_submitted_frame_size_ = frame_size; | 87 last_submitted_frame_size_ = frame_size; |
| 115 | |
| 116 if (display_surface_changed) | |
| 117 UpdateDisplaySurfaceId(); | |
| 118 | |
| 119 // Remove references to surfaces that are no longer embedded. This has to | |
| 120 // happen after the frame is submitted otherwise we could end up deleting | |
| 121 // a surface that is still embedded in the last submitted frame. | |
| 122 if (surface_tracker_.HasReferencesToRemove()) { | |
| 123 compositor_frame_sink_->RemoveSurfaceReferences( | |
| 124 surface_tracker_.GetReferencesToRemove()); | |
| 125 } | |
| 126 } | 88 } |
| 127 } | 89 } |
| 128 | 90 |
| 129 void FrameGenerator::ReclaimResources( | 91 void FrameGenerator::ReclaimResources( |
| 130 const cc::ReturnedResourceArray& resources) { | 92 const cc::ReturnedResourceArray& resources) { |
| 131 // Nothing to do here because FrameGenerator CompositorFrames don't reference | 93 // Nothing to do here because FrameGenerator CompositorFrames don't reference |
| 132 // any resources. | 94 // any resources. |
| 133 } | 95 } |
| 134 | 96 |
| 135 void FrameGenerator::WillDrawSurface() { | 97 void FrameGenerator::WillDrawSurface() { |
| 136 // TODO(fsamuel, staraz): Implement this. | 98 // TODO(fsamuel, staraz): Implement this. |
| 137 } | 99 } |
| 138 | 100 |
| 139 void FrameGenerator::UpdateDisplaySurfaceId() { | |
| 140 // FrameGenerator owns the display root surface and is a bit of a special | |
| 141 // case. There is no surface that embeds the display surface, so nothing | |
| 142 // would reference it. Instead, a reference from the top level root is added | |
| 143 // to mark the display surface as visible. As a result, FrameGenerator is | |
| 144 // responsible for maintaining a reference from the top level root to the | |
| 145 // display surface, in addition to references from the display surface to | |
| 146 // embedded surfaces. | |
| 147 const cc::SurfaceId old_surface_id = surface_tracker_.current_surface_id(); | |
| 148 const cc::SurfaceId new_surface_id( | |
| 149 cc::FrameSinkId(WindowIdToTransportId(root_window_->id()), 0), | |
| 150 local_frame_id_); | |
| 151 | |
| 152 DCHECK_NE(old_surface_id, new_surface_id); | |
| 153 | |
| 154 // Set new SurfaceId for the display surface. This will add references from | |
| 155 // the new display surface to all embedded surfaces. | |
| 156 surface_tracker_.SetCurrentSurfaceId(new_surface_id); | |
| 157 std::vector<cc::SurfaceReference> references_to_add = | |
| 158 surface_tracker_.GetReferencesToAdd(); | |
| 159 | |
| 160 // Adds a reference from the top level root to the new display surface. | |
| 161 references_to_add.push_back(cc::SurfaceReference( | |
| 162 root_window_->delegate()->GetRootSurfaceId(), new_surface_id)); | |
| 163 | |
| 164 compositor_frame_sink_->AddSurfaceReferences(references_to_add); | |
| 165 | |
| 166 // Remove the reference from the top level root to the old display surface | |
| 167 // after we have added references from the new display surface. Not applicable | |
| 168 // for the first display surface. | |
| 169 if (old_surface_id.is_valid()) { | |
| 170 compositor_frame_sink_->RemoveSurfaceReferences( | |
| 171 std::vector<cc::SurfaceReference>{cc::SurfaceReference( | |
| 172 root_window_->delegate()->GetRootSurfaceId(), old_surface_id)}); | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( | 101 cc::CompositorFrame FrameGenerator::GenerateCompositorFrame( |
| 177 const gfx::Rect& output_rect) { | 102 const gfx::Rect& output_rect) { |
| 178 const int render_pass_id = 1; | 103 const int render_pass_id = 1; |
| 179 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); | 104 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); |
| 180 render_pass->SetNew(render_pass_id, output_rect, output_rect, | 105 render_pass->SetNew(render_pass_id, output_rect, output_rect, |
| 181 gfx::Transform()); | 106 gfx::Transform()); |
| 182 | 107 |
| 183 DrawWindow(render_pass.get(), delegate_->GetActiveRootWindow()); | 108 DrawWindow(render_pass.get(), delegate_->GetActiveRootWindow()); |
| 184 | 109 |
| 185 cc::CompositorFrame frame; | 110 cc::CompositorFrame frame; |
| 186 frame.render_pass_list.push_back(std::move(render_pass)); | 111 frame.render_pass_list.push_back(std::move(render_pass)); |
| 187 if (delegate_->IsInHighContrastMode()) { | 112 if (delegate_->IsInHighContrastMode()) { |
| 188 std::unique_ptr<cc::RenderPass> invert_pass = cc::RenderPass::Create(); | 113 std::unique_ptr<cc::RenderPass> invert_pass = cc::RenderPass::Create(); |
| 189 invert_pass->SetNew(2, output_rect, output_rect, gfx::Transform()); | 114 invert_pass->SetNew(2, output_rect, output_rect, gfx::Transform()); |
| 190 cc::SharedQuadState* shared_state = | 115 cc::SharedQuadState* shared_state = |
| 191 invert_pass->CreateAndAppendSharedQuadState(); | 116 invert_pass->CreateAndAppendSharedQuadState(); |
| 192 shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect, | 117 shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect, |
| 193 output_rect, false, 1.f, SkBlendMode::kSrcOver, 0); | 118 output_rect, false, 1.f, SkBlendMode::kSrcOver, 0); |
| 194 auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>(); | 119 auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>(); |
| 195 render_pass->filters.Append(cc::FilterOperation::CreateInvertFilter(1.f)); | 120 render_pass->filters.Append(cc::FilterOperation::CreateInvertFilter(1.f)); |
| 196 quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, | 121 quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, |
| 197 0 /* mask_resource_id */, gfx::Vector2dF() /* mask_uv_scale */, | 122 0 /* mask_resource_id */, gfx::Vector2dF() /* mask_uv_scale */, |
| 198 gfx::Size() /* mask_texture_size */, | 123 gfx::Size() /* mask_texture_size */, |
| 199 gfx::Vector2dF() /* filters_scale */, | 124 gfx::Vector2dF() /* filters_scale */, |
| 200 gfx::PointF() /* filters_origin */); | 125 gfx::PointF() /* filters_origin */); |
| 201 frame.render_pass_list.push_back(std::move(invert_pass)); | 126 frame.render_pass_list.push_back(std::move(invert_pass)); |
| 202 } | 127 } |
| 203 frame.metadata.device_scale_factor = device_scale_factor_; | 128 frame.metadata.device_scale_factor = device_scale_factor_; |
| 204 | 129 |
| 130 if (window_manager_surface_id_.is_valid()) |
| 131 frame.metadata.referenced_surfaces.push_back(window_manager_surface_id_); |
| 132 |
| 205 return frame; | 133 return frame; |
| 206 } | 134 } |
| 207 | 135 |
| 208 void FrameGenerator::DrawWindow(cc::RenderPass* pass, ServerWindow* window) { | 136 void FrameGenerator::DrawWindow(cc::RenderPass* pass, ServerWindow* window) { |
| 209 if (!window || !window->visible()) | 137 if (!window || !window->visible()) |
| 210 return; | 138 return; |
| 211 | 139 |
| 212 if (!window->compositor_frame_sink_manager()) | 140 if (!window->compositor_frame_sink_manager()) |
| 213 return; | 141 return; |
| 214 | 142 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 234 1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting-context_id */); | 162 1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting-context_id */); |
| 235 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); | 163 auto* quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); |
| 236 quad->SetAll(sqs, bounds_at_origin /* rect */, | 164 quad->SetAll(sqs, bounds_at_origin /* rect */, |
| 237 gfx::Rect() /* opaque_rect */, | 165 gfx::Rect() /* opaque_rect */, |
| 238 bounds_at_origin /* visible_rect */, true /* needs_blending*/, | 166 bounds_at_origin /* visible_rect */, true /* needs_blending*/, |
| 239 default_surface_id); | 167 default_surface_id); |
| 240 } | 168 } |
| 241 | 169 |
| 242 void FrameGenerator::OnWindowDestroying(ServerWindow* window) { | 170 void FrameGenerator::OnWindowDestroying(ServerWindow* window) { |
| 243 Remove(window); | 171 Remove(window); |
| 244 ServerWindowCompositorFrameSinkManager* compositor_frame_sink_manager = | |
| 245 window->compositor_frame_sink_manager(); | |
| 246 // If FrameGenerator was observing |window|, then that means it had a | |
| 247 // CompositorFrame at some point in time and should have a | |
| 248 // ServerWindowCompositorFrameSinkManager. | |
| 249 DCHECK(compositor_frame_sink_manager); | |
| 250 | |
| 251 cc::SurfaceId surface_id = | |
| 252 window->compositor_frame_sink_manager()->GetLatestSurfaceId(); | |
| 253 if (surface_id.is_valid()) | |
| 254 surface_tracker_.UnembedSurface(surface_id.frame_sink_id()); | |
| 255 } | 172 } |
| 256 | 173 |
| 257 } // namespace ws | 174 } // namespace ws |
| 258 | 175 |
| 259 } // namespace ui | 176 } // namespace ui |
| OLD | NEW |