diff options
author | dtrainor <dtrainor@chromium.org> | 2016-01-04 01:53:05 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-04 09:54:21 +0000 |
commit | 8e9da48fa5086b27e076b21f729254cc8451c923 (patch) | |
tree | e9dce6ef8014c4a59ad12d3fdcf66f675e9424fe | |
parent | 5b06f2d1b704eec621a691f55fd16db08a5e6554 (diff) | |
download | chromium_src-8e9da48fa5086b27e076b21f729254cc8451c923.zip chromium_src-8e9da48fa5086b27e076b21f729254cc8451c923.tar.gz chromium_src-8e9da48fa5086b27e076b21f729254cc8451c923.tar.bz2 |
Serialize PictureLayer properties.
Serialize the properties specific to the PictureLayer subclass. This
required a few slight changes:
- Don't query LayerImpl::bounds() in PictureLayer::PushPropertiesTo().
Instead rely on either Layer::bounds() or
Layer::paint_properties().bounds depending on the
source_frame_number. Since LayerImpl's bounds are set by
Layer::PushPropertiesTo() right before this check, this should
result in the same behavior.
- Create an EmptyContentLayerClient to be used by all PictureLayer
instances created by
LayerProtoConverter::FindOrAllocateAndConstruct().
BUG=538710
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1527863002
Cr-Commit-Position: refs/heads/master@{#367300}
-rw-r--r-- | blimp/common/proto/blimp_message.proto | 3 | ||||
-rw-r--r-- | blimp/common/proto/input.proto | 3 | ||||
-rw-r--r-- | blimp/common/proto/tab_control.proto | 3 | ||||
-rw-r--r-- | cc/BUILD.gn | 2 | ||||
-rw-r--r-- | cc/cc.gyp | 2 | ||||
-rw-r--r-- | cc/layers/empty_content_layer_client.cc | 45 | ||||
-rw-r--r-- | cc/layers/empty_content_layer_client.h | 47 | ||||
-rw-r--r-- | cc/layers/layer.cc | 2 | ||||
-rw-r--r-- | cc/layers/layer_proto_converter.cc | 11 | ||||
-rw-r--r-- | cc/layers/layer_proto_converter_unittest.cc | 51 | ||||
-rw-r--r-- | cc/layers/picture_layer.cc | 85 | ||||
-rw-r--r-- | cc/layers/picture_layer.h | 8 | ||||
-rw-r--r-- | cc/layers/picture_layer_unittest.cc | 153 | ||||
-rw-r--r-- | cc/playback/display_list_recording_source.cc | 14 | ||||
-rw-r--r-- | cc/playback/display_list_recording_source_unittest.cc | 13 | ||||
-rw-r--r-- | cc/proto/layer.proto | 20 | ||||
-rw-r--r-- | cc/test/fake_display_list_recording_source.cc | 12 |
17 files changed, 420 insertions, 54 deletions
diff --git a/blimp/common/proto/blimp_message.proto b/blimp/common/proto/blimp_message.proto index 733c21fd..db73e03 100644 --- a/blimp/common/proto/blimp_message.proto +++ b/blimp/common/proto/blimp_message.proto @@ -66,7 +66,8 @@ message BlimpMessage { // Feature-specific messages follow. // Only one of these fields may be set per BlimpMessage. - // TODO(kmarshall): use a 'oneof' union when it's supported in Chromium. + // TODO(kmarshall): use a 'oneof' union when it's supported in Chromium. See + // crbug.com/570371. optional TabControlMessage tab_control = 1000; optional NavigationMessage navigation = 1001; optional RenderWidgetMessage render_widget = 1002; diff --git a/blimp/common/proto/input.proto b/blimp/common/proto/input.proto index 7b9a404..a411fc4 100644 --- a/blimp/common/proto/input.proto +++ b/blimp/common/proto/input.proto @@ -87,7 +87,8 @@ message InputMessage { // Input event specific messages follow. // Only one of these fields may be set per InputMessage. - // TODO(dtrainor): use a 'oneof' union when it's supported in Chromium. + // TODO(dtrainor): use a 'oneof' union when it's supported in Chromium. See + // crbug.com/570371. optional GestureScrollBegin gesture_scroll_begin = 4; optional GestureScrollUpdate gesture_scroll_update = 5; optional GestureFlingStart gesture_fling_start = 6; diff --git a/blimp/common/proto/tab_control.proto b/blimp/common/proto/tab_control.proto index d71397c..ead55f0 100644 --- a/blimp/common/proto/tab_control.proto +++ b/blimp/common/proto/tab_control.proto @@ -28,6 +28,7 @@ message TabControlMessage { // Feature-specific messages follow. // Only one of these fields may be set per TabControlMessage. - // TODO(kmarshall): use a 'oneof' union when it's supported in Chromium. + // TODO(kmarshall): use a 'oneof' union when it's supported in Chromium. See + // crbug.com/570371. optional SizeMessage size = 1000; } diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 4f1b235..88fff04 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -123,6 +123,8 @@ component("cc") { "layers/delegated_renderer_layer_impl.h", "layers/draw_properties.cc", "layers/draw_properties.h", + "layers/empty_content_layer_client.cc", + "layers/empty_content_layer_client.h", "layers/heads_up_display_layer.cc", "layers/heads_up_display_layer.h", "layers/heads_up_display_layer_impl.cc", @@ -185,6 +185,8 @@ 'layers/delegated_renderer_layer_impl.h', 'layers/draw_properties.cc', 'layers/draw_properties.h', + 'layers/empty_content_layer_client.cc', + 'layers/empty_content_layer_client.h', 'layers/heads_up_display_layer.cc', 'layers/heads_up_display_layer.h', 'layers/heads_up_display_layer_impl.cc', diff --git a/cc/layers/empty_content_layer_client.cc b/cc/layers/empty_content_layer_client.cc new file mode 100644 index 0000000..1eac1a1 --- /dev/null +++ b/cc/layers/empty_content_layer_client.cc @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/empty_content_layer_client.h" + +#include "cc/playback/display_item_list.h" +#include "cc/playback/display_item_list_settings.h" +#include "ui/gfx/geometry/rect.h" + +namespace cc { + +namespace { +base::LazyInstance<EmptyContentLayerClient> g_empty_content_layer_client = + LAZY_INSTANCE_INITIALIZER; +} + +// static +ContentLayerClient* EmptyContentLayerClient::GetInstance() { + return g_empty_content_layer_client.Pointer(); +} + +EmptyContentLayerClient::EmptyContentLayerClient() {} + +EmptyContentLayerClient::~EmptyContentLayerClient() {} + +gfx::Rect EmptyContentLayerClient::PaintableRegion() { + return gfx::Rect(); +} + +scoped_refptr<DisplayItemList> +EmptyContentLayerClient::PaintContentsToDisplayList( + PaintingControlSetting painting_status) { + return DisplayItemList::Create(gfx::Rect(), DisplayItemListSettings()); +} + +bool EmptyContentLayerClient::FillsBoundsCompletely() const { + return false; +} + +size_t EmptyContentLayerClient::GetApproximateUnsharedMemoryUsage() const { + return 0u; +} + +} // namespace cc diff --git a/cc/layers/empty_content_layer_client.h b/cc/layers/empty_content_layer_client.h new file mode 100644 index 0000000..2554b8a --- /dev/null +++ b/cc/layers/empty_content_layer_client.h @@ -0,0 +1,47 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ +#define CC_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "cc/base/cc_export.h" +#include "cc/layers/content_layer_client.h" +#include "ui/gfx/geometry/rect.h" + +namespace cc { + +class DisplayItemList; + +// This is used by deserialized PictureLayers which have no local +// ContentLayerClient but still have valid content from the original serialized +// PictureLayer. The PictureLayer class requires a valid ContentLayerClient to +// determine if it can draw. This is a dummy client to keep the logic fairly +// straightforward. This is also used by unit tests for creating dummy +// PictureLayers. +class CC_EXPORT EmptyContentLayerClient : public ContentLayerClient { + public: + static ContentLayerClient* GetInstance(); + + // ContentLayerClient implementation. + gfx::Rect PaintableRegion() override; + scoped_refptr<DisplayItemList> PaintContentsToDisplayList( + PaintingControlSetting painting_status) override; + bool FillsBoundsCompletely() const override; + size_t GetApproximateUnsharedMemoryUsage() const override; + + private: + friend struct base::DefaultLazyInstanceTraits<EmptyContentLayerClient>; + + EmptyContentLayerClient(); + ~EmptyContentLayerClient() override; + + DISALLOW_COPY_AND_ASSIGN(EmptyContentLayerClient); +}; + +} // namespace cc + +#endif // CC_LAYERS_EMPTY_CONTENT_LAYER_CLIENT_H_ diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 663f4ae..9d82b58 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -1361,7 +1361,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { } void Layer::SetTypeForProtoSerialization(proto::LayerNode* proto) const { - proto->set_type(proto::LayerType::Base); + proto->set_type(proto::LayerType::LAYER); } void Layer::ToLayerNodeProto(proto::LayerNode* proto) const { diff --git a/cc/layers/layer_proto_converter.cc b/cc/layers/layer_proto_converter.cc index 65e1b14..6564e0b 100644 --- a/cc/layers/layer_proto_converter.cc +++ b/cc/layers/layer_proto_converter.cc @@ -5,8 +5,10 @@ #include "cc/layers/layer_proto_converter.h" #include "base/stl_util.h" +#include "cc/layers/empty_content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/layer_settings.h" +#include "cc/layers/picture_layer.h" #include "cc/proto/layer.pb.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_settings.h" @@ -103,8 +105,15 @@ scoped_refptr<Layer> LayerProtoConverter::FindOrAllocateAndConstruct( return iter->second; DCHECK(proto.has_type()); switch (proto.type()) { - case proto::Base: + // Fall through and build a base layer. This won't have any special layer + // properties but still maintains the layer hierarchy if we run into a + // layer type we don't support. + case proto::UNKNOWN: + case proto::LAYER: return Layer::Create(LayerSettings()).get(); + case proto::PICTURE_LAYER: + return PictureLayer::Create(LayerSettings(), + EmptyContentLayerClient::GetInstance()); } // TODO(nyquist): Add the rest of the necessary LayerTypes. This function // should not return null. diff --git a/cc/layers/layer_proto_converter_unittest.cc b/cc/layers/layer_proto_converter_unittest.cc index 0a85b44..e1a30e6 100644 --- a/cc/layers/layer_proto_converter_unittest.cc +++ b/cc/layers/layer_proto_converter_unittest.cc @@ -4,8 +4,10 @@ #include "cc/layers/layer_proto_converter.h" +#include "cc/layers/empty_content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/layer_settings.h" +#include "cc/layers/picture_layer.h" #include "cc/proto/layer.pb.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" @@ -48,21 +50,21 @@ TEST_F(LayerProtoConverterTest, TestKeepingRoot) { scoped_refptr<Layer> old_root = Layer::Create(LayerSettings()); proto::LayerNode root_node; root_node.set_id(old_root->id()); - root_node.set_type(proto::LayerType::Base); + root_node.set_type(proto::LayerType::LAYER); proto::LayerNode* child_a_node = root_node.add_children(); child_a_node->set_id(442); - child_a_node->set_type(proto::LayerType::Base); + child_a_node->set_type(proto::LayerType::LAYER); child_a_node->set_parent_id(old_root->id()); // root_node proto::LayerNode* child_b_node = root_node.add_children(); child_b_node->set_id(443); - child_b_node->set_type(proto::LayerType::Base); + child_b_node->set_type(proto::LayerType::LAYER); child_b_node->set_parent_id(old_root->id()); // root_node proto::LayerNode* child_c_node = child_b_node->add_children(); child_c_node->set_id(444); - child_c_node->set_type(proto::LayerType::Base); + child_c_node->set_type(proto::LayerType::LAYER); child_c_node->set_parent_id(child_b_node->id()); scoped_refptr<Layer> new_root = @@ -95,21 +97,21 @@ TEST_F(LayerProtoConverterTest, TestSwappingRoot) { */ proto::LayerNode root_node; root_node.set_id(441); - root_node.set_type(proto::LayerType::Base); + root_node.set_type(proto::LayerType::LAYER); proto::LayerNode* child_a_node = root_node.add_children(); child_a_node->set_id(442); - child_a_node->set_type(proto::LayerType::Base); + child_a_node->set_type(proto::LayerType::LAYER); child_a_node->set_parent_id(root_node.id()); proto::LayerNode* child_b_node = root_node.add_children(); child_b_node->set_id(443); - child_b_node->set_type(proto::LayerType::Base); + child_b_node->set_type(proto::LayerType::LAYER); child_b_node->set_parent_id(root_node.id()); proto::LayerNode* child_c_node = child_b_node->add_children(); child_c_node->set_id(444); - child_c_node->set_type(proto::LayerType::Base); + child_c_node->set_type(proto::LayerType::LAYER); child_c_node->set_parent_id(child_b_node->id()); scoped_refptr<Layer> old_root = Layer::Create(LayerSettings()); @@ -339,5 +341,38 @@ TEST_F(LayerProtoConverterTest, DeserializeLayerProperties) { root->SetLayerTreeHost(nullptr); } +TEST_F(LayerProtoConverterTest, PictureLayerTypeSerialization) { + // Make sure that PictureLayers serialize to the + // proto::LayerType::PICTURE_LAYER type. + scoped_refptr<PictureLayer> layer = PictureLayer::Create( + LayerSettings(), EmptyContentLayerClient::GetInstance()); + + proto::LayerNode layer_hierarchy; + LayerProtoConverter::SerializeLayerHierarchy(layer.get(), &layer_hierarchy); + EXPECT_EQ(proto::LayerType::PICTURE_LAYER, layer_hierarchy.type()); +} + +TEST_F(LayerProtoConverterTest, PictureLayerTypeDeserialization) { + // Make sure that proto::LayerType::PICTURE_LAYER ends up building a + // PictureLayer. + scoped_refptr<Layer> old_root = PictureLayer::Create( + LayerSettings(), EmptyContentLayerClient::GetInstance()); + proto::LayerNode root_node; + root_node.set_id(old_root->id()); + root_node.set_type(proto::LayerType::PICTURE_LAYER); + + scoped_refptr<Layer> new_root = + LayerProtoConverter::DeserializeLayerHierarchy(old_root, root_node); + + // Validate that the ids are equal. + EXPECT_EQ(old_root->id(), new_root->id()); + + // Check that the layer type is equal by using the type this layer would + // serialize to. + proto::LayerNode layer_node; + new_root->SetTypeForProtoSerialization(&layer_node); + EXPECT_EQ(proto::LayerType::PICTURE_LAYER, layer_node.type()); +} + } // namespace } // namespace cc diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index 811e806..284f2a3 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc @@ -8,6 +8,9 @@ #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer_impl.h" #include "cc/playback/display_list_recording_source.h" +#include "cc/proto/cc_conversions.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/layer.pb.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -50,25 +53,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); // TODO(danakj): Make is_mask_ a constructor parameter for PictureLayer. DCHECK_EQ(layer_impl->is_mask(), is_mask_); - - int source_frame_number = layer_tree_host()->source_frame_number(); - gfx::Size impl_bounds = layer_impl->bounds(); - gfx::Size recording_source_bounds = recording_source_->GetSize(); - - // If update called, then recording source size must match bounds pushed to - // impl layer. - DCHECK(update_source_frame_number_ != source_frame_number || - impl_bounds == recording_source_bounds) - << " bounds " << impl_bounds.ToString() << " recording source " - << recording_source_bounds.ToString(); - - if (update_source_frame_number_ != source_frame_number && - recording_source_bounds != impl_bounds) { - // Update may not get called for the layer (if it's not in the viewport - // for example, even though it has resized making the recording source no - // longer valid. In this case just destroy the recording source. - recording_source_->SetEmptyBounds(); - } + DropRecordingSourceContentIfInvalid(); layer_impl->SetNearestNeighbor(nearest_neighbor_); @@ -198,8 +183,70 @@ bool PictureLayer::HasDrawableContent() const { return client_ && Layer::HasDrawableContent(); } +void PictureLayer::SetTypeForProtoSerialization(proto::LayerNode* proto) const { + proto->set_type(proto::LayerType::PICTURE_LAYER); +} + +void PictureLayer::LayerSpecificPropertiesToProto( + proto::LayerProperties* proto) { + Layer::LayerSpecificPropertiesToProto(proto); + DropRecordingSourceContentIfInvalid(); + + proto::PictureLayerProperties* picture = proto->mutable_picture(); + recording_source_->ToProtobuf(picture->mutable_recording_source()); + RegionToProto(*invalidation_.region(), picture->mutable_invalidation()); + RectToProto(last_updated_visible_layer_rect_, + picture->mutable_last_updated_visible_layer_rect()); + picture->set_is_mask(is_mask_); + picture->set_nearest_neighbor(nearest_neighbor_); + + picture->set_update_source_frame_number(update_source_frame_number_); + + invalidation_.Clear(); +} + +void PictureLayer::FromLayerSpecificPropertiesProto( + const proto::LayerProperties& proto) { + Layer::FromLayerSpecificPropertiesProto(proto); + const proto::PictureLayerProperties& picture = proto.picture(); + recording_source_->FromProtobuf(picture.recording_source()); + + Region new_invalidation = RegionFromProto(picture.invalidation()); + invalidation_.Swap(&new_invalidation); + last_updated_visible_layer_rect_ = + ProtoToRect(picture.last_updated_visible_layer_rect()); + is_mask_ = picture.is_mask(); + nearest_neighbor_ = picture.nearest_neighbor(); + + update_source_frame_number_ = picture.update_source_frame_number(); +} + void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { benchmark->RunOnLayer(this); } +void PictureLayer::DropRecordingSourceContentIfInvalid() { + int source_frame_number = layer_tree_host()->source_frame_number(); + gfx::Size recording_source_bounds = recording_source_->GetSize(); + + gfx::Size layer_bounds = bounds(); + if (paint_properties().source_frame_number == source_frame_number) + layer_bounds = paint_properties().bounds; + + // If update called, then recording source size must match bounds pushed to + // impl layer. + DCHECK(update_source_frame_number_ != source_frame_number || + layer_bounds == recording_source_bounds) + << " bounds " << layer_bounds.ToString() << " recording source " + << recording_source_bounds.ToString(); + + if (update_source_frame_number_ != source_frame_number && + recording_source_bounds != layer_bounds) { + // Update may not get called for the layer (if it's not in the viewport + // for example), even though it has resized making the recording source no + // longer valid. In this case just destroy the recording source. + recording_source_->SetEmptyBounds(); + } +} + } // namespace cc diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h index 7f1345e..b7e7152 100644 --- a/cc/layers/picture_layer.h +++ b/cc/layers/picture_layer.h @@ -53,10 +53,18 @@ class CC_EXPORT PictureLayer : public Layer { ~PictureLayer() override; bool HasDrawableContent() const override; + void SetTypeForProtoSerialization(proto::LayerNode* proto) const override; + void LayerSpecificPropertiesToProto(proto::LayerProperties* proto) override; + void FromLayerSpecificPropertiesProto( + const proto::LayerProperties& proto) override; bool is_mask() const { return is_mask_; } private: + friend class TestSerializationPictureLayer; + + void DropRecordingSourceContentIfInvalid(); + ContentLayerClient* client_; scoped_ptr<DisplayListRecordingSource> recording_source_; devtools_instrumentation:: diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc index 9568bde..df72639 100644 --- a/cc/layers/picture_layer_unittest.cc +++ b/cc/layers/picture_layer_unittest.cc @@ -8,9 +8,11 @@ #include "base/thread_task_runner_handle.h" #include "cc/layers/content_layer_client.h" +#include "cc/layers/empty_content_layer_client.h" #include "cc/layers/layer_settings.h" #include "cc/layers/picture_layer_impl.h" #include "cc/playback/display_item_list_settings.h" +#include "cc/proto/layer.pb.h" #include "cc/test/fake_display_list_recording_source.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_picture_layer.h" @@ -23,23 +25,144 @@ #include "testing/gtest/include/gtest/gtest.h" namespace cc { -namespace { -class MockContentLayerClient : public ContentLayerClient { +class TestSerializationPictureLayer : public PictureLayer { public: - gfx::Rect PaintableRegion() override { return gfx::Rect(); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting picture_control) override { - return DisplayItemList::Create(gfx::Rect(), DisplayItemListSettings()); + static scoped_refptr<TestSerializationPictureLayer> Create( + const gfx::Size& recording_source_viewport) { + return make_scoped_refptr(new TestSerializationPictureLayer( + LayerSettings(), EmptyContentLayerClient::GetInstance(), + FakeDisplayListRecordingSource::CreateFilledRecordingSource( + recording_source_viewport), + recording_source_viewport)); + } + + FakeDisplayListRecordingSource* recording_source() { + return static_cast<FakeDisplayListRecordingSource*>( + recording_source_.get()); + } + + void set_invalidation(const Region& invalidation) { + *invalidation_.region() = invalidation; + } + + void set_last_updated_visible_layer_rect(const gfx::Rect& rect) { + last_updated_visible_layer_rect_ = rect; + } + + void set_update_source_frame_number(int number) { + update_source_frame_number_ = number; + } + + void set_is_mask(bool is_mask) { is_mask_ = is_mask; } + + void set_nearest_neighbor(bool nearest_neighbor) { + nearest_neighbor_ = nearest_neighbor; } - bool FillsBoundsCompletely() const override { return false; }; - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } + + void ValidateSerialization() { + proto::LayerProperties proto; + LayerSpecificPropertiesToProto(&proto); + + FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); + scoped_refptr<TestSerializationPictureLayer> layer = + TestSerializationPictureLayer::Create(recording_source_viewport_); + host->SetRootLayer(layer); + layer->FromLayerSpecificPropertiesProto(proto); + + // Validate that the PictureLayer specific fields are properly set. + EXPECT_TRUE(recording_source()->EqualsTo(*layer->recording_source())); + EXPECT_EQ(last_updated_visible_layer_rect_, + layer->last_updated_visible_layer_rect_); + EXPECT_EQ(update_source_frame_number_, layer->update_source_frame_number_); + EXPECT_EQ(is_mask_, layer->is_mask_); + EXPECT_EQ(nearest_neighbor_, layer->nearest_neighbor_); + } + + private: + TestSerializationPictureLayer(const LayerSettings& settings, + ContentLayerClient* client, + scoped_ptr<DisplayListRecordingSource> source, + const gfx::Size& recording_source_viewport) + : PictureLayer(settings, client, std::move(source)), + recording_source_viewport_(recording_source_viewport) {} + ~TestSerializationPictureLayer() override {} + + gfx::Size recording_source_viewport_; + + DISALLOW_COPY_AND_ASSIGN(TestSerializationPictureLayer); }; +namespace { + +TEST(PictureLayerTest, TestSetAllPropsSerializationDeserialization) { + FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); + + gfx::Size recording_source_viewport(256, 256); + scoped_refptr<TestSerializationPictureLayer> layer = + TestSerializationPictureLayer::Create(recording_source_viewport); + host->SetRootLayer(layer); + + Region region(gfx::Rect(14, 15, 16, 17)); + layer->set_invalidation(region); + layer->set_last_updated_visible_layer_rect(gfx::Rect(5, 6, 7, 8)); + layer->set_is_mask(true); + layer->set_nearest_neighbor(true); + + layer->SetBounds(recording_source_viewport); + layer->set_update_source_frame_number(0); + layer->recording_source()->SetDisplayListUsesCachedPicture(false); + layer->recording_source()->add_draw_rect( + gfx::Rect(recording_source_viewport)); + layer->recording_source()->SetGenerateDiscardableImagesMetadata(true); + layer->recording_source()->Rerecord(); + layer->ValidateSerialization(); +} + +TEST(PictureLayerTest, TestSerializationDeserialization) { + FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); + + gfx::Size recording_source_viewport(256, 256); + scoped_refptr<TestSerializationPictureLayer> layer = + TestSerializationPictureLayer::Create(recording_source_viewport); + host->SetRootLayer(layer); + + layer->SetBounds(recording_source_viewport); + layer->set_update_source_frame_number(0); + layer->recording_source()->SetDisplayListUsesCachedPicture(false); + layer->recording_source()->add_draw_rect( + gfx::Rect(recording_source_viewport)); + layer->recording_source()->SetGenerateDiscardableImagesMetadata(true); + layer->recording_source()->Rerecord(); + layer->ValidateSerialization(); +} + +TEST(PictureLayerTest, TestEmptySerializationDeserialization) { + FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner; + scoped_ptr<FakeLayerTreeHost> host = + FakeLayerTreeHost::Create(&host_client, &task_graph_runner); + + gfx::Size recording_source_viewport(256, 256); + scoped_refptr<TestSerializationPictureLayer> layer = + TestSerializationPictureLayer::Create(recording_source_viewport); + host->SetRootLayer(layer); + layer->ValidateSerialization(); +} + TEST(PictureLayerTest, NoTilesIfEmptyBounds) { - MockContentLayerClient client; + ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); scoped_refptr<PictureLayer> layer = - PictureLayer::Create(LayerSettings(), &client); + PictureLayer::Create(LayerSettings(), client); layer->SetBounds(gfx::Size(10, 10)); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); @@ -83,10 +206,10 @@ TEST(PictureLayerTest, SuitableForGpuRasterization) { FakeDisplayListRecordingSource* recording_source = recording_source_owned.get(); - MockContentLayerClient client; + ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); scoped_refptr<FakePictureLayer> layer = FakePictureLayer::CreateWithRecordingSource( - LayerSettings(), &client, std::move(recording_source_owned)); + LayerSettings(), client, std::move(recording_source_owned)); FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D); TestTaskGraphRunner task_graph_runner; @@ -99,7 +222,7 @@ TEST(PictureLayerTest, SuitableForGpuRasterization) { gfx::Rect layer_rect(layer_bounds); Region invalidation(layer_rect); recording_source->UpdateAndExpandInvalidation( - &client, &invalidation, layer_bounds, layer_rect, 1, + client, &invalidation, layer_bounds, layer_rect, 1, DisplayListRecordingSource::RECORD_NORMALLY); // Layer is suitable for gpu rasterization by default. @@ -126,9 +249,9 @@ TEST(PictureLayerTest, NonMonotonicSourceFrameNumber) { TestSharedBitmapManager shared_bitmap_manager; TestTaskGraphRunner task_graph_runner; - MockContentLayerClient client; + ContentLayerClient* client = EmptyContentLayerClient::GetInstance(); scoped_refptr<FakePictureLayer> layer = - FakePictureLayer::Create(LayerSettings(), &client); + FakePictureLayer::Create(LayerSettings(), client); LayerTreeHost::InitParams params; params.client = &host_client1; diff --git a/cc/playback/display_list_recording_source.cc b/cc/playback/display_list_recording_source.cc index 9054238..37dc906 100644 --- a/cc/playback/display_list_recording_source.cc +++ b/cc/playback/display_list_recording_source.cc @@ -61,7 +61,8 @@ void DisplayListRecordingSource::ToProtobuf( proto->set_clear_canvas_with_debug_color(clear_canvas_with_debug_color_); proto->set_solid_color(static_cast<uint64_t>(solid_color_)); proto->set_background_color(static_cast<uint64_t>(background_color_)); - display_list_->ToProtobuf(proto->mutable_display_list()); + if (display_list_) + display_list_->ToProtobuf(proto->mutable_display_list()); } void DisplayListRecordingSource::FromProtobuf( @@ -77,9 +78,16 @@ void DisplayListRecordingSource::FromProtobuf( clear_canvas_with_debug_color_ = proto.clear_canvas_with_debug_color(); solid_color_ = static_cast<SkColor>(proto.solid_color()); background_color_ = static_cast<SkColor>(proto.background_color()); - display_list_ = DisplayItemList::CreateFromProto(proto.display_list()); - FinishDisplayItemListUpdate(); + // This might not exist if the |display_list_| of the serialized + // DisplayListRecordingSource was null, wich can happen if |Clear()| is + // called. + if (proto.has_display_list()) { + display_list_ = DisplayItemList::CreateFromProto(proto.display_list()); + FinishDisplayItemListUpdate(); + } else { + display_list_ = nullptr; + } } void DisplayListRecordingSource::UpdateInvalidationForNewViewport( diff --git a/cc/playback/display_list_recording_source_unittest.cc b/cc/playback/display_list_recording_source_unittest.cc index b687160..1649566 100644 --- a/cc/playback/display_list_recording_source_unittest.cc +++ b/cc/playback/display_list_recording_source_unittest.cc @@ -42,6 +42,19 @@ void ValidateRecordingSourceSerialization( EXPECT_TRUE(source->EqualsTo(new_source)); } +TEST(DisplayListRecordingSourceTest, TestNullDisplayListSerialization) { + gfx::Rect recorded_viewport(0, 0, 256, 256); + + scoped_ptr<FakeDisplayListRecordingSource> recording_source = + CreateRecordingSource(recorded_viewport); + recording_source->SetDisplayListUsesCachedPicture(false); + recording_source->SetGenerateDiscardableImagesMetadata(true); + recording_source->Rerecord(); + recording_source->SetEmptyBounds(); + + ValidateRecordingSourceSerialization(recording_source.get()); +} + TEST(DisplayListRecordingSourceTest, TestEmptySerializationDeserialization) { gfx::Rect recorded_viewport(0, 0, 256, 256); diff --git a/cc/proto/layer.proto b/cc/proto/layer.proto index d7b3ce3..41b3f2d 100644 --- a/cc/proto/layer.proto +++ b/cc/proto/layer.proto @@ -4,6 +4,7 @@ syntax = "proto2"; +import "display_list_recording_source.proto"; import "layer_position_constraint.proto"; import "point3f.proto"; import "pointf.proto"; @@ -22,7 +23,9 @@ option optimize_for = LITE_RUNTIME; // Identifies the type of cc:Layer a LayerNode represents. It is used to // facilitate reconstruction of a Layer of the correct type on the client. enum LayerType { - Base = 1; + UNKNOWN = 0; + LAYER = 1; + PICTURE_LAYER = 2; // TODO(nyquist): Add the rest of the necessary LayerTypes. }; @@ -58,6 +61,11 @@ message LayerProperties { // The Layer base class and each descendant have different proto messages // for their specific properties. optional BaseLayerProperties base = 5; + + // Only one of these fields may be set per LayerProperties. + // TODO(dtrainor): use a 'oneof' union when it's supported in Chromium. See + // crbug.com/570371. + optional PictureLayerProperties picture = 6; } message BaseLayerProperties { @@ -121,3 +129,13 @@ message BaseLayerProperties { // TODO(nyquist): Figure out what to do with FrameTimingRequests. // repeated FrameTimingRequest frame_timing_requests = 49; } + +message PictureLayerProperties { + optional DisplayListRecordingSource recording_source = 1; + optional Region invalidation = 2; + optional Rect last_updated_visible_layer_rect = 3; + optional bool is_mask = 4; + optional bool nearest_neighbor = 5; + + optional int64 update_source_frame_number = 6; +}
\ No newline at end of file diff --git a/cc/test/fake_display_list_recording_source.cc b/cc/test/fake_display_list_recording_source.cc index fe0a127..01e6048 100644 --- a/cc/test/fake_display_list_recording_source.cc +++ b/cc/test/fake_display_list_recording_source.cc @@ -27,6 +27,14 @@ FakeDisplayListRecordingSource::CreateRasterSource(bool can_use_lcd) const { bool FakeDisplayListRecordingSource::EqualsTo( const FakeDisplayListRecordingSource& other) { + // The DisplayItemLists are equal if they are both null or they are both not + // null and render to the same thing. + bool display_lists_equal = !display_list_ && !other.display_list_; + if (display_list_ && other.display_list_) { + display_lists_equal = AreDisplayListDrawingResultsSame( + recorded_viewport_, display_list_, other.display_list_); + } + return recorded_viewport_ == other.recorded_viewport_ && size_ == other.size_ && slow_down_raster_scale_factor_for_debug_ == @@ -38,9 +46,7 @@ bool FakeDisplayListRecordingSource::EqualsTo( clear_canvas_with_debug_color_ == other.clear_canvas_with_debug_color_ && solid_color_ == other.solid_color_ && - background_color_ == other.background_color_ && - AreDisplayListDrawingResultsSame(recorded_viewport_, display_list_, - other.display_list_); + background_color_ == other.background_color_ && display_lists_equal; } } // namespace cc |