blob: b3fbe01ebf45ff7bc95b4634d2f654afe35fa5c3 [file] [log] [blame]
[email protected]23063762014-02-26 01:01:561// Copyright 2014 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 "android_webview/browser/browser_view_renderer.h"
6
[email protected]e4a0b192014-02-27 01:47:057#include "android_webview/browser/browser_view_renderer_client.h"
boliub887d3272015-03-19 00:29:268#include "android_webview/browser/child_frame.h"
[email protected]23063762014-02-26 01:01:569#include "base/auto_reset.h"
[email protected]7d67302a2014-05-03 02:17:0710#include "base/command_line.h"
[email protected]23063762014-02-26 01:01:5611#include "base/logging.h"
[email protected]7d67302a2014-05-03 02:17:0712#include "base/strings/string_number_conversions.h"
[email protected]23063762014-02-26 01:01:5613#include "base/strings/stringprintf.h"
hush7d13f842015-02-26 18:32:0714#include "base/supports_user_data.h"
ssid3bc4c0ee2015-01-27 14:21:2615#include "base/trace_event/trace_event_argument.h"
[email protected]8705654b2014-05-24 01:16:1916#include "cc/output/compositor_frame.h"
hush7d13f842015-02-26 18:32:0717#include "content/public/browser/web_contents.h"
[email protected]7d67302a2014-05-03 02:17:0718#include "content/public/common/content_switches.h"
boliu6be0a9122014-08-29 18:59:1019#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]23063762014-02-26 01:01:5620#include "third_party/skia/include/core/SkBitmap.h"
[email protected]23063762014-02-26 01:01:5621#include "third_party/skia/include/core/SkCanvas.h"
22#include "third_party/skia/include/core/SkPicture.h"
[email protected]1dfaaff2014-04-30 14:54:5923#include "third_party/skia/include/core/SkPictureRecorder.h"
tfarina6d5dba562014-10-24 03:48:1424#include "ui/gfx/geometry/vector2d_conversions.h"
[email protected]23063762014-02-26 01:01:5625
[email protected]23063762014-02-26 01:01:5626namespace android_webview {
27
28namespace {
29
boliud9d957b2014-12-17 17:24:0330const double kEpsilon = 1e-8;
31
[email protected]691ac7a2014-06-27 19:09:4932const int64 kFallbackTickTimeoutInMilliseconds = 100;
[email protected]23063762014-02-26 01:01:5633
[email protected]7d67302a2014-05-03 02:17:0734// Used to calculate memory allocation. Determined experimentally.
[email protected]14f7a8b2014-07-03 03:44:5135const size_t kMemoryMultiplier = 20;
[email protected]7d67302a2014-05-03 02:17:0736const size_t kBytesPerPixel = 4;
37const size_t kMemoryAllocationStep = 5 * 1024 * 1024;
boliu6be0a9122014-08-29 18:59:1038uint64 g_memory_override_in_bytes = 0u;
[email protected]7d67302a2014-05-03 02:17:0739
hush7d13f842015-02-26 18:32:0740const void* kBrowserViewRendererUserDataKey = &kBrowserViewRendererUserDataKey;
41
42class BrowserViewRendererUserData : public base::SupportsUserData::Data {
43 public:
44 BrowserViewRendererUserData(BrowserViewRenderer* ptr) : bvr_(ptr) {}
45
46 static BrowserViewRenderer* GetBrowserViewRenderer(
47 content::WebContents* web_contents) {
48 if (!web_contents)
49 return NULL;
50 BrowserViewRendererUserData* data =
51 static_cast<BrowserViewRendererUserData*>(
52 web_contents->GetUserData(kBrowserViewRendererUserDataKey));
53 return data ? data->bvr_ : NULL;
54 }
55
56 private:
57 BrowserViewRenderer* bvr_;
58};
59
[email protected]23063762014-02-26 01:01:5660} // namespace
61
[email protected]7d67302a2014-05-03 02:17:0762// static
revemanec103f02014-09-29 19:12:3163void BrowserViewRenderer::CalculateTileMemoryPolicy() {
pgal.u-szeged929d45a92014-10-28 11:50:4164 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
boliu6be0a9122014-08-29 18:59:1065
66 // If the value was overridden on the command line, use the specified value.
67 bool client_hard_limit_bytes_overridden =
68 cl->HasSwitch(switches::kForceGpuMemAvailableMb);
69 if (client_hard_limit_bytes_overridden) {
70 base::StringToUint64(
71 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
72 switches::kForceGpuMemAvailableMb),
73 &g_memory_override_in_bytes);
74 g_memory_override_in_bytes *= 1024 * 1024;
75 }
[email protected]7d67302a2014-05-03 02:17:0776}
77
hush7d13f842015-02-26 18:32:0778// static
79BrowserViewRenderer* BrowserViewRenderer::FromWebContents(
80 content::WebContents* web_contents) {
81 return BrowserViewRendererUserData::GetBrowserViewRenderer(web_contents);
82}
83
[email protected]e4a0b192014-02-27 01:47:0584BrowserViewRenderer::BrowserViewRenderer(
85 BrowserViewRendererClient* client,
[email protected]596f7e72014-03-21 20:03:2686 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
[email protected]23063762014-02-26 01:01:5687 : client_(client),
hush619ac5b4a2014-10-24 23:51:2788 shared_renderer_state_(ui_task_runner, this),
[email protected]596f7e72014-03-21 20:03:2689 ui_task_runner_(ui_task_runner),
[email protected]7a461432014-06-17 23:50:1290 compositor_(NULL),
[email protected]23063762014-02-26 01:01:5691 is_paused_(false),
92 view_visible_(false),
93 window_visible_(false),
94 attached_to_window_(false),
[email protected]8705654b2014-05-24 01:16:1995 hardware_enabled_(false),
[email protected]23063762014-02-26 01:01:5696 dip_scale_(0.0),
97 page_scale_factor_(1.0),
98 on_new_picture_enable_(false),
99 clear_view_(false),
hushd00f10452015-02-25 22:11:10100 offscreen_pre_raster_(false),
boliu04aa64d2014-11-12 00:31:08101 fallback_tick_pending_(false) {
[email protected]23063762014-02-26 01:01:56102}
103
104BrowserViewRenderer::~BrowserViewRenderer() {
[email protected]7d67302a2014-05-03 02:17:07105}
106
hush7d13f842015-02-26 18:32:07107void BrowserViewRenderer::RegisterWithWebContents(
108 content::WebContents* web_contents) {
109 web_contents->SetUserData(kBrowserViewRendererUserDataKey,
110 new BrowserViewRendererUserData(this));
111}
112
boliu6a7f8262014-12-09 00:31:28113SharedRendererState* BrowserViewRenderer::GetAwDrawGLViewContext() {
114 return &shared_renderer_state_;
hush619ac5b4a2014-10-24 23:51:27115}
116
boliu22c75322014-10-25 02:06:47117bool BrowserViewRenderer::RequestDrawGL(bool wait_for_completion) {
118 return client_->RequestDrawGL(wait_for_completion);
hush619ac5b4a2014-10-24 23:51:27119}
120
[email protected]7d67302a2014-05-03 02:17:07121void BrowserViewRenderer::TrimMemory(const int level, const bool visible) {
boliua3434da2014-10-14 01:31:15122 DCHECK(ui_task_runner_->BelongsToCurrentThread());
[email protected]7d67302a2014-05-03 02:17:07123 // Constants from Android ComponentCallbacks2.
124 enum {
125 TRIM_MEMORY_RUNNING_LOW = 10,
126 TRIM_MEMORY_UI_HIDDEN = 20,
127 TRIM_MEMORY_BACKGROUND = 40,
boliua3d41bdc2014-11-07 22:34:49128 TRIM_MEMORY_MODERATE = 60,
[email protected]7d67302a2014-05-03 02:17:07129 };
130
131 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because
132 // it does not indicate memory pressure, but merely that the app is
133 // backgrounded.
134 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN)
135 return;
136
137 // Do not release resources on view we expect to get DrawGL soon.
138 if (level < TRIM_MEMORY_BACKGROUND && visible)
139 return;
140
boliu77de0212014-10-28 04:06:33141 // Nothing to drop.
142 if (!compositor_ || !hardware_enabled_)
[email protected]7d67302a2014-05-03 02:17:07143 return;
144
145 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
146
hush6ef62052015-04-16 04:46:35147 // If offscreen pre-raster is disabled, drop everything in hardware. Otherwise
148 // keep the tiles and just delete the HardwareRenderer.
boliua3d41bdc2014-11-07 22:34:49149 if (level >= TRIM_MEMORY_MODERATE) {
hush6ef62052015-04-16 04:46:35150 if (offscreen_pre_raster_)
151 shared_renderer_state_.DeleteHardwareRendererOnUI();
152 else
153 shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI();
boliua3d41bdc2014-11-07 22:34:49154 return;
155 }
156
boliu77de0212014-10-28 04:06:33157 // Just set the memory limit to 0 and drop all tiles. This will be reset to
158 // normal levels in the next DrawGL call.
hush6ef62052015-04-16 04:46:35159 if (!offscreen_pre_raster_)
160 compositor_->SetMemoryPolicy(0u);
[email protected]7d67302a2014-05-03 02:17:07161}
162
hush6ef62052015-04-16 04:46:35163void BrowserViewRenderer::UpdateMemoryPolicy() {
164 if (!hardware_enabled_) {
165 compositor_->SetMemoryPolicy(0u);
166 return;
167 }
boliu77de0212014-10-28 04:06:33168
hush6ef62052015-04-16 04:46:35169 size_t bytes_limit = 0u;
170 if (g_memory_override_in_bytes) {
171 bytes_limit = static_cast<size_t>(g_memory_override_in_bytes);
172 } else {
173 gfx::Rect interest_rect = offscreen_pre_raster_
174 ? gfx::Rect(size_)
175 : last_on_draw_global_visible_rect_;
176 size_t width = interest_rect.width();
177 size_t height = interest_rect.height();
178 bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height;
179 // Round up to a multiple of kMemoryAllocationStep.
180 bytes_limit =
181 (bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep;
182 }
183
184 compositor_->SetMemoryPolicy(bytes_limit);
[email protected]23063762014-02-26 01:01:56185}
186
boliu04aa64d2014-11-12 00:31:08187void BrowserViewRenderer::PrepareToDraw(const gfx::Vector2d& scroll,
188 const gfx::Rect& global_visible_rect) {
[email protected]8705654b2014-05-24 01:16:19189 last_on_draw_scroll_offset_ = scroll;
190 last_on_draw_global_visible_rect_ = global_visible_rect;
[email protected]23063762014-02-26 01:01:56191}
192
boliu83cbc8412015-01-14 03:16:59193bool BrowserViewRenderer::CanOnDraw() {
boliue2f869862014-12-03 21:13:48194 if (!compositor_) {
195 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_NoCompositor",
196 TRACE_EVENT_SCOPE_THREAD);
[email protected]8705654b2014-05-24 01:16:19197 return false;
boliue2f869862014-12-03 21:13:48198 }
boliu83cbc8412015-01-14 03:16:59199 if (clear_view_) {
200 TRACE_EVENT_INSTANT0("android_webview", "EarlyOut_ClearView",
201 TRACE_EVENT_SCOPE_THREAD);
202 return false;
203 }
204
205 return true;
206}
207
208bool BrowserViewRenderer::OnDrawHardware() {
209 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware");
sunnypseab5ac92015-04-02 20:26:13210
boliu83cbc8412015-01-14 03:16:59211 shared_renderer_state_.InitializeHardwareDrawIfNeededOnUI();
212
213 if (!CanOnDraw()) {
214 return false;
215 }
[email protected]8705654b2014-05-24 01:16:19216
hush619ac5b4a2014-10-24 23:51:27217 shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_);
boliu4d7902e2015-04-10 20:36:59218 hardware_enabled_ = true;
[email protected]8705654b2014-05-24 01:16:19219
boliub887d3272015-03-19 00:29:26220 return CompositeHw();
boliu96ba1a62014-10-16 02:29:52221}
222
boliub887d3272015-03-19 00:29:26223bool BrowserViewRenderer::CompositeHw() {
sunnypseab5ac92015-04-02 20:26:13224 CancelFallbackTick();
225
boliub887d3272015-03-19 00:29:26226 ReturnResourceFromParent();
hush6ef62052015-04-16 04:46:35227 UpdateMemoryPolicy();
boliu96ba1a62014-10-16 02:29:52228
boliub887d3272015-03-19 00:29:26229 ParentCompositorDrawConstraints parent_draw_constraints =
hush619ac5b4a2014-10-24 23:51:27230 shared_renderer_state_.GetParentDrawConstraintsOnUI();
boliu04aa64d2014-11-12 00:31:08231 gfx::Size surface_size(size_);
[email protected]8705654b2014-05-24 01:16:19232 gfx::Rect viewport(surface_size);
[email protected]8705654b2014-05-24 01:16:19233 gfx::Rect clip = viewport;
[email protected]bd5324592014-07-31 09:09:33234 gfx::Transform transform_for_tile_priority =
boliub887d3272015-03-19 00:29:26235 parent_draw_constraints.transform;
[email protected]bd5324592014-07-31 09:09:33236
237 // If the WebView is on a layer, WebView does not know what transform is
238 // applied onto the layer so global visible rect does not make sense here.
239 // In this case, just use the surface rect for tiling.
240 gfx::Rect viewport_rect_for_tile_priority;
hushd00f10452015-02-25 22:11:10241
242 // Leave viewport_rect_for_tile_priority empty if offscreen_pre_raster_ is on.
243 if (!offscreen_pre_raster_) {
boliub887d3272015-03-19 00:29:26244 if (parent_draw_constraints.is_layer) {
245 viewport_rect_for_tile_priority = parent_draw_constraints.surface_rect;
hushd00f10452015-02-25 22:11:10246 } else {
247 viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
248 }
boliu6b96a042014-10-21 23:23:57249 }
[email protected]bd5324592014-07-31 09:09:33250
251 scoped_ptr<cc::CompositorFrame> frame =
252 compositor_->DemandDrawHw(surface_size,
253 gfx::Transform(),
254 viewport,
255 clip,
256 viewport_rect_for_tile_priority,
257 transform_for_tile_priority);
boliub887d3272015-03-19 00:29:26258 if (!frame.get()) {
259 TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
260 TRACE_EVENT_SCOPE_THREAD);
261 return false;
262 }
263
264 scoped_ptr<ChildFrame> child_frame = make_scoped_ptr(
265 new ChildFrame(frame.Pass(), viewport_rect_for_tile_priority,
266 transform_for_tile_priority, offscreen_pre_raster_,
267 parent_draw_constraints.is_layer));
268
boliub887d3272015-03-19 00:29:26269 // Uncommitted frame can happen with consecutive fallback ticks.
270 ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
271 shared_renderer_state_.SetCompositorFrameOnUI(child_frame.Pass());
272 return true;
[email protected]8705654b2014-05-24 01:16:19273}
274
[email protected]bd5324592014-07-31 09:09:33275void BrowserViewRenderer::UpdateParentDrawConstraints() {
sunnypseab5ac92015-04-02 20:26:13276 PostInvalidateWithFallback();
hushabaade82015-03-20 02:09:29277 ParentCompositorDrawConstraints parent_draw_constraints =
278 shared_renderer_state_.GetParentDrawConstraintsOnUI();
279 client_->ParentDrawConstraintsUpdated(parent_draw_constraints);
[email protected]bd5324592014-07-31 09:09:33280}
281
boliu6439a532014-10-07 06:00:01282void BrowserViewRenderer::ReturnUnusedResource(
boliub887d3272015-03-19 00:29:26283 scoped_ptr<ChildFrame> child_frame) {
284 if (!child_frame.get() || !child_frame->frame.get())
[email protected]8705654b2014-05-24 01:16:19285 return;
[email protected]c62fc982014-06-27 04:49:02286
287 cc::CompositorFrameAck frame_ack;
288 cc::TransferableResource::ReturnResources(
boliub887d3272015-03-19 00:29:26289 child_frame->frame->delegated_frame_data->resource_list,
290 &frame_ack.resources);
boliu105144f2014-10-20 17:54:36291 if (compositor_ && !frame_ack.resources.empty())
[email protected]c62fc982014-06-27 04:49:02292 compositor_->ReturnResources(frame_ack);
[email protected]8705654b2014-05-24 01:16:19293}
294
[email protected]c62fc982014-06-27 04:49:02295void BrowserViewRenderer::ReturnResourceFromParent() {
[email protected]8705654b2014-05-24 01:16:19296 cc::CompositorFrameAck frame_ack;
hush619ac5b4a2014-10-24 23:51:27297 shared_renderer_state_.SwapReturnedResourcesOnUI(&frame_ack.resources);
boliu105144f2014-10-20 17:54:36298 if (compositor_ && !frame_ack.resources.empty()) {
[email protected]7a461432014-06-17 23:50:12299 compositor_->ReturnResources(frame_ack);
[email protected]8705654b2014-05-24 01:16:19300 }
[email protected]23063762014-02-26 01:01:56301}
302
tobiasjs125f6e72015-02-18 17:34:28303void BrowserViewRenderer::DetachFunctorFromView() {
304 client_->DetachFunctorFromView();
hushc4a6fc022014-10-30 01:34:14305}
306
boliu04aa64d2014-11-12 00:31:08307bool BrowserViewRenderer::OnDrawSoftware(SkCanvas* canvas) {
boliu83cbc8412015-01-14 03:16:59308 return CanOnDraw() && CompositeSW(canvas);
[email protected]23063762014-02-26 01:01:56309}
310
311skia::RefPtr<SkPicture> BrowserViewRenderer::CapturePicture(int width,
312 int height) {
313 TRACE_EVENT0("android_webview", "BrowserViewRenderer::CapturePicture");
314
315 // Return empty Picture objects for empty SkPictures.
[email protected]23063762014-02-26 01:01:56316 if (width <= 0 || height <= 0) {
[email protected]c7bd0542014-07-14 18:22:04317 SkPictureRecorder emptyRecorder;
318 emptyRecorder.beginRecording(0, 0);
319 return skia::AdoptRef(emptyRecorder.endRecording());
[email protected]23063762014-02-26 01:01:56320 }
321
322 // Reset scroll back to the origin, will go back to the old
323 // value when scroll_reset is out of scope.
[email protected]7a461432014-06-17 23:50:12324 base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
325 gfx::Vector2dF());
[email protected]23063762014-02-26 01:01:56326
[email protected]1dfaaff2014-04-30 14:54:59327 SkPictureRecorder recorder;
328 SkCanvas* rec_canvas = recorder.beginRecording(width, height, NULL, 0);
[email protected]7a461432014-06-17 23:50:12329 if (compositor_)
[email protected]23063762014-02-26 01:01:56330 CompositeSW(rec_canvas);
[email protected]1dfaaff2014-04-30 14:54:59331 return skia::AdoptRef(recorder.endRecording());
[email protected]23063762014-02-26 01:01:56332}
333
334void BrowserViewRenderer::EnableOnNewPicture(bool enabled) {
335 on_new_picture_enable_ = enabled;
[email protected]23063762014-02-26 01:01:56336}
337
338void BrowserViewRenderer::ClearView() {
339 TRACE_EVENT_INSTANT0("android_webview",
340 "BrowserViewRenderer::ClearView",
341 TRACE_EVENT_SCOPE_THREAD);
342 if (clear_view_)
343 return;
344
345 clear_view_ = true;
346 // Always invalidate ignoring the compositor to actually clear the webview.
sunnypseab5ac92015-04-02 20:26:13347 PostInvalidateWithFallback();
[email protected]23063762014-02-26 01:01:56348}
349
hushd00f10452015-02-25 22:11:10350void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) {
hush6ef62052015-04-16 04:46:35351 if (offscreen_pre_raster_ != enable && compositor_)
352 UpdateMemoryPolicy();
353
hushd00f10452015-02-25 22:11:10354 offscreen_pre_raster_ = enable;
355}
356
[email protected]23063762014-02-26 01:01:56357void BrowserViewRenderer::SetIsPaused(bool paused) {
358 TRACE_EVENT_INSTANT1("android_webview",
359 "BrowserViewRenderer::SetIsPaused",
360 TRACE_EVENT_SCOPE_THREAD,
361 "paused",
362 paused);
363 is_paused_ = paused;
sunnypseab5ac92015-04-02 20:26:13364 UpdateCompositorIsActive();
[email protected]23063762014-02-26 01:01:56365}
366
367void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
368 TRACE_EVENT_INSTANT1("android_webview",
369 "BrowserViewRenderer::SetViewVisibility",
370 TRACE_EVENT_SCOPE_THREAD,
371 "view_visible",
372 view_visible);
373 view_visible_ = view_visible;
374}
375
376void BrowserViewRenderer::SetWindowVisibility(bool window_visible) {
377 TRACE_EVENT_INSTANT1("android_webview",
378 "BrowserViewRenderer::SetWindowVisibility",
379 TRACE_EVENT_SCOPE_THREAD,
380 "window_visible",
381 window_visible);
382 window_visible_ = window_visible;
sunnypseab5ac92015-04-02 20:26:13383 UpdateCompositorIsActive();
[email protected]23063762014-02-26 01:01:56384}
385
386void BrowserViewRenderer::OnSizeChanged(int width, int height) {
387 TRACE_EVENT_INSTANT2("android_webview",
388 "BrowserViewRenderer::OnSizeChanged",
389 TRACE_EVENT_SCOPE_THREAD,
390 "width",
391 width,
392 "height",
393 height);
boliu04aa64d2014-11-12 00:31:08394 size_.SetSize(width, height);
[email protected]23063762014-02-26 01:01:56395}
396
397void BrowserViewRenderer::OnAttachedToWindow(int width, int height) {
398 TRACE_EVENT2("android_webview",
399 "BrowserViewRenderer::OnAttachedToWindow",
400 "width",
401 width,
402 "height",
403 height);
404 attached_to_window_ = true;
boliu04aa64d2014-11-12 00:31:08405 size_.SetSize(width, height);
sunnypseab5ac92015-04-02 20:26:13406 UpdateCompositorIsActive();
[email protected]23063762014-02-26 01:01:56407}
408
409void BrowserViewRenderer::OnDetachedFromWindow() {
410 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDetachedFromWindow");
boliua3d41bdc2014-11-07 22:34:49411 shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI();
[email protected]23063762014-02-26 01:01:56412 attached_to_window_ = false;
[email protected]686474c72014-07-22 02:09:50413 DCHECK(!hardware_enabled_);
sunnypseab5ac92015-04-02 20:26:13414 UpdateCompositorIsActive();
[email protected]686474c72014-07-22 02:09:50415}
[email protected]8705654b2014-05-24 01:16:19416
[email protected]686474c72014-07-22 02:09:50417void BrowserViewRenderer::ReleaseHardware() {
418 DCHECK(hardware_enabled_);
hushc4a6fc022014-10-30 01:34:14419 ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
[email protected]686474c72014-07-22 02:09:50420 ReturnResourceFromParent();
hushc4a6fc022014-10-30 01:34:14421 DCHECK(shared_renderer_state_.ReturnedResourcesEmptyOnUI());
[email protected]686474c72014-07-22 02:09:50422
boliu105144f2014-10-20 17:54:36423 if (compositor_) {
boliu4d7902e2015-04-10 20:36:59424 compositor_->SetMemoryPolicy(0u);
boliu105144f2014-10-20 17:54:36425 }
[email protected]686474c72014-07-22 02:09:50426
boliu105144f2014-10-20 17:54:36427 hardware_enabled_ = false;
[email protected]23063762014-02-26 01:01:56428}
429
[email protected]23063762014-02-26 01:01:56430bool BrowserViewRenderer::IsVisible() const {
431 // Ignore |window_visible_| if |attached_to_window_| is false.
432 return view_visible_ && (!attached_to_window_ || window_visible_);
433}
434
435gfx::Rect BrowserViewRenderer::GetScreenRect() const {
boliu04aa64d2014-11-12 00:31:08436 return gfx::Rect(client_->GetLocationOnScreen(), size_);
[email protected]23063762014-02-26 01:01:56437}
438
439void BrowserViewRenderer::DidInitializeCompositor(
440 content::SynchronousCompositor* compositor) {
441 TRACE_EVENT0("android_webview",
442 "BrowserViewRenderer::DidInitializeCompositor");
[email protected]e4a0b192014-02-27 01:47:05443 DCHECK(compositor);
[email protected]7a461432014-06-17 23:50:12444 DCHECK(!compositor_);
445 compositor_ = compositor;
sunnypseab5ac92015-04-02 20:26:13446 UpdateCompositorIsActive();
[email protected]23063762014-02-26 01:01:56447}
448
449void BrowserViewRenderer::DidDestroyCompositor(
450 content::SynchronousCompositor* compositor) {
451 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
[email protected]7a461432014-06-17 23:50:12452 DCHECK(compositor_);
sunnyps0e3d7212015-06-02 03:09:22453 compositor_->SetIsActive(false);
boliu105144f2014-10-20 17:54:36454 compositor_ = NULL;
[email protected]23063762014-02-26 01:01:56455}
456
[email protected]23063762014-02-26 01:01:56457void BrowserViewRenderer::SetDipScale(float dip_scale) {
458 dip_scale_ = dip_scale;
boliud9d957b2014-12-17 17:24:03459 CHECK_GT(dip_scale_, 0.f);
[email protected]23063762014-02-26 01:01:56460}
461
462gfx::Vector2d BrowserViewRenderer::max_scroll_offset() const {
boliud9d957b2014-12-17 17:24:03463 DCHECK_GT(dip_scale_, 0.f);
[email protected]23063762014-02-26 01:01:56464 return gfx::ToCeiledVector2d(gfx::ScaleVector2d(
465 max_scroll_offset_dip_, dip_scale_ * page_scale_factor_));
466}
467
468void BrowserViewRenderer::ScrollTo(gfx::Vector2d scroll_offset) {
469 gfx::Vector2d max_offset = max_scroll_offset();
470 gfx::Vector2dF scroll_offset_dip;
471 // To preserve the invariant that scrolling to the maximum physical pixel
472 // value also scrolls to the maximum dip pixel value we transform the physical
473 // offset into the dip offset by using a proportion (instead of dividing by
474 // dip_scale * page_scale_factor).
475 if (max_offset.x()) {
476 scroll_offset_dip.set_x((scroll_offset.x() * max_scroll_offset_dip_.x()) /
477 max_offset.x());
478 }
479 if (max_offset.y()) {
480 scroll_offset_dip.set_y((scroll_offset.y() * max_scroll_offset_dip_.y()) /
481 max_offset.y());
482 }
483
boliud9d957b2014-12-17 17:24:03484 DCHECK_LE(0.f, scroll_offset_dip.x());
485 DCHECK_LE(0.f, scroll_offset_dip.y());
486 DCHECK(scroll_offset_dip.x() < max_scroll_offset_dip_.x() ||
487 scroll_offset_dip.x() - max_scroll_offset_dip_.x() < kEpsilon)
488 << scroll_offset_dip.x() << " " << max_scroll_offset_dip_.x();
489 DCHECK(scroll_offset_dip.y() < max_scroll_offset_dip_.y() ||
490 scroll_offset_dip.y() - max_scroll_offset_dip_.y() < kEpsilon)
491 << scroll_offset_dip.y() << " " << max_scroll_offset_dip_.y();
[email protected]23063762014-02-26 01:01:56492
[email protected]7a461432014-06-17 23:50:12493 if (scroll_offset_dip_ == scroll_offset_dip)
494 return;
[email protected]23063762014-02-26 01:01:56495
[email protected]7a461432014-06-17 23:50:12496 scroll_offset_dip_ = scroll_offset_dip;
[email protected]23063762014-02-26 01:01:56497
[email protected]ec2322e2014-05-15 16:32:00498 TRACE_EVENT_INSTANT2("android_webview",
499 "BrowserViewRenderer::ScrollTo",
500 TRACE_EVENT_SCOPE_THREAD,
501 "x",
502 scroll_offset_dip.x(),
503 "y",
504 scroll_offset_dip.y());
505
[email protected]7a461432014-06-17 23:50:12506 if (compositor_)
507 compositor_->DidChangeRootLayerScrollOffset();
[email protected]23063762014-02-26 01:01:56508}
509
510void BrowserViewRenderer::DidUpdateContent() {
511 TRACE_EVENT_INSTANT0("android_webview",
512 "BrowserViewRenderer::DidUpdateContent",
513 TRACE_EVENT_SCOPE_THREAD);
514 clear_view_ = false;
[email protected]23063762014-02-26 01:01:56515 if (on_new_picture_enable_)
516 client_->OnNewPicture();
517}
518
[email protected]23063762014-02-26 01:01:56519void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
520 gfx::Vector2dF scroll_offset_dip) {
[email protected]7a461432014-06-17 23:50:12521 // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
522 // DrawGl when http://crbug.com/249972 is fixed.
523 if (scroll_offset_dip_ == scroll_offset_dip)
524 return;
[email protected]23063762014-02-26 01:01:56525
[email protected]7a461432014-06-17 23:50:12526 scroll_offset_dip_ = scroll_offset_dip;
[email protected]23063762014-02-26 01:01:56527
528 gfx::Vector2d max_offset = max_scroll_offset();
529 gfx::Vector2d scroll_offset;
530 // For an explanation as to why this is done this way see the comment in
531 // BrowserViewRenderer::ScrollTo.
532 if (max_scroll_offset_dip_.x()) {
533 scroll_offset.set_x((scroll_offset_dip.x() * max_offset.x()) /
534 max_scroll_offset_dip_.x());
535 }
536
537 if (max_scroll_offset_dip_.y()) {
538 scroll_offset.set_y((scroll_offset_dip.y() * max_offset.y()) /
539 max_scroll_offset_dip_.y());
540 }
541
boliu2d46b522014-08-29 22:33:44542 DCHECK_LE(0, scroll_offset.x());
543 DCHECK_LE(0, scroll_offset.y());
544 DCHECK_LE(scroll_offset.x(), max_offset.x());
545 DCHECK_LE(scroll_offset.y(), max_offset.y());
[email protected]23063762014-02-26 01:01:56546
547 client_->ScrollContainerViewTo(scroll_offset);
548}
549
550gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
551 return scroll_offset_dip_;
552}
553
554bool BrowserViewRenderer::IsExternalFlingActive() const {
555 return client_->IsFlingActive();
556}
557
[email protected]ec2322e2014-05-15 16:32:00558void BrowserViewRenderer::UpdateRootLayerState(
559 const gfx::Vector2dF& total_scroll_offset_dip,
560 const gfx::Vector2dF& max_scroll_offset_dip,
561 const gfx::SizeF& scrollable_size_dip,
[email protected]23063762014-02-26 01:01:56562 float page_scale_factor,
563 float min_page_scale_factor,
564 float max_page_scale_factor) {
[email protected]ec2322e2014-05-15 16:32:00565 TRACE_EVENT_INSTANT1(
566 "android_webview",
567 "BrowserViewRenderer::UpdateRootLayerState",
568 TRACE_EVENT_SCOPE_THREAD,
569 "state",
boliua3434da2014-10-14 01:31:15570 RootLayerStateAsValue(total_scroll_offset_dip, scrollable_size_dip));
[email protected]ec2322e2014-05-15 16:32:00571
boliud9d957b2014-12-17 17:24:03572 DCHECK_GT(dip_scale_, 0.f);
[email protected]ec2322e2014-05-15 16:32:00573
574 max_scroll_offset_dip_ = max_scroll_offset_dip;
boliud9d957b2014-12-17 17:24:03575 DCHECK_LE(0.f, max_scroll_offset_dip_.x());
576 DCHECK_LE(0.f, max_scroll_offset_dip_.y());
[email protected]ec2322e2014-05-15 16:32:00577
[email protected]23063762014-02-26 01:01:56578 page_scale_factor_ = page_scale_factor;
boliud9d957b2014-12-17 17:24:03579 DCHECK_GT(page_scale_factor_, 0.f);
[email protected]ec2322e2014-05-15 16:32:00580
581 client_->UpdateScrollState(max_scroll_offset(),
582 scrollable_size_dip,
583 page_scale_factor,
584 min_page_scale_factor,
585 max_page_scale_factor);
586 SetTotalRootLayerScrollOffset(total_scroll_offset_dip);
[email protected]23063762014-02-26 01:01:56587}
588
ssid759dd8c2015-02-09 21:25:39589scoped_refptr<base::trace_event::ConvertableToTraceFormat>
boliua3434da2014-10-14 01:31:15590BrowserViewRenderer::RootLayerStateAsValue(
[email protected]ec2322e2014-05-15 16:32:00591 const gfx::Vector2dF& total_scroll_offset_dip,
592 const gfx::SizeF& scrollable_size_dip) {
ssid759dd8c2015-02-09 21:25:39593 scoped_refptr<base::trace_event::TracedValue> state =
594 new base::trace_event::TracedValue();
[email protected]ec2322e2014-05-15 16:32:00595
596 state->SetDouble("total_scroll_offset_dip.x", total_scroll_offset_dip.x());
597 state->SetDouble("total_scroll_offset_dip.y", total_scroll_offset_dip.y());
598
599 state->SetDouble("max_scroll_offset_dip.x", max_scroll_offset_dip_.x());
600 state->SetDouble("max_scroll_offset_dip.y", max_scroll_offset_dip_.y());
601
602 state->SetDouble("scrollable_size_dip.width", scrollable_size_dip.width());
603 state->SetDouble("scrollable_size_dip.height", scrollable_size_dip.height());
604
605 state->SetDouble("page_scale_factor", page_scale_factor_);
boliua3434da2014-10-14 01:31:15606 return state;
[email protected]23063762014-02-26 01:01:56607}
608
609void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
610 gfx::Vector2dF latest_overscroll_delta,
611 gfx::Vector2dF current_fling_velocity) {
612 const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
613 if (accumulated_overscroll == latest_overscroll_delta)
614 overscroll_rounding_error_ = gfx::Vector2dF();
615 gfx::Vector2dF scaled_overscroll_delta =
616 gfx::ScaleVector2d(latest_overscroll_delta, physical_pixel_scale);
617 gfx::Vector2d rounded_overscroll_delta = gfx::ToRoundedVector2d(
618 scaled_overscroll_delta + overscroll_rounding_error_);
619 overscroll_rounding_error_ =
620 scaled_overscroll_delta - rounded_overscroll_delta;
621 client_->DidOverscroll(rounded_overscroll_delta);
622}
623
sunnypseab5ac92015-04-02 20:26:13624void BrowserViewRenderer::PostInvalidate() {
625 TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate",
626 TRACE_EVENT_SCOPE_THREAD);
627 PostInvalidateWithFallback();
628}
[email protected]23063762014-02-26 01:01:56629
sunnypseab5ac92015-04-02 20:26:13630void BrowserViewRenderer::PostInvalidateWithFallback() {
[email protected]23063762014-02-26 01:01:56631 // Always call view invalidate. We rely the Android framework to ignore the
632 // invalidate when it's not needed such as when view is not visible.
[email protected]e4a0b192014-02-27 01:47:05633 client_->PostInvalidate();
[email protected]23063762014-02-26 01:01:56634
635 // Stop fallback ticks when one of these is true.
636 // 1) Webview is paused. Also need to check we are not in clear view since
637 // paused, offscreen still expect clear view to recover.
638 // 2) If we are attached to window and the window is not visible (eg when
639 // app is in the background). We are sure in this case the webview is used
640 // "on-screen" but that updates are not needed when in the background.
641 bool throttle_fallback_tick =
642 (is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
sunnypseab5ac92015-04-02 20:26:13643
644 if (throttle_fallback_tick || fallback_tick_pending_)
[email protected]23063762014-02-26 01:01:56645 return;
646
sunnypseab5ac92015-04-02 20:26:13647 DCHECK(post_fallback_tick_.IsCancelled());
648 DCHECK(fallback_tick_fired_.IsCancelled());
[email protected]23063762014-02-26 01:01:56649
[email protected]691ac7a2014-06-27 19:09:49650 post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick,
651 base::Unretained(this)));
sunnypseab5ac92015-04-02 20:26:13652 ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback());
653 fallback_tick_pending_ = true;
654}
655
656void BrowserViewRenderer::CancelFallbackTick() {
657 post_fallback_tick_.Cancel();
[email protected]691ac7a2014-06-27 19:09:49658 fallback_tick_fired_.Cancel();
boliu4aa98dc62014-10-07 04:35:38659 fallback_tick_pending_ = false;
[email protected]691ac7a2014-06-27 19:09:49660}
661
662void BrowserViewRenderer::PostFallbackTick() {
663 DCHECK(fallback_tick_fired_.IsCancelled());
sunnypseab5ac92015-04-02 20:26:13664 TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick");
665 post_fallback_tick_.Cancel();
[email protected]691ac7a2014-06-27 19:09:49666 fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
667 base::Unretained(this)));
sunnypseab5ac92015-04-02 20:26:13668 ui_task_runner_->PostDelayedTask(
669 FROM_HERE, fallback_tick_fired_.callback(),
670 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
[email protected]23063762014-02-26 01:01:56671}
672
673void BrowserViewRenderer::FallbackTickFired() {
sunnypseab5ac92015-04-02 20:26:13674 TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired");
[email protected]23063762014-02-26 01:01:56675 // This should only be called if OnDraw or DrawGL did not come in time, which
sunnypseab5ac92015-04-02 20:26:13676 // means fallback_tick_pending_ must still be true.
677 DCHECK(fallback_tick_pending_);
678 fallback_tick_fired_.Cancel();
boliu4aa98dc62014-10-07 04:35:38679 fallback_tick_pending_ = false;
sunnypseab5ac92015-04-02 20:26:13680 if (compositor_) {
boliu96ba1a62014-10-16 02:29:52681 if (hardware_enabled_) {
boliub887d3272015-03-19 00:29:26682 CompositeHw();
boliu96ba1a62014-10-16 02:29:52683 } else {
684 ForceFakeCompositeSW();
685 }
boliud3ba7202014-08-29 00:00:38686 }
[email protected]23063762014-02-26 01:01:56687}
688
689void BrowserViewRenderer::ForceFakeCompositeSW() {
[email protected]7a461432014-06-17 23:50:12690 DCHECK(compositor_);
[email protected]e758a2372014-03-05 20:21:52691 SkBitmap bitmap;
692 bitmap.allocN32Pixels(1, 1);
693 bitmap.eraseColor(0);
694 SkCanvas canvas(bitmap);
[email protected]23063762014-02-26 01:01:56695 CompositeSW(&canvas);
696}
697
698bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
[email protected]7a461432014-06-17 23:50:12699 DCHECK(compositor_);
sunnypseab5ac92015-04-02 20:26:13700 CancelFallbackTick();
[email protected]c62fc982014-06-27 04:49:02701 ReturnResourceFromParent();
sunnypseab5ac92015-04-02 20:26:13702 return compositor_->DemandDrawSw(canvas);
[email protected]220e908a2014-03-05 06:23:04703}
704
sunnypseab5ac92015-04-02 20:26:13705void BrowserViewRenderer::UpdateCompositorIsActive() {
706 if (compositor_)
707 compositor_->SetIsActive(!is_paused_ &&
708 (!attached_to_window_ || window_visible_));
[email protected]23063762014-02-26 01:01:56709}
710
boliua3434da2014-10-14 01:31:15711std::string BrowserViewRenderer::ToString() const {
[email protected]23063762014-02-26 01:01:56712 std::string str;
713 base::StringAppendF(&str, "is_paused: %d ", is_paused_);
714 base::StringAppendF(&str, "view_visible: %d ", view_visible_);
715 base::StringAppendF(&str, "window_visible: %d ", window_visible_);
716 base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
717 base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
sunnypseab5ac92015-04-02 20:26:13718 base::StringAppendF(&str, "fallback_tick_pending: %d ",
719 fallback_tick_pending_);
boliu04aa64d2014-11-12 00:31:08720 base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str());
[email protected]23063762014-02-26 01:01:56721 base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
722 base::StringAppendF(&str,
723 "global visible rect: %s ",
[email protected]8705654b2014-05-24 01:16:19724 last_on_draw_global_visible_rect_.ToString().c_str());
[email protected]23063762014-02-26 01:01:56725 base::StringAppendF(
726 &str, "scroll_offset_dip: %s ", scroll_offset_dip_.ToString().c_str());
727 base::StringAppendF(&str,
728 "overscroll_rounding_error_: %s ",
729 overscroll_rounding_error_.ToString().c_str());
730 base::StringAppendF(
731 &str, "on_new_picture_enable: %d ", on_new_picture_enable_);
732 base::StringAppendF(&str, "clear_view: %d ", clear_view_);
[email protected]23063762014-02-26 01:01:56733 return str;
734}
735
736} // namespace android_webview