File: recording_source.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (166 lines) | stat: -rw-r--r-- 5,271 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/layers/recording_source.h"

#include <algorithm>
#include <utility>

#include "base/numerics/safe_math.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/region.h"
#include "cc/layers/content_layer_client.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/solid_color_analyzer.h"
#include "cc/raster/raster_source.h"

namespace {

// We don't perform per-layer solid color analysis when there are too many skia
// operations.
const int kMaxOpsToAnalyzeForLayer = 10;

}  // namespace

namespace cc {

RecordingSource::RecordingSource() = default;
RecordingSource::~RecordingSource() = default;

void RecordingSource::UpdateInvalidationForRecordedBounds(
    const gfx::Rect& old_recorded_bounds,
    const gfx::Rect& new_recorded_bounds,
    Region& invalidation) {
  // Invalidate newly-exposed and no-longer-exposed areas.
  Region newly_exposed_region(new_recorded_bounds);
  newly_exposed_region.Subtract(old_recorded_bounds);
  invalidation.Union(newly_exposed_region);

  Region no_longer_exposed_region(old_recorded_bounds);
  no_longer_exposed_region.Subtract(new_recorded_bounds);
  invalidation.Union(no_longer_exposed_region);
}

void RecordingSource::FinishDisplayItemListUpdate() {
  TRACE_EVENT0("cc", "RecordingSource::FinishDisplayItemListUpdate");
  DetermineIfSolidColor();
  display_list_->EmitTraceSnapshot();

  directly_composited_image_info_ =
      display_list_->GetDirectlyCompositedImageInfo();
  if (directly_composited_image_info_) {
    // Directly composited images are not guaranteed to fully cover every
    // pixel in the layer due to ceiling when calculating the tile content
    // rect from the layer bounds.
    SetRequiresClear(true);
  }
}

void RecordingSource::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
  if (!layer_rect.IsEmpty()) {
    // Clamp invalidation to the layer bounds.
    invalidation_.Union(gfx::IntersectRects(layer_rect, gfx::Rect(size_)));
  }
}

bool RecordingSource::Update(const gfx::Size& layer_size,
                             float recording_scale_factor,
                             ContentLayerClient& client,
                             Region& invalidation) {
  invalidation_.Swap(&invalidation);
  invalidation_.Clear();

  if (size_ == layer_size && invalidation.IsEmpty() && !force_update_) {
    return false;
  }

  size_ = layer_size;
  recording_scale_factor_ = recording_scale_factor;

  scoped_refptr<DisplayItemList> display_list =
      client.PaintContentsToDisplayList();
  if (display_list_ == display_list) {
    // The client should set force_update_ only if it has a new display list.
    CHECK(!force_update_);
    return true;
  }

  force_update_ = false;

  // Do the following only if the display list changes. Though we use
  // recording_scale_factor in DetermineIfSolidColor(), change of it doesn't
  // affect whether the same display list is solid or not.

  gfx::Rect layer_rect(size_);
  gfx::Rect new_recorded_bounds = layer_rect;
  if (can_use_recorded_bounds_) {
    if (std::optional<gfx::Rect> display_list_bounds = display_list->bounds()) {
      new_recorded_bounds.Intersect(*display_list_bounds);
    }
  }

  if (display_list_ &&
      display_list->NeedsAdditionalInvalidationForLCDText(*display_list_)) {
    invalidation = layer_rect;
  } else if (new_recorded_bounds != recorded_bounds_) {
    UpdateInvalidationForRecordedBounds(recorded_bounds_, new_recorded_bounds,
                                        invalidation);
  }

  recorded_bounds_ = new_recorded_bounds;
  display_list_ = std::move(display_list);
  FinishDisplayItemListUpdate();
  return true;
}

void RecordingSource::SetEmptyBounds() {
  size_ = gfx::Size();
  is_solid_color_ = false;

  recorded_bounds_ = gfx::Rect();
  display_list_ = nullptr;
}

void RecordingSource::SetSlowdownRasterScaleFactor(int factor) {
  slow_down_raster_scale_factor_for_debug_ = factor;
}

void RecordingSource::SetBackgroundColor(SkColor4f background_color) {
  background_color_ = background_color;
}

void RecordingSource::SetRequiresClear(bool requires_clear) {
  requires_clear_ = requires_clear;
}

void RecordingSource::SetCanUseRecordedBounds(bool can_use_recorded_bounds) {
  if (can_use_recorded_bounds_ == can_use_recorded_bounds) {
    return;
  }
  can_use_recorded_bounds_ = can_use_recorded_bounds;
  // To force update.
  size_ = gfx::Size();
}

scoped_refptr<RasterSource> RecordingSource::CreateRasterSource() const {
  return base::WrapRefCounted(new RasterSource(*this));
}

void RecordingSource::DetermineIfSolidColor() {
  DCHECK(display_list_);
  is_solid_color_ = false;
  solid_color_ = SkColors::kTransparent;

  if (display_list_->TotalOpCount() > kMaxOpsToAnalyzeForLayer)
    return;

  // TODO(crbug.com/41490692): Allow the solid color not to fill the layer.
  TRACE_EVENT1("cc", "RecordingSource::DetermineIfSolidColor", "opcount",
               display_list_->TotalOpCount());
  is_solid_color_ = display_list_->GetColorIfSolidInRect(
      gfx::ScaleToRoundedRect(gfx::Rect(size_), recording_scale_factor_),
      &solid_color_, kMaxOpsToAnalyzeForLayer);
}

}  // namespace cc