blob: faca49c3ed948ced19929a5e7c97b3f581750c65 [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"
29#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5330
31namespace content {
32
boliuc99f26c12016-04-21 21:58:5933// static
34void SynchronousCompositor::SetClientForWebContents(
35 WebContents* contents,
36 SynchronousCompositorClient* client) {
37 DCHECK(contents);
38 DCHECK(client);
39 WebContentsAndroid* web_contents_android =
40 static_cast<WebContentsImpl*>(contents)->GetWebContentsAndroid();
41 DCHECK(!web_contents_android->synchronous_compositor_client());
42 web_contents_android->set_synchronous_compositor_client(client);
43}
44
45// static
46std::unique_ptr<SynchronousCompositorHost> SynchronousCompositorHost::Create(
47 RenderWidgetHostViewAndroid* rwhva,
48 WebContents* web_contents) {
49 DCHECK(web_contents);
50 WebContentsAndroid* web_contents_android =
51 static_cast<WebContentsImpl*>(web_contents)->GetWebContentsAndroid();
52 if (!web_contents_android->synchronous_compositor_client())
53 return nullptr; // Not using sync compositing.
54
55 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
boliuc99f26c12016-04-21 21:58:5956 bool use_in_proc_software_draw =
57 command_line->HasSwitch(switches::kSingleProcess);
58 return base::WrapUnique(new SynchronousCompositorHost(
boliub2768db2016-06-03 23:35:1659 rwhva, web_contents_android->synchronous_compositor_client(),
boliuc99f26c12016-04-21 21:58:5960 use_in_proc_software_draw));
61}
62
boliubee541f42015-11-05 00:52:5363SynchronousCompositorHost::SynchronousCompositorHost(
64 RenderWidgetHostViewAndroid* rwhva,
boliu4d4b5a82016-02-17 01:55:2165 SynchronousCompositorClient* client,
boliu4d4b5a82016-02-17 01:55:2166 bool use_in_proc_software_draw)
boliubee541f42015-11-05 00:52:5367 : rwhva_(rwhva),
68 client_(client),
thestig529ad8a2016-07-08 20:30:1269 ui_task_runner_(BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)),
hush284add62016-06-17 20:47:3370 process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
boliubee541f42015-11-05 00:52:5371 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
boliu3dd3ca72016-07-29 00:18:3772 rph_observer_(SynchronousCompositorObserver::GetOrCreateFor(process_id_)),
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),
boliubee541f42015-11-05 00:52:5376 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_);
boliubee541f42015-11-05 00:52:5385}
86
87bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
88 bool handled = true;
89 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
boliu42e01312016-05-12 21:47:5290 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OutputSurfaceCreated,
91 OutputSurfaceCreated)
boliubee541f42015-11-05 00:52:5392 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
boliubee541f42015-11-05 00:52:5393 IPC_MESSAGE_UNHANDLED(handled = false)
94 IPC_END_MESSAGE_MAP()
95 return handled;
96}
97
boliuf4e574852016-03-22 19:33:1798SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
boliu31c233ed2016-07-29 05:38:5999 const gfx::Size& viewport_size,
boliubee541f42015-11-05 00:52:53100 const gfx::Rect& viewport_rect_for_tile_priority,
101 const gfx::Transform& transform_for_tile_priority) {
boliu31c233ed2016-07-29 05:38:59102 SyncCompositorDemandDrawHwParams params(viewport_size,
103 viewport_rect_for_tile_priority,
boliubee541f42015-11-05 00:52:53104 transform_for_tile_priority);
boliuf4e574852016-03-22 19:33:17105 SynchronousCompositor::Frame frame;
106 frame.frame.reset(new cc::CompositorFrame);
boliubee541f42015-11-05 00:52:53107 SyncCompositorCommonRendererParams common_renderer_params;
108 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
boliu8f3016e2016-06-04 00:59:18109 routing_id_, params, &common_renderer_params,
boliuf4e574852016-03-22 19:33:17110 &frame.output_surface_id, frame.frame.get()))) {
111 return SynchronousCompositor::Frame();
boliubee541f42015-11-05 00:52:53112 }
113 ProcessCommonParams(common_renderer_params);
boliuf4e574852016-03-22 19:33:17114 if (!frame.frame->delegated_frame_data) {
boliubee541f42015-11-05 00:52:53115 // This can happen if compositor did not swap in this draw.
boliuf4e574852016-03-22 19:33:17116 frame.frame.reset();
boliubee541f42015-11-05 00:52:53117 }
boliuf4e574852016-03-22 19:33:17118 if (frame.frame) {
fsamueld63137a2016-06-24 23:39:51119 UpdateFrameMetaData(frame.frame->metadata.Clone());
boliuf4e574852016-03-22 19:33:17120 }
boliubee541f42015-11-05 00:52:53121 return frame;
122}
123
124void SynchronousCompositorHost::UpdateFrameMetaData(
fsamueld63137a2016-06-24 23:39:51125 cc::CompositorFrameMetadata frame_metadata) {
126 rwhva_->SynchronousFrameMetadata(std::move(frame_metadata));
boliubee541f42015-11-05 00:52:53127}
128
boliu4d4b5a82016-02-17 01:55:21129namespace {
130
131class ScopedSetSkCanvas {
132 public:
133 explicit ScopedSetSkCanvas(SkCanvas* canvas) {
134 SynchronousCompositorSetSkCanvas(canvas);
135 }
136
137 ~ScopedSetSkCanvas() {
138 SynchronousCompositorSetSkCanvas(nullptr);
139 }
140
141 private:
142 DISALLOW_COPY_AND_ASSIGN(ScopedSetSkCanvas);
143};
144
145}
146
147bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21148 SyncCompositorCommonRendererParams common_renderer_params;
149 bool success = false;
dcheng59716272016-04-09 05:19:08150 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliu4d4b5a82016-02-17 01:55:21151 ScopedSetSkCanvas set_sk_canvas(canvas);
152 SyncCompositorDemandDrawSwParams params; // Unused.
153 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18154 routing_id_, params, &success, &common_renderer_params,
155 frame.get()))) {
boliu4d4b5a82016-02-17 01:55:21156 return false;
157 }
158 if (!success)
159 return false;
160 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51161 UpdateFrameMetaData(std::move(frame->metadata));
boliu4d4b5a82016-02-17 01:55:21162 return true;
163}
164
boliucafb1bf2015-12-29 01:40:19165class SynchronousCompositorHost::ScopedSendZeroMemory {
166 public:
167 ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
168 ~ScopedSendZeroMemory() { host_->SendZeroMemory(); }
169
170 private:
171 SynchronousCompositorHost* const host_;
172
173 DISALLOW_COPY_AND_ASSIGN(ScopedSendZeroMemory);
174};
175
176struct SynchronousCompositorHost::SharedMemoryWithSize {
177 base::SharedMemory shm;
178 const size_t stride;
179 const size_t buffer_size;
180
181 SharedMemoryWithSize(size_t stride, size_t buffer_size)
182 : stride(stride), buffer_size(buffer_size) {}
183
184 private:
185 DISALLOW_COPY_AND_ASSIGN(SharedMemoryWithSize);
186};
187
boliubee541f42015-11-05 00:52:53188bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliu4d4b5a82016-02-17 01:55:21189 if (use_in_process_zero_copy_software_draw_)
190 return DemandDrawSwInProc(canvas);
191
boliuf6d263e2015-11-25 03:53:58192 SyncCompositorDemandDrawSwParams params;
193 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
194 canvas->getBaseLayerSize().height());
195 SkIRect canvas_clip;
196 canvas->getClipDeviceBounds(&canvas_clip);
197 params.clip = gfx::SkIRectToRect(canvas_clip);
198 params.transform.matrix() = canvas->getTotalMatrix();
199 if (params.size.IsEmpty())
200 return true;
201
202 SkImageInfo info =
203 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
204 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
205 size_t stride = info.minRowBytes();
206 size_t buffer_size = info.getSafeSize(stride);
207 if (!buffer_size)
208 return false; // Overflow.
209
boliucafb1bf2015-12-29 01:40:19210 SetSoftwareDrawSharedMemoryIfNeeded(stride, buffer_size);
211 if (!software_draw_shm_)
boliuf6d263e2015-11-25 03:53:58212 return false;
213
dcheng59716272016-04-09 05:19:08214 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
boliuf6d263e2015-11-25 03:53:58215 SyncCompositorCommonRendererParams common_renderer_params;
216 bool success = false;
217 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
boliu8f3016e2016-06-04 00:59:18218 routing_id_, params, &success, &common_renderer_params,
219 frame.get()))) {
boliuf6d263e2015-11-25 03:53:58220 return false;
221 }
boliucafb1bf2015-12-29 01:40:19222 ScopedSendZeroMemory send_zero_memory(this);
boliuf6d263e2015-11-25 03:53:58223 if (!success)
224 return false;
225
226 ProcessCommonParams(common_renderer_params);
fsamueld63137a2016-06-24 23:39:51227 UpdateFrameMetaData(std::move(frame->metadata));
boliuf6d263e2015-11-25 03:53:58228
229 SkBitmap bitmap;
boliucafb1bf2015-12-29 01:40:19230 if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
boliuf6d263e2015-11-25 03:53:58231 return false;
232
233 {
234 TRACE_EVENT0("browser", "DrawBitmap");
235 canvas->save();
236 canvas->resetMatrix();
237 canvas->drawBitmap(bitmap, 0, 0);
238 canvas->restore();
239 }
240
241 return true;
boliubee541f42015-11-05 00:52:53242}
243
boliucafb1bf2015-12-29 01:40:19244void SynchronousCompositorHost::SetSoftwareDrawSharedMemoryIfNeeded(
245 size_t stride,
246 size_t buffer_size) {
247 if (software_draw_shm_ && software_draw_shm_->stride == stride &&
248 software_draw_shm_->buffer_size == buffer_size)
249 return;
250 software_draw_shm_.reset();
dcheng59716272016-04-09 05:19:08251 std::unique_ptr<SharedMemoryWithSize> software_draw_shm(
boliucafb1bf2015-12-29 01:40:19252 new SharedMemoryWithSize(stride, buffer_size));
253 {
254 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
255 if (!software_draw_shm->shm.CreateAndMapAnonymous(buffer_size))
256 return;
257 }
258
259 SyncCompositorSetSharedMemoryParams set_shm_params;
260 set_shm_params.buffer_size = buffer_size;
261 base::ProcessHandle renderer_process_handle =
262 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
263 if (!software_draw_shm->shm.ShareToProcess(renderer_process_handle,
264 &set_shm_params.shm_handle)) {
265 return;
266 }
267
boliucafb1bf2015-12-29 01:40:19268 bool success = false;
269 SyncCompositorCommonRendererParams common_renderer_params;
270 if (!sender_->Send(new SyncCompositorMsg_SetSharedMemory(
boliu8f3016e2016-06-04 00:59:18271 routing_id_, set_shm_params, &success, &common_renderer_params)) ||
boliucafb1bf2015-12-29 01:40:19272 !success) {
273 return;
274 }
275 software_draw_shm_ = std::move(software_draw_shm);
276 ProcessCommonParams(common_renderer_params);
277}
278
279void SynchronousCompositorHost::SendZeroMemory() {
280 // No need to check return value.
281 sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
282}
283
boliubee541f42015-11-05 00:52:53284void SynchronousCompositorHost::ReturnResources(
boliuf4e574852016-03-22 19:33:17285 uint32_t output_surface_id,
fsamuelb62b78222016-07-15 01:14:14286 const cc::ReturnedResourceArray& resources) {
287 DCHECK(!resources.empty());
boliuec72a2ed2016-05-10 00:51:56288 sender_->Send(new SyncCompositorMsg_ReclaimResources(
fsamuelb62b78222016-07-15 01:14:14289 routing_id_, output_surface_id, resources));
boliubee541f42015-11-05 00:52:53290}
291
292void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
293 if (bytes_limit_ == bytes_limit)
294 return;
boliu42e01312016-05-12 21:47:52295
296 if (sender_->Send(
297 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit))) {
298 bytes_limit_ = bytes_limit;
299 }
boliubee541f42015-11-05 00:52:53300}
301
302void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
303 const gfx::ScrollOffset& root_offset) {
304 if (root_scroll_offset_ == root_offset)
305 return;
boliubee541f42015-11-05 00:52:53306 root_scroll_offset_ = root_offset;
boliu22cdc6d2016-05-13 19:43:09307 sender_->Send(
308 new SyncCompositorMsg_SetScroll(routing_id_, root_scroll_offset_));
hush92bd35e72015-11-13 22:57:37309}
310
boliu21d8ab142016-04-07 23:33:52311void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
312 const gfx::Point& anchor) {
boliu21d8ab142016-04-07 23:33:52313 SyncCompositorCommonRendererParams common_renderer_params;
314 if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
boliu8f3016e2016-06-04 00:59:18315 routing_id_, zoom_delta, anchor, &common_renderer_params))) {
boliu21d8ab142016-04-07 23:33:52316 return;
317 }
318 ProcessCommonParams(common_renderer_params);
319}
320
boliubee541f42015-11-05 00:52:53321void SynchronousCompositorHost::OnComputeScroll(
322 base::TimeTicks animation_time) {
323 if (!need_animate_scroll_)
324 return;
325 need_animate_scroll_ = false;
326
boliubee541f42015-11-05 00:52:53327 SyncCompositorCommonRendererParams common_renderer_params;
boliu8f3016e2016-06-04 00:59:18328 sender_->Send(
329 new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
boliubee541f42015-11-05 00:52:53330}
331
boliude5b75b2016-03-11 07:02:14332void SynchronousCompositorHost::DidOverscroll(
333 const DidOverscrollParams& over_scroll_params) {
hush83e367c2016-06-18 02:37:54334 client_->DidOverscroll(this, over_scroll_params.accumulated_overscroll,
boliude5b75b2016-03-11 07:02:14335 over_scroll_params.latest_overscroll_delta,
336 over_scroll_params.current_fling_velocity);
337}
338
boliu3dd3ca72016-07-29 00:18:37339void SynchronousCompositorHost::DidSendBeginFrame(
340 ui::WindowAndroid* window_android) {
341 rph_observer_->SyncStateAfterVSync(window_android, this);
boliubee541f42015-11-05 00:52:53342}
343
boliu42e01312016-05-12 21:47:52344void SynchronousCompositorHost::OutputSurfaceCreated() {
345 // New output surface is not aware of state from Browser side. So need to
346 // re-send all browser side state here.
347 sender_->Send(
348 new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit_));
349}
350
boliubee541f42015-11-05 00:52:53351void SynchronousCompositorHost::ProcessCommonParams(
352 const SyncCompositorCommonRendererParams& params) {
353 // Ignore if |renderer_param_version_| is newer than |params.version|. This
354 // comparison takes into account when the unsigned int wraps.
355 if ((renderer_param_version_ - params.version) < 0x80000000) {
356 return;
357 }
358 renderer_param_version_ = params.version;
359 need_animate_scroll_ = params.need_animate_scroll;
boliubee541f42015-11-05 00:52:53360 root_scroll_offset_ = params.total_scroll_offset;
361
boliu17bc31f2016-02-23 18:46:28362 if (need_invalidate_count_ != params.need_invalidate_count) {
363 need_invalidate_count_ = params.need_invalidate_count;
hush83e367c2016-06-18 02:37:54364 client_->PostInvalidate(this);
boliubee541f42015-11-05 00:52:53365 }
366
boliu17bc31f2016-02-23 18:46:28367 if (did_activate_pending_tree_count_ !=
368 params.did_activate_pending_tree_count) {
369 did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
hush83e367c2016-06-18 02:37:54370 client_->DidUpdateContent(this);
boliubee541f42015-11-05 00:52:53371 }
372
373 // Ensure only valid values from compositor are sent to client.
374 // Compositor has page_scale_factor set to 0 before initialization, so check
375 // for that case here.
376 if (params.page_scale_factor) {
377 client_->UpdateRootLayerState(
hush83e367c2016-06-18 02:37:54378 this, gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
boliubee541f42015-11-05 00:52:53379 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
380 params.scrollable_size, params.page_scale_factor,
381 params.min_page_scale_factor, params.max_page_scale_factor);
382 }
383}
384
boliubee541f42015-11-05 00:52:53385} // namespace content