blob: c4292ecd18348e36767b2ffacbfed62a9d171f4a [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
boliucafb1bf2015-12-29 01:40:197#include <utility>
8
boliubee541f42015-11-05 00:52:539#include "base/containers/hash_tables.h"
boliuf6d263e2015-11-25 03:53:5810#include "base/memory/shared_memory.h"
11#include "base/trace_event/trace_event_argument.h"
boliubee541f42015-11-05 00:52:5312#include "cc/output/compositor_frame_ack.h"
13#include "content/browser/renderer_host/render_widget_host_view_android.h"
14#include "content/browser/web_contents/web_contents_impl.h"
15#include "content/common/android/sync_compositor_messages.h"
16#include "content/public/browser/android/synchronous_compositor_client.h"
hush92bd35e72015-11-13 22:57:3717#include "content/public/browser/browser_thread.h"
boliubee541f42015-11-05 00:52:5318#include "content/public/browser/render_view_host.h"
19#include "ipc/ipc_sender.h"
boliuf6d263e2015-11-25 03:53:5820#include "third_party/skia/include/core/SkBitmap.h"
21#include "third_party/skia/include/core/SkCanvas.h"
22#include "third_party/skia/include/core/SkImageInfo.h"
23#include "third_party/skia/include/core/SkRect.h"
24#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5325
26namespace content {
27
28SynchronousCompositorHost::SynchronousCompositorHost(
29 RenderWidgetHostViewAndroid* rwhva,
30 SynchronousCompositorClient* client)
31 : rwhva_(rwhva),
32 client_(client),
hush92bd35e72015-11-13 22:57:3733 ui_task_runner_(
34 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
boliubee541f42015-11-05 00:52:5335 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
36 sender_(rwhva_->GetRenderWidgetHost()),
37 is_active_(false),
38 bytes_limit_(0u),
boliu600cba922015-12-08 04:28:2239 root_scroll_offset_updated_by_browser_(false),
boliubee541f42015-11-05 00:52:5340 renderer_param_version_(0u),
41 need_animate_scroll_(false),
42 need_invalidate_(false),
43 need_begin_frame_(false),
hush92bd35e72015-11-13 22:57:3744 did_activate_pending_tree_(false),
45 weak_ptr_factory_(this) {
boliubee541f42015-11-05 00:52:5346 client_->DidInitializeCompositor(this);
47}
48
49SynchronousCompositorHost::~SynchronousCompositorHost() {
50 client_->DidDestroyCompositor(this);
boliu0c1f91d2016-01-13 19:27:3751 if (weak_ptr_factory_.HasWeakPtrs())
52 UpdateStateTask();
boliubee541f42015-11-05 00:52:5353}
54
55bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
56 bool handled = true;
57 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
58 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
boliu09be0e62015-11-11 00:57:0059 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OverScroll, OnOverScroll)
boliubee541f42015-11-05 00:52:5360 IPC_MESSAGE_UNHANDLED(handled = false)
61 IPC_END_MESSAGE_MAP()
62 return handled;
63}
64
hush45918a82015-12-17 03:50:5965void SynchronousCompositorHost::DidBecomeCurrent() {
66 client_->DidBecomeCurrent(this);
67}
68
boliubee541f42015-11-05 00:52:5369scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
70 const gfx::Size& surface_size,
71 const gfx::Transform& transform,
72 const gfx::Rect& viewport,
73 const gfx::Rect& clip,
74 const gfx::Rect& viewport_rect_for_tile_priority,
75 const gfx::Transform& transform_for_tile_priority) {
76 SyncCompositorDemandDrawHwParams params(surface_size, transform, viewport,
77 clip, viewport_rect_for_tile_priority,
78 transform_for_tile_priority);
79 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
80 SyncCompositorCommonBrowserParams common_browser_params;
81 PopulateCommonParams(&common_browser_params);
82 SyncCompositorCommonRendererParams common_renderer_params;
83 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
84 routing_id_, common_browser_params, params, &common_renderer_params,
85 frame.get()))) {
86 return nullptr;
87 }
88 ProcessCommonParams(common_renderer_params);
89 if (!frame->delegated_frame_data) {
90 // This can happen if compositor did not swap in this draw.
91 frame.reset();
92 }
93 if (frame)
94 UpdateFrameMetaData(frame->metadata);
95 return frame;
96}
97
98void SynchronousCompositorHost::UpdateFrameMetaData(
99 const cc::CompositorFrameMetadata& frame_metadata) {
100 rwhva_->SynchronousFrameMetadata(frame_metadata);
101}
102
boliucafb1bf2015-12-29 01:40:19103class SynchronousCompositorHost::ScopedSendZeroMemory {
104 public:
105 ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
106 ~ScopedSendZeroMemory() { host_->SendZeroMemory(); }
107
108 private:
109 SynchronousCompositorHost* const host_;
110
111 DISALLOW_COPY_AND_ASSIGN(ScopedSendZeroMemory);
112};
113
114struct SynchronousCompositorHost::SharedMemoryWithSize {
115 base::SharedMemory shm;
116 const size_t stride;
117 const size_t buffer_size;
118
119 SharedMemoryWithSize(size_t stride, size_t buffer_size)
120 : stride(stride), buffer_size(buffer_size) {}
121
122 private:
123 DISALLOW_COPY_AND_ASSIGN(SharedMemoryWithSize);
124};
125
boliubee541f42015-11-05 00:52:53126bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliuf6d263e2015-11-25 03:53:58127 SyncCompositorDemandDrawSwParams params;
128 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
129 canvas->getBaseLayerSize().height());
130 SkIRect canvas_clip;
131 canvas->getClipDeviceBounds(&canvas_clip);
132 params.clip = gfx::SkIRectToRect(canvas_clip);
133 params.transform.matrix() = canvas->getTotalMatrix();
134 if (params.size.IsEmpty())
135 return true;
136
137 SkImageInfo info =
138 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
139 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
140 size_t stride = info.minRowBytes();
141 size_t buffer_size = info.getSafeSize(stride);
142 if (!buffer_size)
143 return false; // Overflow.
144
boliucafb1bf2015-12-29 01:40:19145 SetSoftwareDrawSharedMemoryIfNeeded(stride, buffer_size);
146 if (!software_draw_shm_)
boliuf6d263e2015-11-25 03:53:58147 return false;
148
149 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
150 SyncCompositorCommonBrowserParams common_browser_params;
151 PopulateCommonParams(&common_browser_params);
152 SyncCompositorCommonRendererParams common_renderer_params;
153 bool success = false;
154 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
155 routing_id_, common_browser_params, params, &success,
156 &common_renderer_params, frame.get()))) {
157 return false;
158 }
boliucafb1bf2015-12-29 01:40:19159 ScopedSendZeroMemory send_zero_memory(this);
boliuf6d263e2015-11-25 03:53:58160 if (!success)
161 return false;
162
163 ProcessCommonParams(common_renderer_params);
164 UpdateFrameMetaData(frame->metadata);
165
166 SkBitmap bitmap;
boliucafb1bf2015-12-29 01:40:19167 if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
boliuf6d263e2015-11-25 03:53:58168 return false;
169
170 {
171 TRACE_EVENT0("browser", "DrawBitmap");
172 canvas->save();
173 canvas->resetMatrix();
174 canvas->drawBitmap(bitmap, 0, 0);
175 canvas->restore();
176 }
177
178 return true;
boliubee541f42015-11-05 00:52:53179}
180
boliucafb1bf2015-12-29 01:40:19181void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
182 size_t stride,
183 size_t buffer_size) {
184 if (software_draw_shm_ && software_draw_shm_->stride == stride &&
185 software_draw_shm_->buffer_size == buffer_size)
186 return;
187 software_draw_shm_.reset();
188 scoped_ptr<SharedMemoryWithSize> software_draw_shm(
189 new SharedMemoryWithSize(stride, buffer_size));
190 {
191 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
192 if (!software_draw_shm->shm.CreateAndMapAnonymous(buffer_size))
193 return;
194 }
195
196 SyncCompositorSetSharedMemoryParams set_shm_params;
197 set_shm_params.buffer_size = buffer_size;
198 base::ProcessHandle renderer_process_handle =
199 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
200 if (!software_draw_shm->shm.ShareToProcess(renderer_process_handle,
201 &set_shm_params.shm_handle)) {
202 return;
203 }
204
205 SyncCompositorCommonBrowserParams common_browser_params;
206 PopulateCommonParams(&common_browser_params);
207 bool success = false;
208 SyncCompositorCommonRendererParams common_renderer_params;
209 if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
210 routing_id_, common_browser_params, set_shm_params, &success,
211 &common_renderer_params)) ||
212 !success) {
213 return;
214 }
215 software_draw_shm_ = std::move(software_draw_shm);
216 ProcessCommonParams(common_renderer_params);
217}
218
219void SynchronousCompositorHost::SendZeroMemory() {
220 // No need to check return value.
221 sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
222}
223
boliubee541f42015-11-05 00:52:53224void SynchronousCompositorHost::ReturnResources(
225 const cc::CompositorFrameAck& frame_ack) {
226 returned_resources_.insert(returned_resources_.end(),
227 frame_ack.resources.begin(),
228 frame_ack.resources.end());
229}
230
231void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
232 if (bytes_limit_ == bytes_limit)
233 return;
234 bytes_limit_ = bytes_limit;
hush92bd35e72015-11-13 22:57:37235 SendAsyncCompositorStateIfNeeded();
boliubee541f42015-11-05 00:52:53236}
237
238void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
239 const gfx::ScrollOffset& root_offset) {
240 if (root_scroll_offset_ == root_offset)
241 return;
boliu600cba922015-12-08 04:28:22242 root_scroll_offset_updated_by_browser_ = true;
boliubee541f42015-11-05 00:52:53243 root_scroll_offset_ = root_offset;
hush92bd35e72015-11-13 22:57:37244 SendAsyncCompositorStateIfNeeded();
245}
246
247void SynchronousCompositorHost::SendAsyncCompositorStateIfNeeded() {
248 if (weak_ptr_factory_.HasWeakPtrs())
249 return;
250
251 ui_task_runner_->PostTask(
252 FROM_HERE, base::Bind(&SynchronousCompositorHost::UpdateStateTask,
253 weak_ptr_factory_.GetWeakPtr()));
254}
255
256void SynchronousCompositorHost::UpdateStateTask() {
257 SyncCompositorCommonBrowserParams common_browser_params;
258 PopulateCommonParams(&common_browser_params);
259 sender_->Send(
260 new SyncCompositorMsg_UpdateState(routing_id_, common_browser_params));
261 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
boliubee541f42015-11-05 00:52:53262}
263
264void SynchronousCompositorHost::SetIsActive(bool is_active) {
boliu0c1f91d2016-01-13 19:27:37265 if (is_active_ == is_active)
266 return;
boliubee541f42015-11-05 00:52:53267 is_active_ = is_active;
268 UpdateNeedsBeginFrames();
boliu0c1f91d2016-01-13 19:27:37269 SendAsyncCompositorStateIfNeeded();
boliubee541f42015-11-05 00:52:53270}
271
272void SynchronousCompositorHost::OnComputeScroll(
273 base::TimeTicks animation_time) {
274 if (!need_animate_scroll_)
275 return;
276 need_animate_scroll_ = false;
277
278 SyncCompositorCommonBrowserParams common_browser_params;
279 PopulateCommonParams(&common_browser_params);
280 SyncCompositorCommonRendererParams common_renderer_params;
boliu7f873dd2016-01-21 22:37:27281 sender_->Send(new SyncCompositorMsg_ComputeScroll(
282 routing_id_, common_browser_params, animation_time));
boliubee541f42015-11-05 00:52:53283}
284
285InputEventAckState SynchronousCompositorHost::HandleInputEvent(
286 const blink::WebInputEvent& input_event) {
287 SyncCompositorCommonBrowserParams common_browser_params;
288 PopulateCommonParams(&common_browser_params);
289 SyncCompositorCommonRendererParams common_renderer_params;
290 InputEventAckState ack = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
291 if (!sender_->Send(new SyncCompositorMsg_HandleInputEvent(
292 routing_id_, common_browser_params, &input_event,
293 &common_renderer_params, &ack))) {
294 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
295 }
296 ProcessCommonParams(common_renderer_params);
297 return ack;
298}
299
300void SynchronousCompositorHost::BeginFrame(const cc::BeginFrameArgs& args) {
301 if (!is_active_ || !need_begin_frame_)
302 return;
303
304 SyncCompositorCommonBrowserParams common_browser_params;
305 PopulateCommonParams(&common_browser_params);
306 SyncCompositorCommonRendererParams common_renderer_params;
307 if (!sender_->Send(
308 new SyncCompositorMsg_BeginFrame(routing_id_, common_browser_params,
309 args, &common_renderer_params))) {
310 return;
311 }
312 ProcessCommonParams(common_renderer_params);
313}
314
boliu09be0e62015-11-11 00:57:00315void SynchronousCompositorHost::OnOverScroll(
316 const SyncCompositorCommonRendererParams& params,
317 const DidOverscrollParams& over_scroll_params) {
318 ProcessCommonParams(params);
319 client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
320 over_scroll_params.latest_overscroll_delta,
321 over_scroll_params.current_fling_velocity);
322}
323
boliubee541f42015-11-05 00:52:53324void SynchronousCompositorHost::PopulateCommonParams(
325 SyncCompositorCommonBrowserParams* params) {
326 DCHECK(params);
327 DCHECK(params->ack.resources.empty());
328 params->bytes_limit = bytes_limit_;
boliubee541f42015-11-05 00:52:53329 params->ack.resources.swap(returned_resources_);
boliu600cba922015-12-08 04:28:22330 if (root_scroll_offset_updated_by_browser_) {
331 params->root_scroll_offset = root_scroll_offset_;
332 params->update_root_scroll_offset = root_scroll_offset_updated_by_browser_;
333 root_scroll_offset_updated_by_browser_ = false;
334 }
boliu0c1f91d2016-01-13 19:27:37335 params->begin_frame_source_paused = !is_active_;
boliu600cba922015-12-08 04:28:22336
hush92bd35e72015-11-13 22:57:37337 weak_ptr_factory_.InvalidateWeakPtrs();
boliubee541f42015-11-05 00:52:53338}
339
340void SynchronousCompositorHost::ProcessCommonParams(
341 const SyncCompositorCommonRendererParams& params) {
342 // Ignore if |renderer_param_version_| is newer than |params.version|. This
343 // comparison takes into account when the unsigned int wraps.
344 if ((renderer_param_version_ - params.version) < 0x80000000) {
345 return;
346 }
347 renderer_param_version_ = params.version;
348 need_animate_scroll_ = params.need_animate_scroll;
349 if (need_begin_frame_ != params.need_begin_frame) {
350 need_begin_frame_ = params.need_begin_frame;
351 UpdateNeedsBeginFrames();
352 }
353 need_invalidate_ = need_invalidate_ || params.need_invalidate;
354 did_activate_pending_tree_ =
355 did_activate_pending_tree_ || params.did_activate_pending_tree;
356 root_scroll_offset_ = params.total_scroll_offset;
357
358 if (need_invalidate_) {
359 need_invalidate_ = false;
360 client_->PostInvalidate();
361 }
362
363 if (did_activate_pending_tree_) {
364 did_activate_pending_tree_ = false;
365 client_->DidUpdateContent();
366 }
367
368 // Ensure only valid values from compositor are sent to client.
369 // Compositor has page_scale_factor set to 0 before initialization, so check
370 // for that case here.
371 if (params.page_scale_factor) {
372 client_->UpdateRootLayerState(
373 gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
374 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
375 params.scrollable_size, params.page_scale_factor,
376 params.min_page_scale_factor, params.max_page_scale_factor);
377 }
378}
379
380void SynchronousCompositorHost::UpdateNeedsBeginFrames() {
381 rwhva_->OnSetNeedsBeginFrames(is_active_ && need_begin_frame_);
382}
383
384} // namespace content