Move VISUAL_STATE promise to activation
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_impl.cc
blobd3c6b830b7082bf6e2dec32f803b6751d249aa47
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/common/input_messages.h"
19 #include "content/public/browser/android/synchronous_compositor_client.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "ui/gl/gl_surface.h"
25 namespace content {
27 namespace {
29 int GetInProcessRendererId() {
30 content::RenderProcessHost::iterator it =
31 content::RenderProcessHost::AllHostsIterator();
32 if (it.IsAtEnd()) {
33 // There should always be one RPH in single process mode.
34 NOTREACHED();
35 return 0;
38 int id = it.GetCurrentValue()->GetID();
39 it.Advance();
40 DCHECK(it.IsAtEnd()); // Not multiprocess compatible.
41 return id;
44 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
45 LAZY_INSTANCE_INITIALIZER;
47 } // namespace
49 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl);
51 // static
52 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id,
53 int routing_id) {
54 if (g_factory == NULL)
55 return NULL;
56 RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
57 if (!rvh)
58 return NULL;
59 WebContents* contents = WebContents::FromRenderViewHost(rvh);
60 if (!contents)
61 return NULL;
62 return FromWebContents(contents);
65 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
66 int routing_id) {
67 return FromID(GetInProcessRendererId(), routing_id);
70 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents)
71 : compositor_client_(NULL),
72 output_surface_(NULL),
73 begin_frame_source_(nullptr),
74 contents_(contents),
75 routing_id_(contents->GetRoutingID()),
76 input_handler_(NULL),
77 is_active_(false),
78 renderer_needs_begin_frames_(false),
79 weak_ptr_factory_(this) {
80 DCHECK(contents);
81 DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
84 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
85 DCHECK(!output_surface_);
86 DCHECK(!begin_frame_source_);
87 DCHECK(!input_handler_);
90 void SynchronousCompositorImpl::SetClient(
91 SynchronousCompositorClient* compositor_client) {
92 DCHECK(CalledOnValidThread());
93 DCHECK_IMPLIES(compositor_client, !compositor_client_);
94 DCHECK_IMPLIES(!compositor_client, compositor_client_);
96 if (!compositor_client) {
97 SynchronousCompositorRegistry::GetInstance()->UnregisterCompositor(
98 routing_id_, this);
101 compositor_client_ = compositor_client;
103 // SetClient is essentially the constructor and destructor of
104 // SynchronousCompositorImpl.
105 if (compositor_client_) {
106 SynchronousCompositorRegistry::GetInstance()->RegisterCompositor(
107 routing_id_, this);
111 // static
112 void SynchronousCompositor::SetGpuService(
113 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
114 g_factory.Get().SetDeferredGpuService(service);
117 // static
118 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) {
119 g_factory.Get().SetRecordFullDocument(record_full_document);
122 void SynchronousCompositorImpl::DidInitializeRendererObjects(
123 SynchronousCompositorOutputSurface* output_surface,
124 SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
125 cc::InputHandler* input_handler) {
126 DCHECK(!output_surface_);
127 DCHECK(!begin_frame_source_);
128 DCHECK(output_surface);
129 DCHECK(begin_frame_source);
130 DCHECK(compositor_client_);
131 DCHECK(input_handler);
133 output_surface_ = output_surface;
134 begin_frame_source_ = begin_frame_source;
136 begin_frame_source_->SetCompositor(this);
137 output_surface_->SetCompositor(this);
139 output_surface_->SetTreeActivationCallback(
140 base::Bind(&SynchronousCompositorImpl::DidActivatePendingTree,
141 weak_ptr_factory_.GetWeakPtr()));
143 OnNeedsBeginFramesChange(begin_frame_source_->NeedsBeginFrames());
145 compositor_client_->DidInitializeCompositor(this);
147 SetInputHandler(input_handler);
150 void SynchronousCompositorImpl::DidDestroyRendererObjects() {
151 DCHECK(output_surface_);
152 DCHECK(begin_frame_source_);
153 DCHECK(compositor_client_);
155 begin_frame_source_->SetCompositor(nullptr);
156 output_surface_->SetCompositor(nullptr);
157 SetInputHandler(nullptr);
158 compositor_client_->DidDestroyCompositor(this);
159 output_surface_ = nullptr;
160 begin_frame_source_ = nullptr;
163 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
164 gfx::Size surface_size,
165 const gfx::Transform& transform,
166 gfx::Rect viewport,
167 gfx::Rect clip,
168 gfx::Rect viewport_rect_for_tile_priority,
169 const gfx::Transform& transform_for_tile_priority) {
170 DCHECK(CalledOnValidThread());
171 DCHECK(output_surface_);
172 DCHECK(compositor_client_);
173 DCHECK(begin_frame_source_);
175 scoped_ptr<cc::CompositorFrame> frame =
176 output_surface_->DemandDrawHw(surface_size,
177 transform,
178 viewport,
179 clip,
180 viewport_rect_for_tile_priority,
181 transform_for_tile_priority);
183 if (frame.get())
184 UpdateFrameMetaData(frame->metadata);
186 return frame.Pass();
189 void SynchronousCompositorImpl::ReturnResources(
190 const cc::CompositorFrameAck& frame_ack) {
191 DCHECK(CalledOnValidThread());
192 output_surface_->ReturnResources(frame_ack);
195 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
196 DCHECK(CalledOnValidThread());
197 DCHECK(output_surface_);
198 DCHECK(compositor_client_);
199 DCHECK(begin_frame_source_);
201 scoped_ptr<cc::CompositorFrame> frame =
202 output_surface_->DemandDrawSw(canvas);
204 if (frame.get())
205 UpdateFrameMetaData(frame->metadata);
207 return !!frame.get();
210 void SynchronousCompositorImpl::UpdateFrameMetaData(
211 const cc::CompositorFrameMetadata& frame_metadata) {
212 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
213 contents_->GetRenderWidgetHostView());
214 if (rwhv)
215 rwhv->SynchronousFrameMetadata(frame_metadata);
216 DeliverMessages();
219 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
220 DCHECK(CalledOnValidThread());
221 DCHECK(output_surface_);
223 size_t current_bytes_limit = output_surface_->GetMemoryPolicy();
224 output_surface_->SetMemoryPolicy(bytes_limit);
226 if (bytes_limit && !current_bytes_limit) {
227 g_factory.Get().CompositorInitializedHardwareDraw();
228 } else if (!bytes_limit && current_bytes_limit) {
229 g_factory.Get().CompositorReleasedHardwareDraw();
233 void SynchronousCompositorImpl::PostInvalidate() {
234 DCHECK(CalledOnValidThread());
235 DCHECK(compositor_client_);
236 compositor_client_->PostInvalidate();
239 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
240 if (input_handler_)
241 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
244 void SynchronousCompositorImpl::SetIsActive(bool is_active) {
245 TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
246 is_active);
247 is_active_ = is_active;
248 UpdateNeedsBeginFrames();
251 void SynchronousCompositorImpl::OnNeedsBeginFramesChange(
252 bool needs_begin_frames) {
253 renderer_needs_begin_frames_ = needs_begin_frames;
254 UpdateNeedsBeginFrames();
257 void SynchronousCompositorImpl::BeginFrame(const cc::BeginFrameArgs& args) {
258 if (begin_frame_source_)
259 begin_frame_source_->BeginFrame(args);
262 void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
263 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
264 contents_->GetRenderWidgetHostView());
265 if (rwhv)
266 rwhv->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
269 void SynchronousCompositorImpl::SetInputHandler(
270 cc::InputHandler* input_handler) {
271 DCHECK(CalledOnValidThread());
273 if (input_handler_)
274 input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
276 input_handler_ = input_handler;
278 if (input_handler_)
279 input_handler_->SetRootLayerScrollOffsetDelegate(this);
282 void SynchronousCompositorImpl::DidOverscroll(
283 const DidOverscrollParams& params) {
284 DCHECK(compositor_client_);
285 compositor_client_->DidOverscroll(params.accumulated_overscroll,
286 params.latest_overscroll_delta,
287 params.current_fling_velocity);
290 void SynchronousCompositorImpl::DidStopFlinging() {
291 // It's important that the fling-end notification follow the same path as it
292 // takes on other platforms (using an IPC). This ensures consistent
293 // bookkeeping at all stages of the input pipeline.
294 contents_->GetRenderProcessHost()->OnMessageReceived(
295 InputHostMsg_DidStopFlinging(routing_id_));
298 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
299 const blink::WebInputEvent& input_event) {
300 DCHECK(CalledOnValidThread());
301 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
302 contents_->GetRoutingID(), input_event);
305 void SynchronousCompositorImpl::DeliverMessages() {
306 ScopedVector<IPC::Message> messages;
307 output_surface_->GetMessagesToDeliver(&messages);
308 RenderProcessHost* rph = contents_->GetRenderProcessHost();
309 for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
310 i != messages.end();
311 ++i) {
312 rph->OnMessageReceived(**i);
316 void SynchronousCompositorImpl::DidActivatePendingTree() {
317 DCHECK(compositor_client_);
318 compositor_client_->DidUpdateContent();
319 DeliverMessages();
322 gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() {
323 DCHECK(CalledOnValidThread());
324 DCHECK(compositor_client_);
325 // TODO(miletus): Make GetTotalRootLayerScrollOffset return
326 // ScrollOffset. crbug.com/414283.
327 return gfx::ScrollOffset(
328 compositor_client_->GetTotalRootLayerScrollOffset());
331 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
332 DCHECK(CalledOnValidThread());
333 DCHECK(compositor_client_);
334 return compositor_client_->IsExternalFlingActive();
337 void SynchronousCompositorImpl::UpdateRootLayerState(
338 const gfx::ScrollOffset& total_scroll_offset,
339 const gfx::ScrollOffset& max_scroll_offset,
340 const gfx::SizeF& scrollable_size,
341 float page_scale_factor,
342 float min_page_scale_factor,
343 float max_page_scale_factor) {
344 DCHECK(CalledOnValidThread());
345 DCHECK(compositor_client_);
347 // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
348 compositor_client_->UpdateRootLayerState(
349 gfx::ScrollOffsetToVector2dF(total_scroll_offset),
350 gfx::ScrollOffsetToVector2dF(max_scroll_offset),
351 scrollable_size,
352 page_scale_factor,
353 min_page_scale_factor,
354 max_page_scale_factor);
357 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
358 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
359 bool SynchronousCompositorImpl::CalledOnValidThread() const {
360 return BrowserThread::CurrentlyOn(BrowserThread::UI);
363 // static
364 void SynchronousCompositor::SetClientForWebContents(
365 WebContents* contents,
366 SynchronousCompositorClient* client) {
367 DCHECK(contents);
368 if (client) {
369 g_factory.Get(); // Ensure it's initialized.
370 SynchronousCompositorImpl::CreateForWebContents(contents);
372 SynchronousCompositorImpl* instance =
373 SynchronousCompositorImpl::FromWebContents(contents);
374 DCHECK(instance);
375 instance->SetClient(client);
378 } // namespace content