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
android_webview / browser / gfx / display_scheduler_webview.cc [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/browser/gfx/display_scheduler_webview.h"
#include "android_webview/browser/gfx/root_frame_sink.h"
#include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/features.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
namespace android_webview {
DisplaySchedulerWebView::DisplaySchedulerWebView(
RootFrameSink* root_frame_sink,
OverlaysInfoProvider* overlays_info_provider)
: root_frame_sink_(root_frame_sink),
overlays_info_provider_(overlays_info_provider),
use_new_invalidate_heuristic_(
features::UseWebViewNewInvalidateHeuristic()) {
auto* frame_sink_manager =
VizCompositorThreadRunnerWebView::GetInstance()->GetFrameSinkManager();
surface_manager_observation_.Observe(frame_sink_manager->surface_manager());
frame_sink_manager_observation_.Observe(frame_sink_manager);
}
DisplaySchedulerWebView::~DisplaySchedulerWebView() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void DisplaySchedulerWebView::ForceImmediateSwapIfPossible() {
// We can't swap immediately
NOTREACHED();
}
void DisplaySchedulerWebView::SetNeedsOneBeginFrame(bool needs_draw) {
NOTREACHED();
}
void DisplaySchedulerWebView::DidSwapBuffers() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Code below is part of old invalidation heuristic.
if (use_new_invalidate_heuristic_)
return;
bool needs_draw = false;
for (auto it = damaged_frames_.begin(); it != damaged_frames_.end();) {
DCHECK_GT(it->second, 0);
if (!--it->second) {
it = damaged_frames_.erase(it);
} else {
if (!needs_draw) {
TRACE_EVENT_INSTANT2(
"android_webview",
"DisplaySchedulerWebView::DidSwapBuffers first needs_draw",
TRACE_EVENT_SCOPE_THREAD, "frame_sink_id", it->first.ToString(),
"damage_count", it->second);
}
needs_draw = true;
++it;
}
}
root_frame_sink_->SetNeedsDraw(needs_draw);
}
void DisplaySchedulerWebView::OutputSurfaceLost() {
}
bool DisplaySchedulerWebView::IsFrameSinkOverlayed(
viz::FrameSinkId frame_sink_id) {
return overlays_info_provider_ &&
overlays_info_provider_->IsFrameSinkOverlayed(frame_sink_id);
}
void DisplaySchedulerWebView::OnDisplayDamaged(viz::SurfaceId surface_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Code below is part of old invalidation heuristic.
if (use_new_invalidate_heuristic_)
return;
// We don't need to track damage of root frame sink as we submit frame to it
// at DrawAndSwap and Root Renderer sink because Android View.Invalidation is
// handled by SynchronousCompositorHost.
if (surface_id.frame_sink_id() != root_frame_sink_->root_frame_sink_id() &&
!root_frame_sink_->IsChildSurface(surface_id.frame_sink_id()) &&
!IsFrameSinkOverlayed(surface_id.frame_sink_id())) {
int count = damaged_frames_[surface_id.frame_sink_id()] + 1;
TRACE_EVENT_INSTANT2(
"android_webview", "DisplaySchedulerWebView::OnDisplayDamaged",
TRACE_EVENT_SCOPE_THREAD, "frame_sink_id",
surface_id.frame_sink_id().ToString(), "damage_count", count);
// Clamp value to max two frames. Two is enough to keep invalidation
// working, but will prevent number going too high in case if kModeDraw
// doesn't happen for some time.
damaged_frames_[surface_id.frame_sink_id()] = std::min(2, count);
root_frame_sink_->SetNeedsDraw(true);
}
}
void DisplaySchedulerWebView::OnSurfaceHasNewUncommittedFrame(
const viz::SurfaceId& surface_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// We don't need to track damage of root frame sink as we submit frame to it
// at DrawAndSwap and Root Renderer sink because Android View.Invalidation is
// handled by SynchronousCompositorHost.
const bool is_root =
surface_id.frame_sink_id() == root_frame_sink_->root_frame_sink_id();
const bool is_root_renderer =
root_frame_sink_->IsChildSurface(surface_id.frame_sink_id());
const bool is_overlay = IsFrameSinkOverlayed(surface_id.frame_sink_id());
if (!is_root && !is_root_renderer && !is_overlay &&
damage_tracker_->CheckForDisplayDamage(surface_id)) {
root_frame_sink_->OnNewUncommittedFrame(surface_id);
}
}
void DisplaySchedulerWebView::OnCaptureStarted(
const viz::FrameSinkId& frame_sink_id) {
root_frame_sink_->OnCaptureStarted(frame_sink_id);
}
} // namespace android_webview