blob: 181a5addd12905ca1d1694d09713775df847a5cf [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"
boliu3dd3ca72016-07-29 00:18:3714#include "content/browser/android/synchronous_compositor_observer.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,
boliu4d4b5a82016-02-17 01:55:2167 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()),
boliu3dd3ca72016-07-29 00:18:3773 rph_observer_(SynchronousCompositorObserver::GetOrCreateFor(process_id_)),
boliubee541f42015-11-05 00:52:5374 sender_(rwhva_->GetRenderWidgetHost()),
boliu4d4b5a82016-02-17 01:55:2175 use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
boliubee541f42015-11-05 00:52:5376 bytes_limit_(0u),
boliubee541f42015-11-05 00:52:5377 renderer_param_version_(0u),
78 need_animate_scroll_(false),
boliu17bc31f2016-02-23 18:46:2879 need_invalidate_count_(0u),
boliu8f3016e2016-06-04 00:59:1880 did_activate_pending_tree_count_(0u) {
hush284add62016-06-17 20:47:3381 client_->DidInitializeCompositor(this, process_id_, routing_id_);
boliubee541f42015-11-05 00:52:5382}
83
84SynchronousCompositorHost::~SynchronousCompositorHost() {
hush284add62016-06-17 20:47:3385 client_->DidDestroyCompositor(this, process_id_, routing_id_);
boliubee541f42015-11-05 00:52:5386}
87
88bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
89 bool handled = true;
90 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
boliu42e01312016-05-12 21:47:5291 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OutputSurfaceCreated,
92 OutputSurfaceCreated)
boliubee541f42015-11-05 00:52:5393 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
ojars53392992016-09-03 00:09:0694 IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
95 DemandDrawHwReceiveFrame(message))
boliubee541f42015-11-05 00:52:5396 IPC_MESSAGE_UNHANDLED(handled = false)
97 IPC_END_MESSAGE_MAP()
98 return handled;
99}
100
ojars53392992016-09-03 00:09:06101void SynchronousCompositorHost::DemandDrawHwAsync(
102 const gfx::Size& viewport_size,
103 const gfx::Rect& viewport_rect_for_tile_priority,
104 const gfx::Transform& transform_for_tile_priority) {
105 SyncCompositorDemandDrawHwParams params(viewport_size,
106 viewport_rect_for_tile_priority,
107 transform_for_tile_priority);
108 sender_->Send(new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, params));
109}
110
boliuf4e574852016-03-22 19:33:17111SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
boliu31c233ed2016-07-29 05:38:59112 const gfx::Size& viewport_size,
boliubee541f42015-11-05 00:52:53113 const gfx::Rect& viewport_rect_for_tile_priority,
114 const gfx::Transform& transform_for_tile_priority) {
boliu31c233ed2016-07-29 05:38:59115 SyncCompositorDemandDrawHwParams params(viewport_size,
116 viewport_rect_for_tile_priority,
boliubee541f42015-11-05 00:52:53117 transform_for_tile_priority);
ojars53392992016-09-03 00:09:06118 uint32_t output_surface_id;
119 cc::CompositorFrame compositor_frame;
boliubee541f42015-11-05 00:52:53120 SyncCompositorCommonRendererParams common_renderer_params;
ojars53392992016-09-03 00:09:06121
boliubee541f42015-11-05 00:52:53122 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
ojars53392992016-09-03 00:09:06123 routing_id_, params, &common_renderer_params, &output_surface_id,
124 &compositor_frame))) {
boliuf4e574852016-03-22 19:33:17125 return SynchronousCompositor::Frame();
boliubee541f42015-11-05 00:52:53126 }
ojars53392992016-09-03 00:09:06127
boliubee541f42015-11-05 00:52:53128 ProcessCommonParams(common_renderer_params);
ojars53392992016-09-03 00:09:06129
130 return ProcessHardwareFrame(output_surface_id, std::move(compositor_frame));
131}
132
133bool SynchronousCompositorHost::DemandDrawHwReceiveFrame(
134 const IPC::Message& message) {
135 SyncCompositorHostMsg_ReturnFrame::Param param;
136 if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
137 return false;
138 uint32_t output_surface_id = std::get<0>(param);
139 cc::CompositorFrame compositor_frame = std::move(std::get<1>(param));
140 client_->OnDrawHardwareProcessFrame(
141 ProcessHardwareFrame(output_surface_id, std::move(compositor_frame)));
142 return true;
143}
144
145SynchronousCompositor::Frame SynchronousCompositorHost::ProcessHardwareFrame(
146 uint32_t output_surface_id,
147 cc::CompositorFrame compositor_frame) {
148 SynchronousCompositor::Frame frame;
149 frame.frame.reset(new cc::CompositorFrame);
150 frame.output_surface_id = output_surface_id;
151 *frame.frame = std::move(compositor_frame);
boliuf4e574852016-03-22 19:33:17152 if (!frame.frame->delegated_frame_data) {
boliubee541f42015-11-05 00:52:53153 // This can happen if compositor did not swap in this draw.
boliuf4e574852016-03-22 19:33:17154 frame.frame.reset();
boliubee541f42015-11-05 00:52:53155 }
boliuf4e574852016-03-22 19:33:17156 if (frame.frame) {
fsamueld63137a2016-06-24 23:39:51157 UpdateFrameMetaData(frame.frame->metadata.Clone());
boliuf4e574852016-03-22 19:33:17158 }
boliubee541f42015-11-05 00:52:53159 return frame;
160}
161
162void SynchronousCompositorHost::UpdateFrameMetaData(
fsamueld63137a2016-06-24 23:39:51163 cc::CompositorFrameMetadata frame_metadata) {
164 rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
boliubee541f42015-11-05 00:52:53165}
166
boliu4d4b5a82016-02-17 01:55:21167namespace {
168
169class ScopedSetSkCanvas {
170 public:
171 explicit ScopedSetSkCanvas(SkCanvas* canvas) {
172 SynchronousCompositorSetSkCanvas(canvas);
173 }
174
175 ~ScopedSetSkCanvas() {
176 SynchronousCompositorSetSkCanvas(nullptr);
177 }
178
179 private:
180 DISALLOW_COPY_AND_ASSIGN(ScopedSetSkCanvas);
181};
182
183}
184
185bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21186 SyncCompositorCommonRendererParams common_renderer_params;
187 bool success = false;
dcheng59716272016-04-09 05:19:08188 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliu4d4b5a82016-02-17 01:55:21189 ScopedSetSkCanvas set_sk_canvas(canvas);
190 SyncCompositorDemandDrawSwParams params; // Unused.
191 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18192 routing_id_, params, &success, &common_renderer_params,
193 frame.get()))) {
boliu4d4b5a82016-02-17 01:55:21194 return false;
195 }
196 if (!success)
197 return false;
198 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51199 UpdateFrameMetaData(std::move(frame->metadata));
boliu4d4b5a82016-02-17 01:55:21200 return true;
201}
202
boliucafb1bf2015-12-29 01:40:19203class SynchronousCompositorHost::ScopedSendZeroMemory {
204 public:
205 ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
206 ~ScopedSendZeroMemory() { host_->SendZeroMemory(); }
207
208 private:
209 SynchronousCompositorHost* const host_;
210
211 DISALLOW_COPY_AND_ASSIGN(ScopedSendZeroMemory);
212};
213
214struct SynchronousCompositorHost::SharedMemoryWithSize {
215 base::SharedMemory shm;
216 const size_t stride;
217 const size_t buffer_size;
218
219 SharedMemoryWithSize(size_t stride, size_t buffer_size)
220 : stride(stride), buffer_size(buffer_size) {}
221
222 private:
223 DISALLOW_COPY_AND_ASSIGN(SharedMemoryWithSize);
224};
225
boliubee541f42015-11-05 00:52:53226bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21227 if (use_in_process_zero_copy_software_draw_)
228 return DemandDrawSwInProc(canvas);
229
boliuf6d263e2015-11-25 03:53:58230 SyncCompositorDemandDrawSwParams params;
231 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
232 canvas->getBaseLayerSize().height());
233 SkIRect canvas_clip;
234 canvas->getClipDeviceBounds(&canvas_clip);
235 params.clip = gfx::SkIRectToRect(canvas_clip);
236 params.transform.matrix() = canvas->getTotalMatrix();
237 if (params.size.IsEmpty())
238 return true;
239
240 SkImageInfo info =
241 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
242 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
243 size_t stride = info.minRowBytes();
244 size_t buffer_size = info.getSafeSize(stride);
245 if (!buffer_size)
246 return false; // Overflow.
247
boliucafb1bf2015-12-29 01:40:19248 SetSoftwareDrawSharedMemoryIfNeeded(stride, buffer_size);
249 if (!software_draw_shm_)
boliuf6d263e2015-11-25 03:53:58250 return false;
251
dcheng59716272016-04-09 05:19:08252 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliuf6d263e2015-11-25 03:53:58253 SyncCompositorCommonRendererParams common_renderer_params;
254 bool success = false;
255 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18256 routing_id_, params, &success, &common_renderer_params,
257 frame.get()))) {
boliuf6d263e2015-11-25 03:53:58258 return false;
259 }
boliucafb1bf2015-12-29 01:40:19260 ScopedSendZeroMemory send_zero_memory(this);
boliuf6d263e2015-11-25 03:53:58261 if (!success)
262 return false;
263
264 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51265 UpdateFrameMetaData(std::move(frame->metadata));
boliuf6d263e2015-11-25 03:53:58266
267 SkBitmap bitmap;
boliucafb1bf2015-12-29 01:40:19268 if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
boliuf6d263e2015-11-25 03:53:58269 return false;
270
271 {
272 TRACE_EVENT0("browser", "DrawBitmap");
273 canvas->save();
274 canvas->resetMatrix();
275 canvas->drawBitmap(bitmap, 0, 0);
276 canvas->restore();
277 }
278
279 return true;
boliubee541f42015-11-05 00:52:53280}
281
boliucafb1bf2015-12-29 01:40:19282void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
283 size_t stride,
284 size_t buffer_size) {
285 if (software_draw_shm_ && software_draw_shm_->stride == stride &&
286 software_draw_shm_->buffer_size == buffer_size)
287 return;
288 software_draw_shm_.reset();
dcheng59716272016-04-09 05:19:08289 std::unique_ptr<SharedMemoryWithSize> software_draw_shm(
boliucafb1bf2015-12-29 01:40:19290 new SharedMemoryWithSize(stride, buffer_size));
291 {
292 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
293 if (!software_draw_shm->shm.CreateAndMapAnonymous(buffer_size))
294 return;
295 }
296
297 SyncCompositorSetSharedMemoryParams set_shm_params;
298 set_shm_params.buffer_size = buffer_size;
299 base::ProcessHandle renderer_process_handle =
300 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
301 if (!software_draw_shm->shm.ShareToProcess(renderer_process_handle,
302 &set_shm_params.shm_handle)) {
303 return;
304 }
305
boliucafb1bf2015-12-29 01:40:19306 bool success = false;
307 SyncCompositorCommonRendererParams common_renderer_params;
308 if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
boliu8f3016e2016-06-04 00:59:18309 routing_id_, set_shm_params, &success, &common_renderer_params)) ||
boliucafb1bf2015-12-29 01:40:19310 !success) {
311 return;
312 }
313 software_draw_shm_ = std::move(software_draw_shm);
314 ProcessCommonParams(common_renderer_params);
315}
316
317void SynchronousCompositorHost::SendZeroMemory() {
318 // No need to check return value.
319 sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
320}
321
boliubee541f42015-11-05 00:52:53322void SynchronousCompositorHost::ReturnResources(
boliuf4e574852016-03-22 19:33:17323 uint32_t output_surface_id,
fsamuelb62b78222016-07-15 01:14:14324 const cc::ReturnedResourceArray& resources) {
325 DCHECK(!resources.empty());
boliuec72a2ed2016-05-10 00:51:56326 sender_->Send(new SyncCompositorMsg_ReclaimResources(
fsamuelb62b78222016-07-15 01:14:14327 routing_id_, output_surface_id, resources));
boliubee541f42015-11-05 00:52:53328}
329
330void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
331 if (bytes_limit_ == bytes_limit)
332 return;
boliu42e01312016-05-12 21:47:52333
334 if (sender_->Send(
335 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit))) {
336 bytes_limit_ = bytes_limit;
337 }
boliubee541f42015-11-05 00:52:53338}
339
340void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
341 const gfx::ScrollOffset& root_offset) {
342 if (root_scroll_offset_ == root_offset)
343 return;
boliubee541f42015-11-05 00:52:53344 root_scroll_offset_ = root_offset;
boliu22cdc6d2016-05-13 19:43:09345 sender_->Send(
346 new SyncCompositorMsg_SetScroll(routing_id_, root_scroll_offset_));
hush92bd35e72015-11-13 22:57:37347}
348
boliu21d8ab142016-04-07 23:33:52349void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
350 const gfx::Point& anchor) {
boliu21d8ab142016-04-07 23:33:52351 SyncCompositorCommonRendererParams common_renderer_params;
352 if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
boliu8f3016e2016-06-04 00:59:18353 routing_id_, zoom_delta, anchor, &common_renderer_params))) {
boliu21d8ab142016-04-07 23:33:52354 return;
355 }
356 ProcessCommonParams(common_renderer_params);
357}
358
boliubee541f42015-11-05 00:52:53359void SynchronousCompositorHost::OnComputeScroll(
360 base::TimeTicks animation_time) {
361 if (!need_animate_scroll_)
362 return;
363 need_animate_scroll_ = false;
364
boliubee541f42015-11-05 00:52:53365 SyncCompositorCommonRendererParams common_renderer_params;
boliu8f3016e2016-06-04 00:59:18366 sender_->Send(
367 new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
boliubee541f42015-11-05 00:52:53368}
369
boliude5b75b2016-03-11 07:02:14370void SynchronousCompositorHost::DidOverscroll(
chongza8ba91fc2016-08-16 21:39:17371 const ui::DidOverscrollParams& over_scroll_params) {
hush83e367c2016-06-18 02:37:54372 client_->DidOverscroll(this, over_scroll_params.accumulated_overscroll,
boliude5b75b2016-03-11 07:02:14373 over_scroll_params.latest_overscroll_delta,
374 over_scroll_params.current_fling_velocity);
375}
376
boliu3dd3ca72016-07-29 00:18:37377void SynchronousCompositorHost::DidSendBeginFrame(
378 ui::WindowAndroid* window_android) {
379 rph_observer_->SyncStateAfterVSync(window_android, this);
boliubee541f42015-11-05 00:52:53380}
381
boliu42e01312016-05-12 21:47:52382void SynchronousCompositorHost::OutputSurfaceCreated() {
383 // New output surface is not aware of state from Browser side. So need to
384 // re-send all browser side state here.
385 sender_->Send(
386 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit_));
387}
388
boliubee541f42015-11-05 00:52:53389void SynchronousCompositorHost::ProcessCommonParams(
390 const SyncCompositorCommonRendererParams& params) {
391 // Ignore if |renderer_param_version_| is newer than |params.version|. This
392 // comparison takes into account when the unsigned int wraps.
393 if ((renderer_param_version_ - params.version) < 0x80000000) {
394 return;
395 }
396 renderer_param_version_ = params.version;
397 need_animate_scroll_ = params.need_animate_scroll;
boliubee541f42015-11-05 00:52:53398 root_scroll_offset_ = params.total_scroll_offset;
399
boliu17bc31f2016-02-23 18:46:28400 if (need_invalidate_count_ != params.need_invalidate_count) {
401 need_invalidate_count_ = params.need_invalidate_count;
hush83e367c2016-06-18 02:37:54402 client_->PostInvalidate(this);
boliubee541f42015-11-05 00:52:53403 }
404
boliu17bc31f2016-02-23 18:46:28405 if (did_activate_pending_tree_count_ !=
406 params.did_activate_pending_tree_count) {
407 did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
hush83e367c2016-06-18 02:37:54408 client_->DidUpdateContent(this);
boliubee541f42015-11-05 00:52:53409 }
410
411 // Ensure only valid values from compositor are sent to client.
412 // Compositor has page_scale_factor set to 0 before initialization, so check
413 // for that case here.
414 if (params.page_scale_factor) {
415 client_->UpdateRootLayerState(
hush83e367c2016-06-18 02:37:54416 this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
boliubee541f42015-11-05 00:52:53417 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
418 params.scrollable_size, params.page_scale_factor,
419 params.min_page_scale_factor, params.max_page_scale_factor);
420 }
421}
422
boliubee541f42015-11-05 00:52:53423} // namespace content