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..fa2b006763c109910431b943e655376a92dbcd4f 100644 |
| --- a/cc/layers/picture_layer.cc |
| +++ b/cc/layers/picture_layer.cc |
| @@ -31,9 +31,11 @@ PictureLayer::PictureLayer(ContentLayerClient* client) |
| } |
| PictureLayer::PictureLayer(ContentLayerClient* client, |
| - std::unique_ptr<RecordingSource> source) |
| + const PictureLayerData& pl_data, |
| + const ContentLayerClientData& clc_data) |
| : PictureLayer(client) { |
| - recording_source_ = std::move(source); |
| + pl_data_ = pl_data; |
|
vmpstr
2016/07/19 23:43:22
set these in the initialization list just above
Menglin
2016/07/20 00:28:42
Done.
Menglin
2016/07/20 21:25:22
Actually, if i move the initialization in the list
|
| + clc_data_ = clc_data; |
| } |
| PictureLayer::~PictureLayer() { |
| @@ -56,8 +58,10 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { |
| // Preserve lcd text settings from the current raster source. |
| bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText(); |
| + std::unique_ptr<RecordingSource> recording_source( |
|
vmpstr
2016/07/19 23:43:22
Just create this on the stack if you need it. Do y
Menglin
2016/07/20 00:18:13
Currently the raster source is constructed based o
vmpstr
2016/07/20 00:27:06
I think we can just have RasterSource(display_list
Menglin
2016/07/20 21:25:22
I change it to RasterSource(const PictureLayerData
|
| + new RecordingSource(pl_data_, clc_data_)); |
| scoped_refptr<RasterSource> raster_source = |
| - recording_source_->CreateRasterSource(can_use_lcd_text); |
| + recording_source->CreateRasterSource(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 +74,19 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { |
| if (!host) |
| return; |
| - if (!recording_source_) |
| - recording_source_.reset(new RecordingSource); |
| - recording_source_->SetSlowdownRasterScaleFactor( |
| + pl_data_.reset(); |
|
vmpstr
2016/07/19 23:43:22
Where is PictureLayerData defined? I can't find it
Menglin
2016/07/20 00:18:13
Now it's in recording_source.h. I had it there bec
|
| + clc_data_.reset(); |
| + SetSlowdownRasterScaleFactor( |
| 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); |
| Layer::SetNeedsDisplayRect(layer_rect); |
| } |
| @@ -94,9 +96,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 +111,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, RecordingSource::RECORD_NORMALLY, |
| + &pl_data_, &clc_data_, &invalidation_); |
| if (updated) { |
| SetNeedsPushProperties(); |
| @@ -136,12 +138,15 @@ 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_local; |
|
vmpstr
2016/07/19 23:43:22
I don't think you need the word "local".. lack of
Menglin
2016/07/20 21:25:22
Done.
|
| + PictureLayerData pl_data_local = PictureLayerData(); |
| + ContentLayerClientData clc_data_local = ContentLayerClientData(); |
| + UpdateAndExpandInvalidation(&recording_invalidation, layer_size, |
| + RecordingSource::RECORD_NORMALLY, &pl_data_local, |
| + &clc_data_local, &invalidation_local); |
| + std::unique_ptr<RecordingSource> recording_source( |
|
vmpstr
2016/07/19 23:43:22
Same comment as above: Either create it on the sta
Menglin
2016/07/20 21:25:22
Done.
|
| + new RecordingSource(pl_data_local, clc_data_local)); |
| scoped_refptr<RasterSource> raster_source = |
| recording_source->CreateRasterSource(false); |
| @@ -149,7 +154,12 @@ sk_sp<SkPicture> PictureLayer::GetPicture() const { |
| } |
| 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 !clc_data_.display_list || |
| + clc_data_.display_list->IsSuitableForGpuRasterization(); |
| } |
| void PictureLayer::ClearClient() { |
| @@ -179,10 +189,26 @@ void PictureLayer::LayerSpecificPropertiesToProto( |
| DropRecordingSourceContentIfInvalid(); |
| proto::PictureLayerProperties* picture = proto->mutable_picture(); |
| - recording_source_->ToProtobuf(picture->mutable_recording_source()); |
| + |
| + RectToProto(clc_data_.recorded_viewport, |
| + picture->mutable_recorded_viewport()); |
| + SizeToProto(pl_data_.size, picture->mutable_size()); |
| + picture->set_slow_down_raster_scale_factor_for_debug( |
| + pl_data_.slow_down_raster_scale_factor_for_debug); |
| + picture->set_generate_discardable_images_metadata( |
| + pl_data_.generate_discardable_images_metadata); |
| + picture->set_requires_clear(pl_data_.requires_clear); |
| + picture->set_is_solid_color(pl_data_.is_solid_color); |
| + picture->set_clear_canvas_with_debug_color( |
| + pl_data_.clear_canvas_with_debug_color); |
| + picture->set_solid_color(static_cast<uint64_t>(pl_data_.solid_color)); |
| + picture->set_background_color( |
| + static_cast<uint64_t>(pl_data_.background_color)); |
| + if (clc_data_.display_list) |
| + clc_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 +236,35 @@ 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); |
| - |
| + pl_data_.reset(); |
| + clc_data_.reset(); |
| 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()); |
| + clc_data_.recorded_viewport = ProtoToRect(picture.recorded_viewport()); |
| + pl_data_.size = ProtoToSize(picture.size()); |
| + pl_data_.slow_down_raster_scale_factor_for_debug = |
| + picture.slow_down_raster_scale_factor_for_debug(); |
| + pl_data_.generate_discardable_images_metadata = |
| + picture.generate_discardable_images_metadata(); |
| + pl_data_.requires_clear = picture.requires_clear(); |
| + pl_data_.is_solid_color = picture.is_solid_color(); |
| + pl_data_.clear_canvas_with_debug_color = |
| + picture.clear_canvas_with_debug_color(); |
| + pl_data_.solid_color = static_cast<SkColor>(picture.solid_color()); |
| + pl_data_.background_color = static_cast<SkColor>(picture.background_color()); |
| + |
| + // This might not exist if the |clc_data_.display_list| of the serialized |
| + // RecordingSource was null, which can happen if |Clear()| is |
| + // called. |
| + if (picture.has_display_list()) { |
| + clc_data_.display_list = DisplayItemList::CreateFromProto( |
| + picture.display_list(), layer_tree_host()->client_picture_cache(), |
| + &used_engine_picture_ids); |
| + FinishDisplayItemListUpdate(&pl_data_, &clc_data_); |
| + } else { |
| + clc_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 +282,119 @@ void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { |
| benchmark->RunOnLayer(this); |
| } |
| +bool PictureLayer::UpdateAndExpandInvalidation( |
| + Region* invalidation, |
| + const gfx::Size& layer_size, |
| + RecordingSource::RecordingMode recording_mode, |
| + PictureLayerData* pl_data, |
| + ContentLayerClientData* clc_data, |
| + InvalidationRegion* invalidation_state) const { |
| + bool updated = false; |
| + |
| + if (pl_data->size != layer_size) |
| + pl_data->size = layer_size; |
| + |
| + invalidation_state->Swap(invalidation); |
| + invalidation_state->Clear(); |
| + |
| + gfx::Rect new_recorded_viewport = inputs_.client->PaintableRegion(); |
| + if (new_recorded_viewport != clc_data->recorded_viewport) { |
| + UpdateInvalidationForNewViewport(clc_data->recorded_viewport, |
| + new_recorded_viewport, invalidation); |
| + clc_data->recorded_viewport = new_recorded_viewport; |
| + updated = true; |
| + } |
| + |
| + if (!updated && !invalidation->Intersects(clc_data->recorded_viewport)) |
| + return false; |
| + |
| + if (invalidation->IsEmpty()) |
| + return false; |
| + |
| + ContentLayerClient::PaintingControlSetting painting_control = |
| + ContentLayerClient::PAINTING_BEHAVIOR_NORMAL; |
| + |
| + switch (recording_mode) { |
| + case RecordingSource::RECORD_NORMALLY: |
| + // Already setup for normal recording. |
| + break; |
| + case RecordingSource::RECORD_WITH_PAINTING_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED; |
| + break; |
| + case RecordingSource::RECORD_WITH_CACHING_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; |
| + break; |
| + case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED: |
| + painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; |
| + break; |
| + case RecordingSource::RECORD_WITH_SUBSEQUENCE_CACHING_DISABLED: |
| + painting_control = ContentLayerClient::SUBSEQUENCE_CACHING_DISABLED; |
| + break; |
| + case RecordingSource::RECORD_WITH_SK_NULL_CANVAS: |
| + case RecordingSource::RECORDING_MODE_COUNT: |
| + NOTREACHED(); |
| + } |
| + |
| + // TODO(vmpstr): Add a slow_down_recording_scale_factor_for_debug_ to be able |
| + // to slow down recording. |
| + clc_data->display_list = |
| + inputs_.client->PaintContentsToDisplayList(painting_control); |
| + clc_data->painter_reported_memory_usage = |
| + inputs_.client->GetApproximateUnsharedMemoryUsage(); |
| + |
| + FinishDisplayItemListUpdate(pl_data, clc_data); |
| + |
| + return true; |
| +} |
| + |
| +void PictureLayer::SetEmptyBounds() { |
| + pl_data_.size = gfx::Size(); |
| + Clear(); |
| +} |
| + |
| +void PictureLayer::SetSlowdownRasterScaleFactor(int factor) { |
|
vmpstr
2016/07/19 23:43:22
As far as I can tell there's not a lot of places t
Menglin
2016/07/20 00:18:13
OK. I will check each one of them, and do the clea
Menglin
2016/07/20 21:25:22
For now I only removed SetSlowdownRasterScaleFacto
|
| + pl_data_.slow_down_raster_scale_factor_for_debug = factor; |
| +} |
| + |
| +void PictureLayer::SetGenerateDiscardableImagesMetadata( |
| + bool generate_metadata) { |
| + pl_data_.generate_discardable_images_metadata = generate_metadata; |
| +} |
| + |
| +void PictureLayer::SetBackgroundColorSimple(SkColor background_color) { |
| + pl_data_.background_color = background_color; |
| +} |
| + |
| +void PictureLayer::SetRequiresClear(bool requires_clear) { |
| + pl_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(pl_data_.size))); |
| + } |
| +} |
| + |
| +gfx::Size PictureLayer::GetSize() const { |
| + return pl_data_.size; |
| +} |
| + |
| +const DisplayItemList* PictureLayer::GetDisplayItemList() { |
| + return clc_data_.display_list.get(); |
| +} |
| + |
| +void PictureLayer::Clear() { |
| + clc_data_.recorded_viewport = gfx::Rect(); |
| + clc_data_.display_list = nullptr; |
| + clc_data_.painter_reported_memory_usage = 0; |
| + pl_data_.is_solid_color = false; |
| +} |
| + |
| 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 = GetSize(); |
| gfx::Size layer_bounds = bounds(); |
| if (paint_properties().source_frame_number == source_frame_number) |
| @@ -254,8 +412,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(); |
| + SetEmptyBounds(); |
| } |
| } |
| +void PictureLayer::FinishDisplayItemListUpdate( |
| + PictureLayerData* pl_data, |
| + ContentLayerClientData* clc_data) const { |
| + TRACE_EVENT0("cc", "PictureLayer::FinishDisplayItemListUpdate"); |
| + DetermineIfSolidColor(pl_data, clc_data); |
| + clc_data->display_list->EmitTraceSnapshot(); |
| + if (pl_data->generate_discardable_images_metadata) |
| + clc_data->display_list->GenerateDiscardableImagesMetadata(); |
| +} |
| + |
| +void PictureLayer::DetermineIfSolidColor( |
| + PictureLayerData* pl_data, |
| + ContentLayerClientData* clc_data) const { |
| + DCHECK(clc_data->display_list); |
| + pl_data->is_solid_color = false; |
| + pl_data->solid_color = SK_ColorTRANSPARENT; |
| + |
| + if (!clc_data->display_list->ShouldBeAnalyzedForSolidColor()) |
| + return; |
| + |
| + TRACE_EVENT1("cc", "PictureLayer::DetermineIfSolidColor", "opcount", |
| + clc_data->display_list->ApproximateOpCount()); |
| + gfx::Size layer_size = pl_data->size; |
| + skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); |
| + clc_data->display_list->Raster(&canvas, nullptr, gfx::Rect(), 1.f); |
| + pl_data->is_solid_color = canvas.GetColorIfSolid(&pl_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 |