Commit 3fd0c951 authored by tobiasjs's avatar tobiasjs Committed by Commit bot

Move fallback tick software draw.

Ideally we want to remove the fallback ticking of webview entirely, but
in the interim we should move it to the compositor thread in order to
avoid the sync IPC for the software draw as well as the shared memory
allocation.

BUG=431166

Review URL: https://codereview.chromium.org/1782093002

Cr-Commit-Position: refs/heads/master@{#381688}
parent 6b121e47
...@@ -32,8 +32,6 @@ namespace { ...@@ -32,8 +32,6 @@ namespace {
const double kEpsilon = 1e-8; const double kEpsilon = 1e-8;
const int64_t kFallbackTickTimeoutInMilliseconds = 100;
// Used to calculate memory allocation. Determined experimentally. // Used to calculate memory allocation. Determined experimentally.
const size_t kMemoryMultiplier = 20; const size_t kMemoryMultiplier = 20;
const size_t kBytesPerPixel = 4; const size_t kBytesPerPixel = 4;
...@@ -106,7 +104,6 @@ BrowserViewRenderer::BrowserViewRenderer( ...@@ -106,7 +104,6 @@ BrowserViewRenderer::BrowserViewRenderer(
on_new_picture_enable_(false), on_new_picture_enable_(false),
clear_view_(false), clear_view_(false),
offscreen_pre_raster_(false), offscreen_pre_raster_(false),
fallback_tick_pending_(false),
next_compositor_id_(1) {} next_compositor_id_(1) {}
BrowserViewRenderer::~BrowserViewRenderer() { BrowserViewRenderer::~BrowserViewRenderer() {
...@@ -232,12 +229,6 @@ bool BrowserViewRenderer::OnDrawHardware() { ...@@ -232,12 +229,6 @@ bool BrowserViewRenderer::OnDrawHardware() {
shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_); shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_);
hardware_enabled_ = true; hardware_enabled_ = true;
return CompositeHw();
}
bool BrowserViewRenderer::CompositeHw() {
CancelFallbackTick();
ReturnResourceFromParent(); ReturnResourceFromParent();
UpdateMemoryPolicy(); UpdateMemoryPolicy();
...@@ -277,14 +268,13 @@ bool BrowserViewRenderer::CompositeHw() { ...@@ -277,14 +268,13 @@ bool BrowserViewRenderer::CompositeHw() {
viewport_rect_for_tile_priority.IsEmpty(), transform_for_tile_priority, viewport_rect_for_tile_priority.IsEmpty(), transform_for_tile_priority,
offscreen_pre_raster_, parent_draw_constraints.is_layer)); offscreen_pre_raster_, parent_draw_constraints.is_layer));
// Uncommitted frame can happen with consecutive fallback ticks.
ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI()); ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI());
shared_renderer_state_.SetCompositorFrameOnUI(std::move(child_frame)); shared_renderer_state_.SetCompositorFrameOnUI(std::move(child_frame));
return true; return true;
} }
void BrowserViewRenderer::UpdateParentDrawConstraints() { void BrowserViewRenderer::UpdateParentDrawConstraints() {
PostInvalidateWithFallback(); PostInvalidate();
ParentCompositorDrawConstraints parent_draw_constraints = ParentCompositorDrawConstraints parent_draw_constraints =
shared_renderer_state_.GetParentDrawConstraintsOnUI(); shared_renderer_state_.GetParentDrawConstraintsOnUI();
client_->ParentDrawConstraintsUpdated(parent_draw_constraints); client_->ParentDrawConstraintsUpdated(parent_draw_constraints);
...@@ -367,7 +357,7 @@ void BrowserViewRenderer::ClearView() { ...@@ -367,7 +357,7 @@ void BrowserViewRenderer::ClearView() {
clear_view_ = true; clear_view_ = true;
// Always invalidate ignoring the compositor to actually clear the webview. // Always invalidate ignoring the compositor to actually clear the webview.
PostInvalidateWithFallback(); PostInvalidate();
} }
void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) { void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) {
...@@ -700,80 +690,11 @@ void BrowserViewRenderer::DidOverscroll( ...@@ -700,80 +690,11 @@ void BrowserViewRenderer::DidOverscroll(
void BrowserViewRenderer::PostInvalidate() { void BrowserViewRenderer::PostInvalidate() {
TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate", TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate",
TRACE_EVENT_SCOPE_THREAD); TRACE_EVENT_SCOPE_THREAD);
PostInvalidateWithFallback();
}
void BrowserViewRenderer::PostInvalidateWithFallback() {
// Always call view invalidate. We rely the Android framework to ignore the
// invalidate when it's not needed such as when view is not visible.
client_->PostInvalidate(); client_->PostInvalidate();
// Stop fallback ticks when one of these is true.
// 1) Webview is paused. Also need to check we are not in clear view since
// paused, offscreen still expect clear view to recover.
// 2) If we are attached to window and the window is not visible (eg when
// app is in the background). We are sure in this case the webview is used
// "on-screen" but that updates are not needed when in the background.
bool throttle_fallback_tick =
(is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_);
if (throttle_fallback_tick || fallback_tick_pending_)
return;
DCHECK(post_fallback_tick_.IsCancelled());
DCHECK(fallback_tick_fired_.IsCancelled());
post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick,
base::Unretained(this)));
ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback());
fallback_tick_pending_ = true;
}
void BrowserViewRenderer::CancelFallbackTick() {
post_fallback_tick_.Cancel();
fallback_tick_fired_.Cancel();
fallback_tick_pending_ = false;
}
void BrowserViewRenderer::PostFallbackTick() {
DCHECK(fallback_tick_fired_.IsCancelled());
TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick");
post_fallback_tick_.Cancel();
fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired,
base::Unretained(this)));
ui_task_runner_->PostDelayedTask(
FROM_HERE, fallback_tick_fired_.callback(),
base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
}
void BrowserViewRenderer::FallbackTickFired() {
TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired");
// This should only be called if OnDraw or DrawGL did not come in time, which
// means fallback_tick_pending_ must still be true.
DCHECK(fallback_tick_pending_);
fallback_tick_fired_.Cancel();
fallback_tick_pending_ = false;
if (compositor_) {
if (hardware_enabled_ && !size_.IsEmpty()) {
CompositeHw();
} else {
ForceFakeCompositeSW();
}
}
}
void BrowserViewRenderer::ForceFakeCompositeSW() {
DCHECK(compositor_);
SkBitmap bitmap;
bitmap.allocN32Pixels(1, 1);
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
CompositeSW(&canvas);
} }
bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) {
DCHECK(compositor_); DCHECK(compositor_);
CancelFallbackTick();
ReturnResourceFromParent(); ReturnResourceFromParent();
return compositor_->DemandDrawSw(canvas); return compositor_->DemandDrawSw(canvas);
} }
...@@ -792,8 +713,6 @@ std::string BrowserViewRenderer::ToString() const { ...@@ -792,8 +713,6 @@ std::string BrowserViewRenderer::ToString() const {
base::StringAppendF(&str, "window_visible: %d ", window_visible_); base::StringAppendF(&str, "window_visible: %d ", window_visible_);
base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); base::StringAppendF(&str, "dip_scale: %f ", dip_scale_);
base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_);
base::StringAppendF(&str, "fallback_tick_pending: %d ",
fallback_tick_pending_);
base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str()); base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str());
base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_);
base::StringAppendF(&str, base::StringAppendF(&str,
......
...@@ -126,33 +126,15 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { ...@@ -126,33 +126,15 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient {
private: private:
void SetTotalRootLayerScrollOffset(const gfx::Vector2dF& new_value_dip); void SetTotalRootLayerScrollOffset(const gfx::Vector2dF& new_value_dip);
bool CanOnDraw(); bool CanOnDraw();
// Posts an invalidate with fallback tick. All invalidates posted while an
// invalidate is pending will be posted as a single invalidate after the
// pending invalidate is done.
void PostInvalidateWithFallback();
void CancelFallbackTick();
void UpdateCompositorIsActive(); void UpdateCompositorIsActive();
bool CompositeSW(SkCanvas* canvas); bool CompositeSW(SkCanvas* canvas);
scoped_ptr<base::trace_event::ConvertableToTraceFormat> RootLayerStateAsValue( scoped_ptr<base::trace_event::ConvertableToTraceFormat> RootLayerStateAsValue(
const gfx::Vector2dF& total_scroll_offset_dip, const gfx::Vector2dF& total_scroll_offset_dip,
const gfx::SizeF& scrollable_size_dip); const gfx::SizeF& scrollable_size_dip);
bool CompositeHw();
void ReturnUnusedResource(scoped_ptr<ChildFrame> frame); void ReturnUnusedResource(scoped_ptr<ChildFrame> frame);
void ReturnResourceFromParent(); void ReturnResourceFromParent();
// If we call up view invalidate and OnDraw is not called before a deadline,
// then we keep ticking the SynchronousCompositor so it can make progress.
// Do this in a two stage tick due to native MessageLoop favors delayed task,
// so ensure delayed task is inserted only after the draw task returns.
void PostFallbackTick();
void FallbackTickFired();
// Force invoke the compositor to run produce a 1x1 software frame that is
// immediately discarded. This is a hack to force invoke parts of the
// compositor that are not directly exposed here.
void ForceFakeCompositeSW();
gfx::Vector2d max_scroll_offset() const; gfx::Vector2d max_scroll_offset() const;
void UpdateMemoryPolicy(); void UpdateMemoryPolicy();
...@@ -191,10 +173,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { ...@@ -191,10 +173,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient {
gfx::Vector2d last_on_draw_scroll_offset_; gfx::Vector2d last_on_draw_scroll_offset_;
gfx::Rect last_on_draw_global_visible_rect_; gfx::Rect last_on_draw_global_visible_rect_;
base::CancelableClosure post_fallback_tick_;
base::CancelableClosure fallback_tick_fired_;
bool fallback_tick_pending_;
gfx::Size size_; gfx::Size size_;
gfx::SizeF scrollable_size_dip_; gfx::SizeF scrollable_size_dip_;
......
...@@ -26,6 +26,8 @@ namespace content { ...@@ -26,6 +26,8 @@ namespace content {
namespace { namespace {
const int64_t kFallbackTickTimeoutInMilliseconds = 100;
// Do not limit number of resources, so use an unrealistically high value. // Do not limit number of resources, so use an unrealistically high value.
const size_t kNumResourcesLimit = 10 * 1000 * 1000; const size_t kNumResourcesLimit = 10 * 1000 * 1000;
...@@ -75,7 +77,9 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( ...@@ -75,7 +77,9 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
current_sw_canvas_(nullptr), current_sw_canvas_(nullptr),
memory_policy_(0u), memory_policy_(0u),
did_swap_(false), did_swap_(false),
frame_swap_message_queue_(frame_swap_message_queue) { frame_swap_message_queue_(frame_swap_message_queue),
fallback_tick_pending_(false),
fallback_tick_running_(false) {
thread_checker_.DetachFromThread(); thread_checker_.DetachFromThread();
DCHECK(registry_); DCHECK(registry_);
capabilities_.adjust_deadline_for_parent = false; capabilities_.adjust_deadline_for_parent = false;
...@@ -115,6 +119,7 @@ void SynchronousCompositorOutputSurface::DetachFromClient() { ...@@ -115,6 +119,7 @@ void SynchronousCompositorOutputSurface::DetachFromClient() {
registry_->UnregisterOutputSurface(routing_id_, this); registry_->UnregisterOutputSurface(routing_id_, this);
} }
cc::OutputSurface::DetachFromClient(); cc::OutputSurface::DetachFromClient();
CancelFallbackTick();
} }
void SynchronousCompositorOutputSurface::Reshape(const gfx::Size& size, void SynchronousCompositorOutputSurface::Reshape(const gfx::Size& size,
...@@ -127,15 +132,44 @@ void SynchronousCompositorOutputSurface::SwapBuffers( ...@@ -127,15 +132,44 @@ void SynchronousCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) { cc::CompositorFrame* frame) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK(sync_client_); DCHECK(sync_client_);
sync_client_->SwapBuffers(frame); if (!fallback_tick_running_)
sync_client_->SwapBuffers(frame);
client_->DidSwapBuffers(); client_->DidSwapBuffers();
did_swap_ = true; did_swap_ = true;
} }
void SynchronousCompositorOutputSurface::CancelFallbackTick() {
fallback_tick_.Cancel();
fallback_tick_pending_ = false;
}
void SynchronousCompositorOutputSurface::FallbackTickFired() {
DCHECK(CalledOnValidThread());
TRACE_EVENT0("renderer",
"SynchronousCompositorOutputSurface::FallbackTickFired");
base::AutoReset<bool> in_fallback_tick(&fallback_tick_running_, true);
SkBitmap bitmap;
bitmap.allocN32Pixels(1, 1);
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
fallback_tick_pending_ = false;
DemandDrawSw(&canvas);
}
void SynchronousCompositorOutputSurface::Invalidate() { void SynchronousCompositorOutputSurface::Invalidate() {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
if (sync_client_) if (sync_client_)
sync_client_->Invalidate(); sync_client_->Invalidate();
if (!fallback_tick_pending_) {
fallback_tick_.Reset(
base::Bind(&SynchronousCompositorOutputSurface::FallbackTickFired,
base::Unretained(this)));
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE, fallback_tick_.callback(),
base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
fallback_tick_pending_ = true;
}
} }
void SynchronousCompositorOutputSurface::DemandDrawHw( void SynchronousCompositorOutputSurface::DemandDrawHw(
...@@ -148,6 +182,7 @@ void SynchronousCompositorOutputSurface::DemandDrawHw( ...@@ -148,6 +182,7 @@ void SynchronousCompositorOutputSurface::DemandDrawHw(
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK(HasClient()); DCHECK(HasClient());
DCHECK(context_provider_.get()); DCHECK(context_provider_.get());
CancelFallbackTick();
surface_size_ = surface_size; surface_size_ = surface_size;
client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority, client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority,
...@@ -160,6 +195,7 @@ void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { ...@@ -160,6 +195,7 @@ void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK(canvas); DCHECK(canvas);
DCHECK(!current_sw_canvas_); DCHECK(!current_sw_canvas_);
CancelFallbackTick();
base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas); base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -103,6 +104,9 @@ class SynchronousCompositorOutputSurface ...@@ -103,6 +104,9 @@ class SynchronousCompositorOutputSurface
bool hardware_draw); bool hardware_draw);
bool CalledOnValidThread() const; bool CalledOnValidThread() const;
void CancelFallbackTick();
void FallbackTickFired();
const int routing_id_; const int routing_id_;
SynchronousCompositorRegistry* const registry_; // unowned SynchronousCompositorRegistry* const registry_; // unowned
bool registered_; bool registered_;
...@@ -117,6 +121,10 @@ class SynchronousCompositorOutputSurface ...@@ -117,6 +121,10 @@ class SynchronousCompositorOutputSurface
bool did_swap_; bool did_swap_;
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_; scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
base::CancelableClosure fallback_tick_;
bool fallback_tick_pending_;
bool fallback_tick_running_;
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface); DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment