Skip to content

Commit

Permalink
aw: Add RootFrameSink and RootFrameSinkProxy
Browse files Browse the repository at this point in the history
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: kylechar <kylechar@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686597}
  • Loading branch information
Bo Liu authored and Commit Bot committed Aug 13, 2019
1 parent 6381a94 commit 9314061
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 1 deletion.
4 changes: 4 additions & 0 deletions android_webview/browser/gfx/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
20 changes: 19 additions & 1 deletion android_webview/browser/gfx/browser_view_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand All @@ -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);
}

Expand Down Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions android_webview/browser/gfx/browser_view_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand All @@ -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_;
Expand Down
98 changes: 98 additions & 0 deletions android_webview/browser/gfx/root_frame_sink.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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
77 changes: 77 additions & 0 deletions android_webview/browser/gfx/root_frame_sink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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_
123 changes: 123 additions & 0 deletions android_webview/browser/gfx/root_frame_sink_proxy.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// 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

0 comments on commit 9314061

Please sign in to comment.