1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "android_webview/browser/gfx/root_frame_sink_proxy.h"
6 
7 #include <utility>
8 
9 #include "android_webview/browser/gfx/root_frame_sink.h"
10 #include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
11 
12 namespace android_webview {
13 
14 class RootFrameSinkProxy::RootFrameSinkClientImpl : public RootFrameSinkClient {
15  public:
RootFrameSinkClientImpl(RootFrameSinkProxy * owner)16   RootFrameSinkClientImpl(RootFrameSinkProxy* owner) : owner_(owner) {}
17   ~RootFrameSinkClientImpl() override = default;
18 
19   // RootFrameSinkClient implementation
SetNeedsBeginFrames(bool needs_begin_frame)20   void SetNeedsBeginFrames(bool needs_begin_frame) override {
21     owner_->SetNeedsBeginFramesOnViz(needs_begin_frame);
22   }
Invalidate()23   void Invalidate() override { owner_->InvalidateOnViz(); }
ReturnResources(viz::FrameSinkId frame_sink_id,uint32_t layer_tree_frame_sink_id,std::vector<viz::ReturnedResource> resources)24   void ReturnResources(viz::FrameSinkId frame_sink_id,
25                        uint32_t layer_tree_frame_sink_id,
26                        std::vector<viz::ReturnedResource> resources) override {
27     owner_->ReturnResourcesOnViz(frame_sink_id, layer_tree_frame_sink_id,
28                                  std::move(resources));
29   }
30 
31  private:
32   RootFrameSinkProxy* const owner_;
33 };
34 
35 // static
GetRootFrameSinkHelper(base::WeakPtr<RootFrameSinkProxy> proxy)36 scoped_refptr<RootFrameSink> RootFrameSinkProxy::GetRootFrameSinkHelper(
37     base::WeakPtr<RootFrameSinkProxy> proxy) {
38   DCHECK(VizCompositorThreadRunnerWebView::GetInstance()
39              ->task_runner()
40              ->BelongsToCurrentThread());
41   if (proxy)
42     return proxy->without_gpu_;
43   return nullptr;
44 }
45 
RootFrameSinkProxy(const scoped_refptr<base::SingleThreadTaskRunner> & ui_task_runner,RootFrameSinkProxyClient * client,viz::BeginFrameSource * begin_frame_source)46 RootFrameSinkProxy::RootFrameSinkProxy(
47     const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
48     RootFrameSinkProxyClient* client,
49     viz::BeginFrameSource* begin_frame_source)
50     : ui_task_runner_(ui_task_runner),
51       viz_task_runner_(
52           VizCompositorThreadRunnerWebView::GetInstance()->task_runner()),
53       client_(client),
54       begin_frame_source_(begin_frame_source) {
55   DETACH_FROM_THREAD(viz_thread_checker_);
56   viz_task_runner_->PostTask(
57       FROM_HERE, base::BindOnce(&RootFrameSinkProxy::InitializeOnViz,
58                                 base::Unretained(this)));
59 }
60 
InitializeOnViz()61 void RootFrameSinkProxy::InitializeOnViz() {
62   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
63   root_frame_sink_client_ = std::make_unique<RootFrameSinkClientImpl>(this);
64   without_gpu_ =
65       base::MakeRefCounted<RootFrameSink>(root_frame_sink_client_.get());
66 }
67 
~RootFrameSinkProxy()68 RootFrameSinkProxy::~RootFrameSinkProxy() {
69   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
70   VizCompositorThreadRunnerWebView::GetInstance()->PostTaskAndBlock(
71       FROM_HERE, base::BindOnce(&RootFrameSinkProxy::DestroyOnViz,
72                                 base::Unretained(this)));
73   if (observing_bfs_)
74     begin_frame_source_->RemoveObserver(this);
75 }
76 
DestroyOnViz()77 void RootFrameSinkProxy::DestroyOnViz() {
78   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
79   without_gpu_->DettachClient();
80   without_gpu_.reset();
81   weak_ptr_factory_on_viz_.InvalidateWeakPtrs();
82   root_frame_sink_client_.reset();
83 }
84 
SetNeedsBeginFramesOnViz(bool needs_begin_frames)85 void RootFrameSinkProxy::SetNeedsBeginFramesOnViz(bool needs_begin_frames) {
86   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
87   ui_task_runner_->PostTask(
88       FROM_HERE,
89       base::BindOnce(&RootFrameSinkProxy::SetNeedsBeginFramesOnUI,
90                      weak_ptr_factory_.GetWeakPtr(), needs_begin_frames));
91 }
92 
SetNeedsBeginFramesOnUI(bool needs_begin_frames)93 void RootFrameSinkProxy::SetNeedsBeginFramesOnUI(bool needs_begin_frames) {
94   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
95   if (observing_bfs_ == needs_begin_frames)
96     return;
97 
98   observing_bfs_ = needs_begin_frames;
99 
100   if (needs_begin_frames)
101     begin_frame_source_->AddObserver(this);
102   else
103     begin_frame_source_->RemoveObserver(this);
104 }
105 
InvalidateOnViz()106 void RootFrameSinkProxy::InvalidateOnViz() {
107   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
108   ui_task_runner_->PostTask(FROM_HERE,
109                             base::BindOnce(&RootFrameSinkProxy::InvalidateOnUI,
110                                            weak_ptr_factory_.GetWeakPtr()));
111 }
112 
InvalidateOnUI()113 void RootFrameSinkProxy::InvalidateOnUI() {
114   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
115   client_->Invalidate();
116 }
117 
AddChildFrameSinkId(const viz::FrameSinkId & frame_sink_id)118 void RootFrameSinkProxy::AddChildFrameSinkId(
119     const viz::FrameSinkId& frame_sink_id) {
120   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
121   viz_task_runner_->PostTask(
122       FROM_HERE,
123       base::BindOnce(&RootFrameSinkProxy::AddChildFrameSinkIdOnViz,
124                      weak_ptr_factory_on_viz_.GetWeakPtr(), frame_sink_id));
125 }
126 
AddChildFrameSinkIdOnViz(const viz::FrameSinkId & frame_sink_id)127 void RootFrameSinkProxy::AddChildFrameSinkIdOnViz(
128     const viz::FrameSinkId& frame_sink_id) {
129   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
130   without_gpu_->AddChildFrameSinkId(frame_sink_id);
131 }
132 
RemoveChildFrameSinkId(const viz::FrameSinkId & frame_sink_id)133 void RootFrameSinkProxy::RemoveChildFrameSinkId(
134     const viz::FrameSinkId& frame_sink_id) {
135   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
136   viz_task_runner_->PostTask(
137       FROM_HERE,
138       base::BindOnce(&RootFrameSinkProxy::RemoveChildFrameSinkIdOnViz,
139                      weak_ptr_factory_on_viz_.GetWeakPtr(), frame_sink_id));
140 }
141 
RemoveChildFrameSinkIdOnViz(const viz::FrameSinkId & frame_sink_id)142 void RootFrameSinkProxy::RemoveChildFrameSinkIdOnViz(
143     const viz::FrameSinkId& frame_sink_id) {
144   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
145   without_gpu_->RemoveChildFrameSinkId(frame_sink_id);
146 }
147 
OnInputEvent()148 void RootFrameSinkProxy::OnInputEvent() {
149   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
150   had_input_event_ = true;
151 }
152 
BeginFrame(const viz::BeginFrameArgs & args)153 bool RootFrameSinkProxy::BeginFrame(const viz::BeginFrameArgs& args) {
154   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
155   bool invalidate = false;
156   VizCompositorThreadRunnerWebView::GetInstance()->PostTaskAndBlock(
157       FROM_HERE, base::BindOnce(&RootFrameSinkProxy::BeginFrameOnViz,
158                                 base::Unretained(this), args, had_input_event_,
159                                 &invalidate));
160   had_input_event_ = false;
161   return invalidate;
162 }
163 
BeginFrameOnViz(const viz::BeginFrameArgs & args,bool had_input_event,bool * invalidate)164 void RootFrameSinkProxy::BeginFrameOnViz(const viz::BeginFrameArgs& args,
165                                          bool had_input_event,
166                                          bool* invalidate) {
167   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
168   *invalidate = without_gpu_->BeginFrame(args, had_input_event);
169 }
170 
SetBeginFrameSourcePausedOnViz(bool paused)171 void RootFrameSinkProxy::SetBeginFrameSourcePausedOnViz(bool paused) {
172   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
173   without_gpu_->SetBeginFrameSourcePaused(paused);
174 }
175 
GetRootFrameSinkCallback()176 RootFrameSinkGetter RootFrameSinkProxy::GetRootFrameSinkCallback() {
177   return base::BindRepeating(&RootFrameSinkProxy::GetRootFrameSinkHelper,
178                              weak_ptr_factory_on_viz_.GetWeakPtr());
179 }
180 
OnBeginFrameSourcePausedChanged(bool paused)181 void RootFrameSinkProxy::OnBeginFrameSourcePausedChanged(bool paused) {
182   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
183   viz_task_runner_->PostTask(
184       FROM_HERE,
185       base::BindOnce(&RootFrameSinkProxy::SetBeginFrameSourcePausedOnViz,
186                      weak_ptr_factory_on_viz_.GetWeakPtr(), paused));
187 }
188 
OnBeginFrameDerivedImpl(const viz::BeginFrameArgs & args)189 bool RootFrameSinkProxy::OnBeginFrameDerivedImpl(
190     const viz::BeginFrameArgs& args) {
191   DCHECK(client_);
192   if (BeginFrame(args))
193     client_->Invalidate();
194 
195   return true;
196 }
197 
ReturnResourcesOnUI(viz::FrameSinkId frame_sink_id,uint32_t layer_tree_frame_sink_id,std::vector<viz::ReturnedResource> resources)198 void RootFrameSinkProxy::ReturnResourcesOnUI(
199     viz::FrameSinkId frame_sink_id,
200     uint32_t layer_tree_frame_sink_id,
201     std::vector<viz::ReturnedResource> resources) {
202   DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
203   client_->ReturnResourcesFromViz(frame_sink_id, layer_tree_frame_sink_id,
204                                   std::move(resources));
205 }
ReturnResourcesOnViz(viz::FrameSinkId frame_sink_id,uint32_t layer_tree_frame_sink_id,std::vector<viz::ReturnedResource> resources)206 void RootFrameSinkProxy::ReturnResourcesOnViz(
207     viz::FrameSinkId frame_sink_id,
208     uint32_t layer_tree_frame_sink_id,
209     std::vector<viz::ReturnedResource> resources) {
210   DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
211   ui_task_runner_->PostTask(
212       FROM_HERE,
213       base::BindOnce(&RootFrameSinkProxy::ReturnResourcesOnUI,
214                      weak_ptr_factory_.GetWeakPtr(), frame_sink_id,
215                      layer_tree_frame_sink_id, std::move(resources)));
216 }
217 
218 }  // namespace android_webview
219