Chromium Code Reviews| Index: cc/layers/picture_layer.cc |
| diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc |
| index 081e3158841943ab15a3d8bfaeff318afe457f5e..6c842baa7ae739438818d40d08ae291a2f67c5b5 100644 |
| --- a/cc/layers/picture_layer.cc |
| +++ b/cc/layers/picture_layer.cc |
| @@ -8,7 +8,6 @@ |
| #include "base/trace_event/trace_event.h" |
| #include "cc/layers/content_layer_client.h" |
| #include "cc/layers/picture_layer_impl.h" |
| -#include "cc/playback/recording_source.h" |
| #include "cc/proto/cc_conversions.h" |
| #include "cc/proto/gfx_conversions.h" |
| #include "cc/proto/layer.pb.h" |
| @@ -19,6 +18,17 @@ |
| namespace cc { |
| +PictureLayerData::PictureLayerData() = default; |
| + |
| +PictureLayerData::~PictureLayerData() = default; |
| + |
| +ContentLayerClientData::ContentLayerClientData() = default; |
| + |
| +ContentLayerClientData::ContentLayerClientData(const ContentLayerClientData&) = |
| + default; |
| + |
| +ContentLayerClientData::~ContentLayerClientData() = default; |
| + |
| scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) { |
| return make_scoped_refptr(new PictureLayer(client)); |
| } |
| @@ -31,9 +41,11 @@ PictureLayer::PictureLayer(ContentLayerClient* client) |
| } |
| PictureLayer::PictureLayer(ContentLayerClient* client, |
| - std::unique_ptr<RecordingSource> source) |
| + const PictureLayerData& layer_data, |
| + const ContentLayerClientData& client_data) |
| : PictureLayer(client) { |
| - recording_source_ = std::move(source); |
| + layer_data_ = layer_data; |
| + client_data_ = client_data; |
| } |
| PictureLayer::~PictureLayer() { |
| @@ -57,7 +69,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { |
| // Preserve lcd text settings from the current raster source. |
| bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText(); |
| scoped_refptr<RasterSource> raster_source = |
| - recording_source_->CreateRasterSource(can_use_lcd_text); |
| + CreateRasterSource(layer_data_, client_data_, can_use_lcd_text); |
| layer_impl->set_gpu_raster_max_texture_size( |
| layer_tree_host()->device_viewport_size()); |
| layer_impl->UpdateRasterSource(raster_source, &last_updated_invalidation_, |
| @@ -70,21 +82,19 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { |
| if (!host) |
| return; |
| - if (!recording_source_) |
| - recording_source_.reset(new RecordingSource); |
| - recording_source_->SetSlowdownRasterScaleFactor( |
| - host->debug_state().slow_down_raster_scale_factor); |
| + layer_data_ = PictureLayerData(); |
|
vmpstr
2016/07/20 22:18:10
What's the difference between this and ResetLayerA
Menglin
2016/07/20 22:39:31
ResetLayerAndClientData() is essentially
layer_
vmpstr
2016/07/20 23:55:54
Hmm... It certainly isn't reset if it's only reset
|
| + client_data_ = ContentLayerClientData(); |
| + layer_data_.slow_down_raster_scale_factor_for_debug = |
| + host->debug_state().slow_down_raster_scale_factor; |
| // If we need to enable image decode tasks, then we have to generate the |
| // discardable images metadata. |
| const LayerTreeSettings& settings = layer_tree_host()->settings(); |
| - recording_source_->SetGenerateDiscardableImagesMetadata( |
| - settings.image_decode_tasks_enabled); |
| + SetGenerateDiscardableImagesMetadata(settings.image_decode_tasks_enabled); |
| } |
| void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) { |
| DCHECK(!layer_tree_host() || !layer_tree_host()->in_paint_layer_contents()); |
| - if (recording_source_) |
| - recording_source_->SetNeedsDisplayRect(layer_rect); |
| + SetNeedsDisplayRectSimple(layer_rect); |
|
vmpstr
2016/07/20 22:18:10
Can this function go away as well and just be repl
Menglin
2016/07/20 22:39:31
we probably want to keep it since the test code us
vmpstr
2016/07/20 23:55:54
Thanks! FWIW, we sometimes have FooInternal when t
|
| Layer::SetNeedsDisplayRect(layer_rect); |
| } |
| @@ -94,9 +104,9 @@ bool PictureLayer::Update() { |
| gfx::Size layer_size = paint_properties().bounds; |
| - recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor()); |
| - recording_source_->SetRequiresClear(!contents_opaque() && |
| - !inputs_.client->FillsBoundsCompletely()); |
| + SetBackgroundColorSimple(SafeOpaqueBackgroundColor()); |
| + SetRequiresClear(!contents_opaque() && |
| + !inputs_.client->FillsBoundsCompletely()); |
| TRACE_EVENT1("cc", "PictureLayer::Update", |
| "source_frame_number", |
| @@ -109,9 +119,9 @@ bool PictureLayer::Update() { |
| // to the impl side so that it drops tiles that may not have a recording |
| // for them. |
| DCHECK(inputs_.client); |
| - updated |= recording_source_->UpdateAndExpandInvalidation( |
| - inputs_.client, &last_updated_invalidation_, layer_size, |
| - update_source_frame_number_, RecordingSource::RECORD_NORMALLY); |
| + updated |= UpdateAndExpandInvalidation( |
| + &last_updated_invalidation_, layer_size, PictureLayer::RECORD_NORMALLY, |
|
vmpstr
2016/07/20 22:18:10
Do we ever pass something other than "RECORD_NORMA
Menglin
2016/07/20 22:39:31
I checked, it always pass RECORD_NORMALLY
|
| + &layer_data_, &client_data_, &invalidation_); |
|
vmpstr
2016/07/20 22:18:10
In general, if we can eliminate some of these para
Menglin
2016/07/20 22:39:31
but that doesn't work in GetPicture, where it rece
vmpstr
2016/07/20 23:55:54
Oh yeah, good point.
|
| if (updated) { |
| SetNeedsPushProperties(); |
| @@ -136,20 +146,26 @@ sk_sp<SkPicture> PictureLayer::GetPicture() const { |
| return nullptr; |
| gfx::Size layer_size = bounds(); |
| - std::unique_ptr<RecordingSource> recording_source(new RecordingSource); |
| Region recording_invalidation; |
| - recording_source->UpdateAndExpandInvalidation( |
| - inputs_.client, &recording_invalidation, layer_size, |
| - update_source_frame_number_, RecordingSource::RECORD_NORMALLY); |
| - |
| + InvalidationRegion invalidation_regision; |
|
vmpstr
2016/07/20 22:18:10
s/regision/region/
Menglin
2016/07/20 22:39:31
ok
|
| + PictureLayerData layer_data = PictureLayerData(); |
| + ContentLayerClientData client_data = ContentLayerClientData(); |
| + UpdateAndExpandInvalidation(&recording_invalidation, layer_size, |
| + PictureLayer::RECORD_NORMALLY, &layer_data, |
| + &client_data, &invalidation_regision); |
|
Menglin
2016/07/20 22:39:31
Here it needs the local variables
vmpstr
2016/07/20 23:55:54
Acknowledged.
|
| scoped_refptr<RasterSource> raster_source = |
| - recording_source->CreateRasterSource(false); |
| + CreateRasterSource(layer_data, client_data, false); |
| return raster_source->GetFlattenedPicture(); |
| } |
| bool PictureLayer::IsSuitableForGpuRasterization() const { |
| - return recording_source_->IsSuitableForGpuRasterization(); |
| + // The display list needs to be created (see: UpdateAndExpandInvalidation) |
| + // before checking for suitability. There are cases where an update will not |
| + // create a display list (e.g., if the size is empty). We return true in these |
| + // cases because the gpu suitability bit sticks false. |
| + return !client_data_.display_list || |
| + client_data_.display_list->IsSuitableForGpuRasterization(); |
| } |
| void PictureLayer::ClearClient() { |
| @@ -179,10 +195,26 @@ void PictureLayer::LayerSpecificPropertiesToProto( |
| DropRecordingSourceContentIfInvalid(); |
| proto::PictureLayerProperties* picture = proto->mutable_picture(); |
| - recording_source_->ToProtobuf(picture->mutable_recording_source()); |
| + |
| + RectToProto(client_data_.recorded_viewport, |
| + picture->mutable_recorded_viewport()); |
| + SizeToProto(layer_data_.size, picture->mutable_size()); |
| + picture->set_slow_down_raster_scale_factor_for_debug( |
| + layer_data_.slow_down_raster_scale_factor_for_debug); |
| + picture->set_generate_discardable_images_metadata( |
| + layer_data_.generate_discardable_images_metadata); |
| + picture->set_requires_clear(layer_data_.requires_clear); |
| + picture->set_is_solid_color(layer_data_.is_solid_color); |
| + picture->set_clear_canvas_with_debug_color( |
| + layer_data_.clear_canvas_with_debug_color); |
| + picture->set_solid_color(static_cast<uint64_t>(layer_data_.solid_color)); |
| + picture->set_background_color( |
| + static_cast<uint64_t>(layer_data_.background_color)); |
| + if (client_data_.display_list) |
| + client_data_.display_list->ToProtobuf(picture->mutable_display_list()); |
| // Add all SkPicture items to the picture cache. |
| - const DisplayItemList* display_list = recording_source_->GetDisplayItemList(); |
| + const DisplayItemList* display_list = GetDisplayItemList(); |
| if (display_list) { |
| for (auto it = display_list->begin(); it != display_list->end(); ++it) { |
| sk_sp<const SkPicture> picture = it->GetPicture(); |
| @@ -210,13 +242,36 @@ void PictureLayer::FromLayerSpecificPropertiesProto( |
| // If this is a new layer, ensure it has a recording source. During layer |
| // hierarchy deserialization, ::SetLayerTreeHost(...) is not called, but |
| // instead the member is set directly, so it needs to be set here explicitly. |
| - if (!recording_source_) |
| - recording_source_.reset(new RecordingSource); |
| - |
| + layer_data_ = PictureLayerData(); |
| + client_data_ = ContentLayerClientData(); |
| std::vector<uint32_t> used_engine_picture_ids; |
| - recording_source_->FromProtobuf(picture.recording_source(), |
| - layer_tree_host()->client_picture_cache(), |
| - &used_engine_picture_ids); |
| + |
| + DCHECK(layer_tree_host()->client_picture_cache()); |
| + client_data_.recorded_viewport = ProtoToRect(picture.recorded_viewport()); |
| + layer_data_.size = ProtoToSize(picture.size()); |
| + layer_data_.slow_down_raster_scale_factor_for_debug = |
| + picture.slow_down_raster_scale_factor_for_debug(); |
| + layer_data_.generate_discardable_images_metadata = |
| + picture.generate_discardable_images_metadata(); |
| + layer_data_.requires_clear = picture.requires_clear(); |
| + layer_data_.is_solid_color = picture.is_solid_color(); |
| + layer_data_.clear_canvas_with_debug_color = |
| + picture.clear_canvas_with_debug_color(); |
| + layer_data_.solid_color = static_cast<SkColor>(picture.solid_color()); |
| + layer_data_.background_color = |
| + static_cast<SkColor>(picture.background_color()); |
| + |
| + // This might not exist if the |client_data_.display_list| of the serialized |
| + // RecordingSource was null, which can happen if |Clear()| is |
| + // called. |
| + if (picture.has_display_list()) { |
| + client_data_.display_list = DisplayItemList::CreateFromProto( |
| + picture.display_list(), layer_tree_host()->client_picture_cache(), |
| + &used_engine_picture_ids); |
| + FinishDisplayItemListUpdate(&layer_data_, &client_data_); |
| + } else { |
| + client_data_.display_list = nullptr; |
| + } |
| // Inform picture cache about which SkPictures are now in use. |
| for (uint32_t engine_picture_id : used_engine_picture_ids) |
| @@ -234,9 +289,119 @@ void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { |
| benchmark->RunOnLayer(this); |
| } |
| +bool PictureLayer::UpdateAndExpandInvalidation( |
| + Region* invalidation, |
| + const gfx::Size& layer_size, |
| + PictureLayer::RecordingMode recording_mode, |
| + PictureLayerData* layer_data, |
| + ContentLayerClientData* client_data, |
| + InvalidationRegion* invalidation_state) const { |
| + bool updated = false; |
| + |
| + if (layer_data->size != layer_size) |
| + layer_data->size = layer_size; |
| + |
| + invalidation_state->Swap(invalidation); |
| + invalidation_state->Clear(); |
| + |
| + gfx::Rect new_recorded_viewport = inputs_.client->PaintableRegion(); |
| + if (new_recorded_viewport != client_data->recorded_viewport) { |
| + UpdateInvalidationForNewViewport(client_data->recorded_viewport, |
| + new_recorded_viewport, invalidation); |
| + client_data->recorded_viewport = new_recorded_viewport; |
| + updated = true; |
| + } |
| + |
| + if (!updated && !invalidation->Intersects(client_data->recorded_viewport)) |
| + return false; |
| + |
| + if (invalidation->IsEmpty()) |
| + return false; |
| + |
| + ContentLayerClient::PaintingControlSetting painting_control = |
| + ContentLayerClient::PAINTING_BEHAVIOR_NORMAL; |
| + |
| + switch (recording_mode) { |
| + case PictureLayer::RECORD_NORMALLY: |
| + // Already setup for normal recording. |
| + break; |
| + case PictureLayer::RECORD_WITH_PAINTING_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED; |
| + break; |
| + case PictureLayer::RECORD_WITH_CACHING_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; |
| + break; |
| + case PictureLayer::RECORD_WITH_CONSTRUCTION_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; |
| + break; |
| + case PictureLayer::RECORD_WITH_SUBSEQUENCE_CACHING_DISABLED: |
| + painting_control = ContentLayerClient::SUBSEQUENCE_CACHING_DISABLED; |
| + break; |
| + case PictureLayer::RECORD_WITH_SK_NULL_CANVAS: |
| + case PictureLayer::RECORDING_MODE_COUNT: |
| + NOTREACHED(); |
| + } |
| + |
| + // TODO(vmpstr): Add a slow_down_recording_scale_factor_for_debug_ to be able |
| + // to slow down recording. |
| + client_data->display_list = |
| + inputs_.client->PaintContentsToDisplayList(painting_control); |
| + client_data->painter_reported_memory_usage = |
| + inputs_.client->GetApproximateUnsharedMemoryUsage(); |
| + |
| + FinishDisplayItemListUpdate(layer_data, client_data); |
| + |
| + return true; |
| +} |
| + |
| +void PictureLayer::ResetLayerAndClientData() { |
| + layer_data_.size = gfx::Size(); |
| + client_data_.recorded_viewport = gfx::Rect(); |
| + client_data_.display_list = nullptr; |
| + client_data_.painter_reported_memory_usage = 0; |
| + layer_data_.is_solid_color = false; |
| +} |
| + |
| +void PictureLayer::SetGenerateDiscardableImagesMetadata( |
| + bool generate_metadata) { |
| + layer_data_.generate_discardable_images_metadata = generate_metadata; |
| +} |
| + |
| +void PictureLayer::SetBackgroundColorSimple(SkColor background_color) { |
| + layer_data_.background_color = background_color; |
| +} |
| + |
| +void PictureLayer::SetRequiresClear(bool requires_clear) { |
| + layer_data_.requires_clear = requires_clear; |
| +} |
| + |
| +void PictureLayer::SetNeedsDisplayRectSimple(const gfx::Rect& layer_rect) { |
| + if (!layer_rect.IsEmpty()) { |
| + // Clamp invalidation to the layer bounds. |
| + invalidation_.Union( |
| + gfx::IntersectRects(layer_rect, gfx::Rect(layer_data_.size))); |
| + } |
| +} |
| + |
| +gfx::Size PictureLayer::GetSizeInLayerData() const { |
| + return layer_data_.size; |
| +} |
| + |
| +const DisplayItemList* PictureLayer::GetDisplayItemList() { |
| + return client_data_.display_list.get(); |
| +} |
| + |
| +scoped_refptr<RasterSource> PictureLayer::CreateRasterSource( |
| + const PictureLayerData& layer_data, |
| + const ContentLayerClientData& client_data, |
| + bool can_use_lcd_text) const { |
| + return scoped_refptr<RasterSource>(RasterSource::CreateFromDataStruct( |
|
vmpstr
2016/07/20 22:18:10
You don't need to wrap this in scoped_refptr, sinc
|
| + layer_data, client_data, can_use_lcd_text)); |
| +} |
| + |
| void PictureLayer::DropRecordingSourceContentIfInvalid() { |
| int source_frame_number = layer_tree_host()->source_frame_number(); |
| - gfx::Size recording_source_bounds = recording_source_->GetSize(); |
| + gfx::Size recording_source_bounds = GetSizeInLayerData(); |
| gfx::Size layer_bounds = bounds(); |
| if (paint_properties().source_frame_number == source_frame_number) |
| @@ -254,8 +419,50 @@ void PictureLayer::DropRecordingSourceContentIfInvalid() { |
| // 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(); |
| + ResetLayerAndClientData(); |
| } |
| } |
| +void PictureLayer::FinishDisplayItemListUpdate( |
| + PictureLayerData* layer_data, |
| + ContentLayerClientData* client_data) const { |
| + TRACE_EVENT0("cc", "PictureLayer::FinishDisplayItemListUpdate"); |
| + DetermineIfSolidColor(layer_data, client_data); |
| + client_data->display_list->EmitTraceSnapshot(); |
| + if (layer_data->generate_discardable_images_metadata) |
| + client_data->display_list->GenerateDiscardableImagesMetadata(); |
| +} |
| + |
| +void PictureLayer::DetermineIfSolidColor( |
| + PictureLayerData* layer_data, |
| + ContentLayerClientData* client_data) const { |
| + DCHECK(client_data->display_list); |
| + layer_data->is_solid_color = false; |
| + layer_data->solid_color = SK_ColorTRANSPARENT; |
| + |
| + if (!client_data->display_list->ShouldBeAnalyzedForSolidColor()) |
| + return; |
| + |
| + TRACE_EVENT1("cc", "PictureLayer::DetermineIfSolidColor", "opcount", |
| + client_data->display_list->ApproximateOpCount()); |
| + gfx::Size layer_size = layer_data->size; |
| + skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); |
| + client_data->display_list->Raster(&canvas, nullptr, gfx::Rect(), 1.f); |
| + layer_data->is_solid_color = canvas.GetColorIfSolid(&layer_data->solid_color); |
| +} |
| + |
| +void PictureLayer::UpdateInvalidationForNewViewport( |
| + const gfx::Rect& old_recorded_viewport, |
| + const gfx::Rect& new_recorded_viewport, |
| + Region* invalidation) const { |
| + // Invalidate newly-exposed and no-longer-exposed areas. |
| + Region newly_exposed_region(new_recorded_viewport); |
| + newly_exposed_region.Subtract(old_recorded_viewport); |
| + invalidation->Union(newly_exposed_region); |
| + |
| + Region no_longer_exposed_region(old_recorded_viewport); |
| + no_longer_exposed_region.Subtract(new_recorded_viewport); |
| + invalidation->Union(no_longer_exposed_region); |
| +} |
| + |
| } // namespace cc |