Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
1 change: 1 addition & 0 deletions flow/embedded_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void DisplayListEmbedderViewSlice::render_into(DisplayListBuilder* builder) {
}

void ExternalViewEmbedder::SubmitFrame(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) {
frame->Submit();
};
Expand Down
1 change: 1 addition & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ class ExternalViewEmbedder {
//
// It can also allocate frames for overlay surfaces to compose hybrid views.
virtual void SubmitFrame(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame);

// This method provides the embedder a way to do additional tasks after
Expand Down
5 changes: 4 additions & 1 deletion shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@ RasterStatus Rasterizer::DrawToSurface(
RasterStatus Rasterizer::DrawToSurfaceUnsafe(
FrameTimingsRecorder& frame_timings_recorder,
flutter::LayerTree& layer_tree) {
// Always gets the first surface, #0. After Flutter supports multi-view, it
// should get the surface ID from layer_tree.
uint64_t surface_id = 0;
FML_DCHECK(surface_);

compositor_context_->ui_time().SetLapTime(
Expand Down Expand Up @@ -595,7 +598,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
if (external_view_embedder_ &&
(!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
FML_DCHECK(!frame->IsSubmitted());
external_view_embedder_->SubmitFrame(surface_->GetContext(),
external_view_embedder_->SubmitFrame(surface_->GetContext(), surface_id,
std::move(frame));
} else {
frame->Submit();
Expand Down
3 changes: 2 additions & 1 deletion shell/common/rasterizer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder {
MOCK_METHOD0(GetCurrentCanvases, std::vector<SkCanvas*>());
MOCK_METHOD0(GetCurrentBuilders, std::vector<DisplayListBuilder*>());
MOCK_METHOD1(CompositeEmbeddedView, EmbedderPaintContext(int view_id));
MOCK_METHOD2(SubmitFrame,
MOCK_METHOD3(SubmitFrame,
void(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame));
MOCK_METHOD2(EndFrame,
void(bool should_resubmit_frame,
Expand Down
1 change: 1 addition & 0 deletions shell/common/shell_test_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ EmbedderPaintContext ShellTestExternalViewEmbedder::CompositeEmbeddedView(
// |ExternalViewEmbedder|
void ShellTestExternalViewEmbedder::SubmitFrame(
GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) {
if (!frame) {
return;
Expand Down
1 change: 1 addition & 0 deletions shell/common/shell_test_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {

// |ExternalViewEmbedder|
void SubmitFrame(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) override;

// |ExternalViewEmbedder|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int view_id) const {
// |ExternalViewEmbedder|
void AndroidExternalViewEmbedder::SubmitFrame(
GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) {
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder {

// |ExternalViewEmbedder|
void SubmitFrame(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) override;

// |ExternalViewEmbedder|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
},
/*frame_size=*/SkISize::Make(800, 600));

embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));
// Submits frame if no Android view in the current frame.
EXPECT_TRUE(did_submit_frame);
// Doesn't resubmit frame.
Expand Down Expand Up @@ -439,7 +439,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
},
/*frame_size=*/SkISize::Make(800, 600));

embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));
// Doesn't submit frame if there aren't Android views in the previous frame.
EXPECT_FALSE(did_submit_frame);
// Resubmits frame.
Expand Down Expand Up @@ -504,7 +504,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
return true;
},
/*frame_size=*/SkISize::Make(800, 600));
embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));
// Submits frame if there are Android views in the previous frame.
EXPECT_TRUE(did_submit_frame);
// Doesn't resubmit frame.
Expand Down Expand Up @@ -614,7 +614,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
},
/*frame_size=*/SkISize::Make(800, 600));

embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));

EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
Expand Down Expand Up @@ -683,7 +683,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) {
},
/*frame_size=*/SkISize::Make(800, 600));

embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));

EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
Expand Down Expand Up @@ -785,7 +785,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
return true;
},
/*frame_size=*/SkISize::Make(800, 600));
embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));

EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
Expand Down Expand Up @@ -873,7 +873,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
return true;
},
/*frame_size=*/SkISize::Make(800, 600));
embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));

EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
Expand Down Expand Up @@ -985,7 +985,7 @@ TEST(AndroidExternalViewEmbedder, Teardown) {
SkSurface::MakeNull(1000, 1000), framebuffer_info,
[](const SurfaceFrame& surface_frame, SkCanvas* canvas) { return true; },
/*frame_size=*/SkISize::Make(800, 600));
embedder->SubmitFrame(gr_context.get(), std::move(surface_frame));
embedder->SubmitFrame(gr_context.get(), 0, std::move(surface_frame));

embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ class FlutterCompositor {
// Presents the FlutterLayers by updating FlutterView(s) using the
// layer content.
// Present sets frame_started_ to false.
virtual bool Present(const FlutterLayer** layers, size_t layers_count) = 0;
virtual bool Present(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count) = 0;

using PresentCallback = std::function<bool(bool has_flutter_content)>;

Expand Down
12 changes: 7 additions & 5 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,13 @@ - (FlutterCompositor*)createFlutterCompositor {
backing_store);
};

_compositor.present_layers_callback = [](const FlutterLayer** layers, //
size_t layers_count, //
void* user_data //
) {
return reinterpret_cast<flutter::FlutterCompositor*>(user_data)->Present(layers, layers_count);
_compositor.present_layers_surface_callback = [](uint64_t surface_id, //
const FlutterLayer** layers, //
size_t layers_count, //
void* user_data //
) {
return reinterpret_cast<flutter::FlutterCompositor*>(user_data)->Present(surface_id, layers,
layers_count);
};

_compositor.avoid_backing_store_cache = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class FlutterGLCompositor : public FlutterCompositor {
// Presents the FlutterLayers by updating FlutterView(s) using the
// layer content.
// Present sets frame_started_ to false.
bool Present(const FlutterLayer** layers, size_t layers_count) override;
bool Present(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count) override;

private:
const NSOpenGLContext* open_gl_context_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,10 @@
return true;
}

bool FlutterGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) {
// TODO(dkwingsmt): This class only supports single-view for now. As more
// classes are gradually converted to multi-view, it should get the view ID
// from somewhere.
FlutterView* view = GetView(kFlutterDefaultViewId);
bool FlutterGLCompositor::Present(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count) {
FlutterView* view = GetView(surface_id);
if (!view) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ - (nullable FlutterView*)getView:(uint64_t)viewId {
return true;
});

ASSERT_TRUE(macos_compositor->Present(nil, 0));
ASSERT_TRUE(macos_compositor->Present(0, nil, 0));
ASSERT_TRUE(flag);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ class FlutterMetalCompositor : public FlutterCompositor {

// Composites the provided FlutterLayer objects and presents the composited
// frame to the FlutterView(s).
bool Present(const FlutterLayer** layers, size_t layers_count) override;
bool Present(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count) override;

private:
// Presents the platform view layer represented by `layer`. `layer_index` is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,10 @@
return true;
}

bool FlutterMetalCompositor::Present(const FlutterLayer** layers, size_t layers_count) {
// TODO(dkwingsmt): This class only supports single-view for now. As more
// classes are gradually converted to multi-view, it should get the view ID
// from somewhere.
FlutterView* view = GetView(kFlutterDefaultViewId);
bool FlutterMetalCompositor::Present(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count) {
FlutterView* view = GetView(surface_id);
if (!view) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ - (nullable FlutterView*)getView:(uint64_t)viewId {
return true;
});

ASSERT_TRUE(macos_compositor->Present(nil, 0));
ASSERT_TRUE(macos_compositor->Present(0, nil, 0));
ASSERT_TRUE(flag);
}

Expand Down
10 changes: 5 additions & 5 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) {
auto c_collect_callback =
SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
auto c_present_callback =
SAFE_ACCESS(compositor, present_layers_callback, nullptr);
SAFE_ACCESS(compositor, present_layers_surface_callback, nullptr);
bool avoid_backing_store_cache =
SAFE_ACCESS(compositor, avoid_backing_store_cache, false);

Expand All @@ -1058,12 +1058,12 @@ InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) {
};

flutter::EmbedderExternalViewEmbedder::PresentCallback present_callback =
[c_present_callback,
user_data = compositor->user_data](const auto& layers) {
[c_present_callback, user_data = compositor->user_data](
uint64_t surface_id, const auto& layers) {
TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
return c_present_callback(
const_cast<const FlutterLayer**>(layers.data()), layers.size(),
user_data);
surface_id, const_cast<const FlutterLayer**>(layers.data()),
layers.size(), user_data);
};

