| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "blimp/client/feature/compositor/blimp_compositor.h" | |
| 6 | |
| 7 #include "base/bind_helpers.h" | |
| 8 #include "base/command_line.h" | |
| 9 #include "base/memory/ptr_util.h" | |
| 10 #include "base/numerics/safe_conversions.h" | |
| 11 #include "base/single_thread_task_runner.h" | |
| 12 #include "base/threading/thread.h" | |
| 13 #include "base/threading/thread_local.h" | |
| 14 #include "base/threading/thread_restrictions.h" | |
| 15 #include "base/threading/thread_task_runner_handle.h" | |
| 16 #include "blimp/client/core/compositor/blimp_compositor_dependencies.h" | |
| 17 #include "blimp/client/core/compositor/delegated_output_surface.h" | |
| 18 #include "blimp/client/public/compositor/compositor_dependencies.h" | |
| 19 #include "blimp/net/blimp_stats.h" | |
| 20 #include "cc/animation/animation_host.h" | |
| 21 #include "cc/layers/layer.h" | |
| 22 #include "cc/layers/surface_layer.h" | |
| 23 #include "cc/output/output_surface.h" | |
| 24 #include "cc/proto/compositor_message.pb.h" | |
| 25 #include "cc/surfaces/surface.h" | |
| 26 #include "cc/surfaces/surface_factory.h" | |
| 27 #include "cc/surfaces/surface_id_allocator.h" | |
| 28 #include "cc/surfaces/surface_manager.h" | |
| 29 #include "cc/trees/layer_tree_host.h" | |
| 30 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" | |
| 31 #include "net/base/net_errors.h" | |
| 32 #include "ui/gl/gl_surface.h" | |
| 33 | |
| 34 namespace blimp { | |
| 35 namespace client { | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 void SatisfyCallback(cc::SurfaceManager* manager, | |
| 40 const cc::SurfaceSequence& sequence) { | |
| 41 std::vector<uint32_t> sequences; | |
| 42 sequences.push_back(sequence.sequence); | |
| 43 manager->DidSatisfySequences(sequence.client_id, &sequences); | |
| 44 } | |
| 45 | |
| 46 void RequireCallback(cc::SurfaceManager* manager, | |
| 47 const cc::SurfaceId& id, | |
| 48 const cc::SurfaceSequence& sequence) { | |
| 49 cc::Surface* surface = manager->GetSurfaceForId(id); | |
| 50 if (!surface) { | |
| 51 LOG(ERROR) << "Attempting to require callback on nonexistent surface"; | |
| 52 return; | |
| 53 } | |
| 54 surface->AddDestructionDependency(sequence); | |
| 55 } | |
| 56 | |
| 57 } // namespace | |
| 58 | |
| 59 BlimpCompositor::BlimpCompositor( | |
| 60 int render_widget_id, | |
| 61 BlimpCompositorDependencies* compositor_dependencies, | |
| 62 BlimpCompositorClient* client) | |
| 63 : render_widget_id_(render_widget_id), | |
| 64 client_(client), | |
| 65 compositor_dependencies_(compositor_dependencies), | |
| 66 host_should_be_visible_(false), | |
| 67 output_surface_(nullptr), | |
| 68 output_surface_request_pending_(false), | |
| 69 layer_(cc::Layer::Create()), | |
| 70 remote_proto_channel_receiver_(nullptr), | |
| 71 weak_ptr_factory_(this) { | |
| 72 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 73 | |
| 74 surface_id_allocator_ = base::MakeUnique<cc::SurfaceIdAllocator>( | |
| 75 GetEmbedderDeps()->AllocateSurfaceId()); | |
| 76 GetEmbedderDeps()->GetSurfaceManager()->RegisterSurfaceClientId( | |
| 77 surface_id_allocator_->client_id()); | |
| 78 } | |
| 79 | |
| 80 BlimpCompositor::~BlimpCompositor() { | |
| 81 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 82 | |
| 83 if (host_) | |
| 84 DestroyLayerTreeHost(); | |
| 85 | |
| 86 GetEmbedderDeps()->GetSurfaceManager()->InvalidateSurfaceClientId( | |
| 87 surface_id_allocator_->client_id()); | |
| 88 } | |
| 89 | |
| 90 void BlimpCompositor::SetVisible(bool visible) { | |
| 91 host_should_be_visible_ = visible; | |
| 92 if (host_) | |
| 93 host_->SetVisible(host_should_be_visible_); | |
| 94 } | |
| 95 | |
| 96 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { | |
| 97 if (input_manager_) | |
| 98 return input_manager_->OnTouchEvent(motion_event); | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 void BlimpCompositor::RequestNewOutputSurface() { | |
| 103 DCHECK(!surface_factory_); | |
| 104 DCHECK(!output_surface_request_pending_); | |
| 105 | |
| 106 output_surface_request_pending_ = true; | |
| 107 GetEmbedderDeps()->GetContextProvider( | |
| 108 base::Bind(&BlimpCompositor::OnContextProviderCreated, | |
| 109 weak_ptr_factory_.GetWeakPtr())); | |
| 110 } | |
| 111 | |
| 112 void BlimpCompositor::DidInitializeOutputSurface() { | |
| 113 output_surface_request_pending_ = false; | |
| 114 } | |
| 115 | |
| 116 void BlimpCompositor::DidCommitAndDrawFrame() { | |
| 117 BlimpStats::GetInstance()->Add(BlimpStats::COMMIT, 1); | |
| 118 } | |
| 119 | |
| 120 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { | |
| 121 remote_proto_channel_receiver_ = receiver; | |
| 122 } | |
| 123 | |
| 124 void BlimpCompositor::SendCompositorProto( | |
| 125 const cc::proto::CompositorMessage& proto) { | |
| 126 client_->SendCompositorMessage(render_widget_id_, proto); | |
| 127 } | |
| 128 | |
| 129 void BlimpCompositor::OnCompositorMessageReceived( | |
| 130 std::unique_ptr<cc::proto::CompositorMessage> message) { | |
| 131 DCHECK(message->has_to_impl()); | |
| 132 const cc::proto::CompositorMessageToImpl& to_impl_proto = | |
| 133 message->to_impl(); | |
| 134 | |
| 135 DCHECK(to_impl_proto.has_message_type()); | |
| 136 switch (to_impl_proto.message_type()) { | |
| 137 case cc::proto::CompositorMessageToImpl::UNKNOWN: | |
| 138 NOTIMPLEMENTED() << "Ignoring message of UNKNOWN type"; | |
| 139 break; | |
| 140 case cc::proto::CompositorMessageToImpl::INITIALIZE_IMPL: | |
| 141 DCHECK(!host_); | |
| 142 DCHECK(to_impl_proto.has_initialize_impl_message()); | |
| 143 | |
| 144 // Create the remote client LayerTreeHost for the compositor. | |
| 145 CreateLayerTreeHost(to_impl_proto.initialize_impl_message()); | |
| 146 break; | |
| 147 case cc::proto::CompositorMessageToImpl::CLOSE_IMPL: | |
| 148 DCHECK(host_); | |
| 149 | |
| 150 // Destroy the remote client LayerTreeHost for the compositor. | |
| 151 DestroyLayerTreeHost(); | |
| 152 break; | |
| 153 default: | |
| 154 // We should have a receiver if we're getting compositor messages that | |
| 155 // are not INITIALIZE_IMPL or CLOSE_IMPL. | |
| 156 DCHECK(remote_proto_channel_receiver_); | |
| 157 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 void BlimpCompositor::OnContextProviderCreated( | |
| 162 const scoped_refptr<cc::ContextProvider>& provider) { | |
| 163 DCHECK(!surface_factory_) | |
| 164 << "Any connection to the old output surface should have been destroyed"; | |
| 165 | |
| 166 // Make sure we still have a host and we're still expecting an output surface. | |
| 167 // This can happen if the host dies while the request is outstanding and we | |
| 168 // build a new one that hasn't asked for a surface yet. | |
| 169 if (!output_surface_request_pending_) | |
| 170 return; | |
| 171 | |
| 172 // TODO(khushalsagar): Make a worker context and bind it to the current | |
| 173 // thread: | |
| 174 // Worker context is bound to the main thread in RenderThreadImpl. One day | |
| 175 // that will change and then this will have to be removed. | |
| 176 // worker_context_provider->BindToCurrentThread(); | |
| 177 std::unique_ptr<DelegatedOutputSurface> delegated_output_surface = | |
| 178 base::MakeUnique<DelegatedOutputSurface>( | |
| 179 provider, nullptr, base::ThreadTaskRunnerHandle::Get(), | |
| 180 weak_ptr_factory_.GetWeakPtr()); | |
| 181 | |
| 182 host_->SetOutputSurface(std::move(delegated_output_surface)); | |
| 183 } | |
| 184 | |
| 185 void BlimpCompositor::SendWebGestureEvent( | |
| 186 const blink::WebGestureEvent& gesture_event) { | |
| 187 client_->SendWebGestureEvent(render_widget_id_, gesture_event); | |
| 188 } | |
| 189 | |
| 190 void BlimpCompositor::BindToOutputSurface( | |
| 191 base::WeakPtr<BlimpOutputSurface> output_surface) { | |
| 192 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 193 DCHECK(!surface_factory_); | |
| 194 | |
| 195 output_surface_ = output_surface; | |
| 196 surface_factory_ = base::MakeUnique<cc::SurfaceFactory>( | |
| 197 GetEmbedderDeps()->GetSurfaceManager(), this); | |
| 198 } | |
| 199 | |
| 200 void BlimpCompositor::SwapCompositorFrame(cc::CompositorFrame frame) { | |
| 201 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 202 DCHECK(surface_factory_); | |
| 203 | |
| 204 cc::RenderPass* root_pass = | |
| 205 frame.delegated_frame_data->render_pass_list.back().get(); | |
| 206 gfx::Size surface_size = root_pass->output_rect.size(); | |
| 207 | |
| 208 if (surface_id_.is_null() || current_surface_size_ != surface_size) { | |
| 209 DestroyDelegatedContent(); | |
| 210 DCHECK(layer_->children().empty()); | |
| 211 | |
| 212 surface_id_ = surface_id_allocator_->GenerateId(); | |
| 213 surface_factory_->Create(surface_id_); | |
| 214 current_surface_size_ = surface_size; | |
| 215 | |
| 216 // manager must outlive compositors using it. | |
| 217 cc::SurfaceManager* surface_manager = | |
| 218 GetEmbedderDeps()->GetSurfaceManager(); | |
| 219 scoped_refptr<cc::SurfaceLayer> content_layer = cc::SurfaceLayer::Create( | |
| 220 base::Bind(&SatisfyCallback, base::Unretained(surface_manager)), | |
| 221 base::Bind(&RequireCallback, base::Unretained(surface_manager))); | |
| 222 content_layer->SetSurfaceId(surface_id_, 1.f, surface_size); | |
| 223 content_layer->SetBounds(current_surface_size_); | |
| 224 content_layer->SetIsDrawable(true); | |
| 225 content_layer->SetContentsOpaque(true); | |
| 226 | |
| 227 layer_->AddChild(content_layer); | |
| 228 } | |
| 229 | |
| 230 surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame), | |
| 231 base::Closure()); | |
| 232 } | |
| 233 | |
| 234 void BlimpCompositor::UnbindOutputSurface() { | |
| 235 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 236 DCHECK(surface_factory_); | |
| 237 | |
| 238 DestroyDelegatedContent(); | |
| 239 surface_factory_.reset(); | |
| 240 output_surface_ = nullptr; | |
| 241 } | |
| 242 | |
| 243 void BlimpCompositor::ReturnResources( | |
| 244 const cc::ReturnedResourceArray& resources) { | |
| 245 DCHECK(surface_factory_); | |
| 246 compositor_dependencies_->GetCompositorTaskRunner()->PostTask( | |
| 247 FROM_HERE, base::Bind(&BlimpOutputSurface::ReclaimCompositorResources, | |
| 248 output_surface_, resources)); | |
| 249 } | |
| 250 | |
| 251 CompositorDependencies* BlimpCompositor::GetEmbedderDeps() { | |
| 252 return compositor_dependencies_->GetEmbedderDependencies(); | |
| 253 } | |
| 254 | |
| 255 void BlimpCompositor::DestroyDelegatedContent() { | |
| 256 if (surface_id_.is_null()) | |
| 257 return; | |
| 258 | |
| 259 // Remove any references for the surface layer that uses this |surface_id_|. | |
| 260 layer_->RemoveAllChildren(); | |
| 261 surface_factory_->Destroy(surface_id_); | |
| 262 surface_id_ = cc::SurfaceId(); | |
| 263 } | |
| 264 | |
| 265 void BlimpCompositor::CreateLayerTreeHost( | |
| 266 const cc::proto::InitializeImpl& initialize_message) { | |
| 267 DCHECK(!host_); | |
| 268 VLOG(1) << "Creating LayerTreeHost for render widget: " << render_widget_id_; | |
| 269 | |
| 270 // Create the LayerTreeHost | |
| 271 cc::LayerTreeHost::InitParams params; | |
| 272 params.client = this; | |
| 273 params.task_graph_runner = compositor_dependencies_->GetTaskGraphRunner(); | |
| 274 params.gpu_memory_buffer_manager = | |
| 275 GetEmbedderDeps()->GetGpuMemoryBufferManager(); | |
| 276 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); | |
| 277 params.image_serialization_processor = | |
| 278 compositor_dependencies_->GetImageSerializationProcessor(); | |
| 279 params.settings = GetEmbedderDeps()->GetLayerTreeSettings(); | |
| 280 params.animation_host = cc::AnimationHost::CreateMainInstance(); | |
| 281 | |
| 282 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = | |
| 283 compositor_dependencies_->GetCompositorTaskRunner(); | |
| 284 | |
| 285 host_ = cc::LayerTreeHost::CreateRemoteClient( | |
| 286 this /* remote_proto_channel */, compositor_task_runner, ¶ms); | |
| 287 host_->SetVisible(host_should_be_visible_); | |
| 288 | |
| 289 DCHECK(!input_manager_); | |
| 290 input_manager_ = BlimpInputManager::Create( | |
| 291 this, base::ThreadTaskRunnerHandle::Get(), compositor_task_runner, | |
| 292 host_->GetInputHandler()); | |
| 293 } | |
| 294 | |
| 295 void BlimpCompositor::DestroyLayerTreeHost() { | |
| 296 DCHECK(host_); | |
| 297 VLOG(1) << "Destroying LayerTreeHost for render widget: " | |
| 298 << render_widget_id_; | |
| 299 // Tear down the output surface connection with the old LayerTreeHost | |
| 300 // instance. | |
| 301 DestroyDelegatedContent(); | |
| 302 surface_factory_.reset(); | |
| 303 | |
| 304 // Destroy the old LayerTreeHost state. | |
| 305 host_.reset(); | |
| 306 | |
| 307 // Destroy the old input manager state. | |
| 308 // It is important to destroy the LayerTreeHost before destroying the input | |
| 309 // manager as it has a reference to the cc::InputHandlerClient owned by the | |
| 310 // BlimpInputManager. | |
| 311 input_manager_.reset(); | |
| 312 | |
| 313 // Cancel any outstanding OutputSurface requests. That way if we get an async | |
| 314 // callback related to the old request we know to drop it. | |
| 315 output_surface_request_pending_ = false; | |
| 316 | |
| 317 // Make sure we don't have a receiver at this point. | |
| 318 DCHECK(!remote_proto_channel_receiver_); | |
| 319 } | |
| 320 | |
| 321 } // namespace client | |
| 322 } // namespace blimp | |
| OLD | NEW |