Commit 93140617 authored by Bo Liu's avatar Bo Liu Committed by Commit Bot

aw: Add RootFrameSink and RootFrameSinkProxy

Both are per-webview objects.

RootFrameSink lives on the viz thread, and responsible for per-webview
objects that do not require access to the GPU. This is mostly classes
involved for sending begin frames.

RootFrameSinkProxy straddles UI and Viz thread and provides access to
RootFrameSink.

Bug: 805739
Change-Id: I4c7e31882d35eb3f772bd81b62a40a47c279de1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1749527
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686597}
parent 6381a942
......@@ -42,6 +42,10 @@ source_set("gfx") {
"parent_output_surface.h",
"render_thread_manager.cc",
"render_thread_manager.h",
"root_frame_sink.cc",
"root_frame_sink.h",
"root_frame_sink_proxy.cc",
"root_frame_sink_proxy.h",
"scoped_app_gl_state_restore.cc",
"scoped_app_gl_state_restore.h",
"skia_output_surface_dependency_webview.cc",
......
......@@ -7,8 +7,11 @@
#include <memory>
#include <utility>
#include "android_webview/browser/aw_feature_list.h"
#include "android_webview/browser/gfx/browser_view_renderer_client.h"
#include "android_webview/browser/gfx/compositor_frame_consumer.h"
#include "android_webview/browser/gfx/root_frame_sink.h"
#include "android_webview/browser/gfx/root_frame_sink_proxy.h"
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/logging.h"
......@@ -110,7 +113,14 @@ BrowserViewRenderer::BrowserViewRenderer(
on_new_picture_enable_(false),
clear_view_(false),
offscreen_pre_raster_(false),
weak_ptr_factory_(this) {}
weak_ptr_factory_(this) {
if (base::FeatureList::IsEnabled(features::kVizForWebView)) {
root_frame_sink_proxy_ = std::make_unique<RootFrameSinkProxy>(
ui_task_runner_,
base::BindRepeating(&BrowserViewRenderer::SetNeedsBeginFrames,
base::Unretained(this)));
}
}
BrowserViewRenderer::~BrowserViewRenderer() {
DCHECK(compositor_map_.empty());
......@@ -550,6 +560,8 @@ void BrowserViewRenderer::DidInitializeCompositor(
// througout its lifetime.
DCHECK(compositor_map_.count(frame_sink_id) == 0);
compositor_map_[frame_sink_id] = compositor;
if (root_frame_sink_proxy_)
root_frame_sink_proxy_->AddChildFrameSinkId(frame_sink_id);
// At this point, the RVHChanged event for the new RVH that contains the
// |compositor| might have been fired already, in which case just set the
......@@ -570,6 +582,8 @@ void BrowserViewRenderer::DidDestroyCompositor(
copy_requests_.clear();
}
if (root_frame_sink_proxy_)
root_frame_sink_proxy_->RemoveChildFrameSinkId(frame_sink_id);
compositor_map_.erase(frame_sink_id);
}
......@@ -821,6 +835,10 @@ void BrowserViewRenderer::CopyOutput(
PostInvalidate(compositor_);
}
void BrowserViewRenderer::SetNeedsBeginFrames(bool needs_begin_frames) {
NOTIMPLEMENTED();
}
void BrowserViewRenderer::PostInvalidate(
content::SynchronousCompositor* compositor) {
TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate",
......
......@@ -39,6 +39,7 @@ 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.
......@@ -181,6 +182,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient,
CompositorFrameConsumer* compositor_frame_consumer);
void ReleaseHardware();
bool DoUpdateParentDrawData();
void SetNeedsBeginFrames(bool needs_begin_frames);
gfx::Vector2d max_scroll_offset() const;
......@@ -196,6 +198,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient,
BrowserViewRendererClient* const client_;
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
CompositorFrameConsumer* current_compositor_frame_consumer_;
std::unique_ptr<RootFrameSinkProxy> root_frame_sink_proxy_;
// The current compositor that's owned by the current RVH.
content::SynchronousCompositor* compositor_;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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.h"
#include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
#include "base/no_destructor.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
namespace android_webview {
namespace {
viz::FrameSinkId AllocateParentSinkId() {
static base::NoDestructor<viz::FrameSinkIdAllocator> allocator(0u);
return allocator->NextFrameSinkId();
}
} // namespace
RootFrameSink::RootFrameSink(SetNeedsBeginFrameCallback set_needs_begin_frame)
: root_frame_sink_id_(AllocateParentSinkId()),
set_needs_begin_frame_(set_needs_begin_frame) {
constexpr bool is_root = true;
constexpr bool needs_sync_points = true;
GetFrameSinkManager()->RegisterFrameSinkId(root_frame_sink_id_,
false /* report_activationa */);
support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
this, GetFrameSinkManager(), root_frame_sink_id_, is_root,
needs_sync_points);
begin_frame_source_ = std::make_unique<viz::ExternalBeginFrameSource>(this);
GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source_.get(),
root_frame_sink_id_);
}
RootFrameSink::~RootFrameSink() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
GetFrameSinkManager()->UnregisterBeginFrameSource(begin_frame_source_.get());
begin_frame_source_.reset();
support_.reset();
GetFrameSinkManager()->InvalidateFrameSinkId(root_frame_sink_id_);
}
viz::FrameSinkManagerImpl* RootFrameSink::GetFrameSinkManager() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// FrameSinkManagerImpl is global and not owned by this class, which is
// per-AwContents.
return VizCompositorThreadRunnerWebView::GetInstance()->GetFrameSinkManager();
}
void RootFrameSink::DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ReclaimResources(resources);
}
void RootFrameSink::ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Root surface should have no resources to return.
CHECK(resources.empty());
}
void RootFrameSink::OnNeedsBeginFrames(bool needs_begin_frames) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT_INSTANT1("android_webview", "RootFrameSink::OnNeedsBeginFrames",
TRACE_EVENT_SCOPE_THREAD, "needs_begin_frames",
needs_begin_frames);
needs_begin_frames_ = needs_begin_frames;
set_needs_begin_frame_.Run(needs_begin_frames);
}
void RootFrameSink::AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
GetFrameSinkManager()->RegisterFrameSinkHierarchy(root_frame_sink_id_,
frame_sink_id);
}
void RootFrameSink::RemoveChildFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
GetFrameSinkManager()->UnregisterFrameSinkHierarchy(root_frame_sink_id_,
frame_sink_id);
}
bool RootFrameSink::BeginFrame(const viz::BeginFrameArgs& args) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
begin_frame_source_->OnBeginFrame(args);
// This is a hack and wrong. Remove this once we have proper frame submission
// tracking.
return needs_begin_frames_;
}
} // namespace android_webview
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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_ROOT_FRAME_SINK_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_H_
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace viz {
class CompositorFrameSinkSupport;
class FrameSinkManagerImpl;
class ExternalBeginFrameSource;
} // namespace viz
namespace android_webview {
// This class holds per-AwContents classes on the viz thread that do not need
// access to the GPU. It is single-threaded and refcounted on the viz thread.
// This needs to be separate from classes for rendering which requires GPU
// to enable sending begin frames independently from access to GPU.
class RootFrameSink : public base::RefCounted<RootFrameSink>,
public viz::mojom::CompositorFrameSinkClient,
public viz::ExternalBeginFrameSourceClient {
public:
using SetNeedsBeginFrameCallback = base::RepeatingCallback<void(bool)>;
explicit RootFrameSink(SetNeedsBeginFrameCallback set_needs_begin_frame);
viz::CompositorFrameSinkSupport* support() const { return support_.get(); }
const viz::FrameSinkId& root_frame_sink_id() const {
return root_frame_sink_id_;
}
void AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
void RemoveChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
bool BeginFrame(const viz::BeginFrameArgs& args);
// viz::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override;
void OnBeginFrame(const viz::BeginFrameArgs& args,
const viz::FrameTimingDetailsMap& feedbacks) override {}
void OnBeginFramePausedChanged(bool paused) override {}
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
// viz::ExternalBeginFrameSourceClient overrides.
void OnNeedsBeginFrames(bool needs_begin_frames) override;
private:
friend class base::RefCounted<RootFrameSink>;
~RootFrameSink() override;
viz::FrameSinkManagerImpl* GetFrameSinkManager();
const viz::FrameSinkId root_frame_sink_id_;
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
std::unique_ptr<viz::ExternalBeginFrameSource> begin_frame_source_;
bool needs_begin_frames_ = false;
SetNeedsBeginFrameCallback set_needs_begin_frame_;
THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(RootFrameSink);
};
using RootFrameSinkGetter = base::OnceCallback<scoped_refptr<RootFrameSink>()>;
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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"
namespace android_webview {
// 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,
SetNeedsBeginFrameCallback set_needs_begin_frame_callback)
: ui_task_runner_(ui_task_runner),
viz_task_runner_(
VizCompositorThreadRunnerWebView::GetInstance()->task_runner()),
set_needs_begin_frame_callback_(
std::move(set_needs_begin_frame_callback)) {
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_);
without_gpu_ = base::MakeRefCounted<RootFrameSink>(
base::BindRepeating(&RootFrameSinkProxy::SetNeedsBeginFramesOnViz,
weak_ptr_factory_on_viz_.GetWeakPtr()));
}
RootFrameSinkProxy::~RootFrameSinkProxy() {
DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
VizCompositorThreadRunnerWebView::GetInstance()->PostTaskAndBlock(
FROM_HERE, base::BindOnce(&RootFrameSinkProxy::DestroyOnViz,
base::Unretained(this)));
}
void RootFrameSinkProxy::DestroyOnViz() {
DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
DCHECK(without_gpu_->HasOneRef());
without_gpu_.reset();
weak_ptr_factory_on_viz_.InvalidateWeakPtrs();
}
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_);
set_needs_begin_frame_callback_.Run(needs_begin_frames);
}
void RootFrameSinkProxy::AddChildFrameSinkId(
const viz::FrameSinkId& frame_sink_id) {
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);
}
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, &invalidate));
return invalidate;
}
void RootFrameSinkProxy::BeginFrameOnViz(const viz::BeginFrameArgs& args,
bool* invalidate) {
DCHECK_CALLED_ON_VALID_THREAD(viz_thread_checker_);
*invalidate = without_gpu_->BeginFrame(args);
}
RootFrameSinkGetter RootFrameSinkProxy::GetRootFrameSinkCallback() {
return base::BindOnce(&RootFrameSinkProxy::GetRootFrameSinkHelper,
weak_ptr_factory_on_viz_.GetWeakPtr());
}
} // namespace android_webview
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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_ROOT_FRAME_SINK_PROXY_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_PROXY_H_
#include "android_webview/browser/gfx/root_frame_sink.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
namespace viz {
struct BeginFrameArgs;
}
namespace android_webview {
// Per-AwContents object. Straddles UI and Viz thread. Public methods should be
// called on the UI thread unless otherwise specified. Mostly used for creating
// RootFrameSink and routing calls to it.
class RootFrameSinkProxy {
public:
using SetNeedsBeginFrameCallback = RootFrameSink::SetNeedsBeginFrameCallback;
RootFrameSinkProxy(
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
SetNeedsBeginFrameCallback set_needs_begin_frame_callback);
~RootFrameSinkProxy();
void AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
void RemoveChildFrameSinkId(const viz::FrameSinkId& frame_sink_id);
bool BeginFrame(const viz::BeginFrameArgs& args);
// The returned callback can only be called on viz thread.
RootFrameSinkGetter GetRootFrameSinkCallback();
private:
static scoped_refptr<RootFrameSink> GetRootFrameSinkHelper(
base::WeakPtr<RootFrameSinkProxy> proxy);
void InitializeOnViz();
void DestroyOnViz();
void AddChildFrameSinkIdOnViz(const viz::FrameSinkId& frame_sink_id);
void RemoveChildFrameSinkIdOnViz(const viz::FrameSinkId& frame_sink_id);
void BeginFrameOnViz(const viz::BeginFrameArgs& args, bool* invalidate);
void SetNeedsBeginFramesOnViz(bool needs_begin_frames);
void SetNeedsBeginFramesOnUI(bool needs_begin_frames);
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> viz_task_runner_;
SetNeedsBeginFrameCallback set_needs_begin_frame_callback_;
scoped_refptr<RootFrameSink> without_gpu_;
THREAD_CHECKER(ui_thread_checker_);
THREAD_CHECKER(viz_thread_checker_);
base::WeakPtrFactory<RootFrameSinkProxy> weak_ptr_factory_{this};
base::WeakPtrFactory<RootFrameSinkProxy> weak_ptr_factory_on_viz_{this};
DISALLOW_COPY_AND_ASSIGN(RootFrameSinkProxy);
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_GFX_ROOT_FRAME_SINK_PROXY_H_
......@@ -7,19 +7,28 @@
#include <utility>
#include "android_webview/browser/gfx/task_queue_web_view.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/synchronization/waitable_event.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
namespace android_webview {
namespace {
void RunAndDone(base::OnceClosure viz_task, base::OnceClosure done_task) {
std::move(viz_task).Run();
// |done_task| is provided by TaskQueueWebView unblocks the gpu service.
std::move(done_task).Run();
}
void RunAndSignal(base::OnceClosure viz_task, base::WaitableEvent* done) {
std::move(viz_task).Run();
done->Signal();
}
} // namespace
// static
......@@ -68,6 +77,15 @@ void VizCompositorThreadRunnerWebView::ScheduleOnVizAndBlock(
base::BindOnce(&RunAndDone, std::move(task)));
}
void VizCompositorThreadRunnerWebView::PostTaskAndBlock(
const base::Location& from_here,
base::OnceClosure task) {
base::WaitableEvent e;
task_runner()->PostTask(from_here,
base::BindOnce(&RunAndSignal, std::move(task), &e));
e.Wait();
}
VizCompositorThreadRunnerWebView::~VizCompositorThreadRunnerWebView() = default;
base::SingleThreadTaskRunner* VizCompositorThreadRunnerWebView::task_runner() {
......
......@@ -12,6 +12,10 @@
#include "base/threading/thread_checker.h"
#include "components/viz/service/main/viz_compositor_thread_runner.h"
namespace base {
class Location;
} // namespace base
namespace viz {
class FrameSinkManagerImpl;
} // namespace viz
......@@ -35,8 +39,16 @@ class VizCompositorThreadRunnerWebView : public viz::VizCompositorThreadRunner {
static VizCompositorThreadRunnerWebView* GetInstance();
viz::FrameSinkManagerImpl* GetFrameSinkManager();
// Must be called from the TaskQueueWebView thread. |task| is allowed to call
// TaskQueueWebView::ScheduleTask.
void ScheduleOnVizAndBlock(base::OnceClosure task);
// Can be called from any thread, and blocks the caller until the task
// finishes executing.
void PostTaskAndBlock(const base::Location& from_here,
base::OnceClosure task);
// viz::VizCompositorThreadRunner overrides.
base::SingleThreadTaskRunner* task_runner() override;
void CreateFrameSinkManager(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment