Skip to content

Commit

Permalink
Add Surface::GetContext() support on Fuchsia (flutter#20391)
Browse files Browse the repository at this point in the history
This improves raster cache control from apps and enables
GPU acceleration for some offscreen workloads that would
fallback to software.

Test: PlatformViewTests.GetGrContextTest

Co-authored-by: David Reveman <[email protected]>
  • Loading branch information
dreveman and David Reveman authored Aug 11, 2020
1 parent 702b595 commit 0cf4809
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 5 deletions.
4 changes: 4 additions & 0 deletions shell/platform/fuchsia/flutter/compositor_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class CompositorContext final : public flutter::CompositorContext {
return &session_connection_.scene_update_context();
}

GrDirectContext* GetGrContext() {
return session_connection_.vulkan_surface_producer()->gr_context();
}

private:
const std::string debug_label_;
scenic::ViewRefPair view_ref_pair_;
Expand Down
18 changes: 18 additions & 0 deletions shell/platform/fuchsia/flutter/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ Engine::Engine(Delegate& delegate,
OnGetViewEmbedder on_get_view_embedder_callback =
std::bind(&Engine::GetViewEmbedder, this);

OnGetGrContext on_get_gr_context_callback =
std::bind(&Engine::GetGrContext, this);

// SessionListener has a OnScenicError method; invoke this callback on the
// platform thread when that happens. The Session itself should also be
// disconnected when this happens, and it will also attempt to terminate.
Expand Down Expand Up @@ -154,6 +157,7 @@ Engine::Engine(Delegate& delegate,
on_destroy_view_callback = std::move(on_destroy_view_callback),
on_get_view_embedder_callback =
std::move(on_get_view_embedder_callback),
on_get_gr_context_callback = std::move(on_get_gr_context_callback),
vsync_handle = vsync_event_.get(),
product_config = product_config](flutter::Shell& shell) mutable {
return std::make_unique<flutter_runner::PlatformView>(
Expand All @@ -172,6 +176,7 @@ Engine::Engine(Delegate& delegate,
std::move(on_create_view_callback),
std::move(on_destroy_view_callback),
std::move(on_get_view_embedder_callback),
std::move(on_get_gr_context_callback),
vsync_handle, // vsync handle
product_config);
});
Expand Down Expand Up @@ -590,6 +595,19 @@ void Engine::OnSessionSizeChangeHint(float width_change_factor,
});
}

GrDirectContext* Engine::GetGrContext() {
// GetGrContext should be called only after rasterizer is created.
FML_DCHECK(shell_);
FML_DCHECK(shell_->GetRasterizer());

auto rasterizer = shell_->GetRasterizer();
auto compositor_context =
reinterpret_cast<flutter_runner::CompositorContext*>(
rasterizer->compositor_context());
GrDirectContext* gr_context = compositor_context->GetGrContext();
return gr_context;
}

