Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_impl.cc
blob67a04ed97ebc66044adfb093a744a56a0358b95a
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/renderer_host/render_widget_host_view_android.h"
17 #include "content/common/input/did_overscroll_params.h"
18 #include "content/public/browser/android/synchronous_compositor_client.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "ui/gl/gl_surface.h"
24 namespace content {
26 namespace {
28 int GetInProcessRendererId() {
29 content::RenderProcessHost::iterator it =
30 content::RenderProcessHost::AllHostsIterator();
31 if (it.IsAtEnd()) {
32 // There should always be one RPH in single process mode.
33 NOTREACHED();
34 return 0;
37 int id = it.GetCurrentValue()->GetID();
38 it.Advance();
39 DCHECK(it.IsAtEnd()); // Not multiprocess compatible.
40 return id;
43 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
44 LAZY_INSTANCE_INITIALIZER;
46 } // namespace
48 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl);
50 // static
51 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id,
52 int routing_id) {
53 if (g_factory == NULL)
54 return NULL;
55 RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
56 if (!rvh)
57 return NULL;
58 WebContents* contents = WebContents::FromRenderViewHost(rvh);
59 if (!contents)
60 return NULL;
61 return FromWebContents(contents);
64 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
65 int routing_id) {
66 return FromID(GetInProcessRendererId(), routing_id);
69 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents)
70 : compositor_client_(NULL),
71 output_surface_(NULL),
72 begin_frame_source_(nullptr),
73 contents_(contents),
74 routing_id_(contents->GetRoutingID()),
75 input_handler_(NULL),
76 is_active_(false),
77 renderer_needs_begin_frames_(false),
78 weak_ptr_factory_(this) {
79 DCHECK(contents);
80 DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
81 SynchronousCompositorRegistry::GetInstance()->RegisterCompositor(routing_id_,
82 this);
85 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
86 SynchronousCompositorRegistry::GetInstance()->UnregisterCompositor(
87 routing_id_, this);
88 SetInputHandler(NULL);
90 DCHECK(!output_surface_);
91 DCHECK(!begin_frame_source_);
94 void SynchronousCompositorImpl::SetClient(
95 SynchronousCompositorClient* compositor_client) {
96 DCHECK(CalledOnValidThread());
97 compositor_client_ = compositor_client;
100 // static
101 void SynchronousCompositor::SetGpuService(
102 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
103 g_factory.Get().SetDeferredGpuService(service);
106 // static
107 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) {
108 g_factory.Get().SetRecordFullDocument(record_full_document);
111 void SynchronousCompositorImpl::DidInitializeRendererObjects(
112 SynchronousCompositorOutputSurface* output_surface,
113 SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
114 DCHECK(!output_surface_);
115 DCHECK(!begin_frame_source_);
116 DCHECK(output_surface);
117 DCHECK(begin_frame_source);
118 DCHECK(compositor_client_);
120 output_surface_ = output_surface;
121 begin_frame_source_ = begin_frame_source;
123 begin_frame_source_->SetCompositor(this);
124 output_surface_->SetCompositor(this);
126 output_surface_->SetTreeActivationCallback(
127 base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree,
128 weak_ptr_factory_.GetWeakPtr()));
130 OnNeedsBeginFramesChange(begin_frame_source_->NeedsBeginFrames());
132 compositor_client_->DidInitializeCompositor(this);
135 void SynchronousCompositorImpl::DidDestroyRendererObjects() {
136 DCHECK(output_surface_);
137 DCHECK(begin_frame_source_);
139 begin_frame_source_->SetCompositor(nullptr);
140 output_surface_->SetCompositor(nullptr);
141 if (compositor_client_)
142 compositor_client_->DidDestroyCompositor(this);
143 compositor_client_ = nullptr;
144 output_surface_ = nullptr;
145 begin_frame_source_ = nullptr;
148 void SynchronousCompositorImpl::NotifyDidDestroyCompositorToClient() {
149 if (compositor_client_)
150 compositor_client_->DidDestroyCompositor(this);
151 compositor_client_ = nullptr;
154 bool SynchronousCompositorImpl::InitializeHwDraw() {
155 DCHECK(CalledOnValidThread());
156 DCHECK(output_surface_);
158 scoped_refptr<cc::ContextProvider> onscreen_context =
159 g_factory.Get().CreateContextProviderForCompositor();
161 scoped_refptr<cc::ContextProvider> worker_context =
162 g_factory.Get().CreateContextProviderForCompositor();
164 bool success =
165 output_surface_->InitializeHwDraw(onscreen_context, worker_context);
167 if (success)
168 g_factory.Get().CompositorInitializedHardwareDraw();
169 return success;
172 void SynchronousCompositorImpl::ReleaseHwDraw() {
173 DCHECK(CalledOnValidThread());
174 DCHECK(output_surface_);
175 output_surface_->ReleaseHwDraw();
176 g_factory.Get().CompositorReleasedHardwareDraw();
179 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
180 gfx::Size surface_size,
181 const gfx::Transform& transform,
182 gfx::Rect viewport,
183 gfx::Rect clip,
184 gfx::Rect viewport_rect_for_tile_priority,
185 const gfx::Transform& transform_for_tile_priority) {
186 DCHECK(CalledOnValidThread());
187 DCHECK(output_surface_);
188 DCHECK(compositor_client_);
189 DCHECK(begin_frame_source_);
191 scoped_ptr<cc::CompositorFrame> frame =
192 output_surface_->DemandDrawHw(surface_size,
193 transform,
194 viewport,
195 clip,
196 viewport_rect_for_tile_priority,
197 transform_for_tile_priority);
199 if (frame.get())
200 UpdateFrameMetaData(frame->metadata);
202 return frame.Pass();
205 void SynchronousCompositorImpl::ReturnResources(
206 const cc::CompositorFrameAck& frame_ack) {
207 DCHECK(CalledOnValidThread());
208 output_surface_->ReturnResources(frame_ack);
211 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
212 DCHECK(CalledOnValidThread());
213 DCHECK(output_surface_);
214 DCHECK(compositor_client_);
215 DCHECK(begin_frame_source_);
217 scoped_ptr<cc::CompositorFrame> frame =
218 output_surface_->DemandDrawSw(canvas);
220 if (frame.get())
221 UpdateFrameMetaData(frame->metadata);
223 return !!frame.get();
226 void SynchronousCompositorImpl::UpdateFrameMetaData(
227 const cc::CompositorFrameMetadata& frame_metadata) {
228 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
229 contents_->GetRenderWidgetHostView());
230 if (rwhv)
231 rwhv->SynchronousFrameMetadata(frame_metadata);
232 DeliverMessages();
235 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
236 DCHECK(CalledOnValidThread());
237 DCHECK(output_surface_);
239 output_surface_->SetMemoryPolicy(bytes_limit);
242 void SynchronousCompositorImpl::PostInvalidate() {
243 DCHECK(CalledOnValidThread());
244 DCHECK(compositor_client_);
245 compositor_client_->PostInvalidate();
248 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
249 if (input_handler_)
250 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
253 void SynchronousCompositorImpl::SetIsActive(bool is_active) {
254 TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
255 is_active);
256 is_active_ = is_active;
257 UpdateNeedsBeginFrames();
260 void SynchronousCompositorImpl::OnNeedsBeginFramesChange(
261 bool needs_begin_frames) {
262 renderer_needs_begin_frames_ = needs_begin_frames;
263 UpdateNeedsBeginFrames();
266 void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) {
267 if (begin_frame_source_)
268 begin_frame_source_->BeginFrame(args);
271 void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
272 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
273 contents_->GetRenderWidgetHostView());
274 if (rwhv)
275 rwhv->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
278 void SynchronousCompositorImpl::SetInputHandler(
279 cc::InputHandler* input_handler) {
280 DCHECK(CalledOnValidThread());
282 if (input_handler_)
283 input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
285 input_handler_ = input_handler;
287 if (input_handler_)
288 input_handler_->SetRootLayerScrollOffsetDelegate(this);
291 void SynchronousCompositorImpl::DidOverscroll(
292 const DidOverscrollParams& params) {
293 if (compositor_client_) {
294 compositor_client_->DidOverscroll(params.accumulated_overscroll,
295 params.latest_overscroll_delta,
296 params.current_fling_velocity);
300 void SynchronousCompositorImpl::DidStopFlinging() {
301 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
302 contents_->GetRenderWidgetHostView());
303 if (rwhv)
304 rwhv->DidStopFlinging();
307 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
308 const blink::WebInputEvent& input_event) {
309 DCHECK(CalledOnValidThread());
310 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
311 contents_->GetRoutingID(), input_event);
314 void SynchronousCompositorImpl::DeliverMessages() {
315 ScopedVector<IPC::Message> messages;
316 output_surface_->GetMessagesToDeliver(&messages);
317 RenderProcessHost* rph = contents_->GetRenderProcessHost();
318 for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
319 i != messages.end();
320 ++i) {
321 rph->OnMessageReceived(**i);
325 void SynchronousCompositorImpl::DidActivatePendingTree() {
326 if (compositor_client_)
327 compositor_client_->DidUpdateContent();
330 gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() {
331 DCHECK(CalledOnValidThread());
332 if (compositor_client_) {
333 // TODO(miletus): Make GetTotalRootLayerScrollOffset return
334 // ScrollOffset. crbug.com/414283.
335 return gfx::ScrollOffset(
336 compositor_client_->GetTotalRootLayerScrollOffset());
338 return gfx::ScrollOffset();
341 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
342 DCHECK(CalledOnValidThread());
343 if (compositor_client_)
344 return compositor_client_->IsExternalFlingActive();
345 return false;
348 void SynchronousCompositorImpl::UpdateRootLayerState(
349 const gfx::ScrollOffset& total_scroll_offset,
350 const gfx::ScrollOffset& max_scroll_offset,
351 const gfx::SizeF& scrollable_size,
352 float page_scale_factor,
353 float min_page_scale_factor,
354 float max_page_scale_factor) {
355 DCHECK(CalledOnValidThread());
356 if (!compositor_client_)
357 return;
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);
369 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
370 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
371 bool SynchronousCompositorImpl::CalledOnValidThread() const {
372 return BrowserThread::CurrentlyOn(BrowserThread::UI);
375 // static
376 void SynchronousCompositor::SetClientForWebContents(
377 WebContents* contents,
378 SynchronousCompositorClient* client) {
379 DCHECK(contents);
380 if (client) {
381 g_factory.Get(); // Ensure it's initialized.
382 SynchronousCompositorImpl::CreateForWebContents(contents);
384 SynchronousCompositorImpl* instance =
385 SynchronousCompositorImpl::FromWebContents(contents);
386 DCHECK(instance);
387 instance->SetClient(client);
390 } // namespace content