summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/output/output_surface.h2
-rw-r--r--cc/test/fake_output_surface.h7
-rw-r--r--cc/trees/layer_tree_host_impl.cc34
-rw-r--r--cc/trees/layer_tree_host_impl.h2
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc327
-rw-r--r--content/browser/android/in_process/synchronous_compositor_output_surface.cc1
-rw-r--r--content/renderer/gpu/render_widget_compositor.cc5
7 files changed, 264 insertions, 114 deletions
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 4489c10..b38a987 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -60,10 +60,12 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
: delegated_rendering(false),
max_frames_pending(0),
deferred_gl_initialization(false),
+ draw_and_swap_full_viewport_every_frame(false),
adjust_deadline_for_parent(true) {}
bool delegated_rendering;
int max_frames_pending;
bool deferred_gl_initialization;
+ bool draw_and_swap_full_viewport_every_frame;
// This doesn't handle the <webview> case, but once BeginFrame is
// supported natively, we shouldn't need adjust_deadline_for_parent.
bool adjust_deadline_for_parent;
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index 18759ec..dfd4db5 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -56,6 +56,7 @@ class FakeOutputSurface : public OutputSurface {
new FakeOutputSurface(software_device.Pass(), true));
}
+ // TODO(boliu): Use a general factory that takes Capabilities arg.
static scoped_ptr<FakeOutputSurface> CreateDeferredGL(
scoped_ptr<SoftwareOutputDevice> software_device) {
scoped_ptr<FakeOutputSurface> result(
@@ -64,6 +65,12 @@ class FakeOutputSurface : public OutputSurface {
return result.Pass();
}
+ static scoped_ptr<FakeOutputSurface> CreateAlwaysDrawAndSwap3d() {
+ scoped_ptr<FakeOutputSurface> result(Create3d());
+ result->capabilities_.draw_and_swap_full_viewport_every_frame = true;
+ return result.Pass();
+ }
+
CompositorFrame& last_sent_frame() { return last_sent_frame_; }
size_t num_sent_frames() { return num_sent_frames_; }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index f97eea0..1d74dcc0 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -257,17 +257,32 @@ void LayerTreeHostImpl::CommitComplete() {
client_->SendManagedMemoryStats();
}
-bool LayerTreeHostImpl::CanDraw() {
+bool LayerTreeHostImpl::CanDraw() const {
// Note: If you are changing this function or any other function that might
// affect the result of CanDraw, make sure to call
// client_->OnCanDrawStateChanged in the proper places and update the
// NotifyIfCanDrawChanged test.
+ if (!renderer_) {
+ TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer",
+ TRACE_EVENT_SCOPE_THREAD);
+ return false;
+ }
+
+ // Must have an OutputSurface if |renderer_| is not NULL.
+ DCHECK(output_surface_);
+
+ // TODO(boliu): Make draws without root_layer work and move this below
+ // draw_and_swap_full_viewport_every_frame check. Tracked in crbug.com/264967.
if (!active_tree_->root_layer()) {
TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer",
TRACE_EVENT_SCOPE_THREAD);
return false;
}
+
+ if (output_surface_->capabilities().draw_and_swap_full_viewport_every_frame)
+ return true;
+
if (device_viewport_size_.IsEmpty()) {
TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport",
TRACE_EVENT_SCOPE_THREAD);
@@ -279,11 +294,6 @@ bool LayerTreeHostImpl::CanDraw() {
TRACE_EVENT_SCOPE_THREAD);
return false;
}
- if (!renderer_) {
- TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer",
- TRACE_EVENT_SCOPE_THREAD);
- return false;
- }
if (active_tree_->ContentsTexturesPurged()) {
TRACE_EVENT_INSTANT0(
"cc", "LayerTreeHostImpl::CanDraw contents textures purged",
@@ -568,6 +578,8 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
// A copy request should cause damage, so we should not have any copy
// requests in this case.
DCHECK_EQ(0u, active_tree_->LayersWithCopyOutputRequest().size());
+ DCHECK(!output_surface_->capabilities()
+ .draw_and_swap_full_viewport_every_frame);
return true;
}
@@ -730,7 +742,8 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
occlusion_tracker.LeaveLayer(it);
}
- if (have_copy_request)
+ if (have_copy_request ||
+ output_surface_->capabilities().draw_and_swap_full_viewport_every_frame)
draw_frame = true;
rendering_stats_instrumentation_->AddLayersDrawn(layers_drawn);
@@ -972,8 +985,11 @@ bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame,
AddDamageNextUpdate(device_viewport_damage_rect);
}
- if (!CalculateRenderPasses(frame))
+ if (!CalculateRenderPasses(frame)) {
+ DCHECK(!output_surface_->capabilities()
+ .draw_and_swap_full_viewport_every_frame);
return false;
+ }
// If we return true, then we expect DrawLayers() to be called before this
// function is called again.
@@ -1182,6 +1198,8 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
if (frame->has_no_damage) {
TRACE_EVENT0("cc", "EarlyOut_NoDamage");
+ DCHECK(!output_surface_->capabilities()
+ .draw_and_swap_full_viewport_every_frame);
return;
}
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 9a0f72f..87e7726 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -213,7 +213,7 @@ class CC_EXPORT LayerTreeHostImpl
void OnCanDrawStateChangedForTree();
// Implementation
- bool CanDraw();
+ bool CanDraw() const;
OutputSurface* output_surface() const { return output_surface_.get(); }
std::string LayerTreeAsJson() const;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 1fb6c38..2cc43cc9 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -265,6 +265,72 @@ class LayerTreeHostImplTest : public testing::Test,
void pinch_zoom_pan_viewport_and_scroll_boundary_test(
float device_scale_factor);
+ void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
+ // Note: It is not possible to disable the renderer once it has been set,
+ // so we do not need to test that disabling the renderer notifies us
+ // that can_draw changed.
+ EXPECT_FALSE(host_impl_->CanDraw());
+ on_can_draw_state_changed_called_ = false;
+
+ // Set up the root layer, which allows us to draw.
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ EXPECT_TRUE(host_impl_->CanDraw());
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ // Toggle the root layer to make sure it toggles can_draw
+ host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
+ EXPECT_FALSE(host_impl_->CanDraw());
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ SetupScrollAndContentsLayers(gfx::Size(100, 100));
+ EXPECT_TRUE(host_impl_->CanDraw());
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ // Toggle the device viewport size to make sure it toggles can_draw.
+ host_impl_->SetViewportSize(gfx::Size());
+ if (always_draw) {
+ EXPECT_TRUE(host_impl_->CanDraw());
+ } else {
+ EXPECT_FALSE(host_impl_->CanDraw());
+ }
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ host_impl_->SetViewportSize(gfx::Size(100, 100));
+ EXPECT_TRUE(host_impl_->CanDraw());
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ // Toggle contents textures purged without causing any evictions,
+ // and make sure that it does not change can_draw.
+ set_reduce_memory_result(false);
+ host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
+ host_impl_->memory_allocation_limit_bytes() - 1), true);
+ EXPECT_TRUE(host_impl_->CanDraw());
+ EXPECT_FALSE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ // Toggle contents textures purged to make sure it toggles can_draw.
+ set_reduce_memory_result(true);
+ host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
+ host_impl_->memory_allocation_limit_bytes() - 1), true);
+ if (always_draw) {
+ EXPECT_TRUE(host_impl_->CanDraw());
+ } else {
+ EXPECT_FALSE(host_impl_->CanDraw());
+ }
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+
+ host_impl_->active_tree()->ResetContentsTexturesPurged();
+ EXPECT_TRUE(host_impl_->CanDraw());
+ EXPECT_TRUE(on_can_draw_state_changed_called_);
+ on_can_draw_state_changed_called_ = false;
+ }
+
protected:
virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
return CreateFakeOutputSurface();
@@ -294,69 +360,30 @@ class LayerTreeHostImplTest : public testing::Test,
int current_priority_cutoff_value_;
};
+TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
+ bool always_draw = false;
+ CheckNotifyCalledIfCanDrawChanged(always_draw);
+}
+
+TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
+ LayerTreeSettings settings;
+ settings.impl_side_painting = true;
+ host_impl_ = LayerTreeHostImpl::Create(
+ settings, this, &proxy_, &stats_instrumentation_);
+ host_impl_->InitializeRenderer(
+ FakeOutputSurface::CreateAlwaysDrawAndSwap3d().PassAs<OutputSurface>());
+ host_impl_->SetViewportSize(gfx::Size(10, 10));
+
+ bool always_draw = true;
+ CheckNotifyCalledIfCanDrawChanged(always_draw);
+}
+
class TestWebGraphicsContext3DMakeCurrentFails
: public TestWebGraphicsContext3D {
public:
virtual bool makeContextCurrent() OVERRIDE { return false; }
};
-TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
- // Note: It is not possible to disable the renderer once it has been set,
- // so we do not need to test that disabling the renderer notifies us
- // that can_draw changed.
- EXPECT_FALSE(host_impl_->CanDraw());
- on_can_draw_state_changed_called_ = false;
-
- SetupScrollAndContentsLayers(gfx::Size(100, 100));
- EXPECT_TRUE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- // Toggle the root layer to make sure it toggles can_draw
- host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
- EXPECT_FALSE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- SetupScrollAndContentsLayers(gfx::Size(100, 100));
- EXPECT_TRUE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- // Toggle the device viewport size to make sure it toggles can_draw.
- host_impl_->SetViewportSize(gfx::Size());
- EXPECT_FALSE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- host_impl_->SetViewportSize(gfx::Size(100, 100));
- EXPECT_TRUE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- // Toggle contents textures purged without causing any evictions,
- // and make sure that it does not change can_draw.
- set_reduce_memory_result(false);
- host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
- host_impl_->memory_allocation_limit_bytes() - 1), true);
- EXPECT_TRUE(host_impl_->CanDraw());
- EXPECT_FALSE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- // Toggle contents textures purged to make sure it toggles can_draw.
- set_reduce_memory_result(true);
- host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
- host_impl_->memory_allocation_limit_bytes() - 1), true);
- EXPECT_FALSE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-
- host_impl_->active_tree()->ResetContentsTexturesPurged();
- EXPECT_TRUE(host_impl_->CanDraw());
- EXPECT_TRUE(on_can_draw_state_changed_called_);
- on_can_draw_state_changed_called_ = false;
-}
-
TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
ASSERT_FALSE(host_impl_->active_tree()->root_layer());
@@ -2771,32 +2798,47 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
host_impl_->DidDrawAllLayers(frame);
}
-TEST_F(LayerTreeHostImplTest, ViewportCovered) {
- host_impl_->InitializeRenderer(CreateOutputSurface());
- host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
-
- gfx::Size viewport_size(1000, 1000);
- host_impl_->SetViewportSize(viewport_size);
-
- host_impl_->active_tree()->SetRootLayer(
- LayerImpl::Create(host_impl_->active_tree(), 1));
- host_impl_->active_tree()->root_layer()->AddChild(
- BlendStateCheckLayer::Create(host_impl_->active_tree(),
- 2,
- host_impl_->resource_provider()));
- BlendStateCheckLayer* child = static_cast<BlendStateCheckLayer*>(
- host_impl_->active_tree()->root_layer()->children()[0]);
- child->SetExpectation(false, false);
- child->SetContentsOpaque(true);
-
- // No gutter rects
- {
- gfx::Rect layer_rect(0, 0, 1000, 1000);
- child->SetPosition(layer_rect.origin());
- child->SetBounds(layer_rect.size());
- child->SetContentBounds(layer_rect.size());
- child->SetQuadRect(gfx::Rect(layer_rect.size()));
- child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
+class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
+ public:
+ void CreateLayerTreeHostImpl(bool always_draw) {
+ LayerTreeSettings settings;
+ settings.minimum_occlusion_tracking_size = gfx::Size();
+ settings.impl_side_painting = true;
+ host_impl_ = LayerTreeHostImpl::Create(
+ settings, this, &proxy_, &stats_instrumentation_);
+ scoped_ptr<OutputSurface> output_surface;
+ if (always_draw) {
+ output_surface = FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
+ .PassAs<OutputSurface>();
+ } else {
+ output_surface = CreateFakeOutputSurface();
+ }
+ host_impl_->InitializeRenderer(output_surface.Pass());
+ viewport_size_ = gfx::Size(1000, 1000);
+ }
+
+ void SetupActiveTreeLayers() {
+ host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
+ host_impl_->active_tree()->SetRootLayer(
+ LayerImpl::Create(host_impl_->active_tree(), 1));
+ host_impl_->active_tree()->root_layer()->AddChild(
+ BlendStateCheckLayer::Create(host_impl_->active_tree(),
+ 2,
+ host_impl_->resource_provider()));
+ child_ = static_cast<BlendStateCheckLayer*>(
+ host_impl_->active_tree()->root_layer()->children()[0]);
+ child_->SetExpectation(false, false);
+ child_->SetContentsOpaque(true);
+ }
+
+ // Expect no gutter rects.
+ void TestLayerCoversFullViewport() {
+ gfx::Rect layer_rect(viewport_size_);
+ child_->SetPosition(layer_rect.origin());
+ child_->SetBounds(layer_rect.size());
+ child_->SetContentBounds(layer_rect.size());
+ child_->SetQuadRect(gfx::Rect(layer_rect.size()));
+ child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
@@ -2810,18 +2852,18 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
LayerTestCommon::VerifyQuadsExactlyCoverRect(
- frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
+ frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
host_impl_->DidDrawAllLayers(frame);
}
- // Empty visible content area (fullscreen gutter rect)
- {
+ // Expect fullscreen gutter rect.
+ void TestEmptyLayer() {
gfx::Rect layer_rect(0, 0, 0, 0);
- child->SetPosition(layer_rect.origin());
- child->SetBounds(layer_rect.size());
- child->SetContentBounds(layer_rect.size());
- child->SetQuadRect(gfx::Rect(layer_rect.size()));
- child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
+ child_->SetPosition(layer_rect.origin());
+ child_->SetBounds(layer_rect.size());
+ child_->SetContentBounds(layer_rect.size());
+ child_->SetQuadRect(gfx::Rect(layer_rect.size()));
+ child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
@@ -2835,18 +2877,18 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
LayerTestCommon::VerifyQuadsExactlyCoverRect(
- frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
+ frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
host_impl_->DidDrawAllLayers(frame);
}
- // Content area in middle of clip rect (four surrounding gutter rects)
- {
+ // Expect four surrounding gutter rects.
+ void TestLayerInMiddleOfViewport() {
gfx::Rect layer_rect(500, 500, 200, 200);
- child->SetPosition(layer_rect.origin());
- child->SetBounds(layer_rect.size());
- child->SetContentBounds(layer_rect.size());
- child->SetQuadRect(gfx::Rect(layer_rect.size()));
- child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
+ child_->SetPosition(layer_rect.origin());
+ child_->SetBounds(layer_rect.size());
+ child_->SetContentBounds(layer_rect.size());
+ child_->SetQuadRect(gfx::Rect(layer_rect.size()));
+ child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
@@ -2860,11 +2902,96 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
LayerTestCommon::VerifyQuadsExactlyCoverRect(
- frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
+ frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
+ host_impl_->DidDrawAllLayers(frame);
+ }
+
+ // Expect no gutter rects.
+ void TestLayerIsLargerThanViewport() {
+ gfx::Rect layer_rect(viewport_size_.width() + 10,
+ viewport_size_.height() + 10);
+ child_->SetPosition(layer_rect.origin());
+ child_->SetBounds(layer_rect.size());
+ child_->SetContentBounds(layer_rect.size());
+ child_->SetQuadRect(gfx::Rect(layer_rect.size()));
+ child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
+
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
+ ASSERT_EQ(1u, frame.render_passes.size());
+
+ size_t num_gutter_quads = 0;
+ for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
+ num_gutter_quads += (frame.render_passes[0]->quad_list[i]->material ==
+ DrawQuad::SOLID_COLOR) ? 1 : 0;
+ EXPECT_EQ(0u, num_gutter_quads);
+ EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
+
host_impl_->DidDrawAllLayers(frame);
}
+
+ virtual void DidActivatePendingTree() OVERRIDE {
+ did_activate_pending_tree_ = true;
+ }
+
+ protected:
+ gfx::Size viewport_size_;
+ BlendStateCheckLayer* child_;
+ bool did_activate_pending_tree_;
+};
+
+TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
+ bool always_draw = false;
+ CreateLayerTreeHostImpl(always_draw);
+
+ host_impl_->SetViewportSize(viewport_size_);
+ SetupActiveTreeLayers();
+ TestLayerCoversFullViewport();
+ TestEmptyLayer();
+ TestLayerInMiddleOfViewport();
+ TestLayerIsLargerThanViewport();
}
+TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
+ bool always_draw = true;
+ CreateLayerTreeHostImpl(always_draw);
+
+ // Pending tree to force active_tree size invalid. Not used otherwise.
+ host_impl_->CreatePendingTree();
+ host_impl_->SetViewportSize(viewport_size_);
+ EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+
+ SetupActiveTreeLayers();
+ TestEmptyLayer();
+ TestLayerInMiddleOfViewport();
+ TestLayerIsLargerThanViewport();
+}
+
+TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
+ bool always_draw = true;
+ CreateLayerTreeHostImpl(always_draw);
+
+ // Set larger viewport and activate it to active tree.
+ host_impl_->CreatePendingTree();
+ gfx::Size larger_viewport(viewport_size_.width() + 100,
+ viewport_size_.height() + 100);
+ host_impl_->SetViewportSize(larger_viewport);
+ EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+ did_activate_pending_tree_ = false;
+ host_impl_->ActivatePendingTreeIfNeeded();
+ EXPECT_TRUE(did_activate_pending_tree_);
+ EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
+
+ // Shrink pending tree viewport without activating.
+ host_impl_->CreatePendingTree();
+ host_impl_->SetViewportSize(viewport_size_);
+ EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
+
+ SetupActiveTreeLayers();
+ TestEmptyLayer();
+ TestLayerInMiddleOfViewport();
+ TestLayerIsLargerThanViewport();
+}
class ReshapeTrackerContext: public TestWebGraphicsContext3D {
public:
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index eaee24d4..2669b06 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -93,6 +93,7 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
did_swap_buffer_(false),
current_sw_canvas_(NULL) {
capabilities_.deferred_gl_initialization = true;
+ capabilities_.draw_and_swap_full_viewport_every_frame = true;
capabilities_.adjust_deadline_for_parent = false;
// Cannot call out to GetDelegate() here as the output surface is not
// constructed on the correct thread.
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 323039f..3eef56d 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -105,11 +105,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.force_direct_layer_drawing =
cmd->HasSwitch(cc::switches::kForceDirectLayerDrawing);
- // Android WebView does not support forced draw and this is to prevent
- // crashes. Adding support for forced draw is tracked in crbug.com/250909.
- settings.timeout_and_draw_when_animation_checkerboards =
- !widget->UsingSynchronousRendererCompositor();
-
int default_tile_width = settings.default_tile_size.width();
if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1,