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 "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"
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
;
85 bool SynchronousCompositorImpl::InitializeHwDraw(
86 scoped_refptr
<gfx::GLSurface
> surface
) {
87 DCHECK(CalledOnValidThread());
88 DCHECK(output_surface_
);
89 bool success
= output_surface_
->InitializeHwDraw(
91 g_factory
.Get().GetOffscreenContextProviderForCompositorThread());
93 g_factory
.Get().CompositorInitializedHardwareDraw();
97 void SynchronousCompositorImpl::ReleaseHwDraw() {
98 DCHECK(CalledOnValidThread());
99 DCHECK(output_surface_
);
100 output_surface_
->ReleaseHwDraw();
101 g_factory
.Get().CompositorReleasedHardwareDraw();
104 bool SynchronousCompositorImpl::DemandDrawHw(
105 gfx::Size surface_size
,
106 const gfx::Transform
& transform
,
109 bool stencil_enabled
) {
110 DCHECK(CalledOnValidThread());
111 DCHECK(output_surface_
);
113 return output_surface_
->DemandDrawHw(
114 surface_size
, transform
, viewport
, clip
, stencil_enabled
);
117 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas
* canvas
) {
118 DCHECK(CalledOnValidThread());
119 DCHECK(output_surface_
);
121 return output_surface_
->DemandDrawSw(canvas
);
124 void SynchronousCompositorImpl::SetMemoryPolicy(
125 const SynchronousCompositorMemoryPolicy
& policy
) {
126 DCHECK(CalledOnValidThread());
127 DCHECK(output_surface_
);
129 return output_surface_
->SetMemoryPolicy(policy
);
132 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
134 input_handler_
->OnRootLayerDelegatedScrollOffsetChanged();
137 void SynchronousCompositorImpl::DidBindOutputSurface(
138 SynchronousCompositorOutputSurface
* output_surface
) {
139 DCHECK(CalledOnValidThread());
140 output_surface_
= output_surface
;
141 if (compositor_client_
)
142 compositor_client_
->DidInitializeCompositor(this);
145 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
146 SynchronousCompositorOutputSurface
* output_surface
) {
147 DCHECK(CalledOnValidThread());
149 // Allow for transient hand-over when two output surfaces may refer to
150 // a single delegate.
151 if (output_surface_
== output_surface
) {
152 output_surface_
= NULL
;
153 if (compositor_client_
)
154 compositor_client_
->DidDestroyCompositor(this);
155 compositor_client_
= NULL
;
159 void SynchronousCompositorImpl::SetInputHandler(
160 cc::InputHandler
* input_handler
) {
161 DCHECK(CalledOnValidThread());
164 input_handler_
->SetRootLayerScrollOffsetDelegate(NULL
);
166 input_handler_
= input_handler
;
169 input_handler_
->SetRootLayerScrollOffsetDelegate(this);
172 void SynchronousCompositorImpl::DidOverscroll(
173 const cc::DidOverscrollParams
& params
) {
174 if (compositor_client_
) {
175 compositor_client_
->DidOverscroll(params
.accumulated_overscroll
,
176 params
.latest_overscroll_delta
,
177 params
.current_fling_velocity
);
181 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable
) {
182 DCHECK(CalledOnValidThread());
183 if (compositor_client_
)
184 compositor_client_
->SetContinuousInvalidate(enable
);
187 InputEventAckState
SynchronousCompositorImpl::HandleInputEvent(
188 const blink::WebInputEvent
& input_event
) {
189 DCHECK(CalledOnValidThread());
190 return g_factory
.Get().synchronous_input_event_filter()->HandleInputEvent(
191 contents_
->GetRoutingID(), input_event
);
194 void SynchronousCompositorImpl::UpdateFrameMetaData(
195 const cc::CompositorFrameMetadata
& frame_metadata
) {
196 RenderWidgetHostViewAndroid
* rwhv
= static_cast<RenderWidgetHostViewAndroid
*>(
197 contents_
->GetRenderWidgetHostView());
199 rwhv
->SynchronousFrameMetadata(frame_metadata
);
202 void SynchronousCompositorImpl::DidActivatePendingTree() {
203 if (compositor_client_
)
204 compositor_client_
->DidUpdateContent();
207 void SynchronousCompositorImpl::SetMaxScrollOffset(
208 gfx::Vector2dF max_scroll_offset
) {
209 DCHECK(CalledOnValidThread());
210 if (compositor_client_
)
211 compositor_client_
->SetMaxRootLayerScrollOffset(max_scroll_offset
);
214 void SynchronousCompositorImpl::SetTotalScrollOffset(gfx::Vector2dF new_value
) {
215 DCHECK(CalledOnValidThread());
216 if (compositor_client_
)
217 compositor_client_
->SetTotalRootLayerScrollOffset(new_value
);
220 gfx::Vector2dF
SynchronousCompositorImpl::GetTotalScrollOffset() {
221 DCHECK(CalledOnValidThread());
222 if (compositor_client_
)
223 return compositor_client_
->GetTotalRootLayerScrollOffset();
224 return gfx::Vector2dF();
227 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
228 DCHECK(CalledOnValidThread());
229 if (compositor_client_
)
230 return compositor_client_
->IsExternalFlingActive();
234 void SynchronousCompositorImpl::SetTotalPageScaleFactor(
235 float page_scale_factor
) {
236 DCHECK(CalledOnValidThread());
237 if (compositor_client_
)
238 compositor_client_
->SetRootLayerPageScaleFactor(page_scale_factor
);
241 void SynchronousCompositorImpl::SetScrollableSize(gfx::SizeF scrollable_size
) {
242 DCHECK(CalledOnValidThread());
243 if (compositor_client_
)
244 compositor_client_
->SetRootLayerScrollableSize(scrollable_size
);
247 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
248 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
249 bool SynchronousCompositorImpl::CalledOnValidThread() const {
250 return BrowserThread::CurrentlyOn(BrowserThread::UI
);
254 void SynchronousCompositor::SetClientForWebContents(
255 WebContents
* contents
,
256 SynchronousCompositorClient
* client
) {
259 g_factory
.Get(); // Ensure it's initialized.
260 SynchronousCompositorImpl::CreateForWebContents(contents
);
262 if (SynchronousCompositorImpl
* instance
=
263 SynchronousCompositorImpl::FromWebContents(contents
)) {
264 instance
->SetClient(client
);
268 } // namespace content