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 DCHECK(CalledOnValidThread());
129 DCHECK(output_surface_);
131 scoped_ptr<cc::CompositorFrame> frame =
132 output_surface_->DemandDrawHw(surface_size, transform, viewport, clip);
134 UpdateFrameMetaData(frame->metadata);
138 void SynchronousCompositorImpl::ReturnResources(
139 const cc::CompositorFrameAck& frame_ack) {
140 DCHECK(CalledOnValidThread());
141 output_surface_->ReturnResources(frame_ack);
144 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
145 DCHECK(CalledOnValidThread());
146 DCHECK(output_surface_);
148 scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas);
150 UpdateFrameMetaData(frame->metadata);
151 return !!frame.get();
154 void SynchronousCompositorImpl::UpdateFrameMetaData(
155 const cc::CompositorFrameMetadata& frame_metadata) {
156 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
157 contents_->GetRenderWidgetHostView());
159 rwhv->SynchronousFrameMetadata(frame_metadata);
162 void SynchronousCompositorImpl::SetMemoryPolicy(
163 const SynchronousCompositorMemoryPolicy& policy) {
164 DCHECK(CalledOnValidThread());
165 DCHECK(output_surface_);
167 output_surface_->SetMemoryPolicy(policy);
170 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
172 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
175 void SynchronousCompositorImpl::DidBindOutputSurface(
176 SynchronousCompositorOutputSurface* output_surface) {
177 DCHECK(CalledOnValidThread());
178 output_surface_ = output_surface;
179 if (compositor_client_)
180 compositor_client_->DidInitializeCompositor(this);
183 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
184 SynchronousCompositorOutputSurface* output_surface) {
185 DCHECK(CalledOnValidThread());
187 // Allow for transient hand-over when two output surfaces may refer to
188 // a single delegate.
189 if (output_surface_ == output_surface) {
190 output_surface_ = NULL;
191 if (compositor_client_)
192 compositor_client_->DidDestroyCompositor(this);
193 compositor_client_ = NULL;
197 void SynchronousCompositorImpl::SetInputHandler(
198 cc::InputHandler* input_handler) {
199 DCHECK(CalledOnValidThread());
202 input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
204 input_handler_ = input_handler;
207 input_handler_->SetRootLayerScrollOffsetDelegate(this);
210 void SynchronousCompositorImpl::DidOverscroll(
211 const DidOverscrollParams& params) {
212 if (compositor_client_) {
213 compositor_client_->DidOverscroll(params.accumulated_overscroll,
214 params.latest_overscroll_delta,
215 params.current_fling_velocity);
219 void SynchronousCompositorImpl::DidStopFlinging() {
220 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
221 contents_->GetRenderWidgetHostView());
223 rwhv->DidStopFlinging();
226 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
227 DCHECK(CalledOnValidThread());
228 if (compositor_client_)
229 compositor_client_->SetContinuousInvalidate(enable);
232 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
233 const blink::WebInputEvent& input_event) {
234 DCHECK(CalledOnValidThread());
235 return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
236 contents_->GetRoutingID(), input_event);
239 void SynchronousCompositorImpl::DidActivatePendingTree() {
240 if (compositor_client_)
241 compositor_client_->DidUpdateContent();
244 gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
245 DCHECK(CalledOnValidThread());
246 if (compositor_client_)
247 return compositor_client_->GetTotalRootLayerScrollOffset();
248 return gfx::Vector2dF();
251 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
252 DCHECK(CalledOnValidThread());
253 if (compositor_client_)
254 return compositor_client_->IsExternalFlingActive();
258 void SynchronousCompositorImpl::UpdateRootLayerState(
259 const gfx::Vector2dF& total_scroll_offset,
260 const gfx::Vector2dF& max_scroll_offset,
261 const gfx::SizeF& scrollable_size,
262 float page_scale_factor,
263 float min_page_scale_factor,
264 float max_page_scale_factor) {
265 DCHECK(CalledOnValidThread());
266 if (!compositor_client_)
269 compositor_client_->UpdateRootLayerState(total_scroll_offset,
273 min_page_scale_factor,
274 max_page_scale_factor);
277 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
278 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
279 bool SynchronousCompositorImpl::CalledOnValidThread() const {
280 return BrowserThread::CurrentlyOn(BrowserThread::UI);
284 void SynchronousCompositor::SetClientForWebContents(
285 WebContents* contents,
286 SynchronousCompositorClient* client) {
289 g_factory.Get(); // Ensure it's initialized.
290 SynchronousCompositorImpl::CreateForWebContents(contents);
292 if (SynchronousCompositorImpl* instance =
293 SynchronousCompositorImpl::FromWebContents(contents)) {
294 instance->SetClient(client);
298 } // namespace content