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),
69 input_handler_(NULL) {
73 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
74 if (compositor_client_)
75 compositor_client_->DidDestroyCompositor(this);
76 SetInputHandler(NULL);
79 void SynchronousCompositorImpl::SetClient(
80 SynchronousCompositorClient* compositor_client) {
81 DCHECK(CalledOnValidThread());
82 compositor_client_ = compositor_client;
86 void SynchronousCompositor::SetGpuService(
87 scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
88 g_factory.Get().SetDeferredGpuService(service);
91 bool SynchronousCompositorImpl::InitializeHwDraw(
92 scoped_refptr<gfx::GLSurface> surface) {
93 DCHECK(CalledOnValidThread());
94 DCHECK(output_surface_);
96 // Create contexts in this order so that the share group gets passed
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);
103 bool success = output_surface_->InitializeHwDraw(onscreen_context);
106 g_factory.Get().CompositorInitializedHardwareDraw();
110 void SynchronousCompositorImpl::ReleaseHwDraw() {
111 DCHECK(CalledOnValidThread());
112 DCHECK(output_surface_);
113 output_surface_->ReleaseHwDraw();
114 g_factory.Get().CompositorReleasedHardwareDraw();
117 bool SynchronousCompositorImpl::DemandDrawHw(
118 gfx::Size surface_size,
119 const gfx::Transform& transform,
122 bool stencil_enabled) {
123 DCHECK(CalledOnValidThread());
124 DCHECK(output_surface_);
126 return output_surface_->DemandDrawHw(
127 surface_size, transform, viewport, clip, stencil_enabled);
130 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
131 DCHECK(CalledOnValidThread());
132 DCHECK(output_surface_);
134 return output_surface_->DemandDrawSw(canvas);
137 void SynchronousCompositorImpl::SetMemoryPolicy(
138 const SynchronousCompositorMemoryPolicy& policy) {
139 DCHECK(CalledOnValidThread());
140 DCHECK(output_surface_);
142 output_surface_->SetMemoryPolicy(policy);
145 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
147 input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
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);
158 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
159 SynchronousCompositorOutputSurface* output_surface) {
160 DCHECK(CalledOnValidThread());
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;
172 void SynchronousCompositorImpl::SetInputHandler(
173 cc::InputHandler* input_handler) {
174 DCHECK(CalledOnValidThread());
177 input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
179 input_handler_ = input_handler;
182 input_handler_->SetRootLayerScrollOffsetDelegate(this);
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);
194 void SynchronousCompositorImpl::DidStopFlinging() {
195 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
196 contents_->GetRenderWidgetHostView());
198 rwhv->DidStopFlinging();
201 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
202 DCHECK(CalledOnValidThread());
203 if (compositor_client_)
204 compositor_client_->SetContinuousInvalidate(enable);
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);
214 void SynchronousCompositorImpl::UpdateFrameMetaData(
215 const cc::CompositorFrameMetadata& frame_metadata) {
216 RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
217 contents_->GetRenderWidgetHostView());
219 rwhv->SynchronousFrameMetadata(frame_metadata);
222 void SynchronousCompositorImpl::DidActivatePendingTree() {
223 if (compositor_client_)
224 compositor_client_->DidUpdateContent();
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);
234 void SynchronousCompositorImpl::SetTotalScrollOffset(
235 const gfx::Vector2dF& new_value) {
236 DCHECK(CalledOnValidThread());
237 if (compositor_client_)
238 compositor_client_->SetTotalRootLayerScrollOffset(new_value);
241 gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
242 DCHECK(CalledOnValidThread());
243 if (compositor_client_)
244 return compositor_client_->GetTotalRootLayerScrollOffset();
245 return gfx::Vector2dF();
248 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
249 DCHECK(CalledOnValidThread());
250 if (compositor_client_)
251 return compositor_client_->IsExternalFlingActive();
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);
265 void SynchronousCompositorImpl::SetScrollableSize(
266 const gfx::SizeF& scrollable_size) {
267 DCHECK(CalledOnValidThread());
268 if (compositor_client_)
269 compositor_client_->SetRootLayerScrollableSize(scrollable_size);
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);
279 void SynchronousCompositor::SetClientForWebContents(
280 WebContents* contents,
281 SynchronousCompositorClient* client) {
284 g_factory.Get(); // Ensure it's initialized.
285 SynchronousCompositorImpl::CreateForWebContents(contents);
287 if (SynchronousCompositorImpl* instance =
288 SynchronousCompositorImpl::FromWebContents(contents)) {
289 instance->SetClient(client);
293 } // namespace content