blob: 2b588aed0b0f2186c0579d280b63ef64ad1ac6da [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"
boliuc99f26c12016-04-21 21:58:5916#include "content/browser/web_contents/web_contents_android.h"
boliubee541f42015-11-05 00:52:5317#include "content/browser/web_contents/web_contents_impl.h"
18#include "content/common/android/sync_compositor_messages.h"
jbroman801dd272016-04-22 18:54:0219#include "content/common/android/sync_compositor_statics.h"
boliubee541f42015-11-05 00:52:5320#include "content/public/browser/android/synchronous_compositor_client.h"
hush92bd35e72015-11-13 22:57:3721#include "content/public/browser/browser_thread.h"
boliubee541f42015-11-05 00:52:5322#include "content/public/browser/render_view_host.h"
boliuc99f26c12016-04-21 21:58:5923#include "content/public/common/content_switches.h"
boliubee541f42015-11-05 00:52:5324#include "ipc/ipc_sender.h"
boliuf6d263e2015-11-25 03:53:5825#include "third_party/skia/include/core/SkBitmap.h"
26#include "third_party/skia/include/core/SkCanvas.h"
27#include "third_party/skia/include/core/SkImageInfo.h"
28#include "third_party/skia/include/core/SkRect.h"
chongza8ba91fc2016-08-16 21:39:1729#include "ui/events/blink/did_overscroll_params.h"
boliuf6d263e2015-11-25 03:53:5830#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5331
32namespace content {
33
boliuc99f26c12016-04-21 21:58:5934// static
35void SynchronousCompositor::SetClientForWebContents(
36 WebContents* contents,
37 SynchronousCompositorClient* client) {
38 DCHECK(contents);
39 DCHECK(client);
40 WebContentsAndroid* web_contents_android =
41 static_cast<WebContentsImpl*>(contents)->GetWebContentsAndroid();
42 DCHECK(!web_contents_android->synchronous_compositor_client());
43 web_contents_android->set_synchronous_compositor_client(client);
44}
45
46// static
47std::unique_ptr<SynchronousCompositorHost> SynchronousCompositorHost::Create(
48 RenderWidgetHostViewAndroid* rwhva,
49 WebContents* web_contents) {
50 DCHECK(web_contents);
51 WebContentsAndroid* web_contents_android =
52 static_cast<WebContentsImpl*>(web_contents)->GetWebContentsAndroid();
53 if (!web_contents_android->synchronous_compositor_client())
54 return nullptr; // Not using sync compositing.
55
56 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
boliuc99f26c12016-04-21 21:58:5957 bool use_in_proc_software_draw =
58 command_line->HasSwitch(switches::kSingleProcess);
59 return base::WrapUnique(new SynchronousCompositorHost(
boliub2768db2016-06-03 23:35:1660 rwhva, web_contents_android->synchronous_compositor_client(),
boliuc99f26c12016-04-21 21:58:5961 use_in_proc_software_draw));
62}
63
boliubee541f42015-11-05 00:52:5364SynchronousCompositorHost::SynchronousCompositorHost(
65 RenderWidgetHostViewAndroid* rwhva,
boliu4d4b5a82016-02-17 01:55:2166 SynchronousCompositorClient* client,
67 bool use_in_proc_software_draw)
boliubee541f42015-11-05 00:52:5368 : rwhva_(rwhva),
69 client_(client),
thestig529ad8a2016-07-08 20:30:1270 ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
hush284add62016-06-17 20:47:3371 process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
boliubee541f42015-11-05 00:52:5372 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
boliubee541f42015-11-05 00:52:5373 sender_(rwhva_->GetRenderWidgetHost()),
boliu4d4b5a82016-02-17 01:55:2174 use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
boliubee541f42015-11-05 00:52:5375 bytes_limit_(0u),
76 renderer_param_version_(0u),
77 need_animate_scroll_(false),
boliu17bc31f2016-02-23 18:46:2878 need_invalidate_count_(0u),
boliu8f3016e2016-06-04 00:59:1879 did_activate_pending_tree_count_(0u) {
hush284add62016-06-17 20:47:3380 client_->DidInitializeCompositor(this, process_id_, routing_id_);
boliubee541f42015-11-05 00:52:5381}
82
83SynchronousCompositorHost::~SynchronousCompositorHost() {
hush284add62016-06-17 20:47:3384 client_->DidDestroyCompositor(this, process_id_, routing_id_);
boliu524d4c0b2016-10-28 04:04:0585 if (registered_with_filter_) {
86 if (SynchronousCompositorBrowserFilter* filter = GetFilter())
87 filter->UnregisterHost(this);
88 }
boliubee541f42015-11-05 00:52:5389}
90
91bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
92 bool handled = true;
93 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
danakj1120f4c2016-09-15 02:05:3294 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_CompositorFrameSinkCreated,
95 CompositorFrameSinkCreated)
boliubee541f42015-11-05 00:52:5396 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
boliubee541f42015-11-05 00:52:5397 IPC_MESSAGE_UNHANDLED(handled = false)
98 IPC_END_MESSAGE_MAP()
99 return handled;
100}
101
boliuc37cd75b2016-10-24 17:54:39102scoped_refptr<SynchronousCompositor::FrameFuture>
103SynchronousCompositorHost::DemandDrawHwAsync(
ojars53392992016-09-03 00:09:06104 const gfx::Size& viewport_size,
105 const gfx::Rect& viewport_rect_for_tile_priority,
106 const gfx::Transform& transform_for_tile_priority) {
107 SyncCompositorDemandDrawHwParams params(viewport_size,
108 viewport_rect_for_tile_priority,
109 transform_for_tile_priority);
boliuc37cd75b2016-10-24 17:54:39110 scoped_refptr<FrameFuture> frame_future = new FrameFuture();
boliu22557972016-10-25 16:08:29111 if (SynchronousCompositorBrowserFilter* filter = GetFilter()) {
boliu524d4c0b2016-10-28 04:04:05112 if (!registered_with_filter_) {
113 filter->RegisterHost(this);
114 registered_with_filter_ = true;
115 }
boliuc37cd75b2016-10-24 17:54:39116 filter->SetFrameFuture(routing_id_, frame_future);
117 sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
118 } else {
boliuf26c9e0f2016-10-27 16:29:08119 frame_future->SetFrame(nullptr);
boliuc37cd75b2016-10-24 17:54:39120 }
121 return frame_future;
ojars53392992016-09-03 00:09:06122}
123
boliuf4e574852016-03-22 19:33:17124SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
boliu31c233ed2016-07-29 05:38:59125 const gfx::Size& viewport_size,
boliubee541f42015-11-05 00:52:53126 const gfx::Rect& viewport_rect_for_tile_priority,
127 const gfx::Transform& transform_for_tile_priority) {
boliu31c233ed2016-07-29 05:38:59128 SyncCompositorDemandDrawHwParams params(viewport_size,
129 viewport_rect_for_tile_priority,
boliubee541f42015-11-05 00:52:53130 transform_for_tile_priority);
danakj1120f4c2016-09-15 02:05:32131 uint32_t compositor_frame_sink_id;
samans96418732016-10-27 21:24:45132 base::Optional<cc::CompositorFrame> compositor_frame;
boliubee541f42015-11-05 00:52:53133 SyncCompositorCommonRendererParams common_renderer_params;
ojars53392992016-09-03 00:09:06134
boliubee541f42015-11-05 00:52:53135 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
danakj1120f4c2016-09-15 02:05:32136 routing_id_, params, &common_renderer_params,
137 &compositor_frame_sink_id, &compositor_frame))) {
boliuf4e574852016-03-22 19:33:17138 return SynchronousCompositor::Frame();
boliubee541f42015-11-05 00:52:53139 }
ojars53392992016-09-03 00:09:06140
boliubee541f42015-11-05 00:52:53141 ProcessCommonParams(common_renderer_params);
ojars53392992016-09-03 00:09:06142
samans96418732016-10-27 21:24:45143 if (!compositor_frame)
144 return SynchronousCompositor::Frame();
145
ojars53392992016-09-03 00:09:06146 SynchronousCompositor::Frame frame;
147 frame.frame.reset(new cc::CompositorFrame);
danakj1120f4c2016-09-15 02:05:32148 frame.compositor_frame_sink_id = compositor_frame_sink_id;
boliu524d4c0b2016-10-28 04:04:05149 *frame.frame = std::move(*compositor_frame);
samans96418732016-10-27 21:24:45150 UpdateFrameMetaData(frame.frame->metadata.Clone());
boliubee541f42015-11-05 00:52:53151 return frame;
152}
153
154void SynchronousCompositorHost::UpdateFrameMetaData(
fsamueld63137a2016-06-24 23:39:51155 cc::CompositorFrameMetadata frame_metadata) {
156 rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
boliubee541f42015-11-05 00:52:53157}
158
boliu22557972016-10-25 16:08:29159SynchronousCompositorBrowserFilter* SynchronousCompositorHost::GetFilter() {
boliuc37cd75b2016-10-24 17:54:39160 return static_cast<RenderProcessHostImpl*>(
161 rwhva_->GetRenderWidgetHost()->GetProcess())
162 ->synchronous_compositor_filter();
163}
164
boliu4d4b5a82016-02-17 01:55:21165namespace {
166
167class ScopedSetSkCanvas {
168 public:
169 explicit ScopedSetSkCanvas(SkCanvas* canvas) {
170 SynchronousCompositorSetSkCanvas(canvas);
171 }
172
173 ~ScopedSetSkCanvas() {
174 SynchronousCompositorSetSkCanvas(nullptr);
175 }
176
177 private:
178 DISALLOW_COPY_AND_ASSIGN(ScopedSetSkCanvas);
179};
180
181}
182
183bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21184 SyncCompositorCommonRendererParams common_renderer_params;
185 bool success = false;
dcheng59716272016-04-09 05:19:08186 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliu4d4b5a82016-02-17 01:55:21187 ScopedSetSkCanvas set_sk_canvas(canvas);
188 SyncCompositorDemandDrawSwParams params; // Unused.
189 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18190 routing_id_, params, &success, &common_renderer_params,
191 frame.get()))) {
boliu4d4b5a82016-02-17 01:55:21192 return false;
193 }
194 if (!success)
195 return false;
196 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51197 UpdateFrameMetaData(std::move(frame->metadata));
boliu4d4b5a82016-02-17 01:55:21198 return true;
199}
200
boliucafb1bf2015-12-29 01:40:19201class SynchronousCompositorHost::ScopedSendZeroMemory {
202 public:
203 ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
204 ~ScopedSendZeroMemory() { host_->SendZeroMemory(); }
205
206 private:
207 SynchronousCompositorHost* const host_;
208
209 DISALLOW_COPY_AND_ASSIGN(ScopedSendZeroMemory);
210};
211
212struct SynchronousCompositorHost::SharedMemoryWithSize {
213 base::SharedMemory shm;
214 const size_t stride;
215 const size_t buffer_size;
216
217 SharedMemoryWithSize(size_t stride, size_t buffer_size)
218 : stride(stride), buffer_size(buffer_size) {}
219
220 private:
221 DISALLOW_COPY_AND_ASSIGN(SharedMemoryWithSize);
222};
223
boliubee541f42015-11-05 00:52:53224bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21225 if (use_in_process_zero_copy_software_draw_)
226 return DemandDrawSwInProc(canvas);
227
boliuf6d263e2015-11-25 03:53:58228 SyncCompositorDemandDrawSwParams params;
229 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
230 canvas->getBaseLayerSize().height());
231 SkIRect canvas_clip;
232 canvas->getClipDeviceBounds(&canvas_clip);
233 params.clip = gfx::SkIRectToRect(canvas_clip);
234 params.transform.matrix() = canvas->getTotalMatrix();
235 if (params.size.IsEmpty())
236 return true;
237
238 SkImageInfo info =
239 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
240 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
241 size_t stride = info.minRowBytes();
242 size_t buffer_size = info.getSafeSize(stride);
243 if (!buffer_size)
244 return false; // Overflow.
245
boliucafb1bf2015-12-29 01:40:19246 SetSoftwareDrawSharedMemoryIfNeeded(stride, buffer_size);
247 if (!software_draw_shm_)
boliuf6d263e2015-11-25 03:53:58248 return false;
249
dcheng59716272016-04-09 05:19:08250 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliuf6d263e2015-11-25 03:53:58251 SyncCompositorCommonRendererParams common_renderer_params;
252 bool success = false;
253 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18254 routing_id_, params, &success, &common_renderer_params,
255 frame.get()))) {
boliuf6d263e2015-11-25 03:53:58256 return false;
257 }
boliucafb1bf2015-12-29 01:40:19258 ScopedSendZeroMemory send_zero_memory(this);
boliuf6d263e2015-11-25 03:53:58259 if (!success)
260 return false;
261
262 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51263 UpdateFrameMetaData(std::move(frame->metadata));
boliuf6d263e2015-11-25 03:53:58264
265 SkBitmap bitmap;
boliucafb1bf2015-12-29 01:40:19266 if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
boliuf6d263e2015-11-25 03:53:58267 return false;
268
269 {
270 TRACE_EVENT0("browser", "DrawBitmap");
271 canvas->save();
272 canvas->resetMatrix();
273 canvas->drawBitmap(bitmap, 0, 0);
274 canvas->restore();
275 }
276
277 return true;
boliubee541f42015-11-05 00:52:53278}
279
boliucafb1bf2015-12-29 01:40:19280void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
281 size_t stride,
282 size_t buffer_size) {
283 if (software_draw_shm_ && software_draw_shm_->stride == stride &&
284 software_draw_shm_->buffer_size == buffer_size)
285 return;
286 software_draw_shm_.reset();
dcheng59716272016-04-09 05:19:08287 std::unique_ptr<SharedMemoryWithSize> software_draw_shm(
boliucafb1bf2015-12-29 01:40:19288 new SharedMemoryWithSize(stride, buffer_size));
289 {
290 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
291 if (!software_draw_shm->shm.CreateAndMapAnonymous(buffer_size))
292 return;
293 }
294
295 SyncCompositorSetSharedMemoryParams set_shm_params;
296 set_shm_params.buffer_size = buffer_size;
297 base::ProcessHandle renderer_process_handle =
298 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
299 if (!software_draw_shm->shm.ShareToProcess(renderer_process_handle,
300 &set_shm_params.shm_handle)) {
301 return;
302 }
303
boliucafb1bf2015-12-29 01:40:19304 bool success = false;
305 SyncCompositorCommonRendererParams common_renderer_params;
306 if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
boliu8f3016e2016-06-04 00:59:18307 routing_id_, set_shm_params, &success, &common_renderer_params)) ||
boliucafb1bf2015-12-29 01:40:19308 !success) {
309 return;
310 }
311 software_draw_shm_ = std::move(software_draw_shm);
312 ProcessCommonParams(common_renderer_params);
313}
314
315void SynchronousCompositorHost::SendZeroMemory() {
316 // No need to check return value.
317 sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
318}
319
boliubee541f42015-11-05 00:52:53320void SynchronousCompositorHost::ReturnResources(
danakj1120f4c2016-09-15 02:05:32321 uint32_t compositor_frame_sink_id,
fsamuelb62b78222016-07-15 01:14:14322 const cc::ReturnedResourceArray& resources) {
323 DCHECK(!resources.empty());
boliuec72a2ed2016-05-10 00:51:56324 sender_->Send(new SyncCompositorMsg_ReclaimResources(
danakj1120f4c2016-09-15 02:05:32325 routing_id_, compositor_frame_sink_id, resources));
boliubee541f42015-11-05 00:52:53326}
327
328void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
329 if (bytes_limit_ == bytes_limit)
330 return;
boliu42e01312016-05-12 21:47:52331
332 if (sender_->Send(
333 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit))) {
334 bytes_limit_ = bytes_limit;
335 }
boliubee541f42015-11-05 00:52:53336}
337
338void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
339 const gfx::ScrollOffset& root_offset) {
340 if (root_scroll_offset_ == root_offset)
341 return;
342 root_scroll_offset_ = root_offset;
boliu22cdc6d2016-05-13 19:43:09343 sender_->Send(
344 new SyncCompositorMsg_SetScroll(routing_id_, root_scroll_offset_));
hush92bd35e72015-11-13 22:57:37345}
346
boliu21d8ab142016-04-07 23:33:52347void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
348 const gfx::Point& anchor) {
boliu21d8ab142016-04-07 23:33:52349 SyncCompositorCommonRendererParams common_renderer_params;
350 if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
boliu8f3016e2016-06-04 00:59:18351 routing_id_, zoom_delta, anchor, &common_renderer_params))) {
boliu21d8ab142016-04-07 23:33:52352 return;
353 }
354 ProcessCommonParams(common_renderer_params);
355}
356
boliubee541f42015-11-05 00:52:53357void SynchronousCompositorHost::OnComputeScroll(
358 base::TimeTicks animation_time) {
359 if (!need_animate_scroll_)
360 return;
361 need_animate_scroll_ = false;
362
boliubee541f42015-11-05 00:52:53363 SyncCompositorCommonRendererParams common_renderer_params;
boliu8f3016e2016-06-04 00:59:18364 sender_->Send(
365 new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
boliubee541f42015-11-05 00:52:53366}
367
boliude5b75b2016-03-11 07:02:14368void SynchronousCompositorHost::DidOverscroll(
chongza8ba91fc2016-08-16 21:39:17369 const ui::DidOverscrollParams& over_scroll_params) {
hush83e367c2016-06-18 02:37:54370 client_->DidOverscroll(this, over_scroll_params.accumulated_overscroll,
boliude5b75b2016-03-11 07:02:14371 over_scroll_params.latest_overscroll_delta,
372 over_scroll_params.current_fling_velocity);
373}
374
boliu3dd3ca72016-07-29 00:18:37375void SynchronousCompositorHost::DidSendBeginFrame(
376 ui::WindowAndroid* window_android) {
boliu22557972016-10-25 16:08:29377 if (SynchronousCompositorBrowserFilter* filter = GetFilter())
boliuc37cd75b2016-10-24 17:54:39378 filter->SyncStateAfterVSync(window_android, this);
boliubee541f42015-11-05 00:52:53379}
380
danakj1120f4c2016-09-15 02:05:32381void SynchronousCompositorHost::CompositorFrameSinkCreated() {
382 // New CompositorFrameSink is not aware of state from Browser side. So need to
boliu42e01312016-05-12 21:47:52383 // re-send all browser side state here.
384 sender_->Send(
385 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit_));
386}
387
boliubee541f42015-11-05 00:52:53388void SynchronousCompositorHost::ProcessCommonParams(
389 const SyncCompositorCommonRendererParams& params) {
390 // Ignore if |renderer_param_version_| is newer than |params.version|. This
391 // comparison takes into account when the unsigned int wraps.
392 if ((renderer_param_version_ - params.version) < 0x80000000) {
393 return;
394 }
395 renderer_param_version_ = params.version;
396 need_animate_scroll_ = params.need_animate_scroll;
boliubee541f42015-11-05 00:52:53397 root_scroll_offset_ = params.total_scroll_offset;
398
boliu17bc31f2016-02-23 18:46:28399 if (need_invalidate_count_ != params.need_invalidate_count) {
400 need_invalidate_count_ = params.need_invalidate_count;
hush83e367c2016-06-18 02:37:54401 client_->PostInvalidate(this);
boliubee541f42015-11-05 00:52:53402 }
403
boliu17bc31f2016-02-23 18:46:28404 if (did_activate_pending_tree_count_ !=
405 params.did_activate_pending_tree_count) {
406 did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
hush83e367c2016-06-18 02:37:54407 client_->DidUpdateContent(this);
boliubee541f42015-11-05 00:52:53408 }
409
410 // Ensure only valid values from compositor are sent to client.
411 // Compositor has page_scale_factor set to 0 before initialization, so check
412 // for that case here.
413 if (params.page_scale_factor) {
414 client_->UpdateRootLayerState(
hush83e367c2016-06-18 02:37:54415 this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
boliubee541f42015-11-05 00:52:53416 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
417 params.scrollable_size, params.page_scale_factor,
418 params.min_page_scale_factor, params.max_page_scale_factor);
419 }
420}
421
boliubee541f42015-11-05 00:52:53422} // namespace content