Skip to content

Commit

Permalink
[Impeller] Allow image rasterization/decoding before/without surface …
Browse files Browse the repository at this point in the history
…acquisition (#41168)

[Impeller] Allow image rasterization/decoding before/without surface acquisition
  • Loading branch information
dnfield committed Apr 14, 2023
1 parent 460668f commit f091060
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 32 deletions.
2 changes: 1 addition & 1 deletion flow/surface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ bool Surface::EnableRasterCache() const {
return true;
}

impeller::AiksContext* Surface::GetAiksContext() const {
std::shared_ptr<impeller::AiksContext> Surface::GetAiksContext() const {
return nullptr;
}

Expand Down
2 changes: 1 addition & 1 deletion flow/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Surface {

virtual bool EnableRasterCache() const;

virtual impeller::AiksContext* GetAiksContext() const;
virtual std::shared_ptr<impeller::AiksContext> GetAiksContext() const;

/// Capture the `SurfaceData` currently present in the surface.
///
Expand Down
7 changes: 6 additions & 1 deletion shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> Rasterizer::GetSnapshotDelegate()
return weak_factory_.GetWeakPtr();
}

void Rasterizer::SetImpellerContext(
std::weak_ptr<impeller::Context> impeller_context) {
impeller_context_ = std::move(impeller_context);
}

void Rasterizer::Setup(std::unique_ptr<Surface> surface) {
surface_ = std::move(surface);

Expand Down Expand Up @@ -544,7 +549,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
.supports_readback, // surface supports pixel reads
raster_thread_merger_, // thread merger
frame->GetDisplayListBuilder().get(), // display list builder
surface_->GetAiksContext() // aiks context
surface_->GetAiksContext().get() // aiks context
);
if (compositor_frame) {
compositor_context_->raster_cache().BeginFrame();
Expand Down
28 changes: 28 additions & 0 deletions shell/common/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/time/time_point.h"
#if IMPELLER_SUPPORTS_RENDERING
// GN is having trouble understanding how this works in the Fuchsia builds.
#include "flutter/impeller/aiks/aiks_context.h" // nogncheck
#include "flutter/impeller/renderer/context.h" // nogncheck
#endif // IMPELLER_SUPPORTS_RENDERING
#include "flutter/lib/ui/snapshot_delegate.h"
#include "flutter/shell/common/pipeline.h"
#include "flutter/shell/common/snapshot_controller.h"
Expand All @@ -33,6 +38,13 @@
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"

#if !IMPELLER_SUPPORTS_RENDERING
namespace impeller {
class Context;
class AiksContext;
} // namespace impeller
#endif // !IMPELLER_SUPPORTS_RENDERING

namespace flutter {

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -140,6 +152,8 @@ class Rasterizer final : public SnapshotDelegate,
///
~Rasterizer();

void SetImpellerContext(std::weak_ptr<impeller::Context> impeller_context);

//----------------------------------------------------------------------------
/// @brief Rasterizers may be created well before an on-screen surface is
/// available for rendering. Shells usually create a rasterizer in
Expand Down Expand Up @@ -509,6 +523,19 @@ class Rasterizer final : public SnapshotDelegate,
return surface_;
}

// |SnapshotController::Delegate|
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override {
#if IMPELLER_SUPPORTS_RENDERING
if (surface_) {
return surface_->GetAiksContext();
}
if (auto context = impeller_context_.lock()) {
return std::make_shared<impeller::AiksContext>(context);
}
#endif
return nullptr;
}

// |SnapshotController::Delegate|
const std::unique_ptr<SnapshotSurfaceProducer>& GetSnapshotSurfaceProducer()
const override {
Expand Down Expand Up @@ -544,6 +571,7 @@ class Rasterizer final : public SnapshotDelegate,

Delegate& delegate_;
MakeGpuImageBehavior gpu_image_behavior_;
std::weak_ptr<impeller::Context> impeller_context_;
std::unique_ptr<Surface> surface_;
std::unique_ptr<SnapshotSurfaceProducer> snapshot_surface_producer_;
std::unique_ptr<flutter::CompositorContext> compositor_context_;
Expand Down
23 changes: 13 additions & 10 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,30 +186,33 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
!settings.skia_deterministic_rendering_on_cpu),
is_gpu_disabled));

// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}

// Create the rasterizer on the raster thread.
std::promise<std::unique_ptr<Rasterizer>> rasterizer_promise;
auto rasterizer_future = rasterizer_promise.get_future();
std::promise<fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>>
snapshot_delegate_promise;
auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetRasterTaskRunner(), [&rasterizer_promise, //
&snapshot_delegate_promise,
on_create_rasterizer, //
shell = shell.get() //
task_runners.GetRasterTaskRunner(),
[&rasterizer_promise, //
&snapshot_delegate_promise,
on_create_rasterizer, //
shell = shell.get(), //
impeller_context = platform_view->GetImpellerContext() //
]() {
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
rasterizer->SetImpellerContext(impeller_context);
snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
rasterizer_promise.set_value(std::move(rasterizer));
});

// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}

// Ask the platform view for the vsync waiter. This will be used by the engine
// to create the animator.
auto vsync_waiter = platform_view->CreateVSyncWaiter();
Expand Down
3 changes: 3 additions & 0 deletions shell/common/shell_test_platform_view_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class ShellTestPlatformViewMetal final : public ShellTestPlatformView,
// |PlatformView|
std::unique_ptr<Surface> CreateRenderingSurface() override;

// |PlatformView|
std::shared_ptr<impeller::Context> GetImpellerContext() const override;

// |GPUSurfaceMetalDelegate|
GPUCAMetalLayerHandle GetCAMetalLayer(
const SkISize& frame_info) const override;
Expand Down
32 changes: 27 additions & 5 deletions shell/common/shell_test_platform_view_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include <utility>

#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/gpu/gpu_surface_metal_impeller.h"
#include "flutter/shell/gpu/gpu_surface_metal_skia.h"
#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h"
#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h"

namespace flutter {
Expand All @@ -29,12 +31,18 @@
// non-Objective-C TUs.
class DarwinContextMetal {
public:
DarwinContextMetal()
: context_([[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]),
offscreen_texture_(CreateOffscreenTexture([context_.get() device])) {}
explicit DarwinContextMetal(bool impeller)
: context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]),
impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil),
offscreen_texture_(CreateOffscreenTexture(
impeller ? [impeller_context_ context]->GetMTLDevice() : [context_ device])) {}

~DarwinContextMetal() = default;

fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> impeller_context() const {
return impeller_context_;
}

fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context() const { return context_; }

fml::scoped_nsprotocol<id<MTLTexture>> offscreen_texture() const { return offscreen_texture_; }
Expand All @@ -48,6 +56,7 @@ GPUMTLTextureInfo offscreen_texture_info() const {

private:
const fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context_;
const fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> impeller_context_;
const fml::scoped_nsprotocol<id<MTLTexture>> offscreen_texture_;

FML_DISALLOW_COPY_AND_ASSIGN(DarwinContextMetal);
Expand All @@ -61,11 +70,15 @@ GPUMTLTextureInfo offscreen_texture_info() const {
std::shared_ptr<ShellTestExternalViewEmbedder> shell_test_external_view_embedder)
: ShellTestPlatformView(delegate, task_runners),
GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture),
metal_context_(std::make_unique<DarwinContextMetal>()),
metal_context_(std::make_unique<DarwinContextMetal>(GetSettings().enable_impeller)),
create_vsync_waiter_(std::move(create_vsync_waiter)),
vsync_clock_(std::move(vsync_clock)),
shell_test_external_view_embedder_(std::move(shell_test_external_view_embedder)) {
FML_CHECK([metal_context_->context() mainContext] != nil);
if (GetSettings().enable_impeller) {
FML_CHECK([metal_context_->impeller_context() context] != nil);
} else {
FML_CHECK([metal_context_->context() mainContext] != nil);
}
}

ShellTestPlatformViewMetal::~ShellTestPlatformViewMetal() = default;
Expand Down Expand Up @@ -93,10 +106,19 @@ GPUMTLTextureInfo offscreen_texture_info() const {

// |PlatformView|
std::unique_ptr<Surface> ShellTestPlatformViewMetal::CreateRenderingSurface() {
if (GetSettings().enable_impeller) {
return std::make_unique<GPUSurfaceMetalImpeller>(this,
[metal_context_->impeller_context() context]);
}
return std::make_unique<GPUSurfaceMetalSkia>(this, [metal_context_->context() mainContext],
MsaaSampleCount::kNone);
}

// |PlatformView|
std::shared_ptr<impeller::Context> ShellTestPlatformViewMetal::GetImpellerContext() const {
return [metal_context_->impeller_context() context];
}

// |GPUSurfaceMetalDelegate|
GPUCAMetalLayerHandle ShellTestPlatformViewMetal::GetCAMetalLayer(const SkISize& frame_info) const {
FML_CHECK(false) << "A Metal Delegate configured with MTLRenderTargetType::kMTLTexture was asked "
Expand Down
47 changes: 47 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3986,6 +3986,53 @@ TEST_F(ShellTest, PictureToImageSync) {
DestroyShell(std::move(shell));
}

TEST_F(ShellTest, PictureToImageSyncImpellerNoSurface) {
#if !SHELL_ENABLE_METAL
// This test uses the Metal backend.
GTEST_SKIP();
#endif // !SHELL_ENABLE_METAL
auto settings = CreateSettingsForFixture();
settings.enable_impeller = true;
std::unique_ptr<Shell> shell =
CreateShell(settings, //
GetTaskRunnersForFixture(), //
false, //
nullptr, //
false, //
ShellTestPlatformView::BackendType::kMetalBackend //
);

AddNativeCallback("NativeOnBeforeToImageSync",
CREATE_NATIVE_ENTRY([&](auto args) {
// nop
}));

fml::CountDownLatch latch(2);
AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) {
// Teardown and set up rasterizer again.
PlatformViewNotifyDestroyed(shell.get());
PlatformViewNotifyCreated(shell.get());
latch.CountDown();
}));

ASSERT_NE(shell, nullptr);
ASSERT_TRUE(shell->IsSetup());
auto configuration = RunConfiguration::InferFromSettings(settings);

// Important: Do not create the platform view yet!
// This test is making sure that the rasterizer can create the texture
// as expected without a surface.

configuration.SetEntrypoint("toImageSync");
RunEngine(shell.get(), std::move(configuration));
PumpOneFrame(shell.get());

latch.Wait();

PlatformViewNotifyDestroyed(shell.get());
DestroyShell(std::move(shell));
}

