Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions shell/common/snapshot_controller_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
namespace flutter {

namespace {

sk_sp<DlImage> DoMakeRasterSnapshot(
const sk_sp<DisplayList>& display_list,
SkISize size,
Expand Down Expand Up @@ -53,6 +54,27 @@ sk_sp<DlImage> DoMakeRasterSnapshot(
DlImage::OwningContext::kRaster);
}

sk_sp<DlImage> DoMakeRasterSnapshot(
const sk_sp<DisplayList>& display_list,
SkISize size,
const SnapshotController::Delegate& delegate) {
// Ensure that the current thread has a rendering context. This must be done
// before calling GetAiksContext because constructing the AiksContext may
// invoke graphics APIs.
std::unique_ptr<Surface> pbuffer_surface;
if (delegate.GetSurface()) {
delegate.GetSurface()->MakeRenderContextCurrent();
} else if (delegate.GetSnapshotSurfaceProducer()) {
pbuffer_surface =
delegate.GetSnapshotSurfaceProducer()->CreateSnapshotSurface();
if (pbuffer_surface) {
pbuffer_surface->MakeRenderContextCurrent();
}
}

return DoMakeRasterSnapshot(display_list, size, delegate.GetAiksContext());
}

sk_sp<DlImage> DoMakeRasterSnapshot(
sk_sp<DisplayList> display_list,
SkISize picture_size,
Expand Down Expand Up @@ -112,16 +134,14 @@ void SnapshotControllerImpeller::MakeRasterSnapshot(
}
#endif
callback(DoMakeRasterSnapshot(display_list, picture_size,
GetDelegate().GetAiksContext()));
GetDelegate()));
}));
}

sk_sp<DlImage> SnapshotControllerImpeller::MakeRasterSnapshotSync(
sk_sp<DisplayList> display_list,
SkISize picture_size) {
return DoMakeRasterSnapshot(display_list, picture_size,
GetDelegate().GetIsGpuDisabledSyncSwitch(),
GetDelegate().GetAiksContext());
return DoMakeRasterSnapshot(display_list, picture_size, GetDelegate());
}

void SnapshotControllerImpeller::CacheRuntimeStage(
Expand Down
19 changes: 18 additions & 1 deletion shell/platform/android/android_surface_gl_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,24 @@ bool AndroidSurfaceGLImpeller::SetNativeWindow(

// |AndroidSurface|
std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateSnapshotSurface() {
FML_UNREACHABLE();
if (!onscreen_surface_ || !onscreen_surface_->IsValid()) {
onscreen_surface_ = android_context_->CreateOffscreenSurface();
if (!onscreen_surface_) {
FML_DLOG(ERROR) << "Could not create offscreen surface for snapshot.";
return nullptr;
}
}
// Make the snapshot surface current because constucting a
// GPUSurfaceGLImpeller and its AiksContext may invoke graphics APIs.
if (!android_context_->OnscreenContextMakeCurrent(onscreen_surface_.get())) {
FML_DLOG(ERROR) << "Could not make snapshot surface current.";
return nullptr;
}
return std::make_unique<GPUSurfaceGLImpeller>(
this, // delegate
android_context_->GetImpellerContext(), // context
true // render to surface
);
}

// |AndroidSurface|
Expand Down
17 changes: 17 additions & 0 deletions shell/platform/embedder/fixtures/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1595,3 +1595,20 @@ void render_impeller_text_test() {
};
PlatformDispatcher.instance.scheduleFrame();
}

@pragma('vm:entry-point')
// ignore: non_constant_identifier_names
Future<void> render_impeller_image_snapshot_test() async {
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
const Color color = Color.fromARGB(255, 0, 0, 123);
canvas.drawPaint(Paint()..color = color);
final Picture picture = recorder.endRecording();

final Image image = await picture.toImage(100, 100);
final ByteData? imageData = await image.toByteData();
final int pixel = imageData!.getInt32(0);

final bool result = (pixel & 0xFF) == color.alpha && ((pixel >> 8) & 0xFF) == color.blue;
notifyBoolValue(result);
}
27 changes: 27 additions & 0 deletions shell/platform/embedder/tests/embedder_gl_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4814,6 +4814,33 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
ASSERT_FALSE(present_called);
}

TEST_F(EmbedderTest, ImpellerOpenGLImageSnapshot) {
auto& context = GetEmbedderContext<EmbedderTestContextGL>();

bool result = false;
fml::AutoResetWaitableEvent latch;
context.AddNativeCallback("NotifyBoolValue",
CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
result = tonic::DartConverter<bool>::FromDart(
Dart_GetNativeArgument(args, 0));
latch.Signal();
}));

EmbedderConfigBuilder builder(context);
builder.AddCommandLineArgument("--enable-impeller");
builder.SetDartEntrypoint("render_impeller_image_snapshot_test");
builder.SetSurface(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(
EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLFramebuffer);

auto engine = builder.LaunchEngine();
ASSERT_TRUE(engine.is_valid());
latch.Wait();

ASSERT_TRUE(result);
}

TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLSurface) {
auto& context = GetEmbedderContext<EmbedderTestContextGL>();

Expand Down