| // Copyright 2019 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/root_frame_sink_proxy.h" |
| |
| #include <utility> |
| |
| #include "android_webview/browser/gfx/root_frame_sink.h" |
| #include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/task/single_thread_task_runner.h" |
| |
| namespace android_webview { |
| |
| class RootFrameSinkProxy::RootFrameSinkClientImpl : public RootFrameSinkClient { |
| public: |
| RootFrameSinkClientImpl(RootFrameSinkProxy* owner) : owner_(owner) {} |
| ~RootFrameSinkClientImpl() override = default; |
| |
| // RootFrameSinkClient implementation |
| void SetNeedsBeginFrames(bool needs_begin_frame) override { |
| owner_->SetNeedsBeginFramesOnViz(needs_begin_frame); |
| } |
| void Invalidate() override { owner_->InvalidateOnViz(); } |
| void ReturnResources(viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| std::vector<viz::ReturnedResource> resources) override { |
| owner_->ReturnResourcesOnViz(frame_sink_id, layer_tree_frame_sink_id, |
| std::move(resources)); |
| } |
| void OnCompositorFrameTransitionDirectiveProcessed( |
| viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| uint32_t sequence_id) override { |
| owner_->OnCompositorFrameTransitionDirectiveProcessedOnViz( |
| frame_sink_id, layer_tree_frame_sink_id, sequence_id); |
| } |
| |
| private: |
| const raw_ptr<RootFrameSinkProxy> owner_; |
| }; |
| |
| // static |
| scoped_refptr<RootFrameSink> RootFrameSinkProxy::GetRootFrameSinkHelper( |
| base::WeakPtr<RootFrameSinkProxy> proxy) { |
| DCHECK(VizCompositorThreadRunnerWebView::GetInstance() |
| ->task_runner() |
| ->BelongsToCurrentThread()); |
| if (proxy) |
| return proxy->without_gpu_; |
| return nullptr; |
| } |
| |
| RootFrameSinkProxy::RootFrameSinkProxy( |
| const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, |
| RootFrameSinkProxyClient* client, |
| viz::BeginFrameSource* begin_frame_source) |
| : ui_task_runner_(ui_task_runner), |
| viz_task_runner_( |
| VizCompositorThreadRunnerWebView::GetInstance()->task_runner()), |
| client_(client), |
| begin_frame_source_(begin_frame_source) { |
| DETACH_FROM_THREAD(viz_thread_checker_); |
| viz_task_runner_->PostTask( |
| FROM_HERE, base::BindOnce(&RootFrameSinkProxy::InitializeOnViz, |
| base::Unretained(this))); |
| } |
| |
| void RootFrameSinkProxy::InitializeOnViz() { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| root_frame_sink_client_ = std::make_unique<RootFrameSinkClientImpl>(this); |
| without_gpu_ = |
| base::MakeRefCounted<RootFrameSink>(root_frame_sink_client_.get()); |
| } |
| |
| RootFrameSinkProxy::~RootFrameSinkProxy() { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| VizCompositorThreadRunnerWebView::GetInstance()->PostTaskAndBlock( |
| FROM_HERE, base::BindOnce(&RootFrameSinkProxy::DestroyOnViz, |
| base::Unretained(this))); |
| if (observing_bfs_) |
| begin_frame_source_->RemoveObserver(this); |
| } |
| |
| void RootFrameSinkProxy::DestroyOnViz() { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| without_gpu_->DettachClient(); |
| without_gpu_.reset(); |
| weak_ptr_factory_on_viz_.InvalidateWeakPtrs(); |
| root_frame_sink_client_.reset(); |
| } |
| |
| void RootFrameSinkProxy::SetNeedsBeginFramesOnViz(bool needs_begin_frames) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| ui_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::SetNeedsBeginFramesOnUI, |
| weak_ptr_factory_.GetWeakPtr(), needs_begin_frames)); |
| } |
| |
| void RootFrameSinkProxy::SetNeedsBeginFramesOnUI(bool needs_begin_frames) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| if (observing_bfs_ == needs_begin_frames) |
| return; |
| |
| observing_bfs_ = needs_begin_frames; |
| |
| if (needs_begin_frames) |
| begin_frame_source_->AddObserver(this); |
| else |
| begin_frame_source_->RemoveObserver(this); |
| } |
| |
| void RootFrameSinkProxy::InvalidateOnViz() { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| ui_task_runner_->PostTask(FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::InvalidateOnUI, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void RootFrameSinkProxy::InvalidateOnUI() { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| client_->Invalidate(); |
| } |
| |
| void RootFrameSinkProxy::AddChildFrameSinkId( |
| const viz::FrameSinkId& frame_sink_id) { |
| DCHECK_NE(frame_sink_id.client_id(), 0u); |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| viz_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::AddChildFrameSinkIdOnViz, |
| weak_ptr_factory_on_viz_.GetWeakPtr(), frame_sink_id)); |
| } |
| |
| void RootFrameSinkProxy::AddChildFrameSinkIdOnViz( |
| const viz::FrameSinkId& frame_sink_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| without_gpu_->AddChildFrameSinkId(frame_sink_id); |
| } |
| |
| void RootFrameSinkProxy::RemoveChildFrameSinkId( |
| const viz::FrameSinkId& frame_sink_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| viz_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::RemoveChildFrameSinkIdOnViz, |
| weak_ptr_factory_on_viz_.GetWeakPtr(), frame_sink_id)); |
| } |
| |
| void RootFrameSinkProxy::RemoveChildFrameSinkIdOnViz( |
| const viz::FrameSinkId& frame_sink_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| without_gpu_->RemoveChildFrameSinkId(frame_sink_id); |
| } |
| |
| void RootFrameSinkProxy::OnInputEvent() { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| had_input_event_ = true; |
| } |
| |
| bool RootFrameSinkProxy::BeginFrame(const viz::BeginFrameArgs& args) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| bool invalidate = false; |
| VizCompositorThreadRunnerWebView::GetInstance()->PostTaskAndBlock( |
| FROM_HERE, base::BindOnce(&RootFrameSinkProxy::BeginFrameOnViz, |
| base::Unretained(this), args, had_input_event_, |
| &invalidate)); |
| had_input_event_ = false; |
| return invalidate; |
| } |
| |
| void RootFrameSinkProxy::BeginFrameOnViz(const viz::BeginFrameArgs& args, |
| bool had_input_event, |
| bool* invalidate) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| *invalidate = without_gpu_->BeginFrame(args, had_input_event); |
| } |
| |
| void RootFrameSinkProxy::SetBeginFrameSourcePausedOnViz(bool paused) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| without_gpu_->SetBeginFrameSourcePaused(paused); |
| } |
| |
| RootFrameSinkGetter RootFrameSinkProxy::GetRootFrameSinkCallback() { |
| return base::BindRepeating(&RootFrameSinkProxy::GetRootFrameSinkHelper, |
| weak_ptr_factory_on_viz_.GetWeakPtr()); |
| } |
| |
| void RootFrameSinkProxy::OnBeginFrameSourcePausedChanged(bool paused) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| viz_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::SetBeginFrameSourcePausedOnViz, |
| weak_ptr_factory_on_viz_.GetWeakPtr(), paused)); |
| } |
| |
| bool RootFrameSinkProxy::OnBeginFrameDerivedImpl( |
| const viz::BeginFrameArgs& args) { |
| DCHECK(client_); |
| if (BeginFrame(args)) |
| client_->Invalidate(); |
| |
| return true; |
| } |
| |
| void RootFrameSinkProxy::ReturnResourcesOnUI( |
| viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| std::vector<viz::ReturnedResource> resources) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| client_->ReturnResourcesFromViz(frame_sink_id, layer_tree_frame_sink_id, |
| std::move(resources)); |
| } |
| void RootFrameSinkProxy::ReturnResourcesOnViz( |
| viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| std::vector<viz::ReturnedResource> resources) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| ui_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy::ReturnResourcesOnUI, |
| weak_ptr_factory_.GetWeakPtr(), frame_sink_id, |
| layer_tree_frame_sink_id, std::move(resources))); |
| } |
| |
| void RootFrameSinkProxy::OnCompositorFrameTransitionDirectiveProcessedOnUI( |
| viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| uint32_t sequence_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_); |
| client_->OnCompositorFrameTransitionDirectiveProcessed( |
| frame_sink_id, layer_tree_frame_sink_id, sequence_id); |
| } |
| |
| void RootFrameSinkProxy::OnCompositorFrameTransitionDirectiveProcessedOnViz( |
| viz::FrameSinkId frame_sink_id, |
| uint32_t layer_tree_frame_sink_id, |
| uint32_t sequence_id) { |
| DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_); |
| ui_task_runner_->PostTask( |
| FROM_HERE, |
| base::BindOnce(&RootFrameSinkProxy:: |
| OnCompositorFrameTransitionDirectiveProcessedOnUI, |
| weak_ptr_factory_.GetWeakPtr(), frame_sink_id, |
| layer_tree_frame_sink_id, sequence_id)); |
| } |
| |
| } // namespace android_webview |