#if !defined(DART_PRODUCT)
void Engine::WriteProfileToTrace() const {
Dart_Port main_port = shell_->GetEngine()->GetUIIsolateMainPort();
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/fuchsia/flutter/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class Engine final {

flutter::ExternalViewEmbedder* GetViewEmbedder();

GrDirectContext* GetGrContext();

FML_DISALLOW_COPY_AND_ASSIGN(Engine);
};

Expand Down
5 changes: 4 additions & 1 deletion shell/platform/fuchsia/flutter/platform_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ PlatformView::PlatformView(
OnCreateView on_create_view_callback,
OnDestroyView on_destroy_view_callback,
OnGetViewEmbedder on_get_view_embedder_callback,
OnGetGrContext on_get_gr_context_callback,
zx_handle_t vsync_event_handle,
FlutterRunnerProductConfiguration product_config)
: flutter::PlatformView(delegate, std::move(task_runners)),
Expand All @@ -111,6 +112,7 @@ PlatformView::PlatformView(
on_create_view_callback_(std::move(on_create_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),
on_get_view_embedder_callback_(std::move(on_get_view_embedder_callback)),
on_get_gr_context_callback_(std::move(on_get_gr_context_callback)),
ime_client_(this),
vsync_event_handle_(vsync_event_handle),
product_config_(product_config) {
Expand Down Expand Up @@ -581,7 +583,8 @@ std::unique_ptr<flutter::Surface> PlatformView::CreateRenderingSurface() {
// surface is setup once during platform view setup and returned to the
// shell on the initial (and only) |NotifyCreated| call.
auto view_embedder = on_get_view_embedder_callback_();
return std::make_unique<Surface>(debug_label_, view_embedder);
auto gr_context = on_get_gr_context_callback_();
return std::make_unique<Surface>(debug_label_, view_embedder, gr_context);
}

// |flutter::PlatformView|
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/fuchsia/flutter/platform_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ using OnEnableWireframe = fit::function<void(bool)>;
using OnCreateView = fit::function<void(int64_t, bool, bool)>;
using OnDestroyView = fit::function<void(int64_t)>;
using OnGetViewEmbedder = fit::function<flutter::ExternalViewEmbedder*()>;
using OnGetGrContext = fit::function<GrDirectContext*()>;

// The per engine component residing on the platform thread is responsible for
// all platform specific integrations.
Expand Down Expand Up @@ -60,6 +61,7 @@ class PlatformView final : public flutter::PlatformView,
OnCreateView on_create_view_callback,
OnDestroyView on_destroy_view_callback,
OnGetViewEmbedder on_get_view_embedder_callback,
OnGetGrContext on_get_gr_context_callback,
zx_handle_t vsync_event_handle,
FlutterRunnerProductConfiguration product_config);
PlatformView(flutter::PlatformView::Delegate& delegate,
Expand Down Expand Up @@ -100,6 +102,7 @@ class PlatformView final : public flutter::PlatformView,
OnCreateView on_create_view_callback_;
OnDestroyView on_destroy_view_callback_;
OnGetViewEmbedder on_get_view_embedder_callback_;
OnGetGrContext on_get_gr_context_callback_;

int current_text_input_client_ = 0;
fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_;
Expand Down
62 changes: 62 additions & 0 deletions shell/platform/fuchsia/flutter/platform_view_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
flutter::ExternalViewEmbedder* get_view_embedder() {
return surface_->GetExternalViewEmbedder();
}
GrDirectContext* get_gr_context() { return surface_->GetContext(); }

private:
std::unique_ptr<flutter::Surface> surface_;
Expand Down Expand Up @@ -168,6 +169,7 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
Expand Down Expand Up @@ -225,6 +227,7 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
Expand Down Expand Up @@ -293,6 +296,7 @@ TEST_F(PlatformViewTests, CreateViewTest) {
CreateViewCallback, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
Expand Down Expand Up @@ -363,6 +367,7 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
nullptr, // on_create_view_callback,
DestroyViewCallback, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
Expand Down Expand Up @@ -426,6 +431,7 @@ TEST_F(PlatformViewTests, RequestFocusTest) {
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
nullptr, // on_get_gr_context_callback,
nullptr, // on_get_view_embedder_callback,
0u, // vsync_event_handle
{} // product_config
Expand Down Expand Up @@ -501,6 +507,7 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
GetViewEmbedderCallback, // on_get_view_embedder_callback,
nullptr, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);
Expand All @@ -514,4 +521,59 @@ TEST_F(PlatformViewTests, GetViewEmbedderTest) {
EXPECT_EQ(view_embedder, delegate.get_view_embedder());
}

// Test to make sure that PlatformView correctly returns a Surface instance
// that can surface the GrContext provided from GetGrContextCallback.
TEST_F(PlatformViewTests, GetGrContextTest) {
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
MockPlatformViewDelegate delegate;
zx::eventpair a, b;
zx::eventpair::create(/* flags */ 0u, &a, &b);
auto view_ref = fuchsia::ui::views::ViewRef({
.reference = std::move(a),
});
flutter::TaskRunners task_runners =
flutter::TaskRunners("test_runners", // label
nullptr, // platform
flutter_runner::CreateFMLTaskRunner(
async_get_default_dispatcher()), // raster
nullptr, // ui
nullptr // io
);

// Test get GrContext callback function.
sk_sp<GrDirectContext> gr_context =
GrDirectContext::MakeMock(nullptr, GrContextOptions());
auto GetGrContextCallback = [gr_context = gr_context.get()]() {
return gr_context;
};

auto platform_view = flutter_runner::PlatformView(
delegate, // delegate
"test_platform_view", // label
std::move(view_ref), // view_refs
std::move(task_runners), // task_runners
services_provider.service_directory(), // runner_services
nullptr, // parent_environment_service_provider_handle
nullptr, // session_listener_request
nullptr, // on_session_listener_error_callback
nullptr, // session_metrics_did_change_callback
nullptr, // session_size_change_hint_callback
nullptr, // on_enable_wireframe_callback,
nullptr, // on_create_view_callback,
nullptr, // on_destroy_view_callback,
nullptr, // on_get_view_embedder_callback,
GetGrContextCallback, // on_get_gr_context_callback,
0u, // vsync_event_handle
{} // product_config
);

RunLoopUntilIdle();

platform_view.NotifyCreated();

RunLoopUntilIdle();

EXPECT_EQ(gr_context.get(), delegate.get_gr_context());
}

} // namespace flutter_runner_test::flutter_runner_a11y_test
9 changes: 6 additions & 3 deletions shell/platform/fuchsia/flutter/surface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
namespace flutter_runner {

Surface::Surface(std::string debug_label,
flutter::ExternalViewEmbedder* view_embedder)
: debug_label_(std::move(debug_label)), view_embedder_(view_embedder) {}
flutter::ExternalViewEmbedder* view_embedder,
GrDirectContext* gr_context)
: debug_label_(std::move(debug_label)),
view_embedder_(view_embedder),
gr_context_(gr_context) {}

Surface::~Surface() = default;

Expand All @@ -36,7 +39,7 @@ std::unique_ptr<flutter::SurfaceFrame> Surface::AcquireFrame(

// |flutter::Surface|
GrDirectContext* Surface::GetContext() {
return nullptr;
return gr_context_;
}

static zx_status_t DriverWatcher(int dirfd,
Expand Down
4 changes: 3 additions & 1 deletion shell/platform/fuchsia/flutter/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ namespace flutter_runner {
class Surface final : public flutter::Surface {
public:
Surface(std::string debug_label,
flutter::ExternalViewEmbedder* view_embedder);
flutter::ExternalViewEmbedder* view_embedder,
GrDirectContext* gr_context);

~Surface() override;

private:
const bool valid_ = CanConnectToDisplay();
const std::string debug_label_;
flutter::ExternalViewEmbedder* view_embedder_;
GrDirectContext* gr_context_;

// |flutter::Surface|
bool IsValid() override;
Expand Down

0 comments on commit 0cf4809

Please sign in to comment.