OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "blimp/client/feature/compositor/blimp_compositor.h" | 5 #include "blimp/client/feature/compositor/blimp_compositor.h" |
6 | 6 |
7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
10 #include "base/numerics/safe_conversions.h" | 10 #include "base/numerics/safe_conversions.h" |
11 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" |
12 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
13 #include "base/threading/thread_local.h" | 13 #include "base/threading/thread_local.h" |
14 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "blimp/client/core/compositor/delegated_output_surface.h" |
16 #include "blimp/client/feature/compositor/blimp_context_provider.h" | 17 #include "blimp/client/feature/compositor/blimp_context_provider.h" |
17 #include "blimp/client/feature/compositor/blimp_delegating_output_surface.h" | 18 #include "blimp/net/blimp_stats.h" |
18 #include "blimp/client/feature/compositor/blimp_output_surface.h" | |
19 #include "cc/animation/animation_host.h" | 19 #include "cc/animation/animation_host.h" |
20 #include "cc/layers/layer.h" | 20 #include "cc/layers/layer.h" |
| 21 #include "cc/layers/surface_layer.h" |
21 #include "cc/output/output_surface.h" | 22 #include "cc/output/output_surface.h" |
22 #include "cc/proto/compositor_message.pb.h" | 23 #include "cc/proto/compositor_message.pb.h" |
| 24 #include "cc/surfaces/surface.h" |
| 25 #include "cc/surfaces/surface_factory.h" |
| 26 #include "cc/surfaces/surface_id_allocator.h" |
| 27 #include "cc/surfaces/surface_manager.h" |
23 #include "cc/trees/layer_tree_host.h" | 28 #include "cc/trees/layer_tree_host.h" |
24 #include "net/base/net_errors.h" | 29 #include "net/base/net_errors.h" |
25 #include "ui/gl/gl_surface.h" | 30 #include "ui/gl/gl_surface.h" |
26 | 31 |
27 namespace blimp { | 32 namespace blimp { |
28 namespace client { | 33 namespace client { |
29 | 34 |
| 35 namespace { |
| 36 |
| 37 void SatisfyCallback(cc::SurfaceManager* manager, |
| 38 const cc::SurfaceSequence& sequence) { |
| 39 std::vector<uint32_t> sequences; |
| 40 sequences.push_back(sequence.sequence); |
| 41 manager->DidSatisfySequences(sequence.client_id, &sequences); |
| 42 } |
| 43 |
| 44 void RequireCallback(cc::SurfaceManager* manager, |
| 45 const cc::SurfaceId& id, |
| 46 const cc::SurfaceSequence& sequence) { |
| 47 cc::Surface* surface = manager->GetSurfaceForId(id); |
| 48 if (!surface) { |
| 49 LOG(ERROR) << "Attempting to require callback on nonexistent surface"; |
| 50 return; |
| 51 } |
| 52 surface->AddDestructionDependency(sequence); |
| 53 } |
| 54 |
| 55 } // namespace |
| 56 |
30 BlimpCompositor::BlimpCompositor(int render_widget_id, | 57 BlimpCompositor::BlimpCompositor(int render_widget_id, |
| 58 cc::SurfaceManager* surface_manager, |
| 59 uint32_t surface_client_id, |
31 BlimpCompositorClient* client) | 60 BlimpCompositorClient* client) |
32 : render_widget_id_(render_widget_id), | 61 : render_widget_id_(render_widget_id), |
33 client_(client), | 62 client_(client), |
34 window_(gfx::kNullAcceleratedWidget), | |
35 host_should_be_visible_(false), | 63 host_should_be_visible_(false), |
36 output_surface_request_pending_(false), | 64 output_surface_(nullptr), |
37 remote_proto_channel_receiver_(nullptr) {} | 65 surface_manager_(surface_manager), |
| 66 surface_id_allocator_( |
| 67 base::MakeUnique<cc::SurfaceIdAllocator>(surface_client_id)), |
| 68 layer_(cc::Layer::Create()), |
| 69 remote_proto_channel_receiver_(nullptr), |
| 70 weak_factory_(this) { |
| 71 DCHECK(thread_checker_.CalledOnValidThread()); |
| 72 surface_manager_->RegisterSurfaceClientId(surface_id_allocator_->client_id()); |
| 73 } |
38 | 74 |
39 BlimpCompositor::~BlimpCompositor() { | 75 BlimpCompositor::~BlimpCompositor() { |
| 76 DCHECK(thread_checker_.CalledOnValidThread()); |
| 77 |
40 if (host_) | 78 if (host_) |
41 DestroyLayerTreeHost(); | 79 DestroyLayerTreeHost(); |
| 80 surface_manager_->InvalidateSurfaceClientId( |
| 81 surface_id_allocator_->client_id()); |
42 } | 82 } |
43 | 83 |
44 void BlimpCompositor::SetVisible(bool visible) { | 84 void BlimpCompositor::SetVisible(bool visible) { |
45 host_should_be_visible_ = visible; | 85 host_should_be_visible_ = visible; |
46 SetVisibleInternal(host_should_be_visible_); | 86 if (host_) |
47 } | 87 host_->SetVisible(host_should_be_visible_); |
48 | |
49 void BlimpCompositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) { | |
50 if (widget == window_) | |
51 return; | |
52 | |
53 DCHECK(window_ == gfx::kNullAcceleratedWidget); | |
54 window_ = widget; | |
55 | |
56 // The compositor should not be visible if there is no output surface. | |
57 DCHECK(!host_ || !host_->visible()); | |
58 | |
59 // This will properly set visibility and will build the output surface if | |
60 // necessary. | |
61 SetVisibleInternal(host_should_be_visible_); | |
62 } | |
63 | |
64 void BlimpCompositor::ReleaseAcceleratedWidget() { | |
65 if (window_ == gfx::kNullAcceleratedWidget) | |
66 return; | |
67 | |
68 // Hide the compositor and drop the output surface if necessary. | |
69 SetVisibleInternal(false); | |
70 | |
71 window_ = gfx::kNullAcceleratedWidget; | |
72 } | 88 } |
73 | 89 |
74 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { | 90 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { |
75 if (input_manager_) | 91 if (input_manager_) |
76 return input_manager_->OnTouchEvent(motion_event); | 92 return input_manager_->OnTouchEvent(motion_event); |
77 return false; | 93 return false; |
78 } | 94 } |
79 | 95 |
80 void BlimpCompositor::WillBeginMainFrame() {} | 96 void BlimpCompositor::RequestNewOutputSurface() { |
| 97 DCHECK(!surface_factory_) |
| 98 << "Any connection to the old output surface should have been destroyed"; |
81 | 99 |
82 void BlimpCompositor::DidBeginMainFrame() {} | 100 scoped_refptr<BlimpContextProvider> compositor_context_provider = |
| 101 BlimpContextProvider::Create(gfx::kNullAcceleratedWidget, |
| 102 client_->GetGpuMemoryBufferManager()); |
83 | 103 |
84 void BlimpCompositor::BeginMainFrame(const cc::BeginFrameArgs& args) {} | 104 // TODO(khushalsagar): Make a worker context and bind it to the current |
| 105 // thread: |
| 106 // Worker context is bound to the main thread in RenderThreadImpl. One day |
| 107 // that will change and then this will have to be removed. |
| 108 // worker_context_provider->BindToCurrentThread(); |
85 | 109 |
86 void BlimpCompositor::BeginMainFrameNotExpectedSoon() {} | 110 std::unique_ptr<DelegatedOutputSurface> delegated_output_surface = |
| 111 base::MakeUnique<DelegatedOutputSurface>( |
| 112 std::move(compositor_context_provider), nullptr, |
| 113 base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr()); |
87 | 114 |
88 void BlimpCompositor::UpdateLayerTreeHost() {} | 115 host_->SetOutputSurface(std::move(delegated_output_surface)); |
89 | |
90 void BlimpCompositor::ApplyViewportDeltas( | |
91 const gfx::Vector2dF& inner_delta, | |
92 const gfx::Vector2dF& outer_delta, | |
93 const gfx::Vector2dF& elastic_overscroll_delta, | |
94 float page_scale, | |
95 float top_controls_delta) {} | |
96 | |
97 void BlimpCompositor::RequestNewOutputSurface() { | |
98 output_surface_request_pending_ = true; | |
99 HandlePendingOutputSurfaceRequest(); | |
100 } | 116 } |
101 | 117 |
102 void BlimpCompositor::DidInitializeOutputSurface() { | 118 void BlimpCompositor::DidCommitAndDrawFrame() { |
| 119 BlimpStats::GetInstance()->Add(BlimpStats::COMMIT, 1); |
103 } | 120 } |
104 | 121 |
105 void BlimpCompositor::DidFailToInitializeOutputSurface() {} | |
106 | |
107 void BlimpCompositor::WillCommit() {} | |
108 | |
109 void BlimpCompositor::DidCommit() {} | |
110 | |
111 void BlimpCompositor::DidCommitAndDrawFrame() { | |
112 client_->DidCommitAndDrawFrame(); | |
113 } | |
114 | |
115 void BlimpCompositor::DidCompleteSwapBuffers() { | |
116 client_->DidCompleteSwapBuffers(); | |
117 } | |
118 | |
119 void BlimpCompositor::DidCompletePageScaleAnimation() {} | |
120 | |
121 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { | 122 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { |
122 remote_proto_channel_receiver_ = receiver; | 123 remote_proto_channel_receiver_ = receiver; |
123 } | 124 } |
124 | 125 |
125 void BlimpCompositor::SendCompositorProto( | 126 void BlimpCompositor::SendCompositorProto( |
126 const cc::proto::CompositorMessage& proto) { | 127 const cc::proto::CompositorMessage& proto) { |
127 client_->SendCompositorMessage(render_widget_id_, proto); | 128 client_->SendCompositorMessage(render_widget_id_, proto); |
128 } | 129 } |
129 | 130 |
130 void BlimpCompositor::OnCompositorMessageReceived( | 131 void BlimpCompositor::OnCompositorMessageReceived( |
(...skipping 26 matching lines...) Expand all Loading... |
157 DCHECK(remote_proto_channel_receiver_); | 158 DCHECK(remote_proto_channel_receiver_); |
158 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); | 159 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); |
159 } | 160 } |
160 } | 161 } |
161 | 162 |
162 void BlimpCompositor::SendWebGestureEvent( | 163 void BlimpCompositor::SendWebGestureEvent( |
163 const blink::WebGestureEvent& gesture_event) { | 164 const blink::WebGestureEvent& gesture_event) { |
164 client_->SendWebGestureEvent(render_widget_id_, gesture_event); | 165 client_->SendWebGestureEvent(render_widget_id_, gesture_event); |
165 } | 166 } |
166 | 167 |
167 void BlimpCompositor::SetVisibleInternal(bool visible) { | 168 void BlimpCompositor::BindToOutputSurface( |
168 if (!host_) | 169 base::WeakPtr<BlimpOutputSurface> output_surface) { |
| 170 DCHECK(thread_checker_.CalledOnValidThread()); |
| 171 DCHECK(!output_surface_); |
| 172 DCHECK(!surface_factory_); |
| 173 |
| 174 output_surface_ = output_surface; |
| 175 surface_factory_ = |
| 176 base::MakeUnique<cc::SurfaceFactory>(surface_manager_, this); |
| 177 } |
| 178 |
| 179 void BlimpCompositor::SwapCompositorFrame(cc::CompositorFrame frame) { |
| 180 DCHECK(thread_checker_.CalledOnValidThread()); |
| 181 DCHECK(surface_factory_); |
| 182 |
| 183 cc::RenderPass* root_pass = |
| 184 frame.delegated_frame_data->render_pass_list.back().get(); |
| 185 gfx::Size surface_size = root_pass->output_rect.size(); |
| 186 |
| 187 if (surface_id_.is_null() || current_surface_size_ != surface_size) { |
| 188 DestroyDelegatedContent(); |
| 189 DCHECK(layer_->children().empty()); |
| 190 |
| 191 surface_id_ = surface_id_allocator_->GenerateId(); |
| 192 surface_factory_->Create(surface_id_); |
| 193 current_surface_size_ = surface_size; |
| 194 |
| 195 // Manager must outlive compositors using it. |
| 196 scoped_refptr<cc::SurfaceLayer> content_layer = cc::SurfaceLayer::Create( |
| 197 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)), |
| 198 base::Bind(&RequireCallback, base::Unretained(surface_manager_))); |
| 199 content_layer->SetSurfaceId(surface_id_, 1.f, surface_size); |
| 200 content_layer->SetBounds(current_surface_size_); |
| 201 content_layer->SetIsDrawable(true); |
| 202 content_layer->SetContentsOpaque(true); |
| 203 |
| 204 layer_->AddChild(content_layer); |
| 205 } |
| 206 |
| 207 surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame), |
| 208 base::Closure()); |
| 209 } |
| 210 |
| 211 void BlimpCompositor::UnbindOutputSurface() { |
| 212 DCHECK(thread_checker_.CalledOnValidThread()); |
| 213 DCHECK(surface_factory_); |
| 214 |
| 215 DestroyDelegatedContent(); |
| 216 surface_factory_.reset(); |
| 217 output_surface_ = nullptr; |
| 218 } |
| 219 |
| 220 void BlimpCompositor::ReturnResources( |
| 221 const cc::ReturnedResourceArray& resources) { |
| 222 DCHECK(surface_factory_); |
| 223 compositor_task_runner_->PostTask( |
| 224 FROM_HERE, base::Bind(&BlimpOutputSurface::ReclaimCompositorResources, |
| 225 output_surface_, resources)); |
| 226 } |
| 227 |
| 228 void BlimpCompositor::DestroyDelegatedContent() { |
| 229 if (surface_id_.is_null()) |
169 return; | 230 return; |
170 | 231 |
171 VLOG(1) << "Setting visibility to: " << visible | 232 // Remove any references for the surface layer that uses this |surface_id_|. |
172 << " for render widget: " << render_widget_id_; | 233 layer_->RemoveAllChildren(); |
173 | 234 surface_factory_->Destroy(surface_id_); |
174 if (visible && window_ != gfx::kNullAcceleratedWidget) { | 235 surface_id_ = cc::SurfaceId(); |
175 // If we're supposed to be visible and we have a valid | |
176 // gfx::AcceleratedWidget make our compositor visible. If the compositor | |
177 // had an outstanding output surface request, trigger the request again so | |
178 // we build the output surface. | |
179 host_->SetVisible(true); | |
180 if (output_surface_request_pending_) | |
181 HandlePendingOutputSurfaceRequest(); | |
182 } else if (!visible) { | |
183 // If not visible, hide the compositor and have it drop it's output | |
184 // surface. | |
185 host_->SetVisible(false); | |
186 if (!host_->output_surface_lost()) { | |
187 host_->ReleaseOutputSurface(); | |
188 } | |
189 } | |
190 } | 236 } |
191 | 237 |
192 void BlimpCompositor::CreateLayerTreeHost( | 238 void BlimpCompositor::CreateLayerTreeHost( |
193 const cc::proto::InitializeImpl& initialize_message) { | 239 const cc::proto::InitializeImpl& initialize_message) { |
194 DCHECK(!host_); | 240 DCHECK(!host_); |
195 VLOG(1) << "Creating LayerTreeHost for render widget: " << render_widget_id_; | 241 VLOG(1) << "Creating LayerTreeHost for render widget: " << render_widget_id_; |
196 | 242 |
197 // Create the LayerTreeHost | 243 // Create the LayerTreeHost |
198 cc::LayerTreeHost::InitParams params; | 244 cc::LayerTreeHost::InitParams params; |
199 params.client = this; | 245 params.client = this; |
200 params.task_graph_runner = client_->GetTaskGraphRunner(); | 246 params.task_graph_runner = client_->GetTaskGraphRunner(); |
201 params.gpu_memory_buffer_manager = client_->GetGpuMemoryBufferManager(); | 247 params.gpu_memory_buffer_manager = client_->GetGpuMemoryBufferManager(); |
202 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); | 248 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
203 params.image_serialization_processor = | 249 params.image_serialization_processor = |
204 client_->GetImageSerializationProcessor(); | 250 client_->GetImageSerializationProcessor(); |
205 params.settings = client_->GetLayerTreeSettings(); | 251 params.settings = client_->GetLayerTreeSettings(); |
206 params.animation_host = cc::AnimationHost::CreateMainInstance(); | 252 params.animation_host = cc::AnimationHost::CreateMainInstance(); |
207 | 253 |
208 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = | 254 compositor_task_runner_ = client_->GetCompositorTaskRunner(); |
209 client_->GetCompositorTaskRunner(); | |
210 | 255 |
211 host_ = | 256 host_ = cc::LayerTreeHost::CreateRemoteClient( |
212 cc::LayerTreeHost::CreateRemoteClient(this /* remote_proto_channel */, | 257 this /* remote_proto_channel */, compositor_task_runner_, ¶ms); |
213 compositor_task_runner, ¶ms); | 258 host_->SetVisible(host_should_be_visible_); |
214 | |
215 // Now that we have a host, set the visiblity on it correctly. | |
216 SetVisibleInternal(host_should_be_visible_); | |
217 | 259 |
218 DCHECK(!input_manager_); | 260 DCHECK(!input_manager_); |
219 input_manager_ = | 261 input_manager_ = BlimpInputManager::Create( |
220 BlimpInputManager::Create(this, | 262 this, base::ThreadTaskRunnerHandle::Get(), compositor_task_runner_, |
221 base::ThreadTaskRunnerHandle::Get(), | 263 host_->GetInputHandler()); |
222 compositor_task_runner, | |
223 host_->GetInputHandler()); | |
224 } | 264 } |
225 | 265 |
226 void BlimpCompositor::DestroyLayerTreeHost() { | 266 void BlimpCompositor::DestroyLayerTreeHost() { |
227 DCHECK(host_); | 267 DCHECK(host_); |
228 VLOG(1) << "Destroying LayerTreeHost for render widget: " | 268 VLOG(1) << "Destroying LayerTreeHost for render widget: " |
229 << render_widget_id_; | 269 << render_widget_id_; |
230 // Tear down the output surface connection with the old LayerTreeHost | 270 // Tear down the output surface connection with the old LayerTreeHost |
231 // instance. | 271 // instance. |
232 SetVisibleInternal(false); | 272 DestroyDelegatedContent(); |
| 273 surface_factory_.reset(); |
233 | 274 |
234 // Destroy the old LayerTreeHost state. | 275 // Destroy the old LayerTreeHost state. |
235 host_.reset(); | 276 host_.reset(); |
236 | 277 |
237 // Destroy the old input manager state. | 278 // Destroy the old input manager state. |
238 // It is important to destroy the LayerTreeHost before destroying the input | 279 // It is important to destroy the LayerTreeHost before destroying the input |
239 // manager as it has a reference to the cc::InputHandlerClient owned by the | 280 // manager as it has a reference to the cc::InputHandlerClient owned by the |
240 // BlimpInputManager. | 281 // BlimpInputManager. |
241 input_manager_.reset(); | 282 input_manager_.reset(); |
242 | 283 |
243 // Reset other state. | |
244 output_surface_request_pending_ = false; | |
245 | |
246 // Make sure we don't have a receiver at this point. | 284 // Make sure we don't have a receiver at this point. |
247 DCHECK(!remote_proto_channel_receiver_); | 285 DCHECK(!remote_proto_channel_receiver_); |
248 } | 286 } |
249 | 287 |
250 void BlimpCompositor::HandlePendingOutputSurfaceRequest() { | |
251 DCHECK(output_surface_request_pending_); | |
252 | |
253 // We might have had a request from a LayerTreeHost that was then | |
254 // hidden (and hidden means we don't have a native surface). | |
255 // Also make sure we only handle this once. | |
256 if (!host_->visible() || window_ == gfx::kNullAcceleratedWidget) | |
257 return; | |
258 | |
259 scoped_refptr<BlimpContextProvider> display_context_provider = | |
260 BlimpContextProvider::Create(window_, | |
261 client_->GetGpuMemoryBufferManager()); | |
262 scoped_refptr<BlimpContextProvider> compositor_context_provider = | |
263 BlimpContextProvider::Create(gfx::kNullAcceleratedWidget, | |
264 client_->GetGpuMemoryBufferManager()); | |
265 scoped_refptr<BlimpContextProvider> worker_context_provider = nullptr; | |
266 // TODO(khushalsagar): Make a worker context and bind it to the current | |
267 // thread: | |
268 // Worker context is bound to the main thread in RenderThreadImpl. One day | |
269 // that will change and then this will have to be removed. | |
270 // worker_context_provider->BindToCurrentThread(); | |
271 | |
272 auto display_output_surface = | |
273 base::MakeUnique<BlimpOutputSurface>(std::move(display_context_provider)); | |
274 auto delegating_output_surface = | |
275 base::MakeUnique<BlimpDelegatingOutputSurface>( | |
276 std::move(compositor_context_provider), | |
277 std::move(worker_context_provider), std::move(display_output_surface), | |
278 client_->GetGpuMemoryBufferManager(), | |
279 host_->settings().renderer_settings, | |
280 client_->GetCompositorTaskRunner().get()); | |
281 | |
282 host_->SetOutputSurface(std::move(delegating_output_surface)); | |
283 output_surface_request_pending_ = false; | |
284 } | |
285 | |
286 } // namespace client | 288 } // namespace client |
287 } // namespace blimp | 289 } // namespace blimp |
OLD | NEW |