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 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
119 gfx::Size surface_size,
120 const gfx::Transform& transform,
123 gfx::Rect viewport_rect_for_tile_priority,
124 const gfx::Transform& transform_for_tile_priority) {
125 DCHECK(CalledOnValidThread());
126 DCHECK(output_surface_);
128 scoped_ptr<cc::CompositorFrame> frame =
129 output_surface_->DemandDrawHw(surface_size,
133 viewport_rect_for_tile_priority,
134 transform_for_tile_priority);
136 UpdateFrameMetaData(frame->metadata);
141 void SynchronousCompositorImpl::ReturnResources(
142 const cc::CompositorFrameAck& frame_ack) {
143 DCHECK(CalledOnValidThread());
144 output_surface_->ReturnResources(frame_ack);
147 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
148 DCHECK(CalledOnValidThread());
149 DCHECK(output_surface_);
151 scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas);
153 UpdateFrameMetaData(frame->metadata);
154 return !!frame.get();
157 void SynchronousCompositorImpl::UpdateFrameMetaData(
158 const cc::CompositorFrameMetadata& frame_metadata) {
159 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
160 contents_->GetRenderWidgetHostView());
162 rwhv->SynchronousFrameMetadata(frame_metadata);
166 void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
167 DCHECK(CalledOnValidThread());
168 DCHECK(output_surface_);
170 output_surface_->SetMemoryPolicy(bytes_limit);
173 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
175 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
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);
186 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
187 SynchronousCompositorOutputSurface* output_surface) {
188 DCHECK(CalledOnValidThread());
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;
200 void SynchronousCompositorImpl::SetInputHandler(
201 cc::InputHandler* input_handler) {
202 DCHECK(CalledOnValidThread());
205 input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
207 input_handler_ = input_handler;
210 input_handler_->SetRootLayerScrollOffsetDelegate(this);
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);
222 void SynchronousCompositorImpl::DidStopFlinging() {
223 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
224 contents_->GetRenderWidgetHostView());
226 rwhv->DidStopFlinging();
229 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
230 DCHECK(CalledOnValidThread());
231 if (compositor_client_)
232 compositor_client_->SetContinuousInvalidate(enable);
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);
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();
249 rph->OnMessageReceived(**i);
253 void SynchronousCompositorImpl::DidActivatePendingTree() {
254 if (compositor_client_)
255 compositor_client_->DidUpdateContent();
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());
266 return gfx::ScrollOffset();
269 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
270 DCHECK(CalledOnValidThread());
271 if (compositor_client_)
272 return compositor_client_->IsExternalFlingActive();
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_)
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),
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