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/lazy_instance.h" | 9 #include "base/lazy_instance.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/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
14 #include "base/threading/thread_local.h" | 14 #include "base/threading/thread_local.h" |
15 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
16 #include "blimp/client/feature/compositor/blimp_context_provider.h" | 16 #include "blimp/client/feature/compositor/blimp_context_provider.h" |
17 #include "blimp/client/feature/compositor/blimp_layer_tree_settings.h" | 17 #include "blimp/client/feature/compositor/blimp_layer_tree_settings.h" |
18 #include "blimp/client/feature/compositor/blimp_output_surface.h" | 18 #include "blimp/client/feature/compositor/blimp_output_surface.h" |
19 #include "blimp/client/feature/compositor/test/dummy_layer_driver.h" | |
20 #include "blimp/client/feature/render_widget_feature.h" | 19 #include "blimp/client/feature/render_widget_feature.h" |
21 #include "blimp/common/compositor/blimp_task_graph_runner.h" | 20 #include "blimp/common/compositor/blimp_task_graph_runner.h" |
22 #include "cc/layers/layer.h" | 21 #include "cc/layers/layer.h" |
23 #include "cc/layers/layer_settings.h" | 22 #include "cc/layers/layer_settings.h" |
24 #include "cc/output/output_surface.h" | 23 #include "cc/output/output_surface.h" |
25 #include "cc/proto/compositor_message.pb.h" | 24 #include "cc/proto/compositor_message.pb.h" |
26 #include "cc/trees/layer_tree_host.h" | 25 #include "cc/trees/layer_tree_host.h" |
27 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
28 #include "ui/gl/gl_surface.h" | 27 #include "ui/gl/gl_surface.h" |
29 | 28 |
30 namespace blimp { | 29 namespace blimp { |
31 namespace client { | 30 namespace client { |
32 namespace { | 31 namespace { |
33 | 32 |
34 base::LazyInstance<blimp::BlimpTaskGraphRunner> g_task_graph_runner = | 33 base::LazyInstance<blimp::BlimpTaskGraphRunner> g_task_graph_runner = |
35 LAZY_INSTANCE_INITIALIZER; | 34 LAZY_INSTANCE_INITIALIZER; |
36 | 35 |
37 const int kDummyTabId = 0; | 36 const int kDummyTabId = 0; |
38 | 37 |
39 // TODO(dtrainor): Replace this when Layer content comes from the server (see | |
40 // crbug.com/527200 for details). | |
41 base::LazyInstance<DummyLayerDriver> g_dummy_layer_driver = | |
42 LAZY_INSTANCE_INITIALIZER; | |
43 | |
44 } // namespace | 38 } // namespace |
45 | 39 |
46 BlimpCompositor::BlimpCompositor(float dp_to_px, | 40 BlimpCompositor::BlimpCompositor(float dp_to_px, |
47 RenderWidgetFeature* render_widget_feature) | 41 RenderWidgetFeature* render_widget_feature) |
48 : device_scale_factor_(dp_to_px), | 42 : device_scale_factor_(dp_to_px), |
49 window_(gfx::kNullAcceleratedWidget), | 43 window_(gfx::kNullAcceleratedWidget), |
50 host_should_be_visible_(false), | 44 host_should_be_visible_(false), |
51 output_surface_request_pending_(false), | 45 output_surface_request_pending_(false), |
52 remote_proto_channel_receiver_(nullptr), | 46 remote_proto_channel_receiver_(nullptr), |
53 render_widget_feature_(render_widget_feature) { | 47 render_widget_feature_(render_widget_feature) { |
| 48 DCHECK(render_widget_feature_); |
54 render_widget_feature_->SetDelegate(kDummyTabId, this); | 49 render_widget_feature_->SetDelegate(kDummyTabId, this); |
55 } | 50 } |
56 | 51 |
57 BlimpCompositor::~BlimpCompositor() { | 52 BlimpCompositor::~BlimpCompositor() { |
58 render_widget_feature_->RemoveDelegate(kDummyTabId); | 53 render_widget_feature_->RemoveDelegate(kDummyTabId); |
59 SetVisible(false); | 54 SetVisible(false); |
60 | 55 |
61 // Destroy |host_| first, as it has a reference to the |settings_| and runs | 56 // Destroy |host_| first, as it has a reference to the |settings_| and runs |
62 // tasks on |compositor_thread_|. | 57 // tasks on |compositor_thread_|. |
63 host_.reset(); | 58 host_.reset(); |
64 settings_.reset(); | 59 settings_.reset(); |
65 | 60 |
66 // We must destroy |host_| before the |input_manager_|. | 61 // We must destroy |host_| before the |input_manager_|. |
67 input_manager_.reset(); | 62 input_manager_.reset(); |
68 | 63 |
69 if (compositor_thread_) | 64 if (compositor_thread_) |
70 compositor_thread_->Stop(); | 65 compositor_thread_->Stop(); |
71 } | 66 } |
72 | 67 |
73 void BlimpCompositor::SetVisible(bool visible) { | 68 void BlimpCompositor::SetVisible(bool visible) { |
74 // For testing. Remove once we bind to the network layer. | |
75 if (!host_) | |
76 CreateLayerTreeHost(nullptr); | |
77 | |
78 host_should_be_visible_ = visible; | 69 host_should_be_visible_ = visible; |
79 if (!host_ || host_->visible() == visible) | 70 SetVisibleInternal(host_should_be_visible_); |
80 return; | |
81 | |
82 if (visible) { | |
83 // If visible, show the compositor. If the compositor had an outstanding | |
84 // output surface request, trigger the request again so we build the output | |
85 // surface. | |
86 host_->SetVisible(true); | |
87 if (output_surface_request_pending_) | |
88 HandlePendingOutputSurfaceRequest(); | |
89 } else { | |
90 // If not visible, hide the compositor and have it drop it's output surface. | |
91 DCHECK(host_->visible()); | |
92 host_->SetVisible(false); | |
93 if (!host_->output_surface_lost()) | |
94 host_->ReleaseOutputSurface(); | |
95 } | |
96 } | |
97 | |
98 void BlimpCompositor::SetSize(const gfx::Size& size) { | |
99 viewport_size_ = size; | |
100 if (host_) | |
101 host_->SetViewportSize(viewport_size_); | |
102 } | 71 } |
103 | 72 |
104 void BlimpCompositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) { | 73 void BlimpCompositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) { |
105 if (widget == window_) | 74 if (widget == window_) |
106 return; | 75 return; |
107 | 76 |
108 DCHECK(window_ == gfx::kNullAcceleratedWidget); | 77 DCHECK(window_ == gfx::kNullAcceleratedWidget); |
109 window_ = widget; | 78 window_ = widget; |
110 | 79 |
111 // The compositor should not be visible if there is no output surface. | 80 // The compositor should not be visible if there is no output surface. |
112 DCHECK(!host_ || !host_->visible()); | 81 DCHECK(!host_ || !host_->visible()); |
113 | 82 |
114 // This will properly set visibility and will build the output surface if | 83 // This will properly set visibility and will build the output surface if |
115 // necessary. | 84 // necessary. |
116 SetVisible(host_should_be_visible_); | 85 SetVisibleInternal(host_should_be_visible_); |
117 } | 86 } |
118 | 87 |
119 void BlimpCompositor::ReleaseAcceleratedWidget() { | 88 void BlimpCompositor::ReleaseAcceleratedWidget() { |
120 if (window_ == gfx::kNullAcceleratedWidget) | 89 if (window_ == gfx::kNullAcceleratedWidget) |
121 return; | 90 return; |
122 | 91 |
123 // Hide the compositor and drop the output surface if necessary. | 92 // Hide the compositor and drop the output surface if necessary. |
124 SetVisible(false); | 93 SetVisibleInternal(false); |
125 | 94 |
126 window_ = gfx::kNullAcceleratedWidget; | 95 window_ = gfx::kNullAcceleratedWidget; |
127 } | 96 } |
128 | 97 |
129 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { | 98 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { |
130 if (input_manager_) | 99 if (input_manager_) |
131 return input_manager_->OnTouchEvent(motion_event); | 100 return input_manager_->OnTouchEvent(motion_event); |
132 return false; | 101 return false; |
133 } | 102 } |
134 | 103 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { | 145 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { |
177 remote_proto_channel_receiver_ = receiver; | 146 remote_proto_channel_receiver_ = receiver; |
178 } | 147 } |
179 | 148 |
180 void BlimpCompositor::SendCompositorProto( | 149 void BlimpCompositor::SendCompositorProto( |
181 const cc::proto::CompositorMessage& proto) { | 150 const cc::proto::CompositorMessage& proto) { |
182 render_widget_feature_->SendCompositorMessage(kDummyTabId, proto); | 151 render_widget_feature_->SendCompositorMessage(kDummyTabId, proto); |
183 } | 152 } |
184 | 153 |
185 void BlimpCompositor::OnRenderWidgetInitialized() { | 154 void BlimpCompositor::OnRenderWidgetInitialized() { |
186 DVLOG(1) << "OnRenderWidgetInitialized"; | 155 // Destroy the state for the current LayerTreeHost. Since a new render widget |
187 | 156 // has been initialized, we will start receiving compositor messages from |
188 // Tear down the output surface connection with the old LayerTreeHost | 157 // this widget now. |
189 // instance. | 158 if (host_) |
190 SetVisible(false); | 159 DestroyLayerTreeHost(); |
191 | |
192 // Destroy the old LayerTreeHost state. | |
193 host_.reset(); | |
194 | |
195 // Destroy the old input manager state. | |
196 // It is important to destroy the LayerTreeHost before destroying the input | |
197 // manager as it has a reference to the cc::InputHandlerClient owned by the | |
198 // BlimpInputManager. | |
199 input_manager_.reset(); | |
200 | |
201 // Reset other state. | |
202 output_surface_request_pending_ = false; | |
203 | |
204 // Make sure we don't have a receiver at this point. | |
205 DCHECK(!remote_proto_channel_receiver_); | |
206 | |
207 // TODO(khushalsagar): re-initialize compositor and input state for the new | |
208 // render widget. | |
209 SetVisible(true); | |
210 } | 160 } |
211 | 161 |
212 void BlimpCompositor::OnCompositorMessageReceived( | 162 void BlimpCompositor::OnCompositorMessageReceived( |
213 scoped_ptr<cc::proto::CompositorMessage> message) { | 163 scoped_ptr<cc::proto::CompositorMessage> message) { |
214 // TODO(dtrainor, khushalsagar): Look into the CompositorMessage. If it is | 164 DCHECK(message->has_to_impl()); |
215 // initialize or shutdown, create or destroy |host_|. | 165 const cc::proto::CompositorMessageToImpl& to_impl_proto = |
| 166 message->to_impl(); |
216 | 167 |
217 // We should have a receiver if we're getting compositor messages that aren't | 168 DCHECK(to_impl_proto.has_message_type()); |
218 // initialize. | 169 switch (to_impl_proto.message_type()) { |
219 DCHECK(remote_proto_channel_receiver_); | 170 case cc::proto::CompositorMessageToImpl::UNKNOWN: |
220 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); | 171 NOTIMPLEMENTED() << "Ignoring message of UNKNOWN type"; |
| 172 break; |
| 173 case cc::proto::CompositorMessageToImpl::INITIALIZE_IMPL: |
| 174 DCHECK(!host_); |
| 175 DCHECK(to_impl_proto.has_initialize_impl_message()); |
| 176 |
| 177 // Create the remote client LayerTreeHost for the compositor. |
| 178 CreateLayerTreeHost(to_impl_proto.initialize_impl_message()); |
| 179 break; |
| 180 case cc::proto::CompositorMessageToImpl::CLOSE_IMPL: |
| 181 DCHECK(host_); |
| 182 |
| 183 // Destroy the remote client LayerTreeHost for the compositor. |
| 184 DestroyLayerTreeHost(); |
| 185 break; |
| 186 default: |
| 187 // We should have a receiver if we're getting compositor messages that |
| 188 // are not INITIALIZE_IMPL or CLOSE_IMPL. |
| 189 DCHECK(remote_proto_channel_receiver_); |
| 190 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); |
| 191 } |
221 } | 192 } |
222 | 193 |
223 void BlimpCompositor::GenerateLayerTreeSettings( | 194 void BlimpCompositor::GenerateLayerTreeSettings( |
224 cc::LayerTreeSettings* settings) { | 195 cc::LayerTreeSettings* settings) { |
225 PopulateCommonLayerTreeSettings(settings); | 196 PopulateCommonLayerTreeSettings(settings); |
226 } | 197 } |
227 | 198 |
228 void BlimpCompositor::SendWebInputEvent( | 199 void BlimpCompositor::SendWebInputEvent( |
229 const blink::WebInputEvent& input_event) { | 200 const blink::WebInputEvent& input_event) { |
230 render_widget_feature_->SendInputEvent(kDummyTabId, input_event); | 201 render_widget_feature_->SendInputEvent(kDummyTabId, input_event); |
231 } | 202 } |
232 | 203 |
| 204 void BlimpCompositor::SetVisibleInternal(bool visible) { |
| 205 if (!host_) |
| 206 return; |
| 207 |
| 208 if (visible && window_ != gfx::kNullAcceleratedWidget) { |
| 209 // If we're supposed to be visible and we have a valid |
| 210 // gfx::AcceleratedWidget make our compositor visible. If the compositor |
| 211 // had an outstanding output surface request, trigger the request again so |
| 212 // we build the output surface. |
| 213 host_->SetVisible(true); |
| 214 if (output_surface_request_pending_) |
| 215 HandlePendingOutputSurfaceRequest(); |
| 216 } else if (!visible) { |
| 217 // If not visible, hide the compositor and have it drop it's output |
| 218 // surface. |
| 219 host_->SetVisible(false); |
| 220 if (!host_->output_surface_lost()) { |
| 221 host_->ReleaseOutputSurface(); |
| 222 } |
| 223 } |
| 224 } |
| 225 |
233 void BlimpCompositor::CreateLayerTreeHost( | 226 void BlimpCompositor::CreateLayerTreeHost( |
234 scoped_ptr<cc::proto::CompositorMessage> message) { | 227 const cc::proto::InitializeImpl& initialize_message) { |
| 228 DCHECK(!host_); |
| 229 |
235 if (!settings_) { | 230 if (!settings_) { |
236 settings_.reset(new cc::LayerTreeSettings); | 231 settings_.reset(new cc::LayerTreeSettings); |
| 232 |
| 233 // TODO(khushalsagar): The server should selectively send only those |
| 234 // LayerTreeSettings which should remain consistent across the server and |
| 235 // client. Since it currently overrides all settings, ignore them. |
| 236 // See crbug/577985. |
237 GenerateLayerTreeSettings(settings_.get()); | 237 GenerateLayerTreeSettings(settings_.get()); |
238 } | 238 } |
239 | 239 |
240 // Create the LayerTreeHost | 240 // Create the LayerTreeHost |
241 cc::LayerTreeHost::InitParams params; | 241 cc::LayerTreeHost::InitParams params; |
242 params.client = this; | 242 params.client = this; |
243 params.task_graph_runner = g_task_graph_runner.Pointer(); | 243 params.task_graph_runner = g_task_graph_runner.Pointer(); |
244 params.gpu_memory_buffer_manager = &gpu_memory_buffer_manager_; | 244 params.gpu_memory_buffer_manager = &gpu_memory_buffer_manager_; |
245 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); | 245 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
246 params.settings = settings_.get(); | 246 params.settings = settings_.get(); |
247 | 247 |
248 // TODO(dtrainor): Swap this out with the remote client proxy when | 248 // TODO(khushalsagar): Add the GpuMemoryBufferManager to params |
249 // implemented. | 249 |
250 host_ = | 250 host_ = |
251 cc::LayerTreeHost::CreateThreaded(GetCompositorTaskRunner(), ¶ms); | 251 cc::LayerTreeHost::CreateRemoteClient(this /* remote_proto_channel */, |
| 252 GetCompositorTaskRunner(), ¶ms); |
252 | 253 |
253 // If we're supposed to be visible and we have a valid gfx::AcceleratedWidget | 254 // Now that we have a host, set the visiblity on it correctly. |
254 // make our compositor visible. | 255 SetVisibleInternal(host_should_be_visible_); |
255 if (host_should_be_visible_ && window_ != gfx::kNullAcceleratedWidget) | |
256 host_->SetVisible(true); | |
257 | 256 |
258 host_->SetViewportSize(viewport_size_); | |
259 host_->SetDeviceScaleFactor(device_scale_factor_); | |
260 | |
261 // For testing, set the dummy Layer. | |
262 scoped_refptr<cc::Layer> root( | |
263 cc::Layer::Create(BlimpCompositor::LayerSettings())); | |
264 host_->SetRootLayer(root); | |
265 g_dummy_layer_driver.Pointer()->SetParentLayer(root); | |
266 | |
267 // TODO(khushalsagar): Create this after successful initialization of the | |
268 // remote client compositor when implemented. | |
269 DCHECK(!input_manager_); | 257 DCHECK(!input_manager_); |
270 input_manager_ = | 258 input_manager_ = |
271 BlimpInputManager::Create(this, | 259 BlimpInputManager::Create(this, |
272 base::ThreadTaskRunnerHandle::Get(), | 260 base::ThreadTaskRunnerHandle::Get(), |
273 GetCompositorTaskRunner(), | 261 GetCompositorTaskRunner(), |
274 host_->GetInputHandler()); | 262 host_->GetInputHandler()); |
275 } | 263 } |
276 | 264 |
| 265 void BlimpCompositor::DestroyLayerTreeHost() { |
| 266 DCHECK(host_); |
| 267 // Tear down the output surface connection with the old LayerTreeHost |
| 268 // instance. |
| 269 SetVisibleInternal(false); |
| 270 |
| 271 // Destroy the old LayerTreeHost state. |
| 272 host_.reset(); |
| 273 |
| 274 // Destroy the old input manager state. |
| 275 // It is important to destroy the LayerTreeHost before destroying the input |
| 276 // manager as it has a reference to the cc::InputHandlerClient owned by the |
| 277 // BlimpInputManager. |
| 278 input_manager_.reset(); |
| 279 |
| 280 // Reset other state. |
| 281 output_surface_request_pending_ = false; |
| 282 |
| 283 // Make sure we don't have a receiver at this point. |
| 284 DCHECK(!remote_proto_channel_receiver_); |
| 285 } |
| 286 |
277 scoped_refptr<base::SingleThreadTaskRunner> | 287 scoped_refptr<base::SingleThreadTaskRunner> |
278 BlimpCompositor::GetCompositorTaskRunner() { | 288 BlimpCompositor::GetCompositorTaskRunner() { |
279 if (compositor_thread_) | 289 if (compositor_thread_) |
280 return compositor_thread_->task_runner(); | 290 return compositor_thread_->task_runner(); |
281 | 291 |
282 base::Thread::Options thread_options; | 292 base::Thread::Options thread_options; |
283 #if defined(OS_ANDROID) | 293 #if defined(OS_ANDROID) |
284 thread_options.priority = base::ThreadPriority::DISPLAY; | 294 thread_options.priority = base::ThreadPriority::DISPLAY; |
285 #endif | 295 #endif |
286 compositor_thread_.reset(new base::Thread("Compositor")); | 296 compositor_thread_.reset(new base::Thread("Compositor")); |
(...skipping 20 matching lines...) Expand all Loading... |
307 return; | 317 return; |
308 | 318 |
309 scoped_refptr<BlimpContextProvider> context_provider = | 319 scoped_refptr<BlimpContextProvider> context_provider = |
310 BlimpContextProvider::Create(window_, &gpu_memory_buffer_manager_); | 320 BlimpContextProvider::Create(window_, &gpu_memory_buffer_manager_); |
311 | 321 |
312 host_->SetOutputSurface( | 322 host_->SetOutputSurface( |
313 make_scoped_ptr(new BlimpOutputSurface(context_provider))); | 323 make_scoped_ptr(new BlimpOutputSurface(context_provider))); |
314 output_surface_request_pending_ = false; | 324 output_surface_request_pending_ = false; |
315 } | 325 } |
316 | 326 |
317 cc::LayerSettings BlimpCompositor::LayerSettings() { | |
318 cc::LayerSettings settings; | |
319 settings.use_compositor_animation_timelines = true; | |
320 return settings; | |
321 } | |
322 | |
323 } // namespace client | 327 } // namespace client |
324 } // namespace blimp | 328 } // namespace blimp |
OLD | NEW |