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