Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_impl.cc
blobe16539eadfcbb8f13e3ac0931cd7f7d89799658c
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 weak_ptr_factory_(this) {
87 DCHECK(contents);
88 DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
91 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
92 DCHECK(!output_surface_);
93 DCHECK(!begin_frame_source_);
94 DCHECK(!input_handler_);
97 void SynchronousCompositorImpl::SetClient(
98 SynchronousCompositorClient* compositor_client) {
99 DCHECK(CalledOnValidThread());
100 DCHECK_IMPLIES(compositor_client, !compositor_client_);
101 DCHECK_IMPLIES(!compositor_client, compositor_client_);
103 if (!compositor_client) {
104 SynchronousCompositorRegistry::GetInstance()->UnregisterCompositor(
105 routing_id_, this);
108 compositor_client_ = compositor_client;
110 // SetClient is essentially the constructor and destructor of
111 // SynchronousCompositorImpl.
112 if (compositor_client_) {
113 SynchronousCompositorRegistry::GetInstance()->RegisterCompositor(
114 routing_id_, this);
118 void SynchronousCompositorImpl::RegisterWithClient() {
119 DCHECK(CalledOnValidThread());
120 DCHECK(compositor_client_);
121 DCHECK(output_surface_);
122 DCHECK(input_handler_);
123 DCHECK(!registered_with_client_);
124 registered_with_client_ = true;
126 compositor_client_->DidInitializeCompositor(this);
128 output_surface_->SetTreeActivationCallback(
129 base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree,
130 weak_ptr_factory_.GetWeakPtr()));
132 // Setting the delegate causes UpdateRootLayerState immediately so do it
133 // after setting the client.
134 input_handler_->SetRootLayerScrollOffsetDelegate(this);
137 // static
138 void SynchronousCompositor::SetGpuService(
139 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
140 g_factory.Get().SetDeferredGpuService(service);
141 GpuProcessHost::RegisterGpuMainThreadFactory(
142 CreateInProcessGpuThreadForSynchronousCompositor);
145 // static
146 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) {
147 g_factory.Get().SetRecordFullDocument(record_full_document);
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 DCHECK(!output_surface_);
160 DCHECK(!begin_frame_source_);
161 DCHECK(output_surface);
162 DCHECK(begin_frame_source);
163 DCHECK(compositor_client_);
164 DCHECK(input_handler);
166 output_surface_ = output_surface;
167 begin_frame_source_ = begin_frame_source;
168 input_handler_ = input_handler;
170 output_surface_->SetCompositor(this);
171 begin_frame_source_->SetCompositor(this);
174 void SynchronousCompositorImpl::DidDestroyRendererObjects() {
175 DCHECK(output_surface_);
176 DCHECK(begin_frame_source_);
177 DCHECK(compositor_client_);
179 if (registered_with_client_) {
180 input_handler_->SetRootLayerScrollOffsetDelegate(nullptr);
181 output_surface_->SetTreeActivationCallback(base::Closure());
182 compositor_client_->DidDestroyCompositor(this);
183 registered_with_client_ = false;
186 begin_frame_source_->SetCompositor(nullptr);
187 output_surface_->SetCompositor(nullptr);
189 input_handler_ = nullptr;
190 begin_frame_source_ = nullptr;
191 output_surface_ = nullptr;
194 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
195 gfx::Size surface_size,
196 const gfx::Transform& transform,
197 gfx::Rect viewport,
198 gfx::Rect clip,
199 gfx::Rect viewport_rect_for_tile_priority,
200 const gfx::Transform& transform_for_tile_priority) {
201 DCHECK(CalledOnValidThread());
202 DCHECK(output_surface_);
203 DCHECK(compositor_client_);
204 DCHECK(begin_frame_source_);
206 scoped_ptr<cc::CompositorFrame> frame =
207 output_surface_->DemandDrawHw(surface_size,
208 transform,
209 viewport,
210 clip,
211 viewport_rect_for_tile_priority,
212 transform_for_tile_priority);
214 if (frame.get())
215 UpdateFrameMetaData(frame->metadata);
217 return frame.Pass();
220 void SynchronousCompositorImpl::ReturnResources(
221 const cc::CompositorFrameAck& frame_ack) {
222 DCHECK(CalledOnValidThread());
223 output_surface_->ReturnResources(frame_ack);
226 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
227 DCHECK(CalledOnValidThread());
228 DCHECK(output_surface_);
229 DCHECK(compositor_client_);
230 DCHECK(begin_frame_source_);
232 scoped_ptr<cc::CompositorFrame> frame =
233 output_surface_->DemandDrawSw(canvas);
235 if (frame.get())
236 UpdateFrameMetaData(frame->metadata);
238 return !!frame.get();
241 void SynchronousCompositorImpl::UpdateFrameMetaData(
242 const cc::CompositorFrameMetadata& frame_metadata) {
243 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
244 contents_->GetRenderWidgetHostView());
245 if (rwhv)
246 rwhv->SynchronousFrameMetadata(frame_metadata);
247 DeliverMessages();
250 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
251 DCHECK(CalledOnValidThread());
252 DCHECK(output_surface_);
254 size_t current_bytes_limit = output_surface_->GetMemoryPolicy();
255 output_surface_->SetMemoryPolicy(bytes_limit);
257 if (bytes_limit && !current_bytes_limit) {
258 g_factory.Get().CompositorInitializedHardwareDraw();
259 } else if (!bytes_limit && current_bytes_limit) {
260 g_factory.Get().CompositorReleasedHardwareDraw();
264 void SynchronousCompositorImpl::PostInvalidate() {
265 DCHECK(CalledOnValidThread());
266 DCHECK(compositor_client_);
267 if (registered_with_client_)
268 compositor_client_->PostInvalidate();
271 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
272 if (input_handler_)
273 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
276 void SynchronousCompositorImpl::SetIsActive(bool is_active) {
277 TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
278 is_active);
279 is_active_ = is_active;
280 UpdateNeedsBeginFrames();
283 void SynchronousCompositorImpl::OnNeedsBeginFramesChange(
284 bool needs_begin_frames) {
285 renderer_needs_begin_frames_ = needs_begin_frames;
286 UpdateNeedsBeginFrames();
289 void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) {
290 if (!registered_with_client_ && is_active_ && renderer_needs_begin_frames_) {
291 // Make sure this is a BeginFrame that renderer side explicitly requested.
292 // Otherwise it is possible renderer objects not initialized.
293 RegisterWithClient();
294 DCHECK(registered_with_client_);
296 if (begin_frame_source_)
297 begin_frame_source_->BeginFrame(args);
300 void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
301 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
302 contents_->GetRenderWidgetHostView());
303 if (rwhv)
304 rwhv->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
307 void SynchronousCompositorImpl::DidOverscroll(
308 const DidOverscrollParams& params) {
309 DCHECK(compositor_client_);
310 if (registered_with_client_) {
311 compositor_client_->DidOverscroll(params.accumulated_overscroll,
312 params.latest_overscroll_delta,
313 params.current_fling_velocity);
317 void SynchronousCompositorImpl::DidStopFlinging() {
318 // It's important that the fling-end notification follow the same path as it
319 // takes on other platforms (using an IPC). This ensures consistent
320 // bookkeeping at all stages of the input pipeline.
321 contents_->GetRenderProcessHost()->OnMessageReceived(
322 InputHostMsg_DidStopFlinging(routing_id_));
325 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
326 const blink::WebInputEvent& input_event) {
327 DCHECK(CalledOnValidThread());
328 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
329 contents_->GetRoutingID(), input_event);
332 void SynchronousCompositorImpl::DeliverMessages() {
333 ScopedVector<IPC::Message> messages;
334 output_surface_->GetMessagesToDeliver(&messages);
335 RenderProcessHost* rph = contents_->GetRenderProcessHost();
336 for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
337 i != messages.end();
338 ++i) {
339 rph->OnMessageReceived(**i);
343 void SynchronousCompositorImpl::DidActivatePendingTree() {
344 DCHECK(compositor_client_);
345 if (registered_with_client_)
346 compositor_client_->DidUpdateContent();
347 DeliverMessages();
350 gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() {
351 DCHECK(CalledOnValidThread());
352 DCHECK(compositor_client_);
353 if (!registered_with_client_)
354 return gfx::ScrollOffset();
355 // TODO(miletus): Make GetTotalRootLayerScrollOffset return
356 // ScrollOffset. crbug.com/414283.
357 return gfx::ScrollOffset(
358 compositor_client_->GetTotalRootLayerScrollOffset());
361 bool SynchronousCompositorImpl::IsExternalScrollActive() const {
362 DCHECK(CalledOnValidThread());
363 DCHECK(compositor_client_);
364 if (!registered_with_client_)
365 return false;
366 return compositor_client_->IsExternalScrollActive();
369 void SynchronousCompositorImpl::SetNeedsAnimate(
370 const AnimationCallback& animation) {
371 DCHECK(CalledOnValidThread());
372 DCHECK(compositor_client_);
373 if (!registered_with_client_)
374 return;
375 compositor_client_->SetNeedsAnimateScroll(animation);
378 void SynchronousCompositorImpl::UpdateRootLayerState(
379 const gfx::ScrollOffset& total_scroll_offset,
380 const gfx::ScrollOffset& max_scroll_offset,
381 const gfx::SizeF& scrollable_size,
382 float page_scale_factor,
383 float min_page_scale_factor,
384 float max_page_scale_factor) {
385 DCHECK(CalledOnValidThread());
386 DCHECK(compositor_client_);
388 if (registered_with_client_) {
389 // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
390 compositor_client_->UpdateRootLayerState(
391 gfx::ScrollOffsetToVector2dF(total_scroll_offset),
392 gfx::ScrollOffsetToVector2dF(max_scroll_offset),
393 scrollable_size,
394 page_scale_factor,
395 min_page_scale_factor,
396 max_page_scale_factor);
400 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
401 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
402 bool SynchronousCompositorImpl::CalledOnValidThread() const {
403 return BrowserThread::CurrentlyOn(BrowserThread::UI);
406 // static
407 void SynchronousCompositor::SetClientForWebContents(
408 WebContents* contents,
409 SynchronousCompositorClient* client) {
410 DCHECK(contents);
411 if (client) {
412 g_factory.Get(); // Ensure it's initialized.
413 SynchronousCompositorImpl::CreateForWebContents(contents);
415 SynchronousCompositorImpl* instance =
416 SynchronousCompositorImpl::FromWebContents(contents);
417 DCHECK(instance);
418 instance->SetClient(client);
421 } // namespace content