blob: c6e482dba495b37ac7a79094963b44d55685107c [file] [log] [blame]
boliubee541f42015-11-05 00:52:531// Copyright 2015 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.
4
5#include "content/browser/android/synchronous_compositor_host.h"
6
7#include "base/containers/hash_tables.h"
boliuf6d263e2015-11-25 03:53:588#include "base/memory/shared_memory.h"
9#include "base/trace_event/trace_event_argument.h"
boliubee541f42015-11-05 00:52:5310#include "cc/output/compositor_frame_ack.h"
11#include "content/browser/renderer_host/render_widget_host_view_android.h"
12#include "content/browser/web_contents/web_contents_impl.h"
13#include "content/common/android/sync_compositor_messages.h"
14#include "content/public/browser/android/synchronous_compositor_client.h"
hush92bd35e72015-11-13 22:57:3715#include "content/public/browser/browser_thread.h"
boliubee541f42015-11-05 00:52:5316#include "content/public/browser/render_view_host.h"
17#include "ipc/ipc_sender.h"
boliuf6d263e2015-11-25 03:53:5818#include "third_party/skia/include/core/SkBitmap.h"
19#include "third_party/skia/include/core/SkCanvas.h"
20#include "third_party/skia/include/core/SkImageInfo.h"
21#include "third_party/skia/include/core/SkRect.h"
22#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5323
24namespace content {
25
26SynchronousCompositorHost::SynchronousCompositorHost(
27 RenderWidgetHostViewAndroid* rwhva,
28 SynchronousCompositorClient* client)
29 : rwhva_(rwhva),
30 client_(client),
hush92bd35e72015-11-13 22:57:3731 ui_task_runner_(
32 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
boliubee541f42015-11-05 00:52:5333 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
34 sender_(rwhva_->GetRenderWidgetHost()),
35 is_active_(false),
36 bytes_limit_(0u),
boliu600cba922015-12-08 04:28:2237 root_scroll_offset_updated_by_browser_(false),
boliubee541f42015-11-05 00:52:5338 renderer_param_version_(0u),
39 need_animate_scroll_(false),
40 need_invalidate_(false),
41 need_begin_frame_(false),
hush92bd35e72015-11-13 22:57:3742 did_activate_pending_tree_(false),
43 weak_ptr_factory_(this) {
boliubee541f42015-11-05 00:52:5344 client_->DidInitializeCompositor(this);
45}
46
47SynchronousCompositorHost::~SynchronousCompositorHost() {
48 client_->DidDestroyCompositor(this);
49}
50
51bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
52 bool handled = true;
53 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
54 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
boliu09be0e62015-11-11 00:57:0055 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OverScroll, OnOverScroll)
boliubee541f42015-11-05 00:52:5356 IPC_MESSAGE_UNHANDLED(handled = false)
57 IPC_END_MESSAGE_MAP()
58 return handled;
59}
60
61scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
62 const gfx::Size& surface_size,
63 const gfx::Transform& transform,
64 const gfx::Rect& viewport,
65 const gfx::Rect& clip,
66 const gfx::Rect& viewport_rect_for_tile_priority,
67 const gfx::Transform& transform_for_tile_priority) {
68 SyncCompositorDemandDrawHwParams params(surface_size, transform, viewport,
69 clip, viewport_rect_for_tile_priority,
70 transform_for_tile_priority);
71 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
72 SyncCompositorCommonBrowserParams common_browser_params;
73 PopulateCommonParams(&common_browser_params);
74 SyncCompositorCommonRendererParams common_renderer_params;
75 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
76 routing_id_, common_browser_params, params, &common_renderer_params,
77 frame.get()))) {
78 return nullptr;
79 }
80 ProcessCommonParams(common_renderer_params);
81 if (!frame->delegated_frame_data) {
82 // This can happen if compositor did not swap in this draw.
83 frame.reset();
84 }
85 if (frame)
86 UpdateFrameMetaData(frame->metadata);
87 return frame;
88}
89
90void SynchronousCompositorHost::UpdateFrameMetaData(
91 const cc::CompositorFrameMetadata& frame_metadata) {
92 rwhva_->SynchronousFrameMetadata(frame_metadata);
93}
94
95bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliuf6d263e2015-11-25 03:53:5896 SyncCompositorDemandDrawSwParams params;
97 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
98 canvas->getBaseLayerSize().height());
99 SkIRect canvas_clip;
100 canvas->getClipDeviceBounds(&canvas_clip);
101 params.clip = gfx::SkIRectToRect(canvas_clip);
102 params.transform.matrix() = canvas->getTotalMatrix();
103 if (params.size.IsEmpty())
104 return true;
105
106 SkImageInfo info =
107 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
108 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
109 size_t stride = info.minRowBytes();
110 size_t buffer_size = info.getSafeSize(stride);
111 if (!buffer_size)
112 return false; // Overflow.
113
114 base::SharedMemory shm;
115 {
116 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
117 if (!shm.CreateAndMapAnonymous(buffer_size))
118 return false;
119 }
120 base::ProcessHandle renderer_process_handle =
121 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
122 if (!shm.ShareToProcess(renderer_process_handle, &params.shm_handle))
123 return false;
124
125 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
126 SyncCompositorCommonBrowserParams common_browser_params;
127 PopulateCommonParams(&common_browser_params);
128 SyncCompositorCommonRendererParams common_renderer_params;
129 bool success = false;
130 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
131 routing_id_, common_browser_params, params, &success,
132 &common_renderer_params, frame.get()))) {
133 return false;
134 }
135 if (!success)
136 return false;
137
138 ProcessCommonParams(common_renderer_params);
139 UpdateFrameMetaData(frame->metadata);
140
141 SkBitmap bitmap;
142 if (!bitmap.installPixels(info, shm.memory(), stride))
143 return false;
144
145 {
146 TRACE_EVENT0("browser", "DrawBitmap");
147 canvas->save();
148 canvas->resetMatrix();
149 canvas->drawBitmap(bitmap, 0, 0);
150 canvas->restore();
151 }
152
153 return true;
boliubee541f42015-11-05 00:52:53154}
155
156void SynchronousCompositorHost::ReturnResources(
157 const cc::CompositorFrameAck& frame_ack) {
158 returned_resources_.insert(returned_resources_.end(),
159 frame_ack.resources.begin(),
160 frame_ack.resources.end());
161}
162
163void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
164 if (bytes_limit_ == bytes_limit)
165 return;
166 bytes_limit_ = bytes_limit;
hush92bd35e72015-11-13 22:57:37167 SendAsyncCompositorStateIfNeeded();
boliubee541f42015-11-05 00:52:53168}
169
170void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
171 const gfx::ScrollOffset& root_offset) {
172 if (root_scroll_offset_ == root_offset)
173 return;
boliu600cba922015-12-08 04:28:22174 root_scroll_offset_updated_by_browser_ = true;
boliubee541f42015-11-05 00:52:53175 root_scroll_offset_ = root_offset;
hush92bd35e72015-11-13 22:57:37176 SendAsyncCompositorStateIfNeeded();
177}
178
179void SynchronousCompositorHost::SendAsyncCompositorStateIfNeeded() {
180 if (weak_ptr_factory_.HasWeakPtrs())
181 return;
182
183 ui_task_runner_->PostTask(
184 FROM_HERE, base::Bind(&SynchronousCompositorHost::UpdateStateTask,
185 weak_ptr_factory_.GetWeakPtr()));
186}
187
188void SynchronousCompositorHost::UpdateStateTask() {
189 SyncCompositorCommonBrowserParams common_browser_params;
190 PopulateCommonParams(&common_browser_params);
191 sender_->Send(
192 new SyncCompositorMsg_UpdateState(routing_id_, common_browser_params));
193 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
boliubee541f42015-11-05 00:52:53194}
195
196void SynchronousCompositorHost::SetIsActive(bool is_active) {
197 is_active_ = is_active;
198 UpdateNeedsBeginFrames();
199}
200
201void SynchronousCompositorHost::OnComputeScroll(
202 base::TimeTicks animation_time) {
203 if (!need_animate_scroll_)
204 return;
205 need_animate_scroll_ = false;
206
207 SyncCompositorCommonBrowserParams common_browser_params;
208 PopulateCommonParams(&common_browser_params);
209 SyncCompositorCommonRendererParams common_renderer_params;
210 if (!sender_->Send(new SyncCompositorMsg_ComputeScroll(
211 routing_id_, common_browser_params, animation_time,
212 &common_renderer_params))) {
213 return;
214 }
215 ProcessCommonParams(common_renderer_params);
216}
217
218InputEventAckState SynchronousCompositorHost::HandleInputEvent(
219 const blink::WebInputEvent& input_event) {
220 SyncCompositorCommonBrowserParams common_browser_params;
221 PopulateCommonParams(&common_browser_params);
222 SyncCompositorCommonRendererParams common_renderer_params;
223 InputEventAckState ack = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
224 if (!sender_->Send(new SyncCompositorMsg_HandleInputEvent(
225 routing_id_, common_browser_params, &input_event,
226 &common_renderer_params, &ack))) {
227 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
228 }
229 ProcessCommonParams(common_renderer_params);
230 return ack;
231}
232
233void SynchronousCompositorHost::BeginFrame(const cc::BeginFrameArgs& args) {
234 if (!is_active_ || !need_begin_frame_)
235 return;
236
237 SyncCompositorCommonBrowserParams common_browser_params;
238 PopulateCommonParams(&common_browser_params);
239 SyncCompositorCommonRendererParams common_renderer_params;
240 if (!sender_->Send(
241 new SyncCompositorMsg_BeginFrame(routing_id_, common_browser_params,
242 args, &common_renderer_params))) {
243 return;
244 }
245 ProcessCommonParams(common_renderer_params);
246}
247
boliu09be0e62015-11-11 00:57:00248void SynchronousCompositorHost::OnOverScroll(
249 const SyncCompositorCommonRendererParams& params,
250 const DidOverscrollParams& over_scroll_params) {
251 ProcessCommonParams(params);
252 client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
253 over_scroll_params.latest_overscroll_delta,
254 over_scroll_params.current_fling_velocity);
255}
256
boliubee541f42015-11-05 00:52:53257void SynchronousCompositorHost::PopulateCommonParams(
258 SyncCompositorCommonBrowserParams* params) {
259 DCHECK(params);
260 DCHECK(params->ack.resources.empty());
261 params->bytes_limit = bytes_limit_;
boliubee541f42015-11-05 00:52:53262 params->ack.resources.swap(returned_resources_);
boliu600cba922015-12-08 04:28:22263 if (root_scroll_offset_updated_by_browser_) {
264 params->root_scroll_offset = root_scroll_offset_;
265 params->update_root_scroll_offset = root_scroll_offset_updated_by_browser_;
266 root_scroll_offset_updated_by_browser_ = false;
267 }
268
hush92bd35e72015-11-13 22:57:37269 weak_ptr_factory_.InvalidateWeakPtrs();
boliubee541f42015-11-05 00:52:53270}
271
272void SynchronousCompositorHost::ProcessCommonParams(
273 const SyncCompositorCommonRendererParams& params) {
274 // Ignore if |renderer_param_version_| is newer than |params.version|. This
275 // comparison takes into account when the unsigned int wraps.
276 if ((renderer_param_version_ - params.version) < 0x80000000) {
277 return;
278 }
279 renderer_param_version_ = params.version;
280 need_animate_scroll_ = params.need_animate_scroll;
281 if (need_begin_frame_ != params.need_begin_frame) {
282 need_begin_frame_ = params.need_begin_frame;
283 UpdateNeedsBeginFrames();
284 }
285 need_invalidate_ = need_invalidate_ || params.need_invalidate;
286 did_activate_pending_tree_ =
287 did_activate_pending_tree_ || params.did_activate_pending_tree;
288 root_scroll_offset_ = params.total_scroll_offset;
289
290 if (need_invalidate_) {
291 need_invalidate_ = false;
292 client_->PostInvalidate();
293 }
294
295 if (did_activate_pending_tree_) {
296 did_activate_pending_tree_ = false;
297 client_->DidUpdateContent();
298 }
299
300 // Ensure only valid values from compositor are sent to client.
301 // Compositor has page_scale_factor set to 0 before initialization, so check
302 // for that case here.
303 if (params.page_scale_factor) {
304 client_->UpdateRootLayerState(
305 gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
306 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
307 params.scrollable_size, params.page_scale_factor,
308 params.min_page_scale_factor, params.max_page_scale_factor);
309 }
310}
311
312void SynchronousCompositorHost::UpdateNeedsBeginFrames() {
313 rwhva_->OnSetNeedsBeginFrames(is_active_ && need_begin_frame_);
314}
315
316} // namespace content