#if SHELL_ENABLE_GL
// This test uses the GL backend and refers to symbols in egl.h
TEST_F(ShellTest, PictureToImageSyncWithTrampledContext) {
Expand Down
5 changes: 5 additions & 0 deletions shell/common/snapshot_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include "flutter/lib/ui/snapshot_delegate.h"
#include "flutter/shell/common/snapshot_surface_producer.h"

namespace impeller {
class AiksContext;
}

namespace flutter {

class SnapshotController {
Expand All @@ -20,6 +24,7 @@ class SnapshotController {
public:
virtual ~Delegate() = default;
virtual const std::unique_ptr<Surface>& GetSurface() const = 0;
virtual std::shared_ptr<impeller::AiksContext> GetAiksContext() const = 0;
virtual const std::unique_ptr<SnapshotSurfaceProducer>&
GetSnapshotSurfaceProducer() const = 0;
virtual std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch()
Expand Down
7 changes: 2 additions & 5 deletions shell/common/snapshot_controller_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ sk_sp<DlImage> SnapshotControllerImpeller::DoMakeRasterSnapshot(
impeller::DisplayListDispatcher dispatcher;
display_list->Dispatch(dispatcher);
impeller::Picture picture = dispatcher.EndRecordingAsPicture();
if (GetDelegate().GetSurface() &&
GetDelegate().GetSurface()->GetAiksContext()) {
impeller::AiksContext* context =
GetDelegate().GetSurface()->GetAiksContext();

auto context = GetDelegate().GetAiksContext();
if (context) {
auto max_size = context->GetContext()
->GetResourceAllocator()
->GetMaxTextureSizeSupported();
Expand Down
5 changes: 3 additions & 2 deletions shell/gpu/gpu_surface_gl_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ bool GPUSurfaceGLImpeller::EnableRasterCache() const {
}

// |Surface|
impeller::AiksContext* GPUSurfaceGLImpeller::GetAiksContext() const {
return aiks_context_.get();
std::shared_ptr<impeller::AiksContext> GPUSurfaceGLImpeller::GetAiksContext()
const {
return aiks_context_;
}

} // namespace flutter
2 changes: 1 addition & 1 deletion shell/gpu/gpu_surface_gl_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class GPUSurfaceGLImpeller final : public Surface {
bool EnableRasterCache() const override;

// |Surface|
impeller::AiksContext* GetAiksContext() const override;
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;

FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceGLImpeller);
};
Expand Down
2 changes: 1 addition & 1 deletion shell/gpu/gpu_surface_metal_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalImpeller : public Surface {
bool EnableRasterCache() const override;

// |Surface|
impeller::AiksContext* GetAiksContext() const override;
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;

FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceMetalImpeller);
};
Expand Down
4 changes: 2 additions & 2 deletions shell/gpu/gpu_surface_metal_impeller.mm
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
}

// |Surface|
impeller::AiksContext* GPUSurfaceMetalImpeller::GetAiksContext() const {
return aiks_context_.get();
std::shared_ptr<impeller::AiksContext> GPUSurfaceMetalImpeller::GetAiksContext() const {
return aiks_context_;
}

Surface::SurfaceData GPUSurfaceMetalImpeller::GetSurfaceData() const {
Expand Down
5 changes: 3 additions & 2 deletions shell/gpu/gpu_surface_vulkan_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ bool GPUSurfaceVulkanImpeller::EnableRasterCache() const {
}

// |Surface|
impeller::AiksContext* GPUSurfaceVulkanImpeller::GetAiksContext() const {
return aiks_context_.get();
std::shared_ptr<impeller::AiksContext>
GPUSurfaceVulkanImpeller::GetAiksContext() const {
return aiks_context_;
}

} // namespace flutter
2 changes: 1 addition & 1 deletion shell/gpu/gpu_surface_vulkan_impeller.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class GPUSurfaceVulkanImpeller final : public Surface {
bool EnableRasterCache() const override;

// |Surface|
impeller::AiksContext* GetAiksContext() const override;
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;

FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkanImpeller);
};
Expand Down

0 comments on commit f091060

Please sign in to comment.