1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
6
7 #include <memory>
8 #include "base/bind.h"
9 #include "base/optional.h"
10 #include "base/trace_event/traced_value.h"
11 #include "cc/paint/paint_flags.h"
12 #include "cc/paint/paint_op_buffer.h"
13 #include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
14 #include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
15 #include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
16 #include "third_party/blink/renderer/platform/graphics/paint/display_item_list.h"
17 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
18 #include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
19 #include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
20 #include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
21 #include "third_party/blink/renderer/platform/json/json_values.h"
22
23 namespace blink {
24
ContentLayerClientImpl()25 ContentLayerClientImpl::ContentLayerClientImpl()
26 : cc_picture_layer_(cc::PictureLayer::Create(this)),
27 raster_invalidation_function_(
28 base::BindRepeating(&ContentLayerClientImpl::InvalidateRect,
29 base::Unretained(this))),
30 layer_state_(PropertyTreeState::Uninitialized()) {}
31
~ContentLayerClientImpl()32 ContentLayerClientImpl::~ContentLayerClientImpl() {
33 cc_picture_layer_->ClearClient();
34 }
35
AppendAdditionalInfoAsJSON(LayerTreeFlags flags,const cc::Layer & layer,JSONObject & json) const36 void ContentLayerClientImpl::AppendAdditionalInfoAsJSON(
37 LayerTreeFlags flags,
38 const cc::Layer& layer,
39 JSONObject& json) const {
40 #if DCHECK_IS_ON()
41 if (flags & kLayerTreeIncludesDebugInfo)
42 json.SetValue("paintChunkContents", paint_chunk_debug_data_->Clone());
43 #endif
44
45 if ((flags & (kLayerTreeIncludesInvalidations |
46 kLayerTreeIncludesDetailedInvalidations)) &&
47 raster_invalidator_.GetTracking()) {
48 raster_invalidator_.GetTracking()->AsJSON(
49 &json, flags & kLayerTreeIncludesDetailedInvalidations);
50 }
51
52 #if DCHECK_IS_ON()
53 if (flags & kLayerTreeIncludesPaintRecords) {
54 LoggingCanvas canvas;
55 cc_display_item_list_->Raster(&canvas);
56 json.SetValue("paintRecord", canvas.Log());
57 }
58 #endif
59 }
60
UpdateCcPictureLayer(scoped_refptr<const PaintArtifact> paint_artifact,const PaintChunkSubset & paint_chunks,const gfx::Rect & layer_bounds,const PropertyTreeState & layer_state)61 scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
62 scoped_refptr<const PaintArtifact> paint_artifact,
63 const PaintChunkSubset& paint_chunks,
64 const gfx::Rect& layer_bounds,
65 const PropertyTreeState& layer_state) {
66 if (paint_chunks[0].is_cacheable)
67 id_.emplace(paint_chunks[0].id);
68 else
69 id_ = base::nullopt;
70
71 const auto& display_item_list = paint_artifact->GetDisplayItemList();
72
73 #if DCHECK_IS_ON()
74 paint_chunk_debug_data_ = std::make_unique<JSONArray>();
75 for (const auto& chunk : paint_chunks) {
76 auto json = std::make_unique<JSONObject>();
77 json->SetString("data", chunk.ToString());
78 json->SetArray("displayItems",
79 paint_artifact->GetDisplayItemList().DisplayItemsAsJSON(
80 chunk.begin_index, chunk.end_index,
81 DisplayItemList::kShowOnlyDisplayItemTypes));
82 paint_chunk_debug_data_->PushObject(std::move(json));
83 }
84 #endif
85
86 // The raster invalidator will only handle invalidations within a cc::Layer so
87 // we need this invalidation if the layer's properties have changed.
88 if (layer_state != layer_state_)
89 cc_picture_layer_->SetSubtreePropertyChanged();
90
91 raster_invalidator_.Generate(raster_invalidation_function_, paint_artifact,
92 paint_chunks, layer_bounds, layer_state);
93 layer_state_ = layer_state;
94
95 // Note: cc::Layer API assumes the layer bounds start at (0, 0), but the
96 // bounding box of a paint chunk does not necessarily start at (0, 0) (and
97 // could even be negative). Internally the generated layer translates the
98 // paint chunk to align the bounding box to (0, 0) and we set the layer's
99 // offset_to_transform_parent with the origin of the paint chunk here.
100 cc_picture_layer_->SetOffsetToTransformParent(
101 layer_bounds.OffsetFromOrigin());
102 cc_picture_layer_->SetBounds(layer_bounds.size());
103 cc_picture_layer_->SetHitTestable(true);
104
105 base::Optional<RasterUnderInvalidationCheckingParams> params;
106 if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
107 params.emplace(*raster_invalidator_.GetTracking(),
108 IntRect(0, 0, layer_bounds.width(), layer_bounds.height()),
109 paint_chunks[0].id.client.DebugName());
110 }
111 cc_display_item_list_ = PaintChunksToCcLayer::Convert(
112 paint_chunks, layer_state, layer_bounds.OffsetFromOrigin(),
113 display_item_list, cc::DisplayItemList::kTopLevelDisplayItemList,
114 base::OptionalOrNullptr(params));
115
116 cc_picture_layer_->SetIsDrawable(
117 (!layer_bounds.IsEmpty() && cc_display_item_list_->TotalOpCount()) ||
118 // Backdrop filters require the layer to be drawable even if the layer
119 // draws nothing.
120 !layer_state.Effect().BackdropFilter().IsEmpty());
121
122 auto safe_opaque_background_color =
123 paint_artifact->SafeOpaqueBackgroundColor(paint_chunks);
124 cc_picture_layer_->SetSafeOpaqueBackgroundColor(safe_opaque_background_color);
125 // TODO(masonfreed): We don't need to set the background color here; only the
126 // safe opaque background color matters. But making that change would require
127 // rebaselining 787 tests to remove the "background_color" property from the
128 // layer dumps.
129 cc_picture_layer_->SetBackgroundColor(safe_opaque_background_color);
130 return cc_picture_layer_;
131 }
132
133 } // namespace blink
134