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