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_