summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordtrainor <dtrainor@chromium.org>2016-01-04 01:53:05 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-04 09:54:21 +0000
commit8e9da48fa5086b27e076b21f729254cc8451c923 (patch)
treee9dce6ef8014c4a59ad12d3fdcf66f675e9424fe
parent5b06f2d1b704eec621a691f55fd16db08a5e6554 (diff)
downloadchromium_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.proto3
-rw-r--r--blimp/common/proto/input.proto3
-rw-r--r--blimp/common/proto/tab_control.proto3
-rw-r--r--cc/BUILD.gn2
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/layers/empty_content_layer_client.cc45
-rw-r--r--cc/layers/empty_content_layer_client.h47
-rw-r--r--cc/layers/layer.cc2
-rw-r--r--cc/layers/layer_proto_converter.cc11
-rw-r--r--cc/layers/layer_proto_converter_unittest.cc51
-rw-r--r--cc/layers/picture_layer.cc85
-rw-r--r--cc/layers/picture_layer.h8
-rw-r--r--cc/layers/picture_layer_unittest.cc153
-rw-r--r--cc/playback/display_list_recording_source.cc14
-rw-r--r--cc/playback/display_list_recording_source_unittest.cc13
-rw-r--r--cc/proto/layer.proto20
-rw-r--r--cc/test/fake_display_list_recording_source.cc12
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",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index bd5dadb..d9bebc4 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -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