blob: 15a74889b0a34ec58f49e78542015f6bcce84e2c [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
boliuc99f26c12016-04-21 21:58:599#include "base/command_line.h"
boliubee541f42015-11-05 00:52:5310#include "base/containers/hash_tables.h"
boliuc99f26c12016-04-21 21:58:5911#include "base/memory/ptr_util.h"
boliuf6d263e2015-11-25 03:53:5812#include "base/memory/shared_memory.h"
13#include "base/trace_event/trace_event_argument.h"
boliu22557972016-10-25 16:08:2914#include "content/browser/android/synchronous_compositor_browser_filter.h"
boliubee541f42015-11-05 00:52:5315#include "content/browser/renderer_host/render_widget_host_view_android.h"
16#include "content/browser/web_contents/web_contents_impl.h"
17#include "content/common/android/sync_compositor_messages.h"
jbroman801dd272016-04-22 18:54:0218#include "content/common/android/sync_compositor_statics.h"
boliubee541f42015-11-05 00:52:5319#include "content/public/browser/android/synchronous_compositor_client.h"
hush92bd35e72015-11-13 22:57:3720#include "content/public/browser/browser_thread.h"
boliubee541f42015-11-05 00:52:5321#include "content/public/browser/render_view_host.h"
boliuc99f26c12016-04-21 21:58:5922#include "content/public/common/content_switches.h"
boliubee541f42015-11-05 00:52:5323#include "ipc/ipc_sender.h"
boliuf6d263e2015-11-25 03:53:5824#include "third_party/skia/include/core/SkBitmap.h"
25#include "third_party/skia/include/core/SkCanvas.h"
26#include "third_party/skia/include/core/SkImageInfo.h"
27#include "third_party/skia/include/core/SkRect.h"
chongza8ba91fc2016-08-16 21:39:1728#include "ui/events/blink/did_overscroll_params.h"
boliuf6d263e2015-11-25 03:53:5829#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5330
31namespace content {
32
boliuc99f26c12016-04-21 21:58:5933// static
boliuc99f26c12016-04-21 21:58:5934std::unique_ptr<SynchronousCompositorHost> SynchronousCompositorHost::Create(
jinsukkimb53b9952016-11-11 15:33:4335 RenderWidgetHostViewAndroid* rwhva) {
36 if (!rwhva->synchronous_compositor_client())
boliuc99f26c12016-04-21 21:58:5937 return nullptr; // Not using sync compositing.
38
39 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
boliuc99f26c12016-04-21 21:58:5940 bool use_in_proc_software_draw =
41 command_line->HasSwitch(switches::kSingleProcess);
42 return base::WrapUnique(new SynchronousCompositorHost(
jinsukkimb53b9952016-11-11 15:33:4343 rwhva, use_in_proc_software_draw));
boliuc99f26c12016-04-21 21:58:5944}
45
boliubee541f42015-11-05 00:52:5346SynchronousCompositorHost::SynchronousCompositorHost(
47 RenderWidgetHostViewAndroid* rwhva,
boliu4d4b5a82016-02-17 01:55:2148 bool use_in_proc_software_draw)
boliubee541f42015-11-05 00:52:5349 : rwhva_(rwhva),
jinsukkimb53b9952016-11-11 15:33:4350 client_(rwhva->synchronous_compositor_client()),
thestig529ad8a2016-07-08 20:30:1251 ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
hush284add62016-06-17 20:47:3352 process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
boliubee541f42015-11-05 00:52:5353 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
54 sender_(rwhva_->GetRenderWidgetHost()),
boliu4d4b5a82016-02-17 01:55:2155 use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
boliubee541f42015-11-05 00:52:5356 bytes_limit_(0u),
57 renderer_param_version_(0u),
58 need_animate_scroll_(false),
boliu17bc31f2016-02-23 18:46:2859 need_invalidate_count_(0u),
boliu8f3016e2016-06-04 00:59:1860 did_activate_pending_tree_count_(0u) {
hush284add62016-06-17 20:47:3361 client_->DidInitializeCompositor(this, process_id_, routing_id_);
boliubee541f42015-11-05 00:52:5362}
63
64SynchronousCompositorHost::~SynchronousCompositorHost() {
hush284add62016-06-17 20:47:3365 client_->DidDestroyCompositor(this, process_id_, routing_id_);
boliu524d4c0b2016-10-28 04:04:0566 if (registered_with_filter_) {
67 if (SynchronousCompositorBrowserFilter* filter = GetFilter())
68 filter->UnregisterHost(this);
69 }
boliubee541f42015-11-05 00:52:5370}
71
72bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
73 bool handled = true;
74 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
danakj1120f4c2016-09-15 02:05:3275 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_CompositorFrameSinkCreated,
76 CompositorFrameSinkCreated)
boliubee541f42015-11-05 00:52:5377 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
78 IPC_MESSAGE_UNHANDLED(handled = false)
79 IPC_END_MESSAGE_MAP()
80 return handled;
81}
82
boliuc37cd75b2016-10-24 17:54:3983scoped_refptr<SynchronousCompositor::FrameFuture>
84SynchronousCompositorHost::DemandDrawHwAsync(
ojars53392992016-09-03 00:09:0685 const gfx::Size& viewport_size,
86 const gfx::Rect& viewport_rect_for_tile_priority,
87 const gfx::Transform& transform_for_tile_priority) {
boliu0be8dd02016-10-31 16:25:4288 scoped_refptr<FrameFuture> frame_future = new FrameFuture();
89 if (compute_scroll_needs_synchronous_draw_) {
90 compute_scroll_needs_synchronous_draw_ = false;
91 auto frame_ptr = base::MakeUnique<Frame>();
92 *frame_ptr = DemandDrawHw(viewport_size, viewport_rect_for_tile_priority,
93 transform_for_tile_priority);
94 frame_future->SetFrame(std::move(frame_ptr));
95 return frame_future;
96 }
97
ojars53392992016-09-03 00:09:0698 SyncCompositorDemandDrawHwParams params(viewport_size,
99 viewport_rect_for_tile_priority,
100 transform_for_tile_priority);
boliu22557972016-10-25 16:08:29101 if (SynchronousCompositorBrowserFilter* filter = GetFilter()) {
boliu524d4c0b2016-10-28 04:04:05102 if (!registered_with_filter_) {
103 filter->RegisterHost(this);
104 registered_with_filter_ = true;
105 }
boliuc37cd75b2016-10-24 17:54:39106 filter->SetFrameFuture(routing_id_, frame_future);
107 sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
108 } else {
boliuf26c9e0f2016-10-27 16:29:08109 frame_future->SetFrame(nullptr);
boliuc37cd75b2016-10-24 17:54:39110 }
111 return frame_future;
ojars53392992016-09-03 00:09:06112}
113
boliuf4e574852016-03-22 19:33:17114SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
boliu31c233ed2016-07-29 05:38:59115 const gfx::Size& viewport_size,
boliubee541f42015-11-05 00:52:53116 const gfx::Rect& viewport_rect_for_tile_priority,
117 const gfx::Transform& transform_for_tile_priority) {
boliu31c233ed2016-07-29 05:38:59118 SyncCompositorDemandDrawHwParams params(viewport_size,
119 viewport_rect_for_tile_priority,
boliubee541f42015-11-05 00:52:53120 transform_for_tile_priority);
danakj1120f4c2016-09-15 02:05:32121 uint32_t compositor_frame_sink_id;
samans96418732016-10-27 21:24:45122 base::Optional<cc::CompositorFrame> compositor_frame;
boliubee541f42015-11-05 00:52:53123 SyncCompositorCommonRendererParams common_renderer_params;
ojars53392992016-09-03 00:09:06124
boliubee541f42015-11-05 00:52:53125 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
danakj1120f4c2016-09-15 02:05:32126 routing_id_, params, &common_renderer_params,
127 &compositor_frame_sink_id, &compositor_frame))) {
boliuf4e574852016-03-22 19:33:17128 return SynchronousCompositor::Frame();
boliubee541f42015-11-05 00:52:53129 }
ojars53392992016-09-03 00:09:06130
boliubee541f42015-11-05 00:52:53131 ProcessCommonParams(common_renderer_params);
ojars53392992016-09-03 00:09:06132
samans96418732016-10-27 21:24:45133 if (!compositor_frame)
134 return SynchronousCompositor::Frame();
135
ojars53392992016-09-03 00:09:06136 SynchronousCompositor::Frame frame;
137 frame.frame.reset(new cc::CompositorFrame);
danakj1120f4c2016-09-15 02:05:32138 frame.compositor_frame_sink_id = compositor_frame_sink_id;
boliu524d4c0b2016-10-28 04:04:05139 *frame.frame = std::move(*compositor_frame);
samans96418732016-10-27 21:24:45140 UpdateFrameMetaData(frame.frame->metadata.Clone());
boliubee541f42015-11-05 00:52:53141 return frame;
142}
143
144void SynchronousCompositorHost::UpdateFrameMetaData(
fsamueld63137a2016-06-24 23:39:51145 cc::CompositorFrameMetadata frame_metadata) {
146 rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
boliubee541f42015-11-05 00:52:53147}
148
boliu22557972016-10-25 16:08:29149SynchronousCompositorBrowserFilter* SynchronousCompositorHost::GetFilter() {
boliuc37cd75b2016-10-24 17:54:39150 return static_cast<RenderProcessHostImpl*>(
151 rwhva_->GetRenderWidgetHost()->GetProcess())
152 ->synchronous_compositor_filter();
153}
154
boliu4d4b5a82016-02-17 01:55:21155namespace {
156
157class ScopedSetSkCanvas {
158 public:
159 explicit ScopedSetSkCanvas(SkCanvas* canvas) {
160 SynchronousCompositorSetSkCanvas(canvas);
161 }
162
163 ~ScopedSetSkCanvas() {
164 SynchronousCompositorSetSkCanvas(nullptr);
165 }
166
167 private:
168 DISALLOW_COPY_AND_ASSIGN(ScopedSetSkCanvas);
169};
170
171}
172
173bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21174 SyncCompositorCommonRendererParams common_renderer_params;
175 bool success = false;
dcheng59716272016-04-09 05:19:08176 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliu4d4b5a82016-02-17 01:55:21177 ScopedSetSkCanvas set_sk_canvas(canvas);
178 SyncCompositorDemandDrawSwParams params; // Unused.
179 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18180 routing_id_, params, &success, &common_renderer_params,
181 frame.get()))) {
boliu4d4b5a82016-02-17 01:55:21182 return false;
183 }
184 if (!success)
185 return false;
186 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51187 UpdateFrameMetaData(std::move(frame->metadata));
boliu4d4b5a82016-02-17 01:55:21188 return true;
189}
190
boliucafb1bf2015-12-29 01:40:19191class SynchronousCompositorHost::ScopedSendZeroMemory {
192 public:
193 ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
194 ~ScopedSendZeroMemory() { host_->SendZeroMemory(); }
195
196 private:
197 SynchronousCompositorHost* const host_;
198
199 DISALLOW_COPY_AND_ASSIGN(ScopedSendZeroMemory);
200};
201
202struct SynchronousCompositorHost::SharedMemoryWithSize {
203 base::SharedMemory shm;
204 const size_t stride;
205 const size_t buffer_size;
206
207 SharedMemoryWithSize(size_t stride, size_t buffer_size)
208 : stride(stride), buffer_size(buffer_size) {}
209
210 private:
211 DISALLOW_COPY_AND_ASSIGN(SharedMemoryWithSize);
212};
213
boliubee541f42015-11-05 00:52:53214bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21215 if (use_in_process_zero_copy_software_draw_)
216 return DemandDrawSwInProc(canvas);
217
boliuf6d263e2015-11-25 03:53:58218 SyncCompositorDemandDrawSwParams params;
219 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
220 canvas->getBaseLayerSize().height());
reed45325142017-01-27 13:00:07221 SkIRect canvas_clip = canvas->getDeviceClipBounds();
boliuf6d263e2015-11-25 03:53:58222 params.clip = gfx::SkIRectToRect(canvas_clip);
223 params.transform.matrix() = canvas->getTotalMatrix();
224 if (params.size.IsEmpty())
225 return true;
226
227 SkImageInfo info =
228 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
229 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
230 size_t stride = info.minRowBytes();
231 size_t buffer_size = info.getSafeSize(stride);
232 if (!buffer_size)
233 return false; // Overflow.
234
boliucafb1bf2015-12-29 01:40:19235 SetSoftwareDrawSharedMemoryIfNeeded(stride, buffer_size);
236 if (!software_draw_shm_)
boliuf6d263e2015-11-25 03:53:58237 return false;
238
dcheng59716272016-04-09 05:19:08239 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliuf6d263e2015-11-25 03:53:58240 SyncCompositorCommonRendererParams common_renderer_params;
241 bool success = false;
242 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18243 routing_id_, params, &success, &common_renderer_params,
244 frame.get()))) {
boliuf6d263e2015-11-25 03:53:58245 return false;
246 }
boliucafb1bf2015-12-29 01:40:19247 ScopedSendZeroMemory send_zero_memory(this);
boliuf6d263e2015-11-25 03:53:58248 if (!success)
249 return false;
250
251 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51252 UpdateFrameMetaData(std::move(frame->metadata));
boliuf6d263e2015-11-25 03:53:58253
254 SkBitmap bitmap;
boliucafb1bf2015-12-29 01:40:19255 if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
boliuf6d263e2015-11-25 03:53:58256 return false;
257
258 {
259 TRACE_EVENT0("browser", "DrawBitmap");
260 canvas->save();
261 canvas->resetMatrix();
262 canvas->drawBitmap(bitmap, 0, 0);
263 canvas->restore();
264 }
265
266 return true;
boliubee541f42015-11-05 00:52:53267}
268
boliucafb1bf2015-12-29 01:40:19269void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
270 size_t stride,
271 size_t buffer_size) {
272 if (software_draw_shm_ && software_draw_shm_->stride == stride &&
273 software_draw_shm_->buffer_size == buffer_size)
274 return;
275 software_draw_shm_.reset();
dcheng59716272016-04-09 05:19:08276 std::unique_ptr<SharedMemoryWithSize> software_draw_shm(
boliucafb1bf2015-12-29 01:40:19277 new SharedMemoryWithSize(stride, buffer_size));
278 {
279 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
280 if (!software_draw_shm->shm.CreateAndMapAnonymous(buffer_size))
281 return;
282 }
283
284 SyncCompositorSetSharedMemoryParams set_shm_params;
285 set_shm_params.buffer_size = buffer_size;
286 base::ProcessHandle renderer_process_handle =
287 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
288 if (!software_draw_shm->shm.ShareToProcess(renderer_process_handle,
289 &set_shm_params.shm_handle)) {
290 return;
291 }
292
boliucafb1bf2015-12-29 01:40:19293 bool success = false;
294 SyncCompositorCommonRendererParams common_renderer_params;
295 if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
boliu8f3016e2016-06-04 00:59:18296 routing_id_, set_shm_params, &success, &common_renderer_params)) ||
boliucafb1bf2015-12-29 01:40:19297 !success) {
298 return;
299 }
300 software_draw_shm_ = std::move(software_draw_shm);
301 ProcessCommonParams(common_renderer_params);
302}
303
304void SynchronousCompositorHost::SendZeroMemory() {
305 // No need to check return value.
306 sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
307}
308
boliubee541f42015-11-05 00:52:53309void SynchronousCompositorHost::ReturnResources(
danakj1120f4c2016-09-15 02:05:32310 uint32_t compositor_frame_sink_id,
fsamuelb62b78222016-07-15 01:14:14311 const cc::ReturnedResourceArray& resources) {
312 DCHECK(!resources.empty());
boliuec72a2ed2016-05-10 00:51:56313 sender_->Send(new SyncCompositorMsg_ReclaimResources(
danakj1120f4c2016-09-15 02:05:32314 routing_id_, compositor_frame_sink_id, resources));
boliubee541f42015-11-05 00:52:53315}
316
317void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
318 if (bytes_limit_ == bytes_limit)
319 return;
boliu42e01312016-05-12 21:47:52320
321 if (sender_->Send(
322 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit))) {
323 bytes_limit_ = bytes_limit;
324 }
boliubee541f42015-11-05 00:52:53325}
326
327void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
328 const gfx::ScrollOffset& root_offset) {
329 if (root_scroll_offset_ == root_offset)
330 return;
331 root_scroll_offset_ = root_offset;
boliu22cdc6d2016-05-13 19:43:09332 sender_->Send(
333 new SyncCompositorMsg_SetScroll(routing_id_, root_scroll_offset_));
hush92bd35e72015-11-13 22:57:37334}
335
boliu21d8ab142016-04-07 23:33:52336void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
337 const gfx::Point& anchor) {
boliu21d8ab142016-04-07 23:33:52338 SyncCompositorCommonRendererParams common_renderer_params;
339 if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
boliu8f3016e2016-06-04 00:59:18340 routing_id_, zoom_delta, anchor, &common_renderer_params))) {
boliu21d8ab142016-04-07 23:33:52341 return;
342 }
343 ProcessCommonParams(common_renderer_params);
344}
345
boliubee541f42015-11-05 00:52:53346void SynchronousCompositorHost::OnComputeScroll(
347 base::TimeTicks animation_time) {
348 if (!need_animate_scroll_)
349 return;
350 need_animate_scroll_ = false;
351
boliubee541f42015-11-05 00:52:53352 SyncCompositorCommonRendererParams common_renderer_params;
boliu8f3016e2016-06-04 00:59:18353 sender_->Send(
354 new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
boliu0be8dd02016-10-31 16:25:42355 compute_scroll_needs_synchronous_draw_ = true;
boliubee541f42015-11-05 00:52:53356}
357
boliude5b75b2016-03-11 07:02:14358void SynchronousCompositorHost::DidOverscroll(
chongza8ba91fc2016-08-16 21:39:17359 const ui::DidOverscrollParams& over_scroll_params) {
hush83e367c2016-06-18 02:37:54360 client_->DidOverscroll(this, over_scroll_params.accumulated_overscroll,
boliude5b75b2016-03-11 07:02:14361 over_scroll_params.latest_overscroll_delta,
362 over_scroll_params.current_fling_velocity);
363}
364
boliu3dd3ca72016-07-29 00:18:37365void SynchronousCompositorHost::DidSendBeginFrame(
366 ui::WindowAndroid* window_android) {
boliu0be8dd02016-10-31 16:25:42367 compute_scroll_needs_synchronous_draw_ = false;
boliu22557972016-10-25 16:08:29368 if (SynchronousCompositorBrowserFilter* filter = GetFilter())
boliuc37cd75b2016-10-24 17:54:39369 filter->SyncStateAfterVSync(window_android, this);
boliubee541f42015-11-05 00:52:53370}
371
danakj1120f4c2016-09-15 02:05:32372void SynchronousCompositorHost::CompositorFrameSinkCreated() {
373 // New CompositorFrameSink is not aware of state from Browser side. So need to
boliu42e01312016-05-12 21:47:52374 // re-send all browser side state here.
375 sender_->Send(
376 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit_));
377}
378
boliubee541f42015-11-05 00:52:53379void SynchronousCompositorHost::ProcessCommonParams(
380 const SyncCompositorCommonRendererParams& params) {
381 // Ignore if |renderer_param_version_| is newer than |params.version|. This
382 // comparison takes into account when the unsigned int wraps.
383 if ((renderer_param_version_ - params.version) < 0x80000000) {
384 return;
385 }
386 renderer_param_version_ = params.version;
387 need_animate_scroll_ = params.need_animate_scroll;
boliubee541f42015-11-05 00:52:53388 root_scroll_offset_ = params.total_scroll_offset;
389
boliu17bc31f2016-02-23 18:46:28390 if (need_invalidate_count_ != params.need_invalidate_count) {
391 need_invalidate_count_ = params.need_invalidate_count;
hush83e367c2016-06-18 02:37:54392 client_->PostInvalidate(this);
boliubee541f42015-11-05 00:52:53393 }
394
boliu17bc31f2016-02-23 18:46:28395 if (did_activate_pending_tree_count_ !=
396 params.did_activate_pending_tree_count) {
397 did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
hush83e367c2016-06-18 02:37:54398 client_->DidUpdateContent(this);
boliubee541f42015-11-05 00:52:53399 }
400
401 // Ensure only valid values from compositor are sent to client.
402 // Compositor has page_scale_factor set to 0 before initialization, so check
403 // for that case here.
404 if (params.page_scale_factor) {
405 client_->UpdateRootLayerState(
hush83e367c2016-06-18 02:37:54406 this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
boliubee541f42015-11-05 00:52:53407 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
408 params.scrollable_size, params.page_scale_factor,
409 params.min_page_scale_factor, params.max_page_scale_factor);
410 }
411}
412
boliubee541f42015-11-05 00:52:53413} // namespace content