Skip to content

Commit

Permalink
Add destruction test
Browse files Browse the repository at this point in the history
  • Loading branch information
cbracken committed Dec 3, 2022
1 parent 7af0c70 commit 55356b6
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 1 deletion.
32 changes: 32 additions & 0 deletions shell/platform/embedder/fixtures/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,38 @@ void can_composite_platform_views_with_platform_layer_on_bottom() {
PlatformDispatcher.instance.scheduleFrame();
}

@pragma('vm:external-name', 'SignalBeginFrame')
external void signalBeginFrame();

@pragma('vm:entry-point')
void texture_destruction_callback_called_without_custom_compositor() async {
PlatformDispatcher.instance.onBeginFrame = (Duration duration) {
Color red = Color.fromARGB(127, 255, 0, 0);
Size size = Size(50.0, 150.0);
SceneBuilder builder = SceneBuilder();
builder.pushOffset(0.0, 0.0);
builder.addPicture(
Offset(10.0, 10.0), CreateColoredBox(red, size)); // red - flutter
builder.pop();
PlatformDispatcher.instance.views.first.render(builder.build());
};

// Schedule first frame.
final Completer firstFrame = Completer();
PlatformDispatcher.instance.onDrawFrame = () { firstFrame.complete(); };
PlatformDispatcher.instance.scheduleFrame();
await firstFrame.future;

// Schedule second frame to trigger disposal of first surface.
final Completer secondFrame = Completer();
PlatformDispatcher.instance.onDrawFrame = () { secondFrame.complete(); };
PlatformDispatcher.instance.scheduleFrame();
await secondFrame.future;

signalNativeTest();
}


@pragma('vm:entry-point')
void can_render_scene_without_custom_compositor() {
PlatformDispatcher.instance.onBeginFrame = (Duration duration) {
Expand Down
14 changes: 13 additions & 1 deletion shell/platform/embedder/tests/embedder_test_context_metal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,22 @@ bool EmbedderTestContextMetal::PopulateExternalTexture(
}
}

TestMetalContext::TextureInfo EmbedderTestContextMetal::GetTextureInfo() {
return metal_surface_->GetTextureInfo();
}

void EmbedderTestContextMetal::SetNextDrawableCallback(
NextDrawableCallback next_drawable_callback) {
next_drawable_callback_ = next_drawable_callback;
}

FlutterMetalTexture EmbedderTestContextMetal::GetNextDrawable(
const FlutterFrameInfo* frame_info) {
auto texture_info = metal_surface_->GetTextureInfo();
if (next_drawable_callback_ != nullptr) {
return next_drawable_callback_(frame_info);
}

auto texture_info = metal_surface_->GetTextureInfo();
FlutterMetalTexture texture;
texture.struct_size = sizeof(FlutterMetalTexture);
texture.texture_id = texture_info.texture_id;
Expand Down
10 changes: 10 additions & 0 deletions shell/platform/embedder/tests/embedder_test_context_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class EmbedderTestContextMetal : public EmbedderTestContext {
size_t h,
FlutterMetalExternalTexture* output)>;

using NextDrawableCallback =
std::function<FlutterMetalTexture(const FlutterFrameInfo* frame_info)>;

explicit EmbedderTestContextMetal(std::string assets_path = "");

~EmbedderTestContextMetal() override;
Expand All @@ -45,6 +48,12 @@ class EmbedderTestContextMetal : public EmbedderTestContext {

TestMetalContext* GetTestMetalContext();

// Returns the TextureInfo for the test Metal surface.
TestMetalContext::TextureInfo GetTextureInfo();

// Override the default handling for GetNextDrawable.
void SetNextDrawableCallback(NextDrawableCallback next_drawable_callback);

FlutterMetalTexture GetNextDrawable(const FlutterFrameInfo* frame_info);

private:
Expand All @@ -56,6 +65,7 @@ class EmbedderTestContextMetal : public EmbedderTestContext {
std::unique_ptr<TestMetalContext> metal_context_;
std::unique_ptr<TestMetalSurface> metal_surface_;
size_t present_count_ = 0;
NextDrawableCallback next_drawable_callback_ = nullptr;

void SetupSurface(SkISize surface_size) override;

Expand Down
46 changes: 46 additions & 0 deletions shell/platform/embedder/tests/embedder_unittests_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,52 @@ GrBackendTexture backend_texture(texture_size.width(), texture_size.height(), Gr
ASSERT_TRUE(ImageMatchesFixture("scene_without_custom_compositor.png", rendered_scene));
}

TEST_F(EmbedderTest, TextureDestructionCallbackCalledWithoutCustomCompositorMetal) {
EmbedderTestContextMetal& context = reinterpret_cast<EmbedderTestContextMetal&>(
GetEmbedderContext(EmbedderTestContextType::kMetalContext));
EmbedderConfigBuilder builder(context);
builder.SetMetalRendererConfig(SkISize::Make(800, 600));
builder.SetDartEntrypoint("texture_destruction_callback_called_without_custom_compositor");

struct CollectContext {
bool collected = false;
};

auto collect_context = std::make_unique<CollectContext>();
context.SetNextDrawableCallback([&context, &collect_context](const FlutterFrameInfo* frame_info) {
auto texture_info = context.GetTextureInfo();
FlutterMetalTexture texture;
texture.struct_size = sizeof(FlutterMetalTexture);
texture.texture_id = texture_info.texture_id;
texture.texture = reinterpret_cast<FlutterMetalTextureHandle>(texture_info.texture);
texture.user_data = collect_context.get();
texture.destruction_callback = [](void* user_data) {
CollectContext* callback_collect_context = reinterpret_cast<CollectContext*>(user_data);
callback_collect_context->collected = true;
};
return texture;
});

fml::AutoResetWaitableEvent latch;
context.AddNativeCallback(
"SignalNativeTest",
CREATE_NATIVE_ENTRY([&latch](Dart_NativeArguments args) { latch.Signal(); }));

auto engine = builder.LaunchEngine();

// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess);
ASSERT_TRUE(engine.is_valid());

latch.Wait();
EXPECT_TRUE(collect_context->collected);
}

TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownSceneMetal) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kMetalContext);

Expand Down

0 comments on commit 55356b6

Please sign in to comment.