summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-05 19:29:50 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-05 19:29:50 +0000
commitccc8f0fade87ace5881caafd050a678f5d06210a (patch)
tree55cd243b481e0ec25fa389b478cfe254ec0d4216
parentda93365df4a410d37110a739fb06980792b32f78 (diff)
downloadchromium_src-ccc8f0fade87ace5881caafd050a678f5d06210a.zip
chromium_src-ccc8f0fade87ace5881caafd050a678f5d06210a.tar.gz
chromium_src-ccc8f0fade87ace5881caafd050a678f5d06210a.tar.bz2
cc: Be robust against invalid RenderPassDrawQuads.
When the LayerTreeHostImpl drops RenderPasses from its output, it does not also drop the RenderPassDrawQuads that point to them. The direct renderers ignore these quads, so this has never been a problem. However the DelegatedRendererLayerImpl was not able to deal with this correctly and would crash. More problematic is that a compromised renderer could send invalid RenderPassDrawQuads, which the DelegatedRendererLayerImpl must be able to handle gracefully. So, for both cases, we here make the DelegatedRendererLayerImpl ignore invalid RenderPassDrawQuads, and just drop the from its own output. Tests: DelegatedRendererLayerImplTest.InvalidRenderPassDrawQuad R=piman BUG=283630 Review URL: https://chromiumcodereview.appspot.com/23891003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221493 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/layers/delegated_renderer_layer_impl.cc50
-rw-r--r--cc/layers/delegated_renderer_layer_impl.h7
-rw-r--r--cc/layers/delegated_renderer_layer_impl_unittest.cc53
-rw-r--r--cc/test/render_pass_test_utils.h2
4 files changed, 93 insertions, 19 deletions
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index 16d4770..f88885e 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -240,13 +240,19 @@ RenderPass::Id DelegatedRendererLayerImpl::NextContributingRenderPassId(
return RenderPass::Id(previous.layer_id, previous.index + 1);
}
-RenderPass::Id DelegatedRendererLayerImpl::ConvertDelegatedRenderPassId(
- RenderPass::Id delegated_render_pass_id) const {
+bool DelegatedRendererLayerImpl::ConvertDelegatedRenderPassId(
+ RenderPass::Id delegated_render_pass_id,
+ RenderPass::Id* output_render_pass_id) const {
base::hash_map<RenderPass::Id, int>::const_iterator found =
render_passes_index_by_id_.find(delegated_render_pass_id);
- DCHECK(found != render_passes_index_by_id_.end());
+ if (found == render_passes_index_by_id_.end()) {
+ // Be robust against a RenderPass id that isn't part of the frame.
+ return false;
+ }
unsigned delegated_render_pass_index = found->second;
- return RenderPass::Id(id(), IndexToId(delegated_render_pass_index));
+ *output_render_pass_id =
+ RenderPass::Id(id(), IndexToId(delegated_render_pass_index));
+ return true;
}
void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
@@ -254,10 +260,14 @@ void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
DCHECK(HasContributingDelegatedRenderPasses());
for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) {
- RenderPass::Id output_render_pass_id =
- ConvertDelegatedRenderPassId(render_passes_in_draw_order_[i]->id);
+ RenderPass::Id output_render_pass_id(-1, -1);
+ bool present =
+ ConvertDelegatedRenderPassId(render_passes_in_draw_order_[i]->id,
+ &output_render_pass_id);
// Don't clash with the RenderPass we generate if we own a RenderSurface.
+ DCHECK(present) << render_passes_in_draw_order_[i]->id.layer_id << ", "
+ << render_passes_in_draw_order_[i]->id.index;
DCHECK_GT(output_render_pass_id.index, 0);
render_pass_sink->AppendRenderPass(
@@ -447,18 +457,26 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads(
} else {
RenderPass::Id delegated_contributing_render_pass_id =
RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id;
- RenderPass::Id output_contributing_render_pass_id =
- ConvertDelegatedRenderPassId(delegated_contributing_render_pass_id);
- DCHECK(output_contributing_render_pass_id !=
- append_quads_data->render_pass_id);
-
- output_quad = RenderPassDrawQuad::MaterialCast(delegated_quad)->Copy(
- output_shared_quad_state,
- output_contributing_render_pass_id).PassAs<DrawQuad>();
+ RenderPass::Id output_contributing_render_pass_id(-1, -1);
+
+ bool present =
+ ConvertDelegatedRenderPassId(delegated_contributing_render_pass_id,
+ &output_contributing_render_pass_id);
+
+ // The frame may have a RenderPassDrawQuad that points to a RenderPass not
+ // part of the frame. Just ignore these quads.
+ if (present) {
+ DCHECK(output_contributing_render_pass_id !=
+ append_quads_data->render_pass_id);
+
+ output_quad = RenderPassDrawQuad::MaterialCast(delegated_quad)->Copy(
+ output_shared_quad_state,
+ output_contributing_render_pass_id).PassAs<DrawQuad>();
+ }
}
- DCHECK(output_quad.get());
- quad_sink->Append(output_quad.Pass(), append_quads_data);
+ if (output_quad)
+ quad_sink->Append(output_quad.Pass(), append_quads_data);
}
}
diff --git a/cc/layers/delegated_renderer_layer_impl.h b/cc/layers/delegated_renderer_layer_impl.h
index 89b2537..5f55050 100644
--- a/cc/layers/delegated_renderer_layer_impl.h
+++ b/cc/layers/delegated_renderer_layer_impl.h
@@ -71,8 +71,11 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl {
ScopedPtrVector<RenderPass>* render_passes_in_draw_order);
void ClearRenderPasses();
- RenderPass::Id ConvertDelegatedRenderPassId(
- RenderPass::Id delegated_render_pass_id) const;
+ // Returns |true| if the delegated_render_pass_id is part of the current
+ // frame and can be converted.
+ bool ConvertDelegatedRenderPassId(
+ RenderPass::Id delegated_render_pass_id,
+ RenderPass::Id* output_render_pass_id) const;
gfx::Transform DelegatedFrameToLayerSpaceTransform(gfx::Size frame_size)
const;
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index 401ac3c..400a442 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -1245,5 +1245,58 @@ TEST_F(DelegatedRendererLayerImplTestClip, QuadsClipped_LayerClipped_Surface) {
host_impl_->DidDrawAllLayers(frame);
}
+TEST_F(DelegatedRendererLayerImplTest, InvalidRenderPassDrawQuad) {
+ scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(
+ host_impl_->active_tree(), 1).PassAs<LayerImpl>();
+ scoped_ptr<FakeDelegatedRendererLayerImpl> delegated_renderer_layer =
+ FakeDelegatedRendererLayerImpl::Create(host_impl_->active_tree(), 4);
+
+ host_impl_->SetViewportSize(gfx::Size(100, 100));
+
+ delegated_renderer_layer->SetPosition(gfx::Point(3, 3));
+ delegated_renderer_layer->SetBounds(gfx::Size(10, 10));
+ delegated_renderer_layer->SetContentBounds(gfx::Size(10, 10));
+ delegated_renderer_layer->SetDrawsContent(true);
+
+ ScopedPtrVector<RenderPass> delegated_render_passes;
+ TestRenderPass* pass1 = AddRenderPass(
+ &delegated_render_passes,
+ RenderPass::Id(9, 6),
+ gfx::Rect(0, 0, 10, 10),
+ gfx::Transform());
+ AddQuad(pass1, gfx::Rect(0, 0, 6, 6), 33u);
+
+ // This render pass isn't part of the frame.
+ scoped_ptr<TestRenderPass> missing_pass(TestRenderPass::Create());
+ missing_pass->SetNew(RenderPass::Id(9, 7),
+ gfx::Rect(7, 7, 7, 7),
+ gfx::Rect(7, 7, 7, 7),
+ gfx::Transform());
+
+ // But a render pass quad refers to it.
+ AddRenderPassQuad(pass1, missing_pass.get());
+
+ delegated_renderer_layer->SetFrameDataForRenderPasses(
+ &delegated_render_passes);
+
+ // The RenderPasses should be taken by the layer.
+ EXPECT_EQ(0u, delegated_render_passes.size());
+
+ root_layer->AddChild(delegated_renderer_layer.PassAs<LayerImpl>());
+ host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
+
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
+
+ // The DelegatedRendererLayerImpl should drop the bad RenderPassDrawQuad.
+ ASSERT_EQ(1u, frame.render_passes.size());
+ ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
+ EXPECT_EQ(DrawQuad::SOLID_COLOR,
+ frame.render_passes[0]->quad_list[0]->material);
+
+ host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
+ host_impl_->DidDrawAllLayers(frame);
+}
+
} // namespace
} // namespace cc
diff --git a/cc/test/render_pass_test_utils.h b/cc/test/render_pass_test_utils.h
index 01a7ca0..b427e5a 100644
--- a/cc/test/render_pass_test_utils.h
+++ b/cc/test/render_pass_test_utils.h
@@ -50,7 +50,7 @@ void AddRenderPassQuad(TestRenderPass* to_pass,
// Adds a render pass quad with the given mask resource, filter, and transform.
void AddRenderPassQuad(TestRenderPass* toPass,
- TestRenderPass* contributingPass,
+ TestRenderPass* contributing_pass,
ResourceProvider::ResourceId mask_resource_id,
skia::RefPtr<SkImageFilter> filter,
gfx::Transform transform);