| 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 |