Skip to content

Commit f091060

Browse files
authored
[Impeller] Allow image rasterization/decoding before/without surface acquisition (flutter#41168)
[Impeller] Allow image rasterization/decoding before/without surface acquisition
1 parent 460668f commit f091060

16 files changed

+144
-32
lines changed

flow/surface.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bool Surface::EnableRasterCache() const {
2626
return true;
2727
}
2828

29-
impeller::AiksContext* Surface::GetAiksContext() const {
29+
std::shared_ptr<impeller::AiksContext> Surface::GetAiksContext() const {
3030
return nullptr;
3131
}
3232

flow/surface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Surface {
4949

5050
virtual bool EnableRasterCache() const;
5151

52-
virtual impeller::AiksContext* GetAiksContext() const;
52+
virtual std::shared_ptr<impeller::AiksContext> GetAiksContext() const;
5353

5454
/// Capture the `SurfaceData` currently present in the surface.
5555
///

shell/common/rasterizer.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> Rasterizer::GetSnapshotDelegate()
5353
return weak_factory_.GetWeakPtr();
5454
}
5555

56+
void Rasterizer::SetImpellerContext(
57+
std::weak_ptr<impeller::Context> impeller_context) {
58+
impeller_context_ = std::move(impeller_context);
59+
}
60+
5661
void Rasterizer::Setup(std::unique_ptr<Surface> surface) {
5762
surface_ = std::move(surface);
5863

@@ -544,7 +549,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
544549
.supports_readback, // surface supports pixel reads
545550
raster_thread_merger_, // thread merger
546551
frame->GetDisplayListBuilder().get(), // display list builder
547-
surface_->GetAiksContext() // aiks context
552+
surface_->GetAiksContext().get() // aiks context
548553
);
549554
if (compositor_frame) {
550555
compositor_context_->raster_cache().BeginFrame();

shell/common/rasterizer.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
#include "flutter/fml/synchronization/waitable_event.h"
2424
#include "flutter/fml/time/time_delta.h"
2525
#include "flutter/fml/time/time_point.h"
26+
#if IMPELLER_SUPPORTS_RENDERING
27+
// GN is having trouble understanding how this works in the Fuchsia builds.
28+
#include "flutter/impeller/aiks/aiks_context.h" // nogncheck
29+
#include "flutter/impeller/renderer/context.h" // nogncheck
30+
#endif // IMPELLER_SUPPORTS_RENDERING
2631
#include "flutter/lib/ui/snapshot_delegate.h"
2732
#include "flutter/shell/common/pipeline.h"
2833
#include "flutter/shell/common/snapshot_controller.h"
@@ -33,6 +38,13 @@
3338
#include "third_party/skia/include/core/SkRefCnt.h"
3439
#include "third_party/skia/include/gpu/GrDirectContext.h"
3540

41+
#if !IMPELLER_SUPPORTS_RENDERING
42+
namespace impeller {
43+
class Context;
44+
class AiksContext;
45+
} // namespace impeller
46+
#endif // !IMPELLER_SUPPORTS_RENDERING
47+
3648
namespace flutter {
3749

3850
//------------------------------------------------------------------------------
@@ -140,6 +152,8 @@ class Rasterizer final : public SnapshotDelegate,
140152
///
141153
~Rasterizer();
142154

155+
void SetImpellerContext(std::weak_ptr<impeller::Context> impeller_context);
156+
143157
//----------------------------------------------------------------------------
144158
/// @brief Rasterizers may be created well before an on-screen surface is
145159
/// available for rendering. Shells usually create a rasterizer in
@@ -509,6 +523,19 @@ class Rasterizer final : public SnapshotDelegate,
509523
return surface_;
510524
}
511525

526+
// |SnapshotController::Delegate|
527+
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override {
528+
#if IMPELLER_SUPPORTS_RENDERING
529+
if (surface_) {
530+
return surface_->GetAiksContext();
531+
}
532+
if (auto context = impeller_context_.lock()) {
533+
return std::make_shared<impeller::AiksContext>(context);
534+
}
535+
#endif
536+
return nullptr;
537+
}
538+
512539
// |SnapshotController::Delegate|
513540
const std::unique_ptr<SnapshotSurfaceProducer>& GetSnapshotSurfaceProducer()
514541
const override {
@@ -544,6 +571,7 @@ class Rasterizer final : public SnapshotDelegate,
544571

545572
Delegate& delegate_;
546573
MakeGpuImageBehavior gpu_image_behavior_;
574+
std::weak_ptr<impeller::Context> impeller_context_;
547575
std::unique_ptr<Surface> surface_;
548576
std::unique_ptr<SnapshotSurfaceProducer> snapshot_surface_producer_;
549577
std::unique_ptr<flutter::CompositorContext> compositor_context_;

shell/common/shell.cc

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,30 +186,33 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
186186
!settings.skia_deterministic_rendering_on_cpu),
187187
is_gpu_disabled));
188188

189+
// Create the platform view on the platform thread (this thread).
190+
auto platform_view = on_create_platform_view(*shell.get());
191+
if (!platform_view || !platform_view->GetWeakPtr()) {
192+
return nullptr;
193+
}
194+
189195
// Create the rasterizer on the raster thread.
190196
std::promise<std::unique_ptr<Rasterizer>> rasterizer_promise;
191197
auto rasterizer_future = rasterizer_promise.get_future();
192198
std::promise<fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>>
193199
snapshot_delegate_promise;
194200
auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
195201
fml::TaskRunner::RunNowOrPostTask(
196-
task_runners.GetRasterTaskRunner(), [&rasterizer_promise, //
197-
&snapshot_delegate_promise,
198-
on_create_rasterizer, //
199-
shell = shell.get() //
202+
task_runners.GetRasterTaskRunner(),
203+
[&rasterizer_promise, //
204+
&snapshot_delegate_promise,
205+
on_create_rasterizer, //
206+
shell = shell.get(), //
207+
impeller_context = platform_view->GetImpellerContext() //
200208
]() {
201209
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
202210
std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
211+
rasterizer->SetImpellerContext(impeller_context);
203212
snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
204213
rasterizer_promise.set_value(std::move(rasterizer));
205214
});
206215

207-
// Create the platform view on the platform thread (this thread).
208-
auto platform_view = on_create_platform_view(*shell.get());
209-
if (!platform_view || !platform_view->GetWeakPtr()) {
210-
return nullptr;
211-
}
212-
213216
// Ask the platform view for the vsync waiter. This will be used by the engine
214217
// to create the animator.
215218
auto vsync_waiter = platform_view->CreateVSyncWaiter();

shell/common/shell_test_platform_view_metal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class ShellTestPlatformViewMetal final : public ShellTestPlatformView,
4949
// |PlatformView|
5050
std::unique_ptr<Surface> CreateRenderingSurface() override;
5151

52+
// |PlatformView|
53+
std::shared_ptr<impeller::Context> GetImpellerContext() const override;
54+
5255
// |GPUSurfaceMetalDelegate|
5356
GPUCAMetalLayerHandle GetCAMetalLayer(
5457
const SkISize& frame_info) const override;

shell/common/shell_test_platform_view_metal.mm

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include <utility>
1010

1111
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
12+
#include "flutter/shell/gpu/gpu_surface_metal_impeller.h"
1213
#include "flutter/shell/gpu/gpu_surface_metal_skia.h"
14+
#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h"
1315
#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h"
1416

1517
namespace flutter {
@@ -29,12 +31,18 @@
2931
// non-Objective-C TUs.
3032
class DarwinContextMetal {
3133
public:
32-
DarwinContextMetal()
33-
: context_([[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]),
34-
offscreen_texture_(CreateOffscreenTexture([context_.get() device])) {}
34+
explicit DarwinContextMetal(bool impeller)
35+
: context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]),
36+
impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil),
37+
offscreen_texture_(CreateOffscreenTexture(
38+
impeller ? [impeller_context_ context]->GetMTLDevice() : [context_ device])) {}
3539

3640
~DarwinContextMetal() = default;
3741

42+
fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> impeller_context() const {
43+
return impeller_context_;
44+
}
45+
3846
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context() const { return context_; }
3947

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

4957
private:
5058
const fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context_;
59+
const fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> impeller_context_;
5160
const fml::scoped_nsprotocol<id<MTLTexture>> offscreen_texture_;
5261

5362
FML_DISALLOW_COPY_AND_ASSIGN(DarwinContextMetal);
@@ -61,11 +70,15 @@ GPUMTLTextureInfo offscreen_texture_info() const {
6170
std::shared_ptr<ShellTestExternalViewEmbedder> shell_test_external_view_embedder)
6271
: ShellTestPlatformView(delegate, task_runners),
6372
GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture),
64-
metal_context_(std::make_unique<DarwinContextMetal>()),
73+
metal_context_(std::make_unique<DarwinContextMetal>(GetSettings().enable_impeller)),
6574
create_vsync_waiter_(std::move(create_vsync_waiter)),
6675
vsync_clock_(std::move(vsync_clock)),
6776
shell_test_external_view_embedder_(std::move(shell_test_external_view_embedder)) {
68-
FML_CHECK([metal_context_->context() mainContext] != nil);
77+
if (GetSettings().enable_impeller) {
78+
FML_CHECK([metal_context_->impeller_context() context] != nil);
79+
} else {
80+
FML_CHECK([metal_context_->context() mainContext] != nil);
81+
}
6982
}
7083

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

94107
// |PlatformView|
95108
std::unique_ptr<Surface> ShellTestPlatformViewMetal::CreateRenderingSurface() {
109+
if (GetSettings().enable_impeller) {
110+
return std::make_unique<GPUSurfaceMetalImpeller>(this,
111+
[metal_context_->impeller_context() context]);
112+
}
96113
return std::make_unique<GPUSurfaceMetalSkia>(this, [metal_context_->context() mainContext],
97114
MsaaSampleCount::kNone);
98115
}
99116

117+
// |PlatformView|
118+
std::shared_ptr<impeller::Context> ShellTestPlatformViewMetal::GetImpellerContext() const {
119+
return [metal_context_->impeller_context() context];
120+
}
121+
100122
// |GPUSurfaceMetalDelegate|
101123
GPUCAMetalLayerHandle ShellTestPlatformViewMetal::GetCAMetalLayer(const SkISize& frame_info) const {
102124
FML_CHECK(false) << "A Metal Delegate configured with MTLRenderTargetType::kMTLTexture was asked "

shell/common/shell_unittests.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3986,6 +3986,53 @@ TEST_F(ShellTest, PictureToImageSync) {
39863986
DestroyShell(std::move(shell));
39873987
}
39883988

3989+
TEST_F(ShellTest, PictureToImageSyncImpellerNoSurface) {
3990+
#if !SHELL_ENABLE_METAL
3991+
// This test uses the Metal backend.
3992+
GTEST_SKIP();
3993+
#endif // !SHELL_ENABLE_METAL
3994+
auto settings = CreateSettingsForFixture();
3995+
settings.enable_impeller = true;
3996+
std::unique_ptr<Shell> shell =
3997+
CreateShell(settings, //
3998+
GetTaskRunnersForFixture(), //
3999+
false, //
4000+
nullptr, //
4001+
false, //
4002+
ShellTestPlatformView::BackendType::kMetalBackend //
4003+
);
4004+
4005+
AddNativeCallback("NativeOnBeforeToImageSync",
4006+
CREATE_NATIVE_ENTRY([&](auto args) {
4007+
// nop
4008+
}));
4009+
4010+
fml::CountDownLatch latch(2);
4011+
AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&](auto args) {
4012+
// Teardown and set up rasterizer again.
4013+
PlatformViewNotifyDestroyed(shell.get());
4014+
PlatformViewNotifyCreated(shell.get());
4015+
latch.CountDown();
4016+
}));
4017+
4018+
ASSERT_NE(shell, nullptr);
4019+
ASSERT_TRUE(shell->IsSetup());
4020+
auto configuration = RunConfiguration::InferFromSettings(settings);
4021+
4022+
// Important: Do not create the platform view yet!
4023+
// This test is making sure that the rasterizer can create the texture
4024+
// as expected without a surface.
4025+
4026+
configuration.SetEntrypoint("toImageSync");
4027+
RunEngine(shell.get(), std::move(configuration));
4028+
PumpOneFrame(shell.get());
4029+
4030+
latch.Wait();
4031+
4032+
PlatformViewNotifyDestroyed(shell.get());
4033+
DestroyShell(std::move(shell));
4034+
}
4035+
39894036
#if SHELL_ENABLE_GL
39904037
// This test uses the GL backend and refers to symbols in egl.h
39914038
TEST_F(ShellTest, PictureToImageSyncWithTrampledContext) {

shell/common/snapshot_controller.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include "flutter/lib/ui/snapshot_delegate.h"
1313
#include "flutter/shell/common/snapshot_surface_producer.h"
1414

15+
namespace impeller {
16+
class AiksContext;
17+
}
18+
1519
namespace flutter {
1620

1721
class SnapshotController {
@@ -20,6 +24,7 @@ class SnapshotController {
2024
public:
2125
virtual ~Delegate() = default;
2226
virtual const std::unique_ptr<Surface>& GetSurface() const = 0;
27+
virtual std::shared_ptr<impeller::AiksContext> GetAiksContext() const = 0;
2328
virtual const std::unique_ptr<SnapshotSurfaceProducer>&
2429
GetSnapshotSurfaceProducer() const = 0;
2530
virtual std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch()

shell/common/snapshot_controller_impeller.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,8 @@ sk_sp<DlImage> SnapshotControllerImpeller::DoMakeRasterSnapshot(
3636
impeller::DisplayListDispatcher dispatcher;
3737
display_list->Dispatch(dispatcher);
3838
impeller::Picture picture = dispatcher.EndRecordingAsPicture();
39-
if (GetDelegate().GetSurface() &&
40-
GetDelegate().GetSurface()->GetAiksContext()) {
41-
impeller::AiksContext* context =
42-
GetDelegate().GetSurface()->GetAiksContext();
43-
39+
auto context = GetDelegate().GetAiksContext();
40+
if (context) {
4441
auto max_size = context->GetContext()
4542
->GetResourceAllocator()
4643
->GetMaxTextureSizeSupported();

0 commit comments

Comments
 (0)