[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_impl.cc
blob06d622ce3eed794256d4425149de839f1030d74e
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.
5 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/lazy_instance.h"
10 #include "base/message_loop/message_loop.h"
11 #include "cc/input/input_handler.h"
12 #include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h"
13 #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
14 #include "content/browser/android/in_process/synchronous_compositor_registry.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 "ui/gl/gl_surface.h"
26 namespace content {
28 namespace {
30 int GetInProcessRendererId() {
31 content::RenderProcessHost::iterator it =
32 content::RenderProcessHost::AllHostsIterator();
33 if (it.IsAtEnd()) {
34 // There should always be one RPH in single process mode.
35 NOTREACHED();
36 return 0;
39 int id = it.GetCurrentValue()->GetID();
40 it.Advance();
41 DCHECK(it.IsAtEnd()); // Not multiprocess compatible.
42 return id;
45 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
46 LAZY_INSTANCE_INITIALIZER;
48 base::Thread* CreateInProcessGpuThreadForSynchronousCompositor(
49 const InProcessChildThreadParams& params) {
50 return g_factory.Get().CreateInProcessGpuThread(params);
53 } // namespace
55 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl);
57 // static
58 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id,
59 int routing_id) {
60 if (g_factory == nullptr)
61 return nullptr;
62 RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
63 if (!rvh)
64 return nullptr;
65 WebContents* contents = WebContents::FromRenderViewHost(rvh);
66 if (!contents)
67 return nullptr;
68 return FromWebContents(contents);
71 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
72 int routing_id) {
73 return FromID(GetInProcessRendererId(), routing_id);
76 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents)
77 : compositor_client_(nullptr),
78 output_surface_(nullptr),
79 begin_frame_source_(nullptr),
80 contents_(contents),
81 routing_id_(contents->GetRoutingID()),
82 input_handler_(nullptr),
83 registered_with_client_(false),
84 is_active_(true),
85 renderer_needs_begin_frames_(false),
86 need_animate_input_(false),
87 weak_ptr_factory_(this) {
88 DCHECK(contents);
89 DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
92 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
93 DCHECK(!output_surface_);
94 DCHECK(!begin_frame_source_);
95 DCHECK(!input_handler_);
98 void SynchronousCompositorImpl::SetClient(
99 SynchronousCompositorClient* compositor_client) {
100 DCHECK(CalledOnValidThread());
101 DCHECK_IMPLIES(compositor_client, !compositor_client_);
102 DCHECK_IMPLIES(!compositor_client, compositor_client_);
104 if (!compositor_client) {
105 SynchronousCompositorRegistry::GetInstance()->UnregisterCompositor(
106 routing_id_, this);
109 compositor_client_ = compositor_client;
111 // SetClient is essentially the constructor and destructor of
112 // SynchronousCompositorImpl.
113 if (compositor_client_) {
114 SynchronousCompositorRegistry::GetInstance()->RegisterCompositor(
115 routing_id_, this);
119 void SynchronousCompositorImpl::RegisterWithClient() {
120 DCHECK(CalledOnValidThread());
121 DCHECK(compositor_client_);
122 DCHECK(output_surface_);
123 DCHECK(input_handler_);
124 DCHECK(!registered_with_client_);
125 registered_with_client_ = true;
127 compositor_client_->DidInitializeCompositor(this);
129 output_surface_->SetTreeActivationCallback(
130 base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree,
131 weak_ptr_factory_.GetWeakPtr()));
133 // Setting the delegate causes UpdateRootLayerState immediately so do it
134 // after setting the client.
135 input_handler_->SetRootLayerScrollOffsetDelegate(this);
136 // This disables the input system from animating inputs autonomously, instead
137 // routing all input animations through the SynchronousInputHandler, which is
138 // |this| class.
139 synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
142 // static
143 void SynchronousCompositor::SetGpuService(
144 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
145 g_factory.Get().SetDeferredGpuService(service);
146 GpuProcessHost::RegisterGpuMainThreadFactory(
147 CreateInProcessGpuThreadForSynchronousCompositor);
150 // static
151 void SynchronousCompositor::SetUseIpcCommandBuffer() {
152 g_factory.Get().SetUseIpcCommandBuffer();
155 void SynchronousCompositorImpl::DidInitializeRendererObjects(
156 SynchronousCompositorOutputSurface* output_surface,
157 SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
158 cc::InputHandler* input_handler,
159 SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
160 DCHECK(!output_surface_);
161 DCHECK(!begin_frame_source_);
162 DCHECK(output_surface);
163 DCHECK(begin_frame_source);
164 DCHECK(compositor_client_);
165 DCHECK(input_handler);
166 DCHECK(synchronous_input_handler_proxy);
168 output_surface_ = output_surface;
169 begin_frame_source_ = begin_frame_source;
170 input_handler_ = input_handler;
171 synchronous_input_handler_proxy_ = synchronous_input_handler_proxy;
173 output_surface_->SetCompositor(this);
174 begin_frame_source_->SetCompositor(this);
177 void SynchronousCompositorImpl::DidDestroyRendererObjects() {
178 DCHECK(output_surface_);
179 DCHECK(begin_frame_source_);
180 DCHECK(compositor_client_);
182 if (registered_with_client_) {
183 input_handler_->SetRootLayerScrollOffsetDelegate(nullptr);
184 output_surface_->SetTreeActivationCallback(base::Closure());
185 compositor_client_->DidDestroyCompositor(this);
186 registered_with_client_ = false;
189 begin_frame_source_->SetCompositor(nullptr);
190 output_surface_->SetCompositor(nullptr);
192 input_handler_ = nullptr;
193 begin_frame_source_ = nullptr;
194 output_surface_ = nullptr;
195 // Don't propogate this signal from one renderer to the next.
196 need_animate_input_ = false;
199 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
200 gfx::Size surface_size,
201 const gfx::Transform& transform,
202 gfx::Rect viewport,
203 gfx::Rect clip,
204 gfx::Rect viewport_rect_for_tile_priority,
205 const gfx::Transform& transform_for_tile_priority) {
206 DCHECK(CalledOnValidThread());
207 DCHECK(output_surface_);
208 DCHECK(compositor_client_);
209 DCHECK(begin_frame_source_);
211 scoped_ptr<cc::CompositorFrame> frame =
212 output_surface_->DemandDrawHw(surface_size,
213 transform,
214 viewport,
215 clip,
216 viewport_rect_for_tile_priority,
217 transform_for_tile_priority);
219 if (frame.get())
220 UpdateFrameMetaData(frame->metadata);
222 return frame.Pass();
225 void SynchronousCompositorImpl::ReturnResources(
226 const cc::CompositorFrameAck& frame_ack) {
227 DCHECK(CalledOnValidThread());
228 output_surface_->ReturnResources(frame_ack);
231 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
232 DCHECK(CalledOnValidThread());
233 DCHECK(output_surface_);
234 DCHECK(compositor_client_);
235 DCHECK(begin_frame_source_);
237 scoped_ptr<cc::CompositorFrame> frame =
238 output_surface_->DemandDrawSw(canvas);
240 if (frame.get())
241 UpdateFrameMetaData(frame->metadata);
243 return !!frame.get();
246 void SynchronousCompositorImpl::UpdateFrameMetaData(
247 const cc::CompositorFrameMetadata& frame_metadata) {
248 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
249 contents_->GetRenderWidgetHostView());
250 if (rwhv)
251 rwhv->SynchronousFrameMetadata(frame_metadata);
252 DeliverMessages();
255 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
256 DCHECK(CalledOnValidThread());
257 DCHECK(output_surface_);
259 size_t current_bytes_limit = output_surface_->GetMemoryPolicy();
260 output_surface_->SetMemoryPolicy(bytes_limit);
262 if (bytes_limit && !current_bytes_limit) {
263 g_factory.Get().CompositorInitializedHardwareDraw();
264 } else if (!bytes_limit && current_bytes_limit) {
265 g_factory.Get().CompositorReleasedHardwareDraw();
269 void SynchronousCompositorImpl::PostInvalidate() {
270 DCHECK(CalledOnValidThread());
271 DCHECK(compositor_client_);
272 if (registered_with_client_)
273 compositor_client_->PostInvalidate();
276 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset(
277 const gfx::ScrollOffset& root_offset) {
278 DCHECK(CalledOnValidThread());
279 if (!input_handler_)
280 return;
281 input_handler_->OnRootLayerDelegatedScrollOffsetChanged(root_offset);
284 void SynchronousCompositorImpl::SetIsActive(bool is_active) {
285 TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
286 is_active);
287 is_active_ = is_active;
288 UpdateNeedsBeginFrames();
291 void SynchronousCompositorImpl::OnComputeScroll(
292 base::TimeTicks animation_time) {
293 if (need_animate_input_) {
294 need_animate_input_ = false;
295 synchronous_input_handler_proxy_->SynchronouslyAnimate(animation_time);
299 void SynchronousCompositorImpl::OnNeedsBeginFramesChange(
300 bool needs_begin_frames) {
301 renderer_needs_begin_frames_ = needs_begin_frames;
302 UpdateNeedsBeginFrames();
305 void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) {
306 if (!registered_with_client_ && is_active_ && renderer_needs_begin_frames_) {
307 // Make sure this is a BeginFrame that renderer side explicitly requested.
308 // Otherwise it is possible renderer objects not initialized.
309 RegisterWithClient();
310 DCHECK(registered_with_client_);
312 if (begin_frame_source_)
313 begin_frame_source_->BeginFrame(args);
316 void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
317 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
318 contents_->GetRenderWidgetHostView());
319 if (rwhv)
320 rwhv->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
323 void SynchronousCompositorImpl::DidOverscroll(
324 const DidOverscrollParams& params) {
325 DCHECK(compositor_client_);
326 if (registered_with_client_) {
327 compositor_client_->DidOverscroll(params.accumulated_overscroll,
328 params.latest_overscroll_delta,
329 params.current_fling_velocity);
333 void SynchronousCompositorImpl::DidStopFlinging() {
334 // It's important that the fling-end notification follow the same path as it
335 // takes on other platforms (using an IPC). This ensures consistent
336 // bookkeeping at all stages of the input pipeline.
337 contents_->GetRenderProcessHost()->OnMessageReceived(
338 InputHostMsg_DidStopFlinging(routing_id_));
341 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
342 const blink::WebInputEvent& input_event) {
343 DCHECK(CalledOnValidThread());
344 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
345 contents_->GetRoutingID(), input_event);
348 void SynchronousCompositorImpl::DeliverMessages() {
349 ScopedVector<IPC::Message> messages;
350 output_surface_->GetMessagesToDeliver(&messages);
351 RenderProcessHost* rph = contents_->GetRenderProcessHost();
352 for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
353 i != messages.end();
354 ++i) {
355 rph->OnMessageReceived(**i);
359 void SynchronousCompositorImpl::DidActivatePendingTree() {
360 DCHECK(compositor_client_);
361 if (registered_with_client_)
362 compositor_client_->DidUpdateContent();
363 DeliverMessages();
366 void SynchronousCompositorImpl::SetNeedsSynchronousAnimateInput() {
367 DCHECK(CalledOnValidThread());
368 DCHECK(compositor_client_);
369 if (!registered_with_client_)
370 return;
371 need_animate_input_ = true;
372 compositor_client_->PostInvalidate();
375 void SynchronousCompositorImpl::UpdateRootLayerState(
376 const gfx::ScrollOffset& total_scroll_offset,
377 const gfx::ScrollOffset& max_scroll_offset,
378 const gfx::SizeF& scrollable_size,
379 float page_scale_factor,
380 float min_page_scale_factor,
381 float max_page_scale_factor) {
382 DCHECK(CalledOnValidThread());
383 DCHECK(compositor_client_);
385 if (registered_with_client_) {
386 // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
387 compositor_client_->UpdateRootLayerState(
388 gfx::ScrollOffsetToVector2dF(total_scroll_offset),
389 gfx::ScrollOffsetToVector2dF(max_scroll_offset),
390 scrollable_size,
391 page_scale_factor,
392 min_page_scale_factor,
393 max_page_scale_factor);
397 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
398 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
399 bool SynchronousCompositorImpl::CalledOnValidThread() const {
400 return BrowserThread::CurrentlyOn(BrowserThread::UI);
403 // static
404 void SynchronousCompositor::SetClientForWebContents(
405 WebContents* contents,
406 SynchronousCompositorClient* client) {
407 DCHECK(contents);
408 if (client) {
409 g_factory.Get(); // Ensure it's initialized.
410 SynchronousCompositorImpl::CreateForWebContents(contents);
412 SynchronousCompositorImpl* instance =
413 SynchronousCompositorImpl::FromWebContents(contents);
414 DCHECK(instance);
415 instance->SetClient(client);
418 } // namespace content