Upstream version 7.36.149.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   DCHECK(contents);
71 }
72
73 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
74   if (compositor_client_)
75     compositor_client_->DidDestroyCompositor(this);
76   SetInputHandler(NULL);
77 }
78
79 void SynchronousCompositorImpl::SetClient(
80     SynchronousCompositorClient* compositor_client) {
81   DCHECK(CalledOnValidThread());
82   compositor_client_ = compositor_client;
83 }
84
85 // static
86 void SynchronousCompositor::SetGpuService(
87     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
88   g_factory.Get().SetDeferredGpuService(service);
89 }
90
91 bool SynchronousCompositorImpl::InitializeHwDraw(
92     scoped_refptr<gfx::GLSurface> surface) {
93   DCHECK(CalledOnValidThread());
94   DCHECK(output_surface_);
95
96   // Create contexts in this order so that the share group gets passed
97   // along correctly.
98   scoped_refptr<cc::ContextProvider> offscreen_context =
99       g_factory.Get().GetOffscreenContextProviderForCompositorThread();
100   scoped_refptr<cc::ContextProvider> onscreen_context =
101   g_factory.Get().CreateOnscreenContextProviderForCompositorThread(surface);
102
103   bool success = output_surface_->InitializeHwDraw(onscreen_context);
104
105   if (success)
106     g_factory.Get().CompositorInitializedHardwareDraw();
107   return success;
108 }
109
110 void SynchronousCompositorImpl::ReleaseHwDraw() {
111   DCHECK(CalledOnValidThread());
112   DCHECK(output_surface_);
113   output_surface_->ReleaseHwDraw();
114   g_factory.Get().CompositorReleasedHardwareDraw();
115 }
116
117 bool SynchronousCompositorImpl::DemandDrawHw(
118       gfx::Size surface_size,
119       const gfx::Transform& transform,
120       gfx::Rect viewport,
121       gfx::Rect clip,
122       bool stencil_enabled) {
123   DCHECK(CalledOnValidThread());
124   DCHECK(output_surface_);
125
126   return output_surface_->DemandDrawHw(
127       surface_size, transform, viewport, clip, stencil_enabled);
128 }
129
130 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
131   DCHECK(CalledOnValidThread());
132   DCHECK(output_surface_);
133
134   return output_surface_->DemandDrawSw(canvas);
135 }
136
137 void SynchronousCompositorImpl::SetMemoryPolicy(
138     const SynchronousCompositorMemoryPolicy& policy) {
139   DCHECK(CalledOnValidThread());
140   DCHECK(output_surface_);
141
142   output_surface_->SetMemoryPolicy(policy);
143 }
144
145 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
146   if (input_handler_)
147     input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
148 }
149
150 void SynchronousCompositorImpl::DidBindOutputSurface(
151       SynchronousCompositorOutputSurface* output_surface) {
152   DCHECK(CalledOnValidThread());
153   output_surface_ = output_surface;
154   if (compositor_client_)
155     compositor_client_->DidInitializeCompositor(this);
156 }
157
158 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
159        SynchronousCompositorOutputSurface* output_surface) {
160   DCHECK(CalledOnValidThread());
161
162   // Allow for transient hand-over when two output surfaces may refer to
163   // a single delegate.
164   if (output_surface_ == output_surface) {
165     output_surface_ = NULL;
166     if (compositor_client_)
167       compositor_client_->DidDestroyCompositor(this);
168     compositor_client_ = NULL;
169   }
170 }
171
172 void SynchronousCompositorImpl::SetInputHandler(
173     cc::InputHandler* input_handler) {
174   DCHECK(CalledOnValidThread());
175
176   if (input_handler_)
177     input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
178
179   input_handler_ = input_handler;
180
181   if (input_handler_)
182     input_handler_->SetRootLayerScrollOffsetDelegate(this);
183 }
184
185 void SynchronousCompositorImpl::DidOverscroll(
186     const DidOverscrollParams& params) {
187   if (compositor_client_) {
188     compositor_client_->DidOverscroll(params.accumulated_overscroll,
189                                       params.latest_overscroll_delta,
190                                       params.current_fling_velocity);
191   }
192 }
193
194 void SynchronousCompositorImpl::DidStopFlinging() {
195   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
196       contents_->GetRenderWidgetHostView());
197   if (rwhv)
198     rwhv->DidStopFlinging();
199 }
200
201 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
202   DCHECK(CalledOnValidThread());
203   if (compositor_client_)
204     compositor_client_->SetContinuousInvalidate(enable);
205 }
206
207 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
208     const blink::WebInputEvent& input_event) {
209   DCHECK(CalledOnValidThread());
210   return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
211       contents_->GetRoutingID(), input_event);
212 }
213
214 void SynchronousCompositorImpl::UpdateFrameMetaData(
215     const cc::CompositorFrameMetadata& frame_metadata) {
216   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
217       contents_->GetRenderWidgetHostView());
218   if (rwhv)
219     rwhv->SynchronousFrameMetadata(frame_metadata);
220 }
221
222 void SynchronousCompositorImpl::DidActivatePendingTree() {
223   if (compositor_client_)
224     compositor_client_->DidUpdateContent();
225 }
226
227 void SynchronousCompositorImpl::SetMaxScrollOffset(
228     const gfx::Vector2dF& max_scroll_offset) {
229   DCHECK(CalledOnValidThread());
230   if (compositor_client_)
231     compositor_client_->SetMaxRootLayerScrollOffset(max_scroll_offset);
232 }
233
234 void SynchronousCompositorImpl::SetTotalScrollOffset(
235     const gfx::Vector2dF& new_value) {
236   DCHECK(CalledOnValidThread());
237   if (compositor_client_)
238     compositor_client_->SetTotalRootLayerScrollOffset(new_value);
239 }
240
241 gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
242   DCHECK(CalledOnValidThread());
243   if (compositor_client_)
244     return compositor_client_->GetTotalRootLayerScrollOffset();
245   return gfx::Vector2dF();
246 }
247
248 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
249   DCHECK(CalledOnValidThread());
250   if (compositor_client_)
251     return compositor_client_->IsExternalFlingActive();
252   return false;
253 }
254
255 void SynchronousCompositorImpl::SetTotalPageScaleFactorAndLimits(
256     float page_scale_factor,
257     float min_page_scale_factor,
258     float max_page_scale_factor) {
259   DCHECK(CalledOnValidThread());
260   if (compositor_client_)
261     compositor_client_->SetRootLayerPageScaleFactorAndLimits(
262         page_scale_factor, min_page_scale_factor, max_page_scale_factor);
263 }
264
265 void SynchronousCompositorImpl::SetScrollableSize(
266     const gfx::SizeF& scrollable_size) {
267   DCHECK(CalledOnValidThread());
268   if (compositor_client_)
269     compositor_client_->SetRootLayerScrollableSize(scrollable_size);
270 }
271
272 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
273 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
274 bool SynchronousCompositorImpl::CalledOnValidThread() const {
275   return BrowserThread::CurrentlyOn(BrowserThread::UI);
276 }
277
278 // static
279 void SynchronousCompositor::SetClientForWebContents(
280     WebContents* contents,
281     SynchronousCompositorClient* client) {
282   DCHECK(contents);
283   if (client) {
284     g_factory.Get();  // Ensure it's initialized.
285     SynchronousCompositorImpl::CreateForWebContents(contents);
286   }
287   if (SynchronousCompositorImpl* instance =
288       SynchronousCompositorImpl::FromWebContents(contents)) {
289     instance->SetClient(client);
290   }
291 }
292
293 }  // namespace content