OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "content/browser/android/in_process/synchronous_compositor_impl.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/auto_reset.h" | |
10 #include "base/bind.h" | |
11 #include "base/lazy_instance.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "content/browser/android/in_process/synchronous_compositor_factory_impl
.h" | |
14 #include "content/browser/android/in_process/synchronous_compositor_registry_in_
proc.h" | |
15 #include "content/browser/android/in_process/synchronous_input_event_filter.h" | |
16 #include "content/browser/gpu/gpu_process_host.h" | |
17 #include "content/browser/renderer_host/render_widget_host_view_android.h" | |
18 #include "content/common/input/did_overscroll_params.h" | |
19 #include "content/common/input_messages.h" | |
20 #include "content/public/browser/android/synchronous_compositor_client.h" | |
21 #include "content/public/browser/browser_thread.h" | |
22 #include "content/public/browser/render_process_host.h" | |
23 #include "content/public/browser/render_view_host.h" | |
24 #include "content/public/browser/render_widget_host.h" | |
25 #include "content/public/common/child_process_host.h" | |
26 #include "ui/gfx/geometry/scroll_offset.h" | |
27 #include "ui/gl/gl_surface.h" | |
28 | |
29 namespace content { | |
30 | |
31 namespace { | |
32 | |
33 int g_process_id = ChildProcessHost::kInvalidUniqueID; | |
34 | |
35 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory = | |
36 LAZY_INSTANCE_INITIALIZER; | |
37 | |
38 } // namespace | |
39 | |
40 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID( | |
41 int routing_id) { | |
42 if (g_factory == nullptr) | |
43 return nullptr; | |
44 if (g_process_id == ChildProcessHost::kInvalidUniqueID) | |
45 return nullptr; | |
46 RenderViewHost* rvh = RenderViewHost::FromID(g_process_id, routing_id); | |
47 if (!rvh) | |
48 return nullptr; | |
49 RenderWidgetHostViewAndroid* rwhva = | |
50 static_cast<RenderWidgetHostViewAndroid*>(rvh->GetWidget()->GetView()); | |
51 if (!rwhva) | |
52 return nullptr; | |
53 return static_cast<SynchronousCompositorImpl*>( | |
54 rwhva->GetSynchronousCompositor()); | |
55 } | |
56 | |
57 SynchronousCompositorImpl::SynchronousCompositorImpl( | |
58 RenderWidgetHostViewAndroid* rwhva, | |
59 SynchronousCompositorClient* client) | |
60 : rwhva_(rwhva), | |
61 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()), | |
62 compositor_client_(client), | |
63 output_surface_(nullptr), | |
64 begin_frame_source_(nullptr), | |
65 synchronous_input_handler_proxy_(nullptr), | |
66 registered_with_client_(false), | |
67 is_active_(true), | |
68 renderer_needs_begin_frames_(false), | |
69 need_animate_input_(false), | |
70 weak_ptr_factory_(this) { | |
71 DCHECK_NE(routing_id_, MSG_ROUTING_NONE); | |
72 g_factory.Get(); // Ensure it's initialized. | |
73 | |
74 int process_id = rwhva_->GetRenderWidgetHost()->GetProcess()->GetID(); | |
75 if (g_process_id == ChildProcessHost::kInvalidUniqueID) { | |
76 g_process_id = process_id; | |
77 } else { | |
78 DCHECK_EQ(g_process_id, process_id); // Not multiprocess compatible. | |
79 } | |
80 | |
81 SynchronousCompositorRegistryInProc::GetInstance()->RegisterCompositor( | |
82 routing_id_, this); | |
83 } | |
84 | |
85 SynchronousCompositorImpl::~SynchronousCompositorImpl() { | |
86 SynchronousCompositorRegistryInProc::GetInstance()->UnregisterCompositor( | |
87 routing_id_, this); | |
88 } | |
89 | |
90 void SynchronousCompositorImpl::RegisterWithClient() { | |
91 DCHECK(CalledOnValidThread()); | |
92 DCHECK(output_surface_); | |
93 DCHECK(synchronous_input_handler_proxy_); | |
94 DCHECK(!registered_with_client_); | |
95 registered_with_client_ = true; | |
96 | |
97 compositor_client_->DidInitializeCompositor(this); | |
98 compositor_client_->DidBecomeCurrent(this); | |
99 | |
100 output_surface_->SetTreeActivationCallback( | |
101 base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree, | |
102 weak_ptr_factory_.GetWeakPtr())); | |
103 | |
104 // This disables the input system from animating inputs autonomously, instead | |
105 // routing all input animations through the SynchronousInputHandler, which is | |
106 // |this| class. Calling this causes an UpdateRootLayerState() immediately so, | |
107 // do it after setting the client. | |
108 synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this); | |
109 } | |
110 | |
111 void SynchronousCompositorImpl::DidInitializeRendererObjects( | |
112 SynchronousCompositorOutputSurface* output_surface, | |
113 SynchronousCompositorExternalBeginFrameSource* begin_frame_source, | |
114 ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { | |
115 DCHECK(!output_surface_); | |
116 DCHECK(!begin_frame_source_); | |
117 DCHECK(output_surface); | |
118 DCHECK(begin_frame_source); | |
119 DCHECK(synchronous_input_handler_proxy); | |
120 | |
121 output_surface_ = output_surface; | |
122 begin_frame_source_ = begin_frame_source; | |
123 synchronous_input_handler_proxy_ = synchronous_input_handler_proxy; | |
124 | |
125 output_surface_->SetSyncClient(this); | |
126 begin_frame_source_->SetClient(this); | |
127 begin_frame_source_->SetBeginFrameSourcePaused(!is_active_); | |
128 } | |
129 | |
130 void SynchronousCompositorImpl::DidDestroyRendererObjects() { | |
131 DCHECK(output_surface_); | |
132 DCHECK(begin_frame_source_); | |
133 | |
134 if (registered_with_client_) { | |
135 output_surface_->SetTreeActivationCallback(base::Closure()); | |
136 compositor_client_->DidDestroyCompositor(this); | |
137 registered_with_client_ = false; | |
138 } | |
139 | |
140 // This object is being destroyed, so remove pointers to it. | |
141 begin_frame_source_->SetClient(nullptr); | |
142 output_surface_->SetSyncClient(nullptr); | |
143 synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings( | |
144 nullptr); | |
145 | |
146 synchronous_input_handler_proxy_ = nullptr; | |
147 begin_frame_source_ = nullptr; | |
148 output_surface_ = nullptr; | |
149 // Don't propogate this signal from one renderer to the next. | |
150 need_animate_input_ = false; | |
151 } | |
152 | |
153 SynchronousCompositor::Frame SynchronousCompositorImpl::DemandDrawHw( | |
154 const gfx::Size& surface_size, | |
155 const gfx::Transform& transform, | |
156 const gfx::Rect& viewport, | |
157 const gfx::Rect& clip, | |
158 const gfx::Rect& viewport_rect_for_tile_priority, | |
159 const gfx::Transform& transform_for_tile_priority) { | |
160 DCHECK(CalledOnValidThread()); | |
161 DCHECK(output_surface_); | |
162 DCHECK(begin_frame_source_); | |
163 DCHECK(!frame_holder_.frame); | |
164 | |
165 output_surface_->DemandDrawHw(surface_size, transform, viewport, clip, | |
166 viewport_rect_for_tile_priority, | |
167 transform_for_tile_priority); | |
168 | |
169 if (frame_holder_.frame) | |
170 UpdateFrameMetaData(frame_holder_.frame->metadata); | |
171 | |
172 return std::move(frame_holder_); | |
173 } | |
174 | |
175 void SynchronousCompositorImpl::ReturnResources( | |
176 uint32_t output_surface_id, | |
177 const cc::CompositorFrameAck& frame_ack) { | |
178 DCHECK(CalledOnValidThread()); | |
179 output_surface_->ReturnResources(output_surface_id, frame_ack); | |
180 } | |
181 | |
182 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) { | |
183 DCHECK(CalledOnValidThread()); | |
184 DCHECK(output_surface_); | |
185 DCHECK(begin_frame_source_); | |
186 DCHECK(!frame_holder_.frame); | |
187 | |
188 output_surface_->DemandDrawSw(canvas); | |
189 | |
190 bool success = !!frame_holder_.frame; | |
191 if (frame_holder_.frame) { | |
192 UpdateFrameMetaData(frame_holder_.frame->metadata); | |
193 frame_holder_.frame.reset(); | |
194 } | |
195 | |
196 return success; | |
197 } | |
198 | |
199 void SynchronousCompositorImpl::SwapBuffers(uint32_t output_surface_id, | |
200 cc::CompositorFrame* frame) { | |
201 DCHECK(!frame_holder_.frame); | |
202 frame_holder_.output_surface_id = output_surface_id; | |
203 frame_holder_.frame.reset(new cc::CompositorFrame); | |
204 frame->AssignTo(frame_holder_.frame.get()); | |
205 } | |
206 | |
207 void SynchronousCompositorImpl::UpdateFrameMetaData( | |
208 const cc::CompositorFrameMetadata& frame_metadata) { | |
209 rwhva_->SynchronousFrameMetadata(frame_metadata); | |
210 DeliverMessages(); | |
211 } | |
212 | |
213 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) { | |
214 DCHECK(CalledOnValidThread()); | |
215 DCHECK(output_surface_); | |
216 output_surface_->SetMemoryPolicy(bytes_limit); | |
217 } | |
218 | |
219 void SynchronousCompositorImpl::Invalidate() { | |
220 DCHECK(CalledOnValidThread()); | |
221 if (registered_with_client_) | |
222 compositor_client_->PostInvalidate(); | |
223 } | |
224 | |
225 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset( | |
226 const gfx::ScrollOffset& root_offset) { | |
227 DCHECK(CalledOnValidThread()); | |
228 if (!synchronous_input_handler_proxy_) | |
229 return; | |
230 synchronous_input_handler_proxy_->SynchronouslySetRootScrollOffset( | |
231 root_offset); | |
232 } | |
233 | |
234 void SynchronousCompositorImpl::SynchronouslyZoomBy(float zoom_delta, | |
235 const gfx::Point& anchor) { | |
236 DCHECK(CalledOnValidThread()); | |
237 if (!synchronous_input_handler_proxy_) | |
238 return; | |
239 synchronous_input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor); | |
240 } | |
241 | |
242 void SynchronousCompositorImpl::SetIsActive(bool is_active) { | |
243 TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active", | |
244 is_active); | |
245 if (is_active_ == is_active) | |
246 return; | |
247 | |
248 is_active_ = is_active; | |
249 UpdateNeedsBeginFrames(); | |
250 if (begin_frame_source_) | |
251 begin_frame_source_->SetBeginFrameSourcePaused(!is_active_); | |
252 } | |
253 | |
254 void SynchronousCompositorImpl::OnComputeScroll( | |
255 base::TimeTicks animation_time) { | |
256 if (need_animate_input_) { | |
257 need_animate_input_ = false; | |
258 synchronous_input_handler_proxy_->SynchronouslyAnimate(animation_time); | |
259 } | |
260 } | |
261 | |
262 void SynchronousCompositorImpl::OnNeedsBeginFramesChange( | |
263 bool needs_begin_frames) { | |
264 renderer_needs_begin_frames_ = needs_begin_frames; | |
265 UpdateNeedsBeginFrames(); | |
266 } | |
267 | |
268 void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) { | |
269 if (!registered_with_client_ && is_active_ && renderer_needs_begin_frames_) { | |
270 // Make sure this is a BeginFrame that renderer side explicitly requested. | |
271 // Otherwise it is possible renderer objects not initialized. | |
272 RegisterWithClient(); | |
273 DCHECK(registered_with_client_); | |
274 } | |
275 if (begin_frame_source_) | |
276 begin_frame_source_->BeginFrame(args); | |
277 } | |
278 | |
279 void SynchronousCompositorImpl::UpdateNeedsBeginFrames() { | |
280 rwhva_->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_); | |
281 } | |
282 | |
283 void SynchronousCompositorImpl::DidOverscrollInProcess( | |
284 const DidOverscrollParams& params) { | |
285 if (registered_with_client_) { | |
286 compositor_client_->DidOverscroll(params.accumulated_overscroll, | |
287 params.latest_overscroll_delta, | |
288 params.current_fling_velocity); | |
289 } | |
290 } | |
291 | |
292 void SynchronousCompositorImpl::DidStopFlinging() { | |
293 // It's important that the fling-end notification follow the same path as it | |
294 // takes on other platforms (using an IPC). This ensures consistent | |
295 // bookkeeping at all stages of the input pipeline. | |
296 rwhva_->GetRenderWidgetHost()->GetProcess()->OnMessageReceived( | |
297 InputHostMsg_DidStopFlinging(routing_id_)); | |
298 } | |
299 | |
300 InputEventAckState SynchronousCompositorImpl::HandleInputEvent( | |
301 const blink::WebInputEvent& input_event) { | |
302 DCHECK(CalledOnValidThread()); | |
303 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent( | |
304 routing_id_, input_event); | |
305 } | |
306 | |
307 void SynchronousCompositorImpl::DidOverscroll( | |
308 const DidOverscrollParams& params) { | |
309 // SynchronousCompositorImpl uses synchronous DidOverscrollInProcess for | |
310 // overscroll instead of this async path. | |
311 NOTREACHED(); | |
312 } | |
313 | |
314 bool SynchronousCompositorImpl::OnMessageReceived(const IPC::Message& message) { | |
315 NOTREACHED(); | |
316 return false; | |
317 } | |
318 | |
319 void SynchronousCompositorImpl::DidBecomeCurrent() { | |
320 // This is single process synchronous compositor. There is only one | |
321 // RenderViewHost. DidBecomeCurrent could be called before the renderer | |
322 // objects are initialized. So hold off calling DidBecomeCurrent until | |
323 // RegisterWithClient. Intentional no-op here. | |
324 } | |
325 | |
326 void SynchronousCompositorImpl::DeliverMessages() { | |
327 std::vector<std::unique_ptr<IPC::Message>> messages; | |
328 output_surface_->GetMessagesToDeliver(&messages); | |
329 RenderProcessHost* rph = rwhva_->GetRenderWidgetHost()->GetProcess(); | |
330 for (const auto& msg : messages) { | |
331 rph->OnMessageReceived(*msg); | |
332 } | |
333 } | |
334 | |
335 void SynchronousCompositorImpl::DidActivatePendingTree() { | |
336 if (registered_with_client_) | |
337 compositor_client_->DidUpdateContent(); | |
338 DeliverMessages(); | |
339 } | |
340 | |
341 void SynchronousCompositorImpl::SetNeedsSynchronousAnimateInput() { | |
342 DCHECK(CalledOnValidThread()); | |
343 if (!registered_with_client_) | |
344 return; | |
345 need_animate_input_ = true; | |
346 compositor_client_->PostInvalidate(); | |
347 } | |
348 | |
349 void SynchronousCompositorImpl::UpdateRootLayerState( | |
350 const gfx::ScrollOffset& total_scroll_offset, | |
351 const gfx::ScrollOffset& max_scroll_offset, | |
352 const gfx::SizeF& scrollable_size, | |
353 float page_scale_factor, | |
354 float min_page_scale_factor, | |
355 float max_page_scale_factor) { | |
356 DCHECK(CalledOnValidThread()); | |
357 | |
358 if (registered_with_client_) { | |
359 // TODO(miletus): Pass in ScrollOffset. crbug.com/414283. | |
360 compositor_client_->UpdateRootLayerState( | |
361 gfx::ScrollOffsetToVector2dF(total_scroll_offset), | |
362 gfx::ScrollOffsetToVector2dF(max_scroll_offset), | |
363 scrollable_size, | |
364 page_scale_factor, | |
365 min_page_scale_factor, | |
366 max_page_scale_factor); | |
367 } | |
368 } | |
369 | |
370 // Not using base::NonThreadSafe as we want to enforce a more exacting threading | |
371 // requirement: SynchronousCompositorImpl() must only be used on the UI thread. | |
372 bool SynchronousCompositorImpl::CalledOnValidThread() const { | |
373 return BrowserThread::CurrentlyOn(BrowserThread::UI); | |
374 } | |
375 | |
376 } // namespace content | |
OLD | NEW |