blob: 85191d028a1931f3c9c0b2d2cf236f0e018348ee [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
7#include "base/containers/hash_tables.h"
boliuf6d263e2015-11-25 03:53:588#include "base/memory/shared_memory.h"
9#include "base/trace_event/trace_event_argument.h"
boliubee541f42015-11-05 00:52:5310#include "cc/output/compositor_frame_ack.h"
11#include "content/browser/renderer_host/render_widget_host_view_android.h"
12#include "content/browser/web_contents/web_contents_impl.h"
13#include "content/common/android/sync_compositor_messages.h"
14#include "content/public/browser/android/synchronous_compositor_client.h"
hush92bd35e72015-11-13 22:57:3715#include "content/public/browser/browser_thread.h"
boliubee541f42015-11-05 00:52:5316#include "content/public/browser/render_view_host.h"
17#include "ipc/ipc_sender.h"
boliuf6d263e2015-11-25 03:53:5818#include "third_party/skia/include/core/SkBitmap.h"
19#include "third_party/skia/include/core/SkCanvas.h"
20#include "third_party/skia/include/core/SkImageInfo.h"
21#include "third_party/skia/include/core/SkRect.h"
22#include "ui/gfx/skia_util.h"
boliubee541f42015-11-05 00:52:5323
24namespace content {
25
26SynchronousCompositorHost::SynchronousCompositorHost(
27 RenderWidgetHostViewAndroid* rwhva,
28 SynchronousCompositorClient* client)
29 : rwhva_(rwhva),
30 client_(client),
hush92bd35e72015-11-13 22:57:3731 ui_task_runner_(
32 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
boliubee541f42015-11-05 00:52:5333 routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
34 sender_(rwhva_->GetRenderWidgetHost()),
35 is_active_(false),
36 bytes_limit_(0u),
37 renderer_param_version_(0u),
38 need_animate_scroll_(false),
39 need_invalidate_(false),
40 need_begin_frame_(false),
hush92bd35e72015-11-13 22:57:3741 did_activate_pending_tree_(false),
42 weak_ptr_factory_(this) {
boliubee541f42015-11-05 00:52:5343 client_->DidInitializeCompositor(this);
44}
45
46SynchronousCompositorHost::~SynchronousCompositorHost() {
47 client_->DidDestroyCompositor(this);
48}
49
50bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
51 bool handled = true;
52 IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
53 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, ProcessCommonParams)
boliu09be0e62015-11-11 00:57:0054 IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_OverScroll, OnOverScroll)
boliubee541f42015-11-05 00:52:5355 IPC_MESSAGE_UNHANDLED(handled = false)
56 IPC_END_MESSAGE_MAP()
57 return handled;
58}
59
60scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
61 const gfx::Size& surface_size,
62 const gfx::Transform& transform,
63 const gfx::Rect& viewport,
64 const gfx::Rect& clip,
65 const gfx::Rect& viewport_rect_for_tile_priority,
66 const gfx::Transform& transform_for_tile_priority) {
67 SyncCompositorDemandDrawHwParams params(surface_size, transform, viewport,
68 clip, viewport_rect_for_tile_priority,
69 transform_for_tile_priority);
70 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
71 SyncCompositorCommonBrowserParams common_browser_params;
72 PopulateCommonParams(&common_browser_params);
73 SyncCompositorCommonRendererParams common_renderer_params;
74 if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
75 routing_id_, common_browser_params, params, &common_renderer_params,
76 frame.get()))) {
77 return nullptr;
78 }
79 ProcessCommonParams(common_renderer_params);
80 if (!frame->delegated_frame_data) {
81 // This can happen if compositor did not swap in this draw.
82 frame.reset();
83 }
84 if (frame)
85 UpdateFrameMetaData(frame->metadata);
86 return frame;
87}
88
89void SynchronousCompositorHost::UpdateFrameMetaData(
90 const cc::CompositorFrameMetadata& frame_metadata) {
91 rwhva_->SynchronousFrameMetadata(frame_metadata);
92}
93
94bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
boliuf6d263e2015-11-25 03:53:5895 SyncCompositorDemandDrawSwParams params;
96 params.size = gfx::Size(canvas->getBaseLayerSize().width(),
97 canvas->getBaseLayerSize().height());
98 SkIRect canvas_clip;
99 canvas->getClipDeviceBounds(&canvas_clip);
100 params.clip = gfx::SkIRectToRect(canvas_clip);
101 params.transform.matrix() = canvas->getTotalMatrix();
102 if (params.size.IsEmpty())
103 return true;
104
105 SkImageInfo info =
106 SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
107 DCHECK_EQ(kRGBA_8888_SkColorType, info.colorType());
108 size_t stride = info.minRowBytes();
109 size_t buffer_size = info.getSafeSize(stride);
110 if (!buffer_size)
111 return false; // Overflow.
112
113 base::SharedMemory shm;
114 {
115 TRACE_EVENT1("browser", "AllocateSharedMemory", "buffer_size", buffer_size);
116 if (!shm.CreateAndMapAnonymous(buffer_size))
117 return false;
118 }
119 base::ProcessHandle renderer_process_handle =
120 rwhva_->GetRenderWidgetHost()->GetProcess()->GetHandle();
121 if (!shm.ShareToProcess(renderer_process_handle, &params.shm_handle))
122 return false;
123
124 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
125 SyncCompositorCommonBrowserParams common_browser_params;
126 PopulateCommonParams(&common_browser_params);
127 SyncCompositorCommonRendererParams common_renderer_params;
128 bool success = false;
129 if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
130 routing_id_, common_browser_params, params, &success,
131 &common_renderer_params, frame.get()))) {
132 return false;
133 }
134 if (!success)
135 return false;
136
137 ProcessCommonParams(common_renderer_params);
138 UpdateFrameMetaData(frame->metadata);
139
140 SkBitmap bitmap;
141 if (!bitmap.installPixels(info, shm.memory(), stride))
142 return false;
143
144 {
145 TRACE_EVENT0("browser", "DrawBitmap");
146 canvas->save();
147 canvas->resetMatrix();
148 canvas->drawBitmap(bitmap, 0, 0);
149 canvas->restore();
150 }
151
152 return true;
boliubee541f42015-11-05 00:52:53153}
154
155void SynchronousCompositorHost::ReturnResources(
156 const cc::CompositorFrameAck& frame_ack) {
157 returned_resources_.insert(returned_resources_.end(),
158 frame_ack.resources.begin(),
159 frame_ack.resources.end());
160}
161
162void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
163 if (bytes_limit_ == bytes_limit)
164 return;
165 bytes_limit_ = bytes_limit;
hush92bd35e72015-11-13 22:57:37166 SendAsyncCompositorStateIfNeeded();
boliubee541f42015-11-05 00:52:53167}
168
169void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
170 const gfx::ScrollOffset& root_offset) {
171 if (root_scroll_offset_ == root_offset)
172 return;
173 root_scroll_offset_ = root_offset;
hush92bd35e72015-11-13 22:57:37174 SendAsyncCompositorStateIfNeeded();
175}
176
177void SynchronousCompositorHost::SendAsyncCompositorStateIfNeeded() {
178 if (weak_ptr_factory_.HasWeakPtrs())
179 return;
180
181 ui_task_runner_->PostTask(
182 FROM_HERE, base::Bind(&SynchronousCompositorHost::UpdateStateTask,
183 weak_ptr_factory_.GetWeakPtr()));
184}
185
186void SynchronousCompositorHost::UpdateStateTask() {
187 SyncCompositorCommonBrowserParams common_browser_params;
188 PopulateCommonParams(&common_browser_params);
189 sender_->Send(
190 new SyncCompositorMsg_UpdateState(routing_id_, common_browser_params));
191 DCHECK(!weak_ptr_factory_.HasWeakPtrs());
boliubee541f42015-11-05 00:52:53192}
193
194void SynchronousCompositorHost::SetIsActive(bool is_active) {
195 is_active_ = is_active;
196 UpdateNeedsBeginFrames();
197}
198
199void SynchronousCompositorHost::OnComputeScroll(
200 base::TimeTicks animation_time) {
201 if (!need_animate_scroll_)
202 return;
203 need_animate_scroll_ = false;
204
205 SyncCompositorCommonBrowserParams common_browser_params;
206 PopulateCommonParams(&common_browser_params);
207 SyncCompositorCommonRendererParams common_renderer_params;
208 if (!sender_->Send(new SyncCompositorMsg_ComputeScroll(
209 routing_id_, common_browser_params, animation_time,
210 &common_renderer_params))) {
211 return;
212 }
213 ProcessCommonParams(common_renderer_params);
214}
215
216InputEventAckState SynchronousCompositorHost::HandleInputEvent(
217 const blink::WebInputEvent& input_event) {
218 SyncCompositorCommonBrowserParams common_browser_params;
219 PopulateCommonParams(&common_browser_params);
220 SyncCompositorCommonRendererParams common_renderer_params;
221 InputEventAckState ack = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
222 if (!sender_->Send(new SyncCompositorMsg_HandleInputEvent(
223 routing_id_, common_browser_params, &input_event,
224 &common_renderer_params, &ack))) {
225 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
226 }
227 ProcessCommonParams(common_renderer_params);
228 return ack;
229}
230
231void SynchronousCompositorHost::BeginFrame(const cc::BeginFrameArgs& args) {
232 if (!is_active_ || !need_begin_frame_)
233 return;
234
235 SyncCompositorCommonBrowserParams common_browser_params;
236 PopulateCommonParams(&common_browser_params);
237 SyncCompositorCommonRendererParams common_renderer_params;
238 if (!sender_->Send(
239 new SyncCompositorMsg_BeginFrame(routing_id_, common_browser_params,
240 args, &common_renderer_params))) {
241 return;
242 }
243 ProcessCommonParams(common_renderer_params);
244}
245
boliu09be0e62015-11-11 00:57:00246void SynchronousCompositorHost::OnOverScroll(
247 const SyncCompositorCommonRendererParams& params,
248 const DidOverscrollParams& over_scroll_params) {
249 ProcessCommonParams(params);
250 client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
251 over_scroll_params.latest_overscroll_delta,
252 over_scroll_params.current_fling_velocity);
253}
254
boliubee541f42015-11-05 00:52:53255void SynchronousCompositorHost::PopulateCommonParams(
256 SyncCompositorCommonBrowserParams* params) {
257 DCHECK(params);
258 DCHECK(params->ack.resources.empty());
259 params->bytes_limit = bytes_limit_;
260 params->root_scroll_offset = root_scroll_offset_;
261 params->ack.resources.swap(returned_resources_);
hush92bd35e72015-11-13 22:57:37262 weak_ptr_factory_.InvalidateWeakPtrs();
boliubee541f42015-11-05 00:52:53263}
264
265void SynchronousCompositorHost::ProcessCommonParams(
266 const SyncCompositorCommonRendererParams& params) {
267 // Ignore if |renderer_param_version_| is newer than |params.version|. This
268 // comparison takes into account when the unsigned int wraps.
269 if ((renderer_param_version_ - params.version) < 0x80000000) {
270 return;
271 }
272 renderer_param_version_ = params.version;
273 need_animate_scroll_ = params.need_animate_scroll;
274 if (need_begin_frame_ != params.need_begin_frame) {
275 need_begin_frame_ = params.need_begin_frame;
276 UpdateNeedsBeginFrames();
277 }
278 need_invalidate_ = need_invalidate_ || params.need_invalidate;
279 did_activate_pending_tree_ =
280 did_activate_pending_tree_ || params.did_activate_pending_tree;
281 root_scroll_offset_ = params.total_scroll_offset;
282
283 if (need_invalidate_) {
284 need_invalidate_ = false;
285 client_->PostInvalidate();
286 }
287
288 if (did_activate_pending_tree_) {
289 did_activate_pending_tree_ = false;
290 client_->DidUpdateContent();
291 }
292
293 // Ensure only valid values from compositor are sent to client.
294 // Compositor has page_scale_factor set to 0 before initialization, so check
295 // for that case here.
296 if (params.page_scale_factor) {
297 client_->UpdateRootLayerState(
298 gfx::ScrollOffsetToVector2dF(params.total_scroll_offset),
299 gfx::ScrollOffsetToVector2dF(params.max_scroll_offset),
300 params.scrollable_size, params.page_scale_factor,
301 params.min_page_scale_factor, params.max_page_scale_factor);
302 }
303}
304
305void SynchronousCompositorHost::UpdateNeedsBeginFrames() {
306 rwhva_->OnSetNeedsBeginFrames(is_active_ && need_begin_frame_);
307}
308
309} // namespace content