g_tile_area = 256 * 256;
// Also use a high tile limit since there are no file descriptor issues.
- GlobalTileManager::GetInstance()->SetTileLimit(1000);
+ // There is no need to limit number of tiles, so use an effectively
+ // unlimited value as the limit.
+ GlobalTileManager::GetInstance()->SetTileLimit(10 * 1000 * 1000);
return;
}
on_new_picture_enable_(false),
clear_view_(false),
compositor_needs_continuous_invalidate_(false),
+ invalidate_after_composite_(false),
block_invalidates_(false),
+ fallback_tick_pending_(false),
width_(0),
height_(0) {
CHECK(web_contents_);
return;
TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory");
+ DCHECK(hardware_enabled_);
+ DCHECK(compositor_);
RequestMemoryPolicy(zero_policy);
EnforceMemoryPolicyImmediately(zero_policy);
// well as the tile resource allocation in GlobalTileManager.
void BrowserViewRenderer::RequestMemoryPolicy(
SynchronousCompositorMemoryPolicy& new_policy) {
+ DCHECK(compositor_);
GlobalTileManager* manager = GlobalTileManager::GetInstance();
// The following line will call BrowserViewRenderer::SetMemoryPolicy().
if (!compositor_)
return false;
- if (last_on_draw_global_visible_rect_.IsEmpty()) {
- TRACE_EVENT_INSTANT0("android_webview",
- "EarlyOut_EmptyVisibleRect",
- TRACE_EVENT_SCOPE_THREAD);
- shared_renderer_state_->SetForceInvalidateOnNextDrawGL(true);
- return client_->RequestDrawGL(java_canvas, false);
- }
+ shared_renderer_state_->SetScrollOffset(last_on_draw_scroll_offset_);
if (!hardware_enabled_) {
hardware_enabled_ = compositor_->InitializeHwDraw();
if (!hardware_enabled_)
return false;
- ReturnResourceFromParent();
- SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy();
- RequestMemoryPolicy(new_policy);
- compositor_->SetMemoryPolicy(memory_policy_);
+ if (last_on_draw_global_visible_rect_.IsEmpty() &&
+ parent_draw_constraints_.surface_rect.IsEmpty()) {
+ TRACE_EVENT_INSTANT0("android_webview",
+ "EarlyOut_EmptyVisibleRect",
+ TRACE_EVENT_SCOPE_THREAD);
+ shared_renderer_state_->SetForceInvalidateOnNextDrawGL(true);
+ return client_->RequestDrawGL(java_canvas, false);
+ }
- if (shared_renderer_state_->HasDrawGLInput()) {
+ ReturnResourceFromParent();
+ if (shared_renderer_state_->HasCompositorFrame()) {
TRACE_EVENT_INSTANT0("android_webview",
"EarlyOut_PreviousFrameUnconsumed",
TRACE_EVENT_SCOPE_THREAD);
- // TODO(boliu): Rename this method. We didn't actually composite here.
- DidComposite();
+ DidSkipCompositeInDraw();
return client_->RequestDrawGL(java_canvas, false);
}
- scoped_ptr<DrawGLInput> draw_gl_input(new DrawGLInput);
- draw_gl_input->scroll_offset = last_on_draw_scroll_offset_;
- draw_gl_input->width = width_;
- draw_gl_input->height = height_;
+ scoped_ptr<cc::CompositorFrame> frame = CompositeHw();
+ if (!frame.get())
+ return false;
+
+ shared_renderer_state_->SetCompositorFrame(frame.Pass(), false);
+ GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
+ return client_->RequestDrawGL(java_canvas, false);
+}
+
+scoped_ptr<cc::CompositorFrame> BrowserViewRenderer::CompositeHw() {
+ SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy();
+ RequestMemoryPolicy(new_policy);
+ compositor_->SetMemoryPolicy(memory_policy_);
parent_draw_constraints_ = shared_renderer_state_->ParentDrawConstraints();
gfx::Size surface_size(width_, height_);
// applied onto the layer so global visible rect does not make sense here.
// In this case, just use the surface rect for tiling.
gfx::Rect viewport_rect_for_tile_priority;
- if (parent_draw_constraints_.is_layer)
+ if (parent_draw_constraints_.is_layer ||
+ last_on_draw_global_visible_rect_.IsEmpty()) {
viewport_rect_for_tile_priority = parent_draw_constraints_.surface_rect;
- else
+ } else {
viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
+ }
scoped_ptr<cc::CompositorFrame> frame =
compositor_->DemandDrawHw(surface_size,
clip,
viewport_rect_for_tile_priority,
transform_for_tile_priority);
- if (!frame.get())
- return false;
-
- GlobalTileManager::GetInstance()->DidUse(tile_manager_key_);
-
- frame->AssignTo(&draw_gl_input->frame);
- shared_renderer_state_->SetDrawGLInput(draw_gl_input.Pass());
- DidComposite();
- return client_->RequestDrawGL(java_canvas, false);
+ if (frame.get())
+ DidComposite();
+ return frame.Pass();
}
void BrowserViewRenderer::UpdateParentDrawConstraints() {
// Post an invalidate if the parent draw constraints are stale and there is
// no pending invalidate.
- if (shared_renderer_state_->NeedsForceInvalidateOnNextDrawGL() ||
+ bool needs_force_invalidate =
+ shared_renderer_state_->NeedsForceInvalidateOnNextDrawGL();
+ if (needs_force_invalidate ||
!parent_draw_constraints_.Equals(
- shared_renderer_state_->ParentDrawConstraints())) {
+ shared_renderer_state_->ParentDrawConstraints())) {
shared_renderer_state_->SetForceInvalidateOnNextDrawGL(false);
- EnsureContinuousInvalidation(true);
+ EnsureContinuousInvalidation(true, needs_force_invalidate);
}
}
-void BrowserViewRenderer::ReturnUnusedResource(scoped_ptr<DrawGLInput> input) {
- if (!input.get())
+void BrowserViewRenderer::ReturnUnusedResource(
+ scoped_ptr<cc::CompositorFrame> frame) {
+ if (!frame.get())
return;
cc::CompositorFrameAck frame_ack;
cc::TransferableResource::ReturnResources(
- input->frame.delegated_frame_data->resource_list,
- &frame_ack.resources);
- if (!frame_ack.resources.empty())
+ frame->delegated_frame_data->resource_list, &frame_ack.resources);
+ if (compositor_ && !frame_ack.resources.empty())
compositor_->ReturnResources(frame_ack);
}
void BrowserViewRenderer::ReturnResourceFromParent() {
cc::CompositorFrameAck frame_ack;
shared_renderer_state_->SwapReturnedResources(&frame_ack.resources);
- if (!frame_ack.resources.empty()) {
+ if (compositor_ && !frame_ack.resources.empty()) {
compositor_->ReturnResources(frame_ack);
}
}
+void BrowserViewRenderer::DidSkipCommitFrame() {
+ // Treat it the same way as skipping onDraw.
+ DidSkipCompositeInDraw();
+}
+
bool BrowserViewRenderer::OnDrawSoftware(jobject java_canvas) {
if (!compositor_) {
TRACE_EVENT_INSTANT0(
clear_view_ = true;
// Always invalidate ignoring the compositor to actually clear the webview.
- EnsureContinuousInvalidation(true);
+ EnsureContinuousInvalidation(true, false);
}
void BrowserViewRenderer::SetIsPaused(bool paused) {
"paused",
paused);
is_paused_ = paused;
- EnsureContinuousInvalidation(false);
+ EnsureContinuousInvalidation(false, false);
}
void BrowserViewRenderer::SetViewVisibility(bool view_visible) {
"window_visible",
window_visible);
window_visible_ = window_visible;
- EnsureContinuousInvalidation(false);
+ EnsureContinuousInvalidation(false, false);
}
void BrowserViewRenderer::OnSizeChanged(int width, int height) {
void BrowserViewRenderer::ReleaseHardware() {
DCHECK(hardware_enabled_);
- ReturnUnusedResource(shared_renderer_state_->PassDrawGLInput());
+ ReturnUnusedResource(shared_renderer_state_->PassCompositorFrame());
ReturnResourceFromParent();
DCHECK(shared_renderer_state_->ReturnedResourcesEmpty());
- compositor_->ReleaseHwDraw();
- hardware_enabled_ = false;
+ if (compositor_) {
+ compositor_->ReleaseHwDraw();
+ SynchronousCompositorMemoryPolicy zero_policy;
+ RequestMemoryPolicy(zero_policy);
+ }
- SynchronousCompositorMemoryPolicy zero_policy;
- RequestMemoryPolicy(zero_policy);
+ hardware_enabled_ = false;
GlobalTileManager::GetInstance()->Remove(tile_manager_key_);
}
content::SynchronousCompositor* compositor) {
TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
DCHECK(compositor_);
- compositor_ = NULL;
SynchronousCompositorMemoryPolicy zero_policy;
+ if (hardware_enabled_) {
+ RequestMemoryPolicy(zero_policy);
+ }
DCHECK(memory_policy_ == zero_policy);
+ compositor_ = NULL;
}
void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
invalidate);
compositor_needs_continuous_invalidate_ = invalidate;
- EnsureContinuousInvalidation(false);
+ EnsureContinuousInvalidation(false, false);
}
void BrowserViewRenderer::SetDipScale(float dip_scale) {
client_->DidOverscroll(rounded_overscroll_delta);
}
-void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) {
+void BrowserViewRenderer::EnsureContinuousInvalidation(
+ bool force_invalidate,
+ bool skip_reschedule_tick) {
+ if (force_invalidate)
+ invalidate_after_composite_ = true;
+
// This method should be called again when any of these conditions change.
bool need_invalidate =
- compositor_needs_continuous_invalidate_ || force_invalidate;
+ compositor_needs_continuous_invalidate_ || invalidate_after_composite_;
if (!need_invalidate || block_invalidates_)
return;
+ if (!compositor_needs_continuous_invalidate_ && invalidate_after_composite_)
+ invalidate_after_composite_ = false;
+
// 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();
return;
block_invalidates_ = compositor_needs_continuous_invalidate_;
+ if (skip_reschedule_tick && fallback_tick_pending_)
+ return;
// Unretained here is safe because the callbacks are cancelled when
// they are destroyed.
post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick,
base::Unretained(this)));
fallback_tick_fired_.Cancel();
+ fallback_tick_pending_ = false;
// No need to reschedule fallback tick if compositor does not need to be
// ticked. This can happen if this is reached because force_invalidate is
// true.
- if (compositor_needs_continuous_invalidate_)
+ if (compositor_needs_continuous_invalidate_) {
+ fallback_tick_pending_ = true;
ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback());
+ }
}
void BrowserViewRenderer::PostFallbackTick() {
// This should only be called if OnDraw or DrawGL did not come in time, which
// means block_invalidates_ must still be true.
DCHECK(block_invalidates_);
+ fallback_tick_pending_ = false;
if (compositor_needs_continuous_invalidate_ && compositor_) {
- ForceFakeCompositeSW();
+ if (hardware_enabled_) {
+ ReturnResourceFromParent();
+ ReturnUnusedResource(shared_renderer_state_->PassCompositorFrame());
+ scoped_ptr<cc::CompositorFrame> frame = CompositeHw();
+ if (frame.get()) {
+ shared_renderer_state_->SetCompositorFrame(frame.Pass(), true);
+ }
+ } else {
+ ForceFakeCompositeSW();
+ }
} else {
// Pretend we just composited to unblock further invalidates.
DidComposite();
block_invalidates_ = false;
post_fallback_tick_.Cancel();
fallback_tick_fired_.Cancel();
- EnsureContinuousInvalidation(false);
+ fallback_tick_pending_ = false;
+ EnsureContinuousInvalidation(false, false);
+}
+
+void BrowserViewRenderer::DidSkipCompositeInDraw() {
+ block_invalidates_ = false;
+ EnsureContinuousInvalidation(true, true);
}
std::string BrowserViewRenderer::ToString(AwDrawGLInfo* draw_info) const {