return {std::make_unique<flutter::EmbedderExternalViewEmbedder>(
Expand Down
16 changes: 12 additions & 4 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,8 @@ typedef struct {
size_t struct_size;
/// The size of the render target the engine expects to render into.
FlutterSize size;
/// Indicates the view that owns the layer this store is backing.
uint64_t surface_id;
} FlutterBackingStoreConfig;

typedef enum {
Expand Down Expand Up @@ -1424,14 +1426,18 @@ typedef bool (*FlutterBackingStoreCollectCallback)(
typedef bool (*FlutterLayersPresentCallback)(const FlutterLayer** layers,
size_t layers_count,
void* user_data);
typedef bool (*FlutterLayersPresentSurfaceCallback)(uint64_t surface_id,
const FlutterLayer** layers,
size_t layers_count,
void* user_data);

typedef struct {
/// This size of this struct. Must be sizeof(FlutterCompositor).
size_t struct_size;
/// A baton that in not interpreted by the engine in any way. If it passed
/// back to the embedder in `FlutterCompositor.create_backing_store_callback`,
/// `FlutterCompositor.collect_backing_store_callback` and
/// `FlutterCompositor.present_layers_callback`
/// `FlutterCompositor.present_layers_surface_callback`
void* user_data;
/// A callback invoked by the engine to obtain a backing store for a specific
/// `FlutterLayer`.
Expand All @@ -1444,11 +1450,13 @@ typedef struct {
/// A callback invoked by the engine to release the backing store. The
/// embedder may collect any resources associated with the backing store.
FlutterBackingStoreCollectCallback collect_backing_store_callback;
/// Callback invoked by the engine to composite the contents of each layer
/// onto the screen.
FlutterLayersPresentCallback present_layers_callback;
/// A deprecated callback. It is not used and should not be set.
void* _deprecated_present_layers_callback;
/// Avoid caching backing stores provided by this compositor.
bool avoid_backing_store_cache;
/// Callback invoked by the engine to composite the contents of each layer
/// onto the screen.
FlutterLayersPresentSurfaceCallback present_layers_surface_callback;
} FlutterCompositor;

typedef struct {
Expand Down
9 changes: 6 additions & 3 deletions shell/platform/embedder/embedder_external_view_embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,23 @@ EmbedderPaintContext EmbedderExternalViewEmbedder::CompositeEmbeddedView(
}

static FlutterBackingStoreConfig MakeBackingStoreConfig(
const SkISize& backing_store_size) {
const SkISize& backing_store_size,
uint64_t surface_id) {
FlutterBackingStoreConfig config = {};

config.struct_size = sizeof(config);

config.size.width = backing_store_size.width();
config.size.height = backing_store_size.height();
config.surface_id = surface_id;

return config;
}

// |ExternalViewEmbedder|
void EmbedderExternalViewEmbedder::SubmitFrame(
GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) {
auto [matched_render_targets, pending_keys] =
render_target_cache_.GetExistingTargetsInCache(pending_views_);
Expand Down Expand Up @@ -184,7 +187,7 @@ void EmbedderExternalViewEmbedder::SubmitFrame(
const auto render_surface_size = external_view->GetRenderSurfaceSize();

const auto backing_store_config =
MakeBackingStoreConfig(render_surface_size);
MakeBackingStoreConfig(render_surface_size, frame_view_id);

// This is where the embedder will create render targets for us. Control
// flow to the embedder makes the engine susceptible to having the embedder
Expand Down Expand Up @@ -263,7 +266,7 @@ void EmbedderExternalViewEmbedder::SubmitFrame(
// Flush the layer description down to the embedder for presentation.
//
// @warning: Embedder may trample on our OpenGL context here.
presented_layers.InvokePresentCallback(present_callback_);
presented_layers.InvokePresentCallback(present_callback_, frame_view_id);
}

// See why this is necessary in the comment where this collection in realized.
Expand Down
4 changes: 3 additions & 1 deletion shell/platform/embedder/embedder_external_view_embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
GrDirectContext* context,
const FlutterBackingStoreConfig& config)>;
using PresentCallback =
std::function<bool(const std::vector<const FlutterLayer*>& layers)>;
std::function<bool(uint64_t surface_id,
const std::vector<const FlutterLayer*>& layers)>;
using SurfaceTransformationCallback = std::function<SkMatrix(void)>;

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -101,6 +102,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {

// |ExternalViewEmbedder|
void SubmitFrame(GrDirectContext* context,
uint64_t frame_view_id,
std::unique_ptr<SurfaceFrame> frame) override;

// |ExternalViewEmbedder|
Expand Down
Loading