diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 02:37:55 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-28 02:37:55 +0000 |
commit | 8b0f8255da1adf1f7275427e709a49c1689a079e (patch) | |
tree | 99479d30a6f68f0ab9732e5fd02ac9b18187c9d0 | |
parent | d980d065a42772a1196342c727b0377d0590f512 (diff) | |
download | chromium_src-8b0f8255da1adf1f7275427e709a49c1689a079e.zip chromium_src-8b0f8255da1adf1f7275427e709a49c1689a079e.tar.gz chromium_src-8b0f8255da1adf1f7275427e709a49c1689a079e.tar.bz2 |
cc: Make damage on delegated frame damage the host layer.
When the delegated renderer layer receives a frame, it should
be considered damaged by the compositor in the same place that
the frame had damage.
If multiple frames come between commits, then aggregate the
damage together. If the scale at which the frame will be draw
changes, then damage the whole layer.
Tests:
LayerTreeHostDelegatedTestLayerUsesFrameDamage.runSingleThread
LayerTreeHostDelegatedTestLayerUsesFrameDamage.runMultiThread
R=piman
BUG=123444
Depends on: https://codereview.chromium.org/12328118/
Review URL: https://chromiumcodereview.appspot.com/12340095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185123 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/delegated_renderer_layer.cc | 26 | ||||
-rw-r--r-- | cc/delegated_renderer_layer.h | 14 | ||||
-rw-r--r-- | cc/delegated_renderer_layer_impl.cc | 62 | ||||
-rw-r--r-- | cc/delegated_renderer_layer_impl.h | 23 | ||||
-rw-r--r-- | cc/layer_impl.h | 6 | ||||
-rw-r--r-- | cc/layer_tree_host_unittest_delegated.cc | 229 | ||||
-rw-r--r-- | cc/test/layer_tree_test_common.cc | 3 | ||||
-rw-r--r-- | cc/test/layer_tree_test_common.h | 3 |
8 files changed, 336 insertions, 30 deletions
diff --git a/cc/delegated_renderer_layer.cc b/cc/delegated_renderer_layer.cc index 01167c9..f1e10a5 100644 --- a/cc/delegated_renderer_layer.cc +++ b/cc/delegated_renderer_layer.cc @@ -4,6 +4,7 @@ #include "cc/delegated_renderer_layer.h" +#include "cc/delegated_frame_data.h" #include "cc/delegated_renderer_layer_impl.h" namespace cc { @@ -29,7 +30,30 @@ void DelegatedRendererLayer::pushPropertiesTo(LayerImpl* impl) { DelegatedRendererLayerImpl* delegated_impl = static_cast<DelegatedRendererLayerImpl*>(impl); - delegated_impl->CreateChildIdIfNeeded(); + + delegated_impl->SetDisplaySize(display_size_); + + if (frame_data_) + delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_); + + damage_in_frame_ = gfx::RectF(); +} + +void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) { + if (display_size_ == size) + return; + display_size_ = size; + setNeedsCommit(); +} + +void DelegatedRendererLayer::SetFrameData( + scoped_ptr<DelegatedFrameData> new_frame_data) { + frame_data_ = new_frame_data.Pass(); + if (!frame_data_->render_pass_list.empty()) { + RenderPass* root_pass = frame_data_->render_pass_list.back(); + damage_in_frame_.Union(root_pass->damage_rect); + } + setNeedsCommit(); } } // namespace cc diff --git a/cc/delegated_renderer_layer.h b/cc/delegated_renderer_layer.h index 5529b76..f8c847d 100644 --- a/cc/delegated_renderer_layer.h +++ b/cc/delegated_renderer_layer.h @@ -9,6 +9,7 @@ #include "cc/layer.h" namespace cc { +class DelegatedFrameData; class CC_EXPORT DelegatedRendererLayer : public Layer { public: @@ -18,11 +19,22 @@ class CC_EXPORT DelegatedRendererLayer : public Layer { OVERRIDE; virtual void pushPropertiesTo(LayerImpl* impl) OVERRIDE; + // Set the size at which the frame should be displayed, with the origin at the + // layer's origin. This must always contain at least the layer's bounds. A + // value of (0, 0) implies that the frame should be displayed to fit exactly + // in the layer's bounds. + void SetDisplaySize(gfx::Size size); + + void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data); + protected: DelegatedRendererLayer(); + virtual ~DelegatedRendererLayer(); private: - virtual ~DelegatedRendererLayer(); + scoped_ptr<DelegatedFrameData> frame_data_; + gfx::RectF damage_in_frame_; + gfx::Size display_size_; }; } diff --git a/cc/delegated_renderer_layer_impl.cc b/cc/delegated_renderer_layer_impl.cc index 85920f3..a8cdd54 100644 --- a/cc/delegated_renderer_layer_impl.cc +++ b/cc/delegated_renderer_layer_impl.cc @@ -5,6 +5,7 @@ #include "cc/delegated_renderer_layer_impl.h" #include "cc/append_quads_data.h" +#include "cc/delegated_frame_data.h" #include "cc/layer_tree_impl.h" #include "cc/math_util.h" #include "cc/quad_sink.h" @@ -35,6 +36,46 @@ bool DelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const { return render_passes_in_draw_order_.size() > 1; } +void DelegatedRendererLayerImpl::SetFrameData( + scoped_ptr<DelegatedFrameData> frame_data, + gfx::RectF damage_in_frame) { + CreateChildIdIfNeeded(); + DCHECK(child_id_); + + // Display size is already set so we can compute what the damage rect + // will be in layer space. + RenderPass* new_root_pass = frame_data->render_pass_list.empty() ? + NULL : frame_data->render_pass_list.back(); + bool new_frame_is_empty = !new_root_pass; + + RenderPass* old_root_pass = render_passes_in_draw_order_.empty() ? + NULL : render_passes_in_draw_order_.back(); + bool old_frame_is_empty = !old_root_pass; + + gfx::RectF damage_in_layer; + if (new_frame_is_empty) { + if (!old_frame_is_empty) + damage_in_layer = gfx::Rect(bounds()); + } else { + DCHECK(!new_root_pass->output_rect.IsEmpty()); + damage_in_layer = MathUtil::mapClippedRect( + DelegatedFrameToLayerSpaceTransform(new_root_pass->output_rect.size()), + damage_in_frame); + } + setUpdateRect(gfx::UnionRects(updateRect(), damage_in_layer)); + + // TODO(danakj): Convert the resource ids the render passes and return data + // for a frame ack. + SetRenderPasses(frame_data->render_pass_list); +} + +void DelegatedRendererLayerImpl::SetDisplaySize(gfx::Size size) { + if (display_size_ == size) + return; + display_size_ = size; + noteLayerPropertyChanged(); +} + void DelegatedRendererLayerImpl::SetRenderPasses( ScopedPtrVector<RenderPass>& render_passes_in_draw_order) { gfx::RectF old_root_damage; @@ -73,6 +114,17 @@ void DelegatedRendererLayerImpl::didLoseOutputSurface() { ClearChildId(); } +gfx::Transform DelegatedRendererLayerImpl::DelegatedFrameToLayerSpaceTransform( + gfx::Size frame_size) const { + gfx::Size display_size = display_size_.IsEmpty() ? bounds() : display_size_; + + gfx::Transform delegated_frame_to_layer_space_transform; + delegated_frame_to_layer_space_transform.Scale( + static_cast<double>(display_size.width()) / frame_size.width(), + static_cast<double>(display_size.height()) / frame_size.height()); + return delegated_frame_to_layer_space_transform; +} + static inline int IndexToId(int index) { return index + 1; } static inline int IdToIndex(int id) { return id - 1; } @@ -171,16 +223,8 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads( // Don't allow areas inside the bounds that are empty. DCHECK(display_size_.IsEmpty() || gfx::Rect(display_size_).Contains(gfx::Rect(bounds()))); - gfx::Size display_size = - display_size_.IsEmpty() ? bounds() : display_size_; - - gfx::Transform delegated_frame_to_layer_space_transform; - delegated_frame_to_layer_space_transform.Scale( - static_cast<double>(display_size.width()) / frame_size.width(), - static_cast<double>(display_size.height()) / frame_size.height()); - gfx::Transform delegated_frame_to_target_transform = - drawTransform() * delegated_frame_to_layer_space_transform; + drawTransform() * DelegatedFrameToLayerSpaceTransform(frame_size); output_shared_quad_state->content_to_target_transform.ConcatTransform( delegated_frame_to_target_transform); diff --git a/cc/delegated_renderer_layer_impl.h b/cc/delegated_renderer_layer_impl.h index 0121b2e..1b40008 100644 --- a/cc/delegated_renderer_layer_impl.h +++ b/cc/delegated_renderer_layer_impl.h @@ -11,6 +11,7 @@ #include "cc/scoped_ptr_vector.h" namespace cc { +class DelegatedFrameData; class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { public: @@ -31,31 +32,34 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { virtual void appendQuads( QuadSink& quad_sink, AppendQuadsData& append_quads_data) OVERRIDE; + // TODO(danakj): Make private // This gives ownership of the RenderPasses to the layer. void SetRenderPasses(ScopedPtrVector<RenderPass>&); void ClearRenderPasses(); - // Set the size at which the frame should be displayed, with the origin at the - // layer's origin. This must always contain at least the layer's bounds. A - // value of (0, 0) implies that the frame should be displayed to fit exactly - // in the layer's bounds. - void set_display_size(gfx::Size size) { display_size_ = size; } - void AppendContributingRenderPasses(RenderPassSink* render_pass_sink); - // Creates an ID with the resource provider for the child renderer - // that will be sending quads to the layer. - void CreateChildIdIfNeeded(); + void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data, + gfx::RectF damage_in_frame); + + void SetDisplaySize(gfx::Size size); + int child_id() const { return child_id_; } private: DelegatedRendererLayerImpl(LayerTreeImpl* tree_impl, int id); + // Creates an ID with the resource provider for the child renderer + // that will be sending quads to the layer. + void CreateChildIdIfNeeded(); void ClearChildId(); RenderPass::Id ConvertDelegatedRenderPassId( RenderPass::Id delegated_render_pass_id) const; + gfx::Transform DelegatedFrameToLayerSpaceTransform(gfx::Size frame_size) + const; + void AppendRenderPassQuads( QuadSink* quad_sink, AppendQuadsData* append_quads_data, @@ -67,6 +71,7 @@ class CC_EXPORT DelegatedRendererLayerImpl : public LayerImpl { ScopedPtrVector<RenderPass> render_passes_in_draw_order_; base::hash_map<RenderPass::Id, int> render_passes_index_by_id_; + gfx::Size display_size_; int child_id_; }; diff --git a/cc/layer_impl.h b/cc/layer_impl.h index 20b2384..a325aa0 100644 --- a/cc/layer_impl.h +++ b/cc/layer_impl.h @@ -324,9 +324,6 @@ protected: void AsValueInto(base::DictionaryValue* dict) const; -private: - void updateScrollbarPositions(); - void noteLayerSurfacePropertyChanged(); void noteLayerPropertyChanged(); void noteLayerPropertyChangedForSubtree(); @@ -334,6 +331,9 @@ private: // Note carefully this does not affect the current layer. void noteLayerPropertyChangedForDescendants(); +private: + void updateScrollbarPositions(); + virtual const char* layerTypeAsString() const; void dumpLayer(std::string*, int indent) const; diff --git a/cc/layer_tree_host_unittest_delegated.cc b/cc/layer_tree_host_unittest_delegated.cc index e3bedfc..6fe3f8f 100644 --- a/cc/layer_tree_host_unittest_delegated.cc +++ b/cc/layer_tree_host_unittest_delegated.cc @@ -4,6 +4,7 @@ #include "cc/layer_tree_host.h" +#include "cc/delegated_frame_data.h" #include "cc/delegated_renderer_layer.h" #include "cc/delegated_renderer_layer_impl.h" #include "cc/layer_tree_impl.h" @@ -14,16 +15,62 @@ namespace cc { namespace { // These tests deal with delegated renderer layers. -class LayerTreeHostDelegatedTest : public ThreadedTest {}; +class LayerTreeHostDelegatedTest : public ThreadedTest { + protected: + class TestDelegatedRendererLayer : public DelegatedRendererLayer { + public: + static scoped_refptr<DelegatedRendererLayer> Create( + LayerTreeHostDelegatedTest* test) { + return new TestDelegatedRendererLayer(test); + } -class LayerTreeHostDelegatedTestCreateChildId + virtual void update(ResourceUpdateQueue& queue, + const OcclusionTracker* occlusion, + RenderingStats* stats) OVERRIDE { + DelegatedRendererLayer::update(queue, occlusion, stats); + test_->UpdateDelegatedLayer(this); + + } + protected: + explicit TestDelegatedRendererLayer(LayerTreeHostDelegatedTest* test) + : DelegatedRendererLayer(), + test_(test) {} + virtual ~TestDelegatedRendererLayer() {} + LayerTreeHostDelegatedTest* test_; + }; + + // Called by each delegated renderer layer when update is called on it. + virtual void UpdateDelegatedLayer(TestDelegatedRendererLayer* layer) {} + + scoped_ptr<DelegatedFrameData> CreateFrameData(gfx::Rect root_output_rect, + gfx::Rect root_damage_rect) { + scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); + + scoped_ptr<RenderPass> root_pass(RenderPass::Create()); + root_pass->SetNew(RenderPass::Id(1, 1), + root_output_rect, + root_damage_rect, + gfx::Transform()); + frame->render_pass_list.push_back(root_pass.Pass()); + return frame.Pass(); + } + + scoped_ptr<DelegatedFrameData> CreateEmptyFrameData() { + scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData); + return frame.Pass(); + } +}; + +class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer : public LayerTreeHostDelegatedTest { public: virtual void setupTree() OVERRIDE { root_ = Layer::create(); + root_->setAnchorPoint(gfx::PointF()); root_->setBounds(gfx::Size(10, 10)); - delegated_ = DelegatedRendererLayer::Create(); + delegated_ = TestDelegatedRendererLayer::Create(this); + delegated_->setAnchorPoint(gfx::PointF()); delegated_->setBounds(gfx::Size(10, 10)); delegated_->setIsDrawable(true); @@ -33,11 +80,32 @@ class LayerTreeHostDelegatedTestCreateChildId } virtual void beginTest() OVERRIDE { - num_activates_ = 0; - did_reset_child_id_ = false; postSetNeedsCommitToMainThread(); } + virtual void afterTest() OVERRIDE {} + + protected: + scoped_refptr<Layer> root_; + scoped_refptr<DelegatedRendererLayer> delegated_; +}; + +class LayerTreeHostDelegatedTestCreateChildId + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + LayerTreeHostDelegatedTestCreateChildId() + : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(), + num_activates_(0), + did_reset_child_id_(false) {} + + virtual void UpdateDelegatedLayer(TestDelegatedRendererLayer* layer) + OVERRIDE { + if (testEnded()) + return; + layer->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 1, 1), + gfx::Rect(0, 0, 1, 1))); + } + virtual void treeActivatedOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { LayerImpl* root_impl = host_impl->activeTree()->RootLayer(); DelegatedRendererLayerImpl* delegated_impl = @@ -81,11 +149,158 @@ class LayerTreeHostDelegatedTestCreateChildId protected: int num_activates_; bool did_reset_child_id_; - scoped_refptr<Layer> root_; - scoped_refptr<DelegatedRendererLayer> delegated_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestCreateChildId) +class LayerTreeHostDelegatedTestLayerUsesFrameDamage + : public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer { + public: + LayerTreeHostDelegatedTestLayerUsesFrameDamage() + : LayerTreeHostDelegatedTestCaseSingleDelegatedLayer(), + first_draw_for_source_frame_(true) {} + + virtual void didCommit() OVERRIDE { + int next_source_frame_number = m_layerTreeHost->commitNumber(); + switch (next_source_frame_number) { + case 1: + // Should create a total amount of gfx::Rect(2, 2, 10, 6) damage. + // The frame size is 20x20 while the layer is 10x10, so this should + // produce a gfx::Rect(1, 1, 5, 3) damage rect. + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20), + gfx::Rect(2, 2, 5, 5))); + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 20, 20), + gfx::Rect(7, 2, 5, 6))); + break; + case 2: + // Should create zero damage. + m_layerTreeHost->setNeedsCommit(); + break; + case 3: + // Should damage the full viewport. + delegated_->setBounds(gfx::Size(2, 2)); + break; + case 4: + // Should create zero damage. + m_layerTreeHost->setNeedsCommit(); + break; + case 5: + // Should damage the full layer. + delegated_->setBounds(gfx::Size(6, 6)); + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5), + gfx::Rect(1, 1, 2, 2))); + break; + case 6: + // Should create zero damage. + m_layerTreeHost->setNeedsCommit(); + break; + case 7: + // Should damage the full layer. + delegated_->SetDisplaySize(gfx::Size(10, 10)); + break; + case 8: + // Should create zero damage. + m_layerTreeHost->setNeedsCommit(); + break; + case 9: + // Setting an empty frame should damage the whole layer the + // first time. + delegated_->SetFrameData(CreateEmptyFrameData()); + break; + case 10: + // Setting an empty frame shouldn't damage anything after the + // first time. + delegated_->SetFrameData(CreateEmptyFrameData()); + break; + case 11: + // Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is + // 5x5 and the display size is now set to 10x10, so this should result + // in a gfx::Rect(2, 2, 4, 4) damage rect. + delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5), + gfx::Rect(1, 1, 2, 2))); + break; + case 12: + // Should create zero damage. + m_layerTreeHost->setNeedsCommit(); + break; + } + first_draw_for_source_frame_ = true; + } + + virtual bool prepareToDrawOnThread(LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData& frame, + bool result) { + EXPECT_TRUE(result); + + if (!first_draw_for_source_frame_) + return result; + + gfx::RectF damage_rect = frame.renderPasses.back()->damage_rect; + + switch (host_impl->activeTree()->source_frame_number()) { + case 0: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(), + damage_rect.ToString()); + break; + case 1: + EXPECT_EQ(gfx::RectF(1.f, 1.f, 5.f, 3.f).ToString(), + damage_rect.ToString()); + break; + case 2: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + break; + case 3: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 10.f, 10.f).ToString(), + damage_rect.ToString()); + break; + case 4: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + break; + case 5: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); + break; + case 6: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + break; + case 7: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); + break; + case 8: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + break; + case 9: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 6.f, 6.f).ToString(), + damage_rect.ToString()); + break; + case 10: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + break; + case 11: + EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(), + damage_rect.ToString()); + break; + case 12: + EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(), + damage_rect.ToString()); + endTest(); + break; + } + + return result; + } + + protected: + bool first_draw_for_source_frame_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestLayerUsesFrameDamage) + } // namespace } // namespace cc diff --git a/cc/test/layer_tree_test_common.cc b/cc/test/layer_tree_test_common.cc index 2240279..82603d7 100644 --- a/cc/test/layer_tree_test_common.cc +++ b/cc/test/layer_tree_test_common.cc @@ -289,6 +289,7 @@ ThreadedTest::ThreadedTest() , m_timedOut(false) , m_scheduled(false) , m_started(false) + , m_ended(false) , m_implThread(0) , m_weakFactory(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { @@ -399,6 +400,8 @@ void ThreadedTest::scheduleComposite() void ThreadedTest::realEndTest() { + m_ended = true; + if (m_layerTreeHost && proxy()->commitPendingForTesting()) { proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::realEndTest, m_mainThreadWeakPtr)); return; diff --git a/cc/test/layer_tree_test_common.h b/cc/test/layer_tree_test_common.h index 82fe126..25a1fd8 100644 --- a/cc/test/layer_tree_test_common.h +++ b/cc/test/layer_tree_test_common.h @@ -131,12 +131,15 @@ protected: scoped_ptr<MockLayerImplTreeHostClient> m_client; scoped_ptr<LayerTreeHost> m_layerTreeHost; + bool testEnded() const { return m_ended; } + private: bool m_beginning; bool m_endWhenBeginReturns; bool m_timedOut; bool m_scheduled; bool m_started; + bool m_ended; scoped_ptr<Thread> m_mainCCThread; scoped_ptr<base::Thread> m_implThread; |