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/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"
24 int GetInProcessRendererId() {
25 content::RenderProcessHost::iterator it
=
26 content::RenderProcessHost::AllHostsIterator();
28 // There should always be one RPH in single process mode.
33 int id
= it
.GetCurrentValue()->GetID();
35 DCHECK(it
.IsAtEnd()); // Not multiprocess compatible.
39 base::LazyInstance
<SynchronousCompositorFactoryImpl
>::Leaky g_factory
=
40 LAZY_INSTANCE_INITIALIZER
;
44 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl
);
47 SynchronousCompositorImpl
* SynchronousCompositorImpl::FromID(int process_id
,
49 if (g_factory
== NULL
)
51 RenderViewHost
* rvh
= RenderViewHost::FromID(process_id
, routing_id
);
54 WebContents
* contents
= WebContents::FromRenderViewHost(rvh
);
57 return FromWebContents(contents
);
60 SynchronousCompositorImpl
* SynchronousCompositorImpl::FromRoutingID(
62 return FromID(GetInProcessRendererId(), routing_id
);
65 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents
* contents
)
66 : compositor_client_(NULL
),
67 output_surface_(NULL
),
70 weak_ptr_factory_(this) {
74 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
75 if (compositor_client_
)
76 compositor_client_
->DidDestroyCompositor(this);
77 SetInputHandler(NULL
);
80 void SynchronousCompositorImpl::SetClient(
81 SynchronousCompositorClient
* compositor_client
) {
82 DCHECK(CalledOnValidThread());
83 compositor_client_
= compositor_client
;
87 void SynchronousCompositor::SetGpuService(
88 scoped_refptr
<gpu::InProcessCommandBuffer::Service
> service
) {
89 g_factory
.Get().SetDeferredGpuService(service
);
93 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document
) {
94 g_factory
.Get().SetRecordFullDocument(record_full_document
);
97 bool SynchronousCompositorImpl::InitializeHwDraw() {
98 DCHECK(CalledOnValidThread());
99 DCHECK(output_surface_
);
101 scoped_refptr
<cc::ContextProvider
> onscreen_context
=
102 g_factory
.Get().CreateOnscreenContextProviderForCompositorThread();
104 bool success
= output_surface_
->InitializeHwDraw(onscreen_context
);
107 g_factory
.Get().CompositorInitializedHardwareDraw();
111 void SynchronousCompositorImpl::ReleaseHwDraw() {
112 DCHECK(CalledOnValidThread());
113 DCHECK(output_surface_
);
114 output_surface_
->ReleaseHwDraw();
115 g_factory
.Get().CompositorReleasedHardwareDraw();
118 gpu::GLInProcessContext
* SynchronousCompositorImpl::GetShareContext() {
119 DCHECK(CalledOnValidThread());
120 return g_factory
.Get().GetShareContext();
123 scoped_ptr
<cc::CompositorFrame
> SynchronousCompositorImpl::DemandDrawHw(
124 gfx::Size surface_size
,
125 const gfx::Transform
& transform
,
128 gfx::Rect viewport_rect_for_tile_priority
,
129 const gfx::Transform
& transform_for_tile_priority
) {
130 DCHECK(CalledOnValidThread());
131 DCHECK(output_surface_
);
133 scoped_ptr
<cc::CompositorFrame
> frame
=
134 output_surface_
->DemandDrawHw(surface_size
,
138 viewport_rect_for_tile_priority
,
139 transform_for_tile_priority
);
141 UpdateFrameMetaData(frame
->metadata
);
146 void SynchronousCompositorImpl::ReturnResources(
147 const cc::CompositorFrameAck
& frame_ack
) {
148 DCHECK(CalledOnValidThread());
149 output_surface_
->ReturnResources(frame_ack
);
152 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas
* canvas
) {
153 DCHECK(CalledOnValidThread());
154 DCHECK(output_surface_
);
156 scoped_ptr
<cc::CompositorFrame
> frame
= output_surface_
->DemandDrawSw(canvas
);
158 UpdateFrameMetaData(frame
->metadata
);
159 return !!frame
.get();
162 void SynchronousCompositorImpl::UpdateFrameMetaData(
163 const cc::CompositorFrameMetadata
& frame_metadata
) {
164 RenderWidgetHostViewAndroid
* rwhv
= static_cast<RenderWidgetHostViewAndroid
*>(
165 contents_
->GetRenderWidgetHostView());
167 rwhv
->SynchronousFrameMetadata(frame_metadata
);
171 void SynchronousCompositorImpl::SetMemoryPolicy(
172 const SynchronousCompositorMemoryPolicy
& policy
) {
173 DCHECK(CalledOnValidThread());
174 DCHECK(output_surface_
);
176 output_surface_
->SetMemoryPolicy(policy
);
179 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
181 input_handler_
->OnRootLayerDelegatedScrollOffsetChanged();
184 void SynchronousCompositorImpl::DidBindOutputSurface(
185 SynchronousCompositorOutputSurface
* output_surface
) {
186 DCHECK(CalledOnValidThread());
187 output_surface_
= output_surface
;
188 if (compositor_client_
)
189 compositor_client_
->DidInitializeCompositor(this);
192 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
193 SynchronousCompositorOutputSurface
* output_surface
) {
194 DCHECK(CalledOnValidThread());
196 // Allow for transient hand-over when two output surfaces may refer to
197 // a single delegate.
198 if (output_surface_
== output_surface
) {
199 output_surface_
= NULL
;
200 if (compositor_client_
)
201 compositor_client_
->DidDestroyCompositor(this);
202 compositor_client_
= NULL
;
206 void SynchronousCompositorImpl::SetInputHandler(
207 cc::InputHandler
* input_handler
) {
208 DCHECK(CalledOnValidThread());
211 input_handler_
->SetRootLayerScrollOffsetDelegate(NULL
);
213 input_handler_
= input_handler
;
216 input_handler_
->SetRootLayerScrollOffsetDelegate(this);
219 void SynchronousCompositorImpl::DidOverscroll(
220 const DidOverscrollParams
& params
) {
221 if (compositor_client_
) {
222 compositor_client_
->DidOverscroll(params
.accumulated_overscroll
,
223 params
.latest_overscroll_delta
,
224 params
.current_fling_velocity
);
228 void SynchronousCompositorImpl::DidStopFlinging() {
229 RenderWidgetHostViewAndroid
* rwhv
= static_cast<RenderWidgetHostViewAndroid
*>(
230 contents_
->GetRenderWidgetHostView());
232 rwhv
->DidStopFlinging();
235 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable
) {
236 DCHECK(CalledOnValidThread());
237 if (compositor_client_
)
238 compositor_client_
->SetContinuousInvalidate(enable
);
241 InputEventAckState
SynchronousCompositorImpl::HandleInputEvent(
242 const blink::WebInputEvent
& input_event
) {
243 DCHECK(CalledOnValidThread());
244 return g_factory
.Get().synchronous_input_event_filter()->HandleInputEvent(
245 contents_
->GetRoutingID(), input_event
);
248 void SynchronousCompositorImpl::DeliverMessages() {
249 ScopedVector
<IPC::Message
> messages
;
250 output_surface_
->GetMessagesToDeliver(&messages
);
251 RenderProcessHost
* rph
= contents_
->GetRenderProcessHost();
252 for (ScopedVector
<IPC::Message
>::const_iterator i
= messages
.begin();
255 rph
->OnMessageReceived(**i
);
259 void SynchronousCompositorImpl::DidActivatePendingTree() {
260 if (compositor_client_
)
261 compositor_client_
->DidUpdateContent();
264 gfx::Vector2dF
SynchronousCompositorImpl::GetTotalScrollOffset() {
265 DCHECK(CalledOnValidThread());
266 if (compositor_client_
)
267 return compositor_client_
->GetTotalRootLayerScrollOffset();
268 return gfx::Vector2dF();
271 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
272 DCHECK(CalledOnValidThread());
273 if (compositor_client_
)
274 return compositor_client_
->IsExternalFlingActive();
278 void SynchronousCompositorImpl::UpdateRootLayerState(
279 const gfx::Vector2dF
& total_scroll_offset
,
280 const gfx::Vector2dF
& max_scroll_offset
,
281 const gfx::SizeF
& scrollable_size
,
282 float page_scale_factor
,
283 float min_page_scale_factor
,
284 float max_page_scale_factor
) {
285 DCHECK(CalledOnValidThread());
286 if (!compositor_client_
)
289 compositor_client_
->UpdateRootLayerState(total_scroll_offset
,
293 min_page_scale_factor
,
294 max_page_scale_factor
);
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
);
304 void SynchronousCompositor::SetClientForWebContents(
305 WebContents
* contents
,
306 SynchronousCompositorClient
* client
) {
309 g_factory
.Get(); // Ensure it's initialized.
310 SynchronousCompositorImpl::CreateForWebContents(contents
);
312 if (SynchronousCompositorImpl
* instance
=
313 SynchronousCompositorImpl::FromWebContents(contents
)) {
314 instance
->SetClient(client
);
318 } // namespace content