Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / android / in_process / synchronous_compositor_impl.cc
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 "base/lazy_instance.h"
8 #include "base/message_loop/message_loop.h"
9 #include "cc/input/input_handler.h"
10 #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
11 #include "content/browser/android/in_process/synchronous_input_event_filter.h"
12 #include "content/browser/renderer_host/render_widget_host_view_android.h"
13 #include "content/common/input/did_overscroll_params.h"
14 #include "content/public/browser/android/synchronous_compositor_client.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "ui/gl/gl_surface.h"
19
20 namespace content {
21
22 namespace {
23
24 int GetInProcessRendererId() {
25   content::RenderProcessHost::iterator it =
26       content::RenderProcessHost::AllHostsIterator();
27   if (it.IsAtEnd()) {
28     // There should always be one RPH in single process mode.
29     NOTREACHED();
30     return 0;
31   }
32
33   int id = it.GetCurrentValue()->GetID();
34   it.Advance();
35   DCHECK(it.IsAtEnd());  // Not multiprocess compatible.
36   return id;
37 }
38
39 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
40     LAZY_INSTANCE_INITIALIZER;
41
42 }  // namespace
43
44 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl);
45
46 // static
47 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id,
48                                                              int routing_id) {
49   if (g_factory == NULL)
50     return NULL;
51   RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
52   if (!rvh)
53     return NULL;
54   WebContents* contents = WebContents::FromRenderViewHost(rvh);
55   if (!contents)
56     return NULL;
57   return FromWebContents(contents);
58 }
59
60 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
61     int routing_id) {
62   return FromID(GetInProcessRendererId(), routing_id);
63 }
64
65 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents)
66     : compositor_client_(NULL),
67       output_surface_(NULL),
68       contents_(contents),
69       input_handler_(NULL),
70       weak_ptr_factory_(this) {
71   DCHECK(contents);
72 }
73
74 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
75   if (compositor_client_)
76     compositor_client_->DidDestroyCompositor(this);
77   SetInputHandler(NULL);
78 }
79
80 void SynchronousCompositorImpl::SetClient(
81     SynchronousCompositorClient* compositor_client) {
82   DCHECK(CalledOnValidThread());
83   compositor_client_ = compositor_client;
84 }
85
86 // static
87 void SynchronousCompositor::SetGpuService(
88     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
89   g_factory.Get().SetDeferredGpuService(service);
90 }
91
92 // static
93 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) {
94   g_factory.Get().SetRecordFullDocument(record_full_document);
95 }
96
97 bool SynchronousCompositorImpl::InitializeHwDraw() {
98   DCHECK(CalledOnValidThread());
99   DCHECK(output_surface_);
100
101   scoped_refptr<cc::ContextProvider> onscreen_context =
102       g_factory.Get().CreateOnscreenContextProviderForCompositorThread();
103
104   bool success = output_surface_->InitializeHwDraw(onscreen_context);
105
106   if (success)
107     g_factory.Get().CompositorInitializedHardwareDraw();
108   return success;
109 }
110
111 void SynchronousCompositorImpl::ReleaseHwDraw() {
112   DCHECK(CalledOnValidThread());
113   DCHECK(output_surface_);
114   output_surface_->ReleaseHwDraw();
115   g_factory.Get().CompositorReleasedHardwareDraw();
116 }
117
118 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
119     gfx::Size surface_size,
120     const gfx::Transform& transform,
121     gfx::Rect viewport,
122     gfx::Rect clip,
123     gfx::Rect viewport_rect_for_tile_priority,
124     const gfx::Transform& transform_for_tile_priority) {
125   DCHECK(CalledOnValidThread());
126   DCHECK(output_surface_);
127
128   scoped_ptr<cc::CompositorFrame> frame =
129       output_surface_->DemandDrawHw(surface_size,
130                                     transform,
131                                     viewport,
132                                     clip,
133                                     viewport_rect_for_tile_priority,
134                                     transform_for_tile_priority);
135   if (frame.get())
136     UpdateFrameMetaData(frame->metadata);
137
138   return frame.Pass();
139 }
140
141 void SynchronousCompositorImpl::ReturnResources(
142     const cc::CompositorFrameAck& frame_ack) {
143   DCHECK(CalledOnValidThread());
144   output_surface_->ReturnResources(frame_ack);
145 }
146
147 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
148   DCHECK(CalledOnValidThread());
149   DCHECK(output_surface_);
150
151   scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas);
152   if (frame.get())
153     UpdateFrameMetaData(frame->metadata);
154   return !!frame.get();
155 }
156
157 void SynchronousCompositorImpl::UpdateFrameMetaData(
158     const cc::CompositorFrameMetadata& frame_metadata) {
159   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
160       contents_->GetRenderWidgetHostView());
161   if (rwhv)
162     rwhv->SynchronousFrameMetadata(frame_metadata);
163   DeliverMessages();
164 }
165
166 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
167   DCHECK(CalledOnValidThread());
168   DCHECK(output_surface_);
169
170   output_surface_->SetMemoryPolicy(bytes_limit);
171 }
172
173 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
174   if (input_handler_)
175     input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
176 }
177
178 void SynchronousCompositorImpl::DidBindOutputSurface(
179       SynchronousCompositorOutputSurface* output_surface) {
180   DCHECK(CalledOnValidThread());
181   output_surface_ = output_surface;
182   if (compositor_client_)
183     compositor_client_->DidInitializeCompositor(this);
184 }
185
186 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
187        SynchronousCompositorOutputSurface* output_surface) {
188   DCHECK(CalledOnValidThread());
189
190   // Allow for transient hand-over when two output surfaces may refer to
191   // a single delegate.
192   if (output_surface_ == output_surface) {
193     output_surface_ = NULL;
194     if (compositor_client_)
195       compositor_client_->DidDestroyCompositor(this);
196     compositor_client_ = NULL;
197   }
198 }
199
200 void SynchronousCompositorImpl::SetInputHandler(
201     cc::InputHandler* input_handler) {
202   DCHECK(CalledOnValidThread());
203
204   if (input_handler_)
205     input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
206
207   input_handler_ = input_handler;
208
209   if (input_handler_)
210     input_handler_->SetRootLayerScrollOffsetDelegate(this);
211 }
212
213 void SynchronousCompositorImpl::DidOverscroll(
214     const DidOverscrollParams& params) {
215   if (compositor_client_) {
216     compositor_client_->DidOverscroll(params.accumulated_overscroll,
217                                       params.latest_overscroll_delta,
218                                       params.current_fling_velocity);
219   }
220 }
221
222 void SynchronousCompositorImpl::DidStopFlinging() {
223   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
224       contents_->GetRenderWidgetHostView());
225   if (rwhv)
226     rwhv->DidStopFlinging();
227 }
228
229 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
230   DCHECK(CalledOnValidThread());
231   if (compositor_client_)
232     compositor_client_->SetContinuousInvalidate(enable);
233 }
234
235 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
236     const blink::WebInputEvent& input_event) {
237   DCHECK(CalledOnValidThread());
238   return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
239       contents_->GetRoutingID(), input_event);
240 }
241
242 void SynchronousCompositorImpl::DeliverMessages() {
243   ScopedVector<IPC::Message> messages;
244   output_surface_->GetMessagesToDeliver(&messages);
245   RenderProcessHost* rph = contents_->GetRenderProcessHost();
246   for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
247        i != messages.end();
248        ++i) {
249     rph->OnMessageReceived(**i);
250   }
251 }
252
253 void SynchronousCompositorImpl::DidActivatePendingTree() {
254   if (compositor_client_)
255     compositor_client_->DidUpdateContent();
256 }
257
258 gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() {
259   DCHECK(CalledOnValidThread());
260   if (compositor_client_) {
261     // TODO(miletus): Make GetTotalRootLayerScrollOffset return
262     // ScrollOffset. crbug.com/414283.
263     return gfx::ScrollOffset(
264         compositor_client_->GetTotalRootLayerScrollOffset());
265   }
266   return gfx::ScrollOffset();
267 }
268
269 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
270   DCHECK(CalledOnValidThread());
271   if (compositor_client_)
272     return compositor_client_->IsExternalFlingActive();
273   return false;
274 }
275
276 void SynchronousCompositorImpl::UpdateRootLayerState(
277     const gfx::ScrollOffset& total_scroll_offset,
278     const gfx::ScrollOffset& max_scroll_offset,
279     const gfx::SizeF& scrollable_size,
280     float page_scale_factor,
281     float min_page_scale_factor,
282     float max_page_scale_factor) {
283   DCHECK(CalledOnValidThread());
284   if (!compositor_client_)
285     return;
286
287   // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
288   compositor_client_->UpdateRootLayerState(
289       gfx::ScrollOffsetToVector2dF(total_scroll_offset),
290       gfx::ScrollOffsetToVector2dF(max_scroll_offset),
291       scrollable_size,
292       page_scale_factor,
293       min_page_scale_factor,
294       max_page_scale_factor);
295 }
296
297 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
298 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
299 bool SynchronousCompositorImpl::CalledOnValidThread() const {
300   return BrowserThread::CurrentlyOn(BrowserThread::UI);
301 }
302
303 // static
304 void SynchronousCompositor::SetClientForWebContents(
305     WebContents* contents,
306     SynchronousCompositorClient* client) {
307   DCHECK(contents);
308   if (client) {
309     g_factory.Get();  // Ensure it's initialized.
310     SynchronousCompositorImpl::CreateForWebContents(contents);
311   }
312   if (SynchronousCompositorImpl* instance =
313       SynchronousCompositorImpl::FromWebContents(contents)) {
314     instance->SetClient(client);
315   }
316 }
317
318 }  // namespace content