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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
android_webview / browser / gfx / browser_view_renderer.h [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_BROWSER_GFX_BROWSER_VIEW_RENDERER_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_BROWSER_VIEW_RENDERER_H_
#include <stddef.h>
#include <map>
#include <optional>
#include <set>
#include "android_webview/browser/gfx/begin_frame_source_webview.h"
#include "android_webview/browser/gfx/child_frame.h"
#include "android_webview/browser/gfx/compositor_frame_producer.h"
#include "android_webview/browser/gfx/parent_compositor_draw_constraints.h"
#include "android_webview/browser/gfx/root_frame_sink_proxy.h"
#include "base/cancelable_callback.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/android/synchronous_compositor_client.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
class SkCanvas;
class SkPicture;
namespace content {
class WebContents;
}
namespace android_webview {
class BrowserViewRendererClient;
class ChildFrame;
class CompositorFrameConsumer;
class RootFrameSinkProxy;
// Interface for all the WebView-specific content rendering operations.
// Provides software and hardware rendering and the Capture Picture API.
//
// Lifetime: WebView
class BrowserViewRenderer : public content::SynchronousCompositorClient,
public CompositorFrameProducer,
public RootFrameSinkProxyClient {
public:
static void CalculateTileMemoryPolicy();
static BrowserViewRenderer* FromWebContents(
content::WebContents* web_contents);
BrowserViewRenderer(
BrowserViewRendererClient* client,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
BrowserViewRenderer(const BrowserViewRenderer&) = delete;
BrowserViewRenderer& operator=(const BrowserViewRenderer&) = delete;
~BrowserViewRenderer() override;
void RegisterWithWebContents(content::WebContents* web_contents);
// The BrowserViewRenderer client is responsible for ensuring that
// the current compositor frame consumer has been set correctly via
// this method. The consumer is added to the set of registered
// consumers if it is not already registered.
void SetCurrentCompositorFrameConsumer(
CompositorFrameConsumer* compositor_frame_consumer);
// Called before either OnDrawHardware or OnDrawSoftware to set the view
// state of this frame. |scroll| is the view's current scroll offset.
// |global_visible_rect| is the intersection of the view size and the window
// in window coordinates.
void PrepareToDraw(const gfx::Point& scroll,
const gfx::Rect& global_visible_rect);
// Main handlers for view drawing. A false return value indicates no new
// frame is produced.
bool OnDrawHardware();
bool OnDrawSoftware(SkCanvas* canvas);
float GetVelocityInPixelsPerSecond();
bool NeedToDrawBackgroundColor();
// CapturePicture API methods.
sk_sp<SkPicture> CapturePicture(int width, int height);
void EnableOnNewPicture(bool enabled);
void ClearView();
void SetOffscreenPreRaster(bool enabled);
// View update notifications.
void SetIsPaused(bool paused);
void SetViewVisibility(bool visible);
void SetWindowVisibility(bool visible);
void OnSizeChanged(int width, int height);
void OnAttachedToWindow(int width, int height);
void OnDetachedFromWindow();
void ZoomBy(float delta);
void OnComputeScroll(base::TimeTicks animation_time);
// Sets the scale for logical<->physical pixel conversions.
void SetDipScale(float dip_scale);
float dip_scale() const { return dip_scale_; }
float page_scale_factor() const { return page_scale_factor_; }
// Set the root layer scroll offset to |new_value|. The |new_value| here is in
// physical pixel.
void ScrollTo(const gfx::Point& new_value);
// Set root layer scroll offset on the next scroll state update.
void RestoreScrollAfterTransition(const gfx::Point& new_value);
// Android views hierarchy gluing.
bool IsVisible() const;
gfx::Rect GetScreenRect() const;
bool view_visible() const { return view_visible_; }
bool window_visible() const { return window_visible_; }
bool attached_to_window() const { return attached_to_window_; }
bool was_attached() const { return was_attached_; }
gfx::Size size() const { return size_; }
bool IsClientVisible() const;
void TrimMemory();
// SynchronousCompositorClient overrides.
void DidInitializeCompositor(content::SynchronousCompositor* compositor,
const viz::FrameSinkId& frame_sink_id) override;
void DidDestroyCompositor(content::SynchronousCompositor* compositor,
const viz::FrameSinkId& frame_sink_id) override;
void PostInvalidate(content::SynchronousCompositor* compositor) override;
void DidUpdateContent(content::SynchronousCompositor* compositor) override;
void OnInputEvent();
// |total_scroll_offset|, |total_max_scroll_offset|, and |scrollable_size| are
// in DIP scale when --use-zoom-for-dsf is disabled. Otherwise, they are in
// physical pixel scale.
void UpdateRootLayerState(content::SynchronousCompositor* compositor,
const gfx::PointF& total_scroll_offset,
const gfx::PointF& total_max_scroll_offset,
const gfx::SizeF& scrollable_size,
float page_scale_factor,
float min_page_scale_factor,
float max_page_scale_factor) override;
void DidOverscroll(content::SynchronousCompositor* compositor,
const gfx::Vector2dF& accumulated_overscroll,
const gfx::Vector2dF& latest_overscroll_delta,
const gfx::Vector2dF& current_fling_velocity) override;
ui::TouchHandleDrawable* CreateDrawable() override;
void CopyOutput(
content::SynchronousCompositor* compositor,
std::unique_ptr<viz::CopyOutputRequest> copy_request) override;
void AddBeginFrameCompletionCallback(base::OnceClosure callback) override;
void SetThreads(const std::vector<viz::Thread>& threads) override;
// CompositorFrameProducer overrides
base::WeakPtr<CompositorFrameProducer> GetWeakPtr() override;
void RemoveCompositorFrameConsumer(
CompositorFrameConsumer* consumer) override;
void ReturnUsedResources(std::vector<viz::ReturnedResource> resources,
const viz::FrameSinkId& frame_sink_id,
uint32_t layer_tree_frame_sink_id) override;
void OnParentDrawDataUpdated(
CompositorFrameConsumer* compositor_frame_consumer) override;
void OnViewTreeForceDarkStateChanged(
bool view_tree_force_dark_state) override;
void ChildSurfaceWasEvicted() override;
void SetActiveFrameSinkId(const viz::FrameSinkId& frame_sink_id);
// RootFrameSinkProxy overrides
void Invalidate() override;
void ReturnResourcesFromViz(
viz::FrameSinkId frame_sink_id,
uint32_t layer_tree_frame_sink_id,
std::vector<viz::ReturnedResource> resources) override;
void OnCompositorFrameTransitionDirectiveProcessed(
viz::FrameSinkId frame_sink_id,
uint32_t layer_tree_frame_sink_id,
uint32_t sequence_id) override;
// Visible for testing.
content::SynchronousCompositor* GetActiveCompositorForTesting() const {
return compositor_;
}
bool window_visible_for_tests() const { return window_visible_; }
private:
void SetActiveCompositor(content::SynchronousCompositor* compositor);
void SetTotalRootLayerScrollOffset(const gfx::PointF& new_value_dip);
bool CanOnDraw();
bool CompositeSW(SkCanvas* canvas, bool software_canvas);
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
RootLayerStateAsValue(const gfx::PointF& total_scroll_offset_dip,
const gfx::SizeF& scrollable_size_dip);
void ReturnUncommittedFrames(ChildFrameQueue frame);
void ReturnUnusedResource(std::unique_ptr<ChildFrame> frame);
void ReturnResourceFromParent(
CompositorFrameConsumer* compositor_frame_consumer);
void ReleaseHardware();
bool DoUpdateParentDrawData();
void UpdateBeginFrameSource();
void UpdateForegroundForGpuResources();
gfx::Point max_scroll_offset() const;
// Return the tile rect in view space.
gfx::Rect ComputeTileRectAndUpdateMemoryPolicy();
content::SynchronousCompositor* FindCompositor(
const viz::FrameSinkId& frame_sink_id) const;
// For debug tracing or logging. Return the string representation of this
// view renderer's state.
std::string ToString() const;
void SetBrowserIOThreadId(base::PlatformThreadId thread_id);
const raw_ptr<BrowserViewRendererClient> client_;
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
raw_ptr<CompositorFrameConsumer> current_compositor_frame_consumer_;
std::unique_ptr<RootFrameSinkProxy> root_frame_sink_proxy_;
// The current compositor that's owned by the current RVH.
raw_ptr<content::SynchronousCompositor> compositor_;
// The id of the most recent RVH according to RVHChanged.
viz::FrameSinkId frame_sink_id_;
// A map from compositor's per-WebView unique ID to the compositor's raw
// pointer. A raw pointer here is fine because the entry will be erased when
// a compositor is destroyed.
std::map<viz::FrameSinkId,
raw_ptr<content::SynchronousCompositor, CtnExperimental>>
compositor_map_;
bool is_paused_;
bool view_visible_;
bool window_visible_; // Only applicable if |attached_to_window_| is true.
bool attached_to_window_;
bool was_attached_; // Whether the view was attached to window at least once.
bool hardware_enabled_;
float dip_scale_;
float page_scale_factor_;
float min_page_scale_factor_;
float max_page_scale_factor_;
bool on_new_picture_enable_;
bool clear_view_;
bool foreground_for_gpu_resources_ = false;
// Used for metrics, indicates if we called invalidate since last draw.
bool did_invalidate_since_last_draw_ = false;
// Approximates whether render thread functor has a frame to draw. It is safe
// for Java side to stop blitting the background color once this is true.
bool has_rendered_frame_ = false;
bool offscreen_pre_raster_;
CopyOutputRequestQueue copy_requests_;
gfx::Point last_on_draw_scroll_offset_;
gfx::Rect last_on_draw_global_visible_rect_;
gfx::Size size_;
gfx::SizeF scrollable_size_dip_;
// When zoom-for-dsf enabled |max_scroll_offset_unscaled_| and
// |scroll_offset_unscaled_| is in physical pixel; otherwise, they are in dip
gfx::PointF scroll_offset_unscaled_;
gfx::PointF max_scroll_offset_unscaled_;
// Used to prevent rounding errors from accumulating enough to generate
// visible skew (especially noticeable when scrolling up and down in the same
// spot over a period of time).
gfx::Vector2dF overscroll_rounding_error_;
// The scroll to apply after the next scroll state update.
std::optional<gfx::Point> scroll_on_scroll_state_update_;
ParentCompositorDrawConstraints external_draw_constraints_;
std::unique_ptr<BeginFrameSourceWebView> begin_frame_source_;
std::vector<viz::Thread> renderer_threads_;
base::PlatformThreadId browser_io_thread_id_ = base::kInvalidThreadId;
base::WeakPtrFactory<BrowserViewRenderer> weak_ptr_factory_{this};
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_GFX_BROWSER_VIEW_RENDERER_H_