forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
render_frame_metadata_observer_impl.cc
193 lines (170 loc) · 8.03 KB
/
render_frame_metadata_observer_impl.cc
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/render_frame_metadata_observer_impl.h"
#include <cmath>
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
namespace content {
namespace {
#if defined(OS_ANDROID)
constexpr float kEdgeThreshold = 10.0f;
#endif
}
RenderFrameMetadataObserverImpl::RenderFrameMetadataObserverImpl(
mojom::RenderFrameMetadataObserverRequest request,
mojom::RenderFrameMetadataObserverClientPtrInfo client_info)
: request_(std::move(request)),
client_info_(std::move(client_info)),
render_frame_metadata_observer_binding_(this) {}
RenderFrameMetadataObserverImpl::~RenderFrameMetadataObserverImpl() {}
void RenderFrameMetadataObserverImpl::BindToCurrentThread() {
DCHECK(request_.is_pending());
render_frame_metadata_observer_binding_.Bind(std::move(request_));
render_frame_metadata_observer_client_.Bind(std::move(client_info_));
}
void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission(
const cc::RenderFrameMetadata& render_frame_metadata,
viz::CompositorFrameMetadata* compositor_frame_metadata,
bool force_send) {
// By default only report metadata changes for fields which have a low
// frequency of change. However if there are changes in high frequency
// fields these can be reported while testing is enabled.
bool send_metadata = false;
bool needs_activation_notification = true;
if (render_frame_metadata_observer_client_) {
if (report_all_frame_submissions_for_testing_enabled_) {
last_frame_token_ = compositor_frame_metadata->frame_token;
compositor_frame_metadata->send_frame_token_to_embedder = true;
render_frame_metadata_observer_client_->OnFrameSubmissionForTesting(
last_frame_token_);
send_metadata = !last_render_frame_metadata_ ||
*last_render_frame_metadata_ != render_frame_metadata;
} else {
send_metadata = !last_render_frame_metadata_ ||
ShouldSendRenderFrameMetadata(
*last_render_frame_metadata_, render_frame_metadata,
&needs_activation_notification);
}
send_metadata |= force_send;
}
// Allways cache the full metadata, so that it can correctly be sent upon
// ReportAllFrameSubmissionsForTesting. This must only be done after we've
// compared the two for changes.
last_render_frame_metadata_ = render_frame_metadata;
// If the metadata is different, updates all the observers; or the metadata is
// generated for first time and same as the default value, update the default
// value to all the observers.
if (send_metadata && render_frame_metadata_observer_client_) {
// Sending |root_scroll_offset| outside of tests would leave the browser
// process with out of date information. It is an optional parameter
// which we clear here.
auto metadata_copy = render_frame_metadata;
#if !defined(OS_ANDROID)
if (!report_all_frame_submissions_for_testing_enabled_)
metadata_copy.root_scroll_offset = base::nullopt;
#endif
last_frame_token_ = compositor_frame_metadata->frame_token;
compositor_frame_metadata->send_frame_token_to_embedder =
needs_activation_notification;
render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged(
needs_activation_notification ? last_frame_token_ : 0u, metadata_copy);
TRACE_EVENT_WITH_FLOW1(
TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
"RenderFrameMetadataObserverImpl::OnRenderFrameSubmission",
metadata_copy.local_surface_id_allocation &&
metadata_copy.local_surface_id_allocation->IsValid()
? metadata_copy.local_surface_id_allocation->local_surface_id()
.submission_trace_id() +
metadata_copy.local_surface_id_allocation->local_surface_id()
.embed_trace_id()
: 0,
TRACE_EVENT_FLAG_FLOW_OUT, "local_surface_id_allocation",
metadata_copy.local_surface_id_allocation
? metadata_copy.local_surface_id_allocation->local_surface_id()
.ToString()
: "null");
}
// Always cache the initial frame token, so that if a test connects later on
// it can be notified of the initial state.
if (!last_frame_token_) {
last_frame_token_ = compositor_frame_metadata->frame_token;
compositor_frame_metadata->send_frame_token_to_embedder =
needs_activation_notification;
}
}
void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting(
bool enabled) {
report_all_frame_submissions_for_testing_enabled_ = enabled;
if (!enabled || !last_frame_token_)
return;
// When enabled for testing send the cached metadata.
DCHECK(render_frame_metadata_observer_client_);
DCHECK(last_render_frame_metadata_.has_value());
render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged(
last_frame_token_, *last_render_frame_metadata_);
}
// static
bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata(
const cc::RenderFrameMetadata& rfm1,
const cc::RenderFrameMetadata& rfm2,
bool* needs_activation_notification) {
if (rfm1.root_background_color != rfm2.root_background_color ||
rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top ||
rfm1.selection != rfm2.selection ||
rfm1.page_scale_factor != rfm2.page_scale_factor ||
rfm1.external_page_scale_factor != rfm2.external_page_scale_factor ||
rfm1.is_mobile_optimized != rfm2.is_mobile_optimized ||
rfm1.device_scale_factor != rfm2.device_scale_factor ||
rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels ||
rfm1.top_controls_height != rfm2.top_controls_height ||
rfm1.top_controls_shown_ratio != rfm2.top_controls_shown_ratio ||
rfm1.local_surface_id_allocation != rfm2.local_surface_id_allocation) {
*needs_activation_notification = true;
return true;
}
#if defined(OS_ANDROID)
if (rfm1.bottom_controls_height != rfm2.bottom_controls_height ||
rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio ||
rfm1.min_page_scale_factor != rfm2.min_page_scale_factor ||
rfm1.max_page_scale_factor != rfm2.max_page_scale_factor ||
rfm1.root_overflow_y_hidden != rfm2.root_overflow_y_hidden ||
rfm1.scrollable_viewport_size != rfm2.scrollable_viewport_size ||
rfm1.root_layer_size != rfm2.root_layer_size ||
rfm1.has_transparent_background != rfm2.has_transparent_background) {
*needs_activation_notification = true;
return true;
}
gfx::Vector2dF old_root_scroll_offset =
rfm1.root_scroll_offset.value_or(gfx::Vector2dF());
gfx::Vector2dF new_root_scroll_offset =
rfm2.root_scroll_offset.value_or(gfx::Vector2dF());
gfx::RectF old_viewport_rect(
gfx::PointF(old_root_scroll_offset.x(), old_root_scroll_offset.y()),
rfm1.scrollable_viewport_size);
gfx::RectF new_viewport_rect(
gfx::PointF(new_root_scroll_offset.x(), new_root_scroll_offset.y()),
rfm2.scrollable_viewport_size);
gfx::RectF new_root_layer_rect(rfm2.root_layer_size);
bool at_left_or_right_edge =
rfm2.root_layer_size.width() > rfm2.scrollable_viewport_size.width() &&
(std::abs(new_viewport_rect.right() - new_root_layer_rect.right()) <
kEdgeThreshold ||
std::abs(new_viewport_rect.x() - new_root_layer_rect.x()) <
kEdgeThreshold);
bool at_top_or_bottom_edge =
rfm2.root_layer_size.height() > rfm2.scrollable_viewport_size.height() &&
(std::abs(new_viewport_rect.y() - new_root_layer_rect.y()) <
kEdgeThreshold ||
std::abs(new_viewport_rect.bottom() - new_root_layer_rect.bottom()) <
kEdgeThreshold);
if (old_viewport_rect != new_viewport_rect &&
(at_left_or_right_edge || at_top_or_bottom_edge)) {
*needs_activation_notification = false;
return true;
}
#endif
*needs_activation_notification = false;
return false;
}
} // namespace content