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 DCHECK(thread_checker_.CalledOnValidThread()); | |
71 surface_manager_->RegisterSurfaceClientId(surface_id_allocator_->client_id()); | |
72 } | |
38 | 73 |
39 BlimpCompositor::~BlimpCompositor() { | 74 BlimpCompositor::~BlimpCompositor() { |
75 DCHECK(thread_checker_.CalledOnValidThread()); | |
76 | |
40 if (host_) | 77 if (host_) |
41 DestroyLayerTreeHost(); | 78 DestroyLayerTreeHost(); |
79 surface_manager_->InvalidateSurfaceClientId( | |
80 surface_id_allocator_->client_id()); | |
42 } | 81 } |
43 | 82 |
44 void BlimpCompositor::SetVisible(bool visible) { | 83 void BlimpCompositor::SetVisible(bool visible) { |
45 host_should_be_visible_ = visible; | 84 host_should_be_visible_ = visible; |
46 SetVisibleInternal(host_should_be_visible_); | 85 if (host_) |
47 } | 86 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 } | 87 } |
73 | 88 |
74 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { | 89 bool BlimpCompositor::OnTouchEvent(const ui::MotionEvent& motion_event) { |
75 if (input_manager_) | 90 if (input_manager_) |
76 return input_manager_->OnTouchEvent(motion_event); | 91 return input_manager_->OnTouchEvent(motion_event); |
77 return false; | 92 return false; |
78 } | 93 } |
79 | 94 |
80 void BlimpCompositor::WillBeginMainFrame() {} | 95 void BlimpCompositor::RequestNewOutputSurface() { |
96 DCHECK(!surface_factory_) | |
97 << "Any connection to the old output surface should have been destroyed"; | |
81 | 98 |
82 void BlimpCompositor::DidBeginMainFrame() {} | 99 scoped_refptr<BlimpContextProvider> compositor_context_provider = |
100 BlimpContextProvider::Create(gfx::kNullAcceleratedWidget, | |
101 client_->GetGpuMemoryBufferManager()); | |
83 | 102 |
84 void BlimpCompositor::BeginMainFrame(const cc::BeginFrameArgs& args) {} | 103 // TODO(khushalsagar): Make a worker context and bind it to the current |
104 // thread: | |
105 // Worker context is bound to the main thread in RenderThreadImpl. One day | |
106 // that will change and then this will have to be removed. | |
107 // worker_context_provider->BindToCurrentThread(); | |
85 | 108 |
86 void BlimpCompositor::BeginMainFrameNotExpectedSoon() {} | 109 std::unique_ptr<DelegatedOutputSurface> delegated_output_surface = |
110 base::MakeUnique<DelegatedOutputSurface>( | |
111 std::move(compositor_context_provider), nullptr, | |
112 base::ThreadTaskRunnerHandle::Get(), compositor_task_runner_, this); | |
87 | 113 |
88 void BlimpCompositor::UpdateLayerTreeHost() {} | 114 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 } | 115 } |
101 | 116 |
102 void BlimpCompositor::DidInitializeOutputSurface() { | 117 void BlimpCompositor::DidCommitAndDrawFrame() { |
118 BlimpStats::GetInstance()->Add(BlimpStats::COMMIT, 1); | |
103 } | 119 } |
104 | 120 |
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) { | 121 void BlimpCompositor::SetProtoReceiver(ProtoReceiver* receiver) { |
122 remote_proto_channel_receiver_ = receiver; | 122 remote_proto_channel_receiver_ = receiver; |
123 } | 123 } |
124 | 124 |
125 void BlimpCompositor::SendCompositorProto( | 125 void BlimpCompositor::SendCompositorProto( |
126 const cc::proto::CompositorMessage& proto) { | 126 const cc::proto::CompositorMessage& proto) { |
127 client_->SendCompositorMessage(render_widget_id_, proto); | 127 client_->SendCompositorMessage(render_widget_id_, proto); |
128 } | 128 } |
129 | 129 |
130 void BlimpCompositor::OnCompositorMessageReceived( | 130 void BlimpCompositor::OnCompositorMessageReceived( |
(...skipping 26 matching lines...) Expand all Loading... | |
157 DCHECK(remote_proto_channel_receiver_); | 157 DCHECK(remote_proto_channel_receiver_); |
158 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); | 158 remote_proto_channel_receiver_->OnProtoReceived(std::move(message)); |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 void BlimpCompositor::SendWebGestureEvent( | 162 void BlimpCompositor::SendWebGestureEvent( |
163 const blink::WebGestureEvent& gesture_event) { | 163 const blink::WebGestureEvent& gesture_event) { |
164 client_->SendWebGestureEvent(render_widget_id_, gesture_event); | 164 client_->SendWebGestureEvent(render_widget_id_, gesture_event); |
165 } | 165 } |
166 | 166 |
167 void BlimpCompositor::SetVisibleInternal(bool visible) { | 167 void BlimpCompositor::BindToOutputSurface(BlimpOutputSurface* output_surface) { |
168 if (!host_) | 168 DCHECK(thread_checker_.CalledOnValidThread()); |
169 DCHECK(!output_surface_); | |
170 DCHECK(!surface_factory_); | |
171 | |
172 output_surface_ = output_surface; | |
173 surface_factory_ = | |
174 base::MakeUnique<cc::SurfaceFactory>(surface_manager_, this); | |
175 } | |
176 | |
177 void BlimpCompositor::SwapCompositorFrame(cc::CompositorFrame frame) { | |
178 DCHECK(thread_checker_.CalledOnValidThread()); | |
179 DCHECK(surface_factory_); | |
180 | |
181 cc::RenderPass* root_pass = | |
182 frame.delegated_frame_data->render_pass_list.back().get(); | |
183 gfx::Size surface_size = root_pass->output_rect.size(); | |
184 | |
185 if (surface_id_.is_null() || current_surface_size_ != surface_size) { | |
186 DestroyDelegatedContent(); | |
187 DCHECK(layer_->children().empty()); | |
188 | |
189 surface_id_ = surface_id_allocator_->GenerateId(); | |
190 surface_factory_->Create(surface_id_); | |
191 current_surface_size_ = surface_size; | |
192 | |
193 // manager must outlive compositors using it. | |
David Trainor- moved to gerrit
2016/08/24 23:09:34
manager -> Manager
Khushal
2016/08/25 02:35:39
Done.
| |
194 scoped_refptr<cc::SurfaceLayer> content_layer = cc::SurfaceLayer::Create( | |
195 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)), | |
196 base::Bind(&RequireCallback, base::Unretained(surface_manager_))); | |
197 content_layer->SetSurfaceId(surface_id_, 1.f, surface_size); | |
198 content_layer->SetBounds(current_surface_size_); | |
199 content_layer->SetIsDrawable(true); | |
200 content_layer->SetContentsOpaque(true); | |
201 | |
202 layer_->AddChild(content_layer); | |
203 } | |
204 | |
205 surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame), | |
206 base::Closure()); | |
207 } | |
208 | |
209 void BlimpCompositor::UnbindOutputSurface(BlimpOutputSurface* output_surface) { | |
210 DCHECK(thread_checker_.CalledOnValidThread()); | |
211 DCHECK(surface_factory_); | |
212 DCHECK_EQ(output_surface_, output_surface); | |
213 | |
214 DestroyDelegatedContent(); | |
215 surface_factory_.reset(); | |
216 output_surface_ = nullptr; | |
217 } | |
218 | |
219 void BlimpCompositor::ReturnResources( | |
220 const cc::ReturnedResourceArray& resources) { | |
221 DCHECK(surface_factory_); | |
222 output_surface_->ReclaimCompositorResources(resources); | |
223 } | |
224 | |
225 void BlimpCompositor::DestroyDelegatedContent() { | |
226 if (surface_id_.is_null()) | |
169 return; | 227 return; |
170 | 228 |
171 VLOG(1) << "Setting visibility to: " << visible | 229 // Remove any references for the surface layer that uses this |surface_id_|. |
172 << " for render widget: " << render_widget_id_; | 230 layer_->RemoveAllChildren(); |
173 | 231 surface_factory_->Destroy(surface_id_); |
174 if (visible && window_ != gfx::kNullAcceleratedWidget) { | 232 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 } | 233 } |
191 | 234 |
192 void BlimpCompositor::CreateLayerTreeHost( | 235 void BlimpCompositor::CreateLayerTreeHost( |
193 const cc::proto::InitializeImpl& initialize_message) { | 236 const cc::proto::InitializeImpl& initialize_message) { |
194 DCHECK(!host_); | 237 DCHECK(!host_); |
195 VLOG(1) << "Creating LayerTreeHost for render widget: " << render_widget_id_; | 238 VLOG(1) << "Creating LayerTreeHost for render widget: " << render_widget_id_; |
196 | 239 |
197 // Create the LayerTreeHost | 240 // Create the LayerTreeHost |
198 cc::LayerTreeHost::InitParams params; | 241 cc::LayerTreeHost::InitParams params; |
199 params.client = this; | 242 params.client = this; |
200 params.task_graph_runner = client_->GetTaskGraphRunner(); | 243 params.task_graph_runner = client_->GetTaskGraphRunner(); |
201 params.gpu_memory_buffer_manager = client_->GetGpuMemoryBufferManager(); | 244 params.gpu_memory_buffer_manager = client_->GetGpuMemoryBufferManager(); |
202 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); | 245 params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
203 params.image_serialization_processor = | 246 params.image_serialization_processor = |
204 client_->GetImageSerializationProcessor(); | 247 client_->GetImageSerializationProcessor(); |
205 params.settings = client_->GetLayerTreeSettings(); | 248 params.settings = client_->GetLayerTreeSettings(); |
206 params.animation_host = cc::AnimationHost::CreateMainInstance(); | 249 params.animation_host = cc::AnimationHost::CreateMainInstance(); |
207 | 250 |
208 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = | 251 compositor_task_runner_ = client_->GetCompositorTaskRunner(); |
209 client_->GetCompositorTaskRunner(); | |
210 | 252 |
211 host_ = | 253 host_ = cc::LayerTreeHost::CreateRemoteClient( |
212 cc::LayerTreeHost::CreateRemoteClient(this /* remote_proto_channel */, | 254 this /* remote_proto_channel */, compositor_task_runner_, ¶ms); |
213 compositor_task_runner, ¶ms); | 255 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 | 256 |
218 DCHECK(!input_manager_); | 257 DCHECK(!input_manager_); |
219 input_manager_ = | 258 input_manager_ = BlimpInputManager::Create( |
220 BlimpInputManager::Create(this, | 259 this, base::ThreadTaskRunnerHandle::Get(), compositor_task_runner_, |
221 base::ThreadTaskRunnerHandle::Get(), | 260 host_->GetInputHandler()); |
222 compositor_task_runner, | |
223 host_->GetInputHandler()); | |
224 } | 261 } |
225 | 262 |
226 void BlimpCompositor::DestroyLayerTreeHost() { | 263 void BlimpCompositor::DestroyLayerTreeHost() { |
227 DCHECK(host_); | 264 DCHECK(host_); |
228 VLOG(1) << "Destroying LayerTreeHost for render widget: " | 265 VLOG(1) << "Destroying LayerTreeHost for render widget: " |
229 << render_widget_id_; | 266 << render_widget_id_; |
230 // Tear down the output surface connection with the old LayerTreeHost | 267 // Tear down the output surface connection with the old LayerTreeHost |
231 // instance. | 268 // instance. |
232 SetVisibleInternal(false); | 269 DestroyDelegatedContent(); |
270 surface_factory_.reset(); | |
233 | 271 |
234 // Destroy the old LayerTreeHost state. | 272 // Destroy the old LayerTreeHost state. |
235 host_.reset(); | 273 host_.reset(); |
236 | 274 |
237 // Destroy the old input manager state. | 275 // Destroy the old input manager state. |
238 // It is important to destroy the LayerTreeHost before destroying the input | 276 // 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 | 277 // manager as it has a reference to the cc::InputHandlerClient owned by the |
240 // BlimpInputManager. | 278 // BlimpInputManager. |
241 input_manager_.reset(); | 279 input_manager_.reset(); |
242 | 280 |
243 // Reset other state. | |
244 output_surface_request_pending_ = false; | |
245 | |
246 // Make sure we don't have a receiver at this point. | 281 // Make sure we don't have a receiver at this point. |
247 DCHECK(!remote_proto_channel_receiver_); | 282 DCHECK(!remote_proto_channel_receiver_); |
248 } | 283 } |
249 | 284 |
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 | 285 } // namespace client |
287 } // namespace blimp | 286 } // namespace blimp |
OLD | NEW |