Don't call release_proc when attempting to wrap an SkSurface which fails (flutter/engine#25901)

This commit is contained in:
George Wright 2021-05-03 16:42:51 -07:00 committed by GitHub
parent 0184cd3c70
commit 65d744bcdf
4 changed files with 194 additions and 6 deletions

View File

@ -469,9 +469,6 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
if (!surface) {
FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
if (texture->destruction_callback) {
texture->destruction_callback(texture->user_data);
}
return nullptr;
}
@ -514,9 +511,6 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
if (!surface) {
FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
if (framebuffer->destruction_callback) {
framebuffer->destruction_callback(framebuffer->user_data);
}
return nullptr;
}
return surface;

View File

@ -920,3 +920,20 @@ void snapshot_large_scene(int max_size) async {
snapshotsCallback(big_image, small_image);
}
@pragma('vm:entry-point')
void invalid_backingstore() {
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());
};
PlatformDispatcher.instance.onDrawFrame = () {
signalNativeTest();
};
PlatformDispatcher.instance.scheduleFrame();
}

View File

@ -3495,5 +3495,127 @@ TEST_F(EmbedderTest, ObjectsPostedViaPortsServicedOnSecondaryTaskHeap) {
}
}
TEST_F(EmbedderTest, CreateInvalidBackingstoreOpenGLTexture) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kOpenGLContext);
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(
EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture);
builder.SetDartEntrypoint("invalid_backingstore");
class TestCollectOnce {
public:
// Collect() should only be called once
void Collect() {
ASSERT_FALSE(collected_);
collected_ = true;
}
private:
bool collected_ = false;
};
fml::AutoResetWaitableEvent latch;
builder.GetCompositor().create_backing_store_callback =
[](const FlutterBackingStoreConfig* config, //
FlutterBackingStore* backing_store_out, //
void* user_data //
) {
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
// Deliberately set this to be invalid
backing_store_out->user_data = nullptr;
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeTexture;
backing_store_out->open_gl.texture.target = 0;
backing_store_out->open_gl.texture.name = 0;
backing_store_out->open_gl.texture.format = 0;
backing_store_out->open_gl.texture.user_data = new TestCollectOnce();
backing_store_out->open_gl.texture.destruction_callback =
[](void* user_data) {
reinterpret_cast<TestCollectOnce*>(user_data)->Collect();
};
return true;
};
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();
}
TEST_F(EmbedderTest, CreateInvalidBackingstoreOpenGLFramebuffer) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kOpenGLContext);
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(
EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer);
builder.SetDartEntrypoint("invalid_backingstore");
class TestCollectOnce {
public:
// Collect() should only be called once
void Collect() {
ASSERT_FALSE(collected_);
collected_ = true;
}
private:
bool collected_ = false;
};
fml::AutoResetWaitableEvent latch;
builder.GetCompositor().create_backing_store_callback =
[](const FlutterBackingStoreConfig* config, //
FlutterBackingStore* backing_store_out, //
void* user_data //
) {
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
// Deliberately set this to be invalid
backing_store_out->user_data = nullptr;
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
backing_store_out->open_gl.framebuffer.target = 0;
backing_store_out->open_gl.framebuffer.name = 0;
backing_store_out->open_gl.framebuffer.user_data =
new TestCollectOnce();
backing_store_out->open_gl.framebuffer.destruction_callback =
[](void* user_data) {
reinterpret_cast<TestCollectOnce*>(user_data)->Collect();
};
return true;
};
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();
}
} // namespace testing
} // namespace flutter

View File

@ -379,5 +379,60 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownSceneMetal) {
ASSERT_TRUE(ImageMatchesFixture("compositor.png", scene_image));
}
TEST_F(EmbedderTest, CreateInvalidBackingstoreMetalTexture) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kMetalContext);
EmbedderConfigBuilder builder(context);
builder.SetMetalRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture);
builder.SetDartEntrypoint("invalid_backingstore");
class TestCollectOnce {
public:
// Collect() should only be called once
void Collect() {
ASSERT_FALSE(collected_);
collected_ = true;
}
private:
bool collected_ = false;
};
fml::AutoResetWaitableEvent latch;
builder.GetCompositor().create_backing_store_callback =
[](const FlutterBackingStoreConfig* config, //
FlutterBackingStore* backing_store_out, //
void* user_data //
) {
backing_store_out->type = kFlutterBackingStoreTypeMetal;
// Deliberately set this to be invalid
backing_store_out->user_data = nullptr;
backing_store_out->metal.texture.texture = 0;
backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore);
backing_store_out->metal.texture.user_data = new TestCollectOnce();
backing_store_out->metal.texture.destruction_callback = [](void* user_data) {
reinterpret_cast<TestCollectOnce*>(user_data)->Collect();
};
return true;
};
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();
}
} // namespace testing
} // namespace flutter