mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Multiview ExternalViewEmbedder (flutter/engine#46169)
This PR adds multiview support for `ExternalViewEmbedder`.
## Nomenclature
The term **view** can be ambiguous in `ExternalViewEmbedder`, and therefore the following terms are used:
* A **native view** refers to the final drawing surface that to composite layers to. It is the "view" used in other places of the engine, such as `Shell::AddView`.
* A **platform view** refers a platform view, a layer that holds content to be embedded.
## Change
The lifecycle of `ExternalViewEmbedder` is changed:
<table>
<thead>
<tr>
<th>Before PR</th>
<th>After PR</th>
<th>How it's called</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan=2>BeginFrame</td>
<td>BeginFrame</td>
<td>Once per frame</td>
</tr>
<tr>
<td>PrepareFlutterView</td>
<td>Once per flutter view</td>
</tr>
<tr>
<td>SubmitFrame</td>
<td>SubmitFlutterView (renamed)</td>
<td>Once per flutter view</td>
</tr>
<tr>
<td>EndFrame</td>
<td>EndFrame (unchanged)</td>
<td>Once per frame</td>
</tr>
</tbody>
</table>
* `BeginFrame` should perform per-frame actions, such as merge-unmerging threads.
* `PrepareView` should perform per-native-view preparations, such as recording the view ID and view size.
This change is necessary because some actions in `PrepareView` needs to be refreshed at the beginning of drawing every native view.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
parent
2b37d51467
commit
673fca77cf
@ -42,13 +42,19 @@ bool DisplayListEmbedderViewSlice::recording_ended() {
|
||||
return builder_ == nullptr;
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::SubmitFrame(
|
||||
void ExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
frame->Submit();
|
||||
}
|
||||
|
||||
bool ExternalViewEmbedder::SupportsDynamicThreadMerging() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::Teardown() {}
|
||||
|
||||
void MutatorsStack::PushClipRect(const SkRect& rect) {
|
||||
std::shared_ptr<Mutator> element = std::make_shared<Mutator>(rect);
|
||||
vector_.push_back(element);
|
||||
@ -112,10 +118,4 @@ const std::vector<std::shared_ptr<Mutator>>::const_iterator MutatorsStack::End()
|
||||
return vector_.end();
|
||||
}
|
||||
|
||||
bool ExternalViewEmbedder::SupportsDynamicThreadMerging() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::Teardown() {}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -369,6 +369,29 @@ class DisplayListEmbedderViewSlice : public EmbedderViewSlice {
|
||||
//
|
||||
// Used on iOS, Android (hybrid composite mode), and on embedded platforms
|
||||
// that provide a system compositor as part of the project arguments.
|
||||
//
|
||||
// There are two kinds of "view IDs" in the context of ExternalViewEmbedder, and
|
||||
// specific names are used to avoid ambiguation:
|
||||
//
|
||||
// * ExternalViewEmbedder composites a stack of layers. Each layer's content
|
||||
// might be from Flutter widgets, or a platform view, which displays platform
|
||||
// native components. Each platform view is labeled by a view ID, which
|
||||
// corresponds to the ID from `PlatformViewsRegistry.getNextPlatformViewId`
|
||||
// from the framework. In the context of `ExternalViewEmbedder`, this ID is
|
||||
// called platform_view_id.
|
||||
// * The layers are compositied into a single rectangular surface, displayed by
|
||||
// taking up an entire native window or part of a window. Each such surface
|
||||
// is labeled by a view ID, which corresponds to `FlutterView.viewID` from
|
||||
// dart:ui. In the context of `ExternalViewEmbedder`, this ID is called
|
||||
// flutter_view_id.
|
||||
//
|
||||
// The lifecycle of drawing a frame using ExternalViewEmbedder is:
|
||||
//
|
||||
// 1. At the start of a frame, call |BeginFrame|, then |SetUsedThisFrame| to
|
||||
// true.
|
||||
// 2. For each view to be drawn, call |PrepareFlutterView|, then
|
||||
// |SubmitFlutterView|.
|
||||
// 3. At the end of a frame, if |GetUsedThisFrame| is true, call |EndFrame|.
|
||||
class ExternalViewEmbedder {
|
||||
// TODO(cyanglaz): Make embedder own the `EmbeddedViewParams`.
|
||||
|
||||
@ -383,7 +406,7 @@ class ExternalViewEmbedder {
|
||||
// from the on-screen render target.
|
||||
virtual DlCanvas* GetRootCanvas() = 0;
|
||||
|
||||
// Call this in-lieu of |SubmitFrame| to clear pre-roll state and
|
||||
// Call this in-lieu of |SubmitFlutterView| to clear pre-roll state and
|
||||
// sets the stage for the next pre-roll.
|
||||
virtual void CancelFrame() = 0;
|
||||
|
||||
@ -392,13 +415,11 @@ class ExternalViewEmbedder {
|
||||
// The `raster_thread_merger` will be null if |SupportsDynamicThreadMerging|
|
||||
// returns false.
|
||||
virtual void BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) = 0;
|
||||
|
||||
virtual void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
int64_t platform_view_id,
|
||||
std::unique_ptr<EmbeddedViewParams> params) = 0;
|
||||
|
||||
// This needs to get called after |Preroll| finishes on the layer tree.
|
||||
@ -411,14 +432,19 @@ class ExternalViewEmbedder {
|
||||
}
|
||||
|
||||
// Must be called on the UI thread.
|
||||
virtual DlCanvas* CompositeEmbeddedView(int64_t view_id) = 0;
|
||||
virtual DlCanvas* CompositeEmbeddedView(int64_t platform_view_id) = 0;
|
||||
|
||||
// Prepare for a view to be drawn.
|
||||
virtual void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) = 0;
|
||||
|
||||
// Implementers must submit the frame by calling frame.Submit().
|
||||
//
|
||||
// This method can mutate the root Skia canvas before submitting the frame.
|
||||
//
|
||||
// It can also allocate frames for overlay surfaces to compose hybrid views.
|
||||
virtual void SubmitFrame(
|
||||
virtual void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame);
|
||||
@ -462,7 +488,7 @@ class ExternalViewEmbedder {
|
||||
|
||||
// Pushes the platform view id of a visited platform view to a list of
|
||||
// visited platform views.
|
||||
virtual void PushVisitedPlatformView(int64_t view_id) {}
|
||||
virtual void PushVisitedPlatformView(int64_t platform_view_id) {}
|
||||
|
||||
// Pushes a DlImageFilter object to each platform view within a list of
|
||||
// visited platform views.
|
||||
|
||||
@ -25,11 +25,14 @@ void MockViewEmbedder::CancelFrame() {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void MockViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void MockViewEmbedder::PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void MockViewEmbedder::PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
|
||||
@ -25,12 +25,15 @@ class MockViewEmbedder : public ExternalViewEmbedder {
|
||||
void CancelFrame() override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
|
||||
@ -16,6 +16,10 @@ void main() {
|
||||
internalBootstrapBrowserTest(() => testMain);
|
||||
}
|
||||
|
||||
// Ignoring the deprecated member use because we're specifically testing
|
||||
// deprecated API.
|
||||
// ignore: deprecated_member_use
|
||||
|
||||
void testMain() {
|
||||
test('hashValues and hashList can hash lots of huge values effectively', () {
|
||||
final int hashValueFromArgs = hashValues(
|
||||
|
||||
@ -562,13 +562,6 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces(
|
||||
std::unique_ptr<FrameItem> Rasterizer::DrawToSurfacesUnsafe(
|
||||
FrameTimingsRecorder& frame_timings_recorder,
|
||||
std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
|
||||
// TODO(dkwingsmt): The rasterizer only supports rendering a single view
|
||||
// and that view must be the implicit view. Properly support multi-view
|
||||
// in the future.
|
||||
// See https://github.com/flutter/flutter/issues/135530, item 2 & 4.
|
||||
FML_CHECK(tasks.size() == 1u) << "Unexpected size of " << tasks.size();
|
||||
FML_DCHECK(tasks.front()->view_id == kFlutterImplicitViewId);
|
||||
|
||||
compositor_context_->ui_time().SetLapTime(
|
||||
frame_timings_recorder.GetBuildDuration());
|
||||
|
||||
@ -593,11 +586,8 @@ std::unique_ptr<FrameItem> Rasterizer::DrawToSurfacesUnsafe(
|
||||
if (external_view_embedder_) {
|
||||
FML_DCHECK(!external_view_embedder_->GetUsedThisFrame());
|
||||
external_view_embedder_->SetUsedThisFrame(true);
|
||||
external_view_embedder_->BeginFrame(
|
||||
// TODO(dkwingsmt): Add all views here.
|
||||
// See https://github.com/flutter/flutter/issues/135530, item 4.
|
||||
tasks.front()->layer_tree->frame_size(), surface_->GetContext(),
|
||||
tasks.front()->device_pixel_ratio, raster_thread_merger_);
|
||||
external_view_embedder_->BeginFrame(surface_->GetContext(),
|
||||
raster_thread_merger_);
|
||||
}
|
||||
|
||||
std::optional<fml::TimePoint> presentation_time = std::nullopt;
|
||||
@ -664,6 +654,8 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe(
|
||||
|
||||
DlCanvas* embedder_root_canvas = nullptr;
|
||||
if (external_view_embedder_) {
|
||||
external_view_embedder_->PrepareFlutterView(
|
||||
view_id, layer_tree.frame_size(), device_pixel_ratio);
|
||||
// TODO(dkwingsmt): Add view ID here.
|
||||
embedder_root_canvas = external_view_embedder_->GetRootCanvas();
|
||||
}
|
||||
@ -704,7 +696,7 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe(
|
||||
// for accurate performance metrics.
|
||||
if (frame->framebuffer_info().supports_partial_repaint &&
|
||||
!layer_tree.is_leaf_layer_tracing_enabled()) {
|
||||
// Disable partial repaint if external_view_embedder_ SubmitFrame is
|
||||
// Disable partial repaint if external_view_embedder_ SubmitFlutterView is
|
||||
// involved - ExternalViewEmbedder unconditionally clears the entire
|
||||
// surface and also partial repaint with platform view present is
|
||||
// something that still need to be figured out.
|
||||
@ -750,7 +742,7 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe(
|
||||
if (external_view_embedder_ &&
|
||||
(!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
|
||||
FML_DCHECK(!frame->IsSubmitted());
|
||||
external_view_embedder_->SubmitFrame(
|
||||
external_view_embedder_->SubmitFlutterView(
|
||||
surface_->GetContext(), surface_->GetAiksContext(), std::move(frame));
|
||||
} else {
|
||||
frame->Submit();
|
||||
|
||||
@ -92,11 +92,15 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
MOCK_METHOD(
|
||||
void,
|
||||
BeginFrame,
|
||||
(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
(GrDirectContext * context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger),
|
||||
(override));
|
||||
MOCK_METHOD(void,
|
||||
PrepareFlutterView,
|
||||
(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio),
|
||||
(override));
|
||||
MOCK_METHOD(void,
|
||||
PrerollCompositeEmbeddedView,
|
||||
(int64_t view_id, std::unique_ptr<EmbeddedViewParams> params),
|
||||
@ -108,7 +112,7 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
(override));
|
||||
MOCK_METHOD(DlCanvas*, CompositeEmbeddedView, (int64_t view_id), (override));
|
||||
MOCK_METHOD(void,
|
||||
SubmitFrame,
|
||||
SubmitFlutterView,
|
||||
(GrDirectContext * context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame),
|
||||
@ -215,12 +219,16 @@ TEST(RasterizerTest,
|
||||
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
|
||||
/*device_pixel_ratio=*/2.0,
|
||||
BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/
|
||||
fml::RefPtr<fml::RasterThreadMerger>(nullptr)))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFrame).Times(1);
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/kImplicitViewId,
|
||||
/*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFlutterView).Times(1);
|
||||
EXPECT_CALL(
|
||||
*external_view_embedder,
|
||||
EndFrame(/*should_resubmit_frame=*/false,
|
||||
@ -288,12 +296,15 @@ TEST(
|
||||
EXPECT_CALL(*surface, MakeRenderContextCurrent())
|
||||
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
|
||||
/*device_pixel_ratio=*/2.0,
|
||||
/*raster_thread_merger=*/_))
|
||||
EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFrame).Times(0);
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/kImplicitViewId,
|
||||
/*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFlutterView).Times(0);
|
||||
EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
@ -364,12 +375,15 @@ TEST(
|
||||
EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
|
||||
/*device_pixel_ratio=*/2.0,
|
||||
/*raster_thread_merger=*/_))
|
||||
EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFrame).Times(1);
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/kImplicitViewId,
|
||||
/*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFlutterView).Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
@ -443,12 +457,15 @@ TEST(RasterizerTest,
|
||||
EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
|
||||
/*device_pixel_ratio=*/2.0,
|
||||
/*raster_thread_merger=*/_))
|
||||
EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(2);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFrame).Times(2);
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/kImplicitViewId,
|
||||
/*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(2);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFlutterView).Times(2);
|
||||
EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(2);
|
||||
@ -466,13 +483,13 @@ TEST(RasterizerTest,
|
||||
pipeline->Produce().Complete(std::move(layer_tree_item));
|
||||
EXPECT_TRUE(result.success);
|
||||
|
||||
// The Draw() will respectively call BeginFrame(), SubmitFrame() and
|
||||
// The Draw() will respectively call BeginFrame(), SubmitFlutterView() and
|
||||
// EndFrame() one time.
|
||||
ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
|
||||
rasterizer->Draw(pipeline);
|
||||
|
||||
// The DrawLastLayerTrees() will respectively call BeginFrame(), SubmitFrame()
|
||||
// and EndFrame() one more time, totally 2 times.
|
||||
// The DrawLastLayerTrees() will respectively call BeginFrame(),
|
||||
// SubmitFlutterView() and EndFrame() one more time, totally 2 times.
|
||||
rasterizer->DrawLastLayerTrees(CreateFinishedBuildRecorder());
|
||||
}
|
||||
|
||||
@ -555,10 +572,13 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) {
|
||||
rasterizer->SetExternalViewEmbedder(external_view_embedder);
|
||||
rasterizer->Setup(std::move(surface));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(0);
|
||||
EXPECT_CALL(*external_view_embedder,
|
||||
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
|
||||
/*device_pixel_ratio=*/2.0,
|
||||
/*raster_thread_merger=*/_))
|
||||
PrepareFlutterView(/*flutter_view_id=*/kImplicitViewId,
|
||||
/*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(0);
|
||||
EXPECT_CALL(
|
||||
*external_view_embedder,
|
||||
@ -635,6 +655,83 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) {
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
TEST(RasterizerTest, drawMultipleViewsWithExternalViewEmbedder) {
|
||||
std::string test_name =
|
||||
::testing::UnitTest::GetInstance()->current_test_info()->name();
|
||||
ThreadHost thread_host("io.flutter.test." + test_name + ".",
|
||||
ThreadHost::Type::kPlatform |
|
||||
ThreadHost::Type::kRaster | ThreadHost::Type::kIo |
|
||||
ThreadHost::Type::kUi);
|
||||
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
|
||||
thread_host.raster_thread->GetTaskRunner(),
|
||||
thread_host.ui_thread->GetTaskRunner(),
|
||||
thread_host.io_thread->GetTaskRunner());
|
||||
NiceMock<MockDelegate> delegate;
|
||||
Settings settings;
|
||||
ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
|
||||
EXPECT_CALL(delegate, GetTaskRunners())
|
||||
.WillRepeatedly(ReturnRef(task_runners));
|
||||
EXPECT_CALL(delegate, OnFrameRasterized(_));
|
||||
auto rasterizer = std::make_unique<Rasterizer>(delegate);
|
||||
auto surface = std::make_unique<NiceMock<MockSurface>>();
|
||||
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
|
||||
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
|
||||
rasterizer->SetExternalViewEmbedder(external_view_embedder);
|
||||
EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
|
||||
.WillRepeatedly(Return(false));
|
||||
EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*surface, AcquireFrame(SkISize())).Times(2);
|
||||
ON_CALL(*surface, AcquireFrame).WillByDefault([](const SkISize& size) {
|
||||
SurfaceFrame::FramebufferInfo framebuffer_info;
|
||||
framebuffer_info.supports_readback = true;
|
||||
return std::make_unique<SurfaceFrame>(
|
||||
/*surface=*/
|
||||
nullptr, framebuffer_info,
|
||||
/*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
});
|
||||
EXPECT_CALL(*surface, MakeRenderContextCurrent())
|
||||
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
|
||||
|
||||
EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
EXPECT_CALL(
|
||||
*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/0, /*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/1.5))
|
||||
.Times(1);
|
||||
EXPECT_CALL(
|
||||
*external_view_embedder,
|
||||
PrepareFlutterView(/*flutter_view_id=*/1, /*frame_size=*/SkISize(),
|
||||
/*device_pixel_ratio=*/2.0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*external_view_embedder, SubmitFlutterView).Times(2);
|
||||
EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
|
||||
/*raster_thread_merger=*/_))
|
||||
.Times(1);
|
||||
|
||||
rasterizer->Setup(std::move(surface));
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
|
||||
auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
|
||||
std::vector<std::unique_ptr<LayerTreeTask>> tasks;
|
||||
tasks.push_back(std::make_unique<LayerTreeTask>(
|
||||
0, std::make_unique<LayerTree>(LayerTree::Config(), SkISize()), 1.5));
|
||||
tasks.push_back(std::make_unique<LayerTreeTask>(
|
||||
1, std::make_unique<LayerTree>(LayerTree::Config(), SkISize()), 2.0));
|
||||
auto layer_tree_item = std::make_unique<FrameItem>(
|
||||
std::move(tasks), CreateFinishedBuildRecorder());
|
||||
PipelineProduceResult result =
|
||||
pipeline->Produce().Complete(std::move(layer_tree_item));
|
||||
EXPECT_TRUE(result.success);
|
||||
ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
|
||||
rasterizer->Draw(pipeline);
|
||||
latch.Signal();
|
||||
});
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
TEST(RasterizerTest,
|
||||
drawWithGpuEnabledAndSurfaceAllowsDrawingWhenGpuDisabledDoesAcquireFrame) {
|
||||
std::string test_name =
|
||||
|
||||
@ -41,10 +41,14 @@ void ShellTestExternalViewEmbedder::CancelFrame() {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void ShellTestExternalViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void ShellTestExternalViewEmbedder::PrepareFlutterView(
|
||||
int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {
|
||||
visited_platform_views_.clear();
|
||||
mutators_stacks_.clear();
|
||||
current_composition_params_.clear();
|
||||
@ -89,7 +93,7 @@ DlCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView(
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void ShellTestExternalViewEmbedder::SubmitFrame(
|
||||
void ShellTestExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
|
||||
@ -28,7 +28,7 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
// returns the new `post_preroll_result`.
|
||||
void UpdatePostPrerollResult(PostPrerollResult post_preroll_result);
|
||||
|
||||
// Gets the number of times the SubmitFrame method has been called in
|
||||
// Gets the number of times the SubmitFlutterView method has been called in
|
||||
// the external view embedder.
|
||||
int GetSubmittedFrameCount();
|
||||
|
||||
@ -46,12 +46,15 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
void CancelFrame() override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
@ -74,9 +77,10 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
const SkRect& filter_rect) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void EndFrame(bool should_resubmit_frame,
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
|
||||
#include "flutter/common/constants.h"
|
||||
#include "flutter/fml/synchronization/waitable_event.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
|
||||
@ -62,11 +63,11 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int64_t view_id) const {
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void AndroidExternalViewEmbedder::SubmitFrame(
|
||||
void AndroidExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame");
|
||||
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFlutterView");
|
||||
|
||||
if (!FrameHasPlatformLayers()) {
|
||||
frame->Submit();
|
||||
@ -257,10 +258,22 @@ void AndroidExternalViewEmbedder::Reset() {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void AndroidExternalViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
|
||||
// JNI method must be called on the platform thread.
|
||||
if (raster_thread_merger->IsOnPlatformThread()) {
|
||||
jni_facade_->FlutterViewBeginFrame();
|
||||
}
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void AndroidExternalViewEmbedder::PrepareFlutterView(
|
||||
int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {
|
||||
// TODO(dkwingsmt): This class only supports rendering into the implicit view.
|
||||
// Properly support multi-view in the future.
|
||||
FML_DCHECK(flutter_view_id == kFlutterImplicitViewId);
|
||||
Reset();
|
||||
|
||||
// The surface size changed. Therefore, destroy existing surfaces as
|
||||
@ -269,10 +282,6 @@ void AndroidExternalViewEmbedder::BeginFrame(
|
||||
DestroySurfaces();
|
||||
}
|
||||
surface_pool_->SetFrameSize(frame_size);
|
||||
// JNI method must be called on the platform thread.
|
||||
if (raster_thread_merger->IsOnPlatformThread()) {
|
||||
jni_facade_->FlutterViewBeginFrame();
|
||||
}
|
||||
|
||||
frame_size_ = frame_size;
|
||||
device_pixel_ratio_ = device_pixel_ratio;
|
||||
|
||||
@ -43,9 +43,10 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
DlCanvas* CompositeEmbeddedView(int64_t view_id) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
PostPrerollResult PostPrerollAction(
|
||||
@ -56,12 +57,15 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
DlCanvas* GetRootCanvas() override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void CancelFrame() override;
|
||||
|
||||
|
||||
@ -27,6 +27,8 @@ namespace testing {
|
||||
using ::testing::ByMove;
|
||||
using ::testing::Return;
|
||||
|
||||
constexpr int64_t kImplicitViewId = 0;
|
||||
|
||||
class TestAndroidSurfaceFactory : public AndroidSurfaceFactory {
|
||||
public:
|
||||
using TestSurfaceProducer =
|
||||
@ -144,8 +146,9 @@ TEST(AndroidExternalViewEmbedder, RasterizerRunsOnPlatformThread) {
|
||||
ASSERT_FALSE(raster_thread_merger->IsMerged());
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(SkISize::Make(10, 20), nullptr, 1.0,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(10, 20), 1.0);
|
||||
|
||||
// Push a platform view.
|
||||
embedder->PrerollCompositeEmbeddedView(
|
||||
0, std::make_unique<EmbeddedViewParams>());
|
||||
@ -197,8 +200,8 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRect) {
|
||||
GetThreadMergerFromPlatformThread(&rasterizer_thread);
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(SkISize::Make(100, 100), nullptr, 1.5,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(100, 100), 1.5);
|
||||
|
||||
MutatorsStack stack;
|
||||
SkMatrix matrix;
|
||||
@ -225,8 +228,8 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRectChangedParams) {
|
||||
GetThreadMergerFromPlatformThread(&rasterizer_thread);
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(SkISize::Make(100, 100), nullptr, 1.5,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(100, 100), 1.5);
|
||||
|
||||
auto view_id = 0;
|
||||
|
||||
@ -254,7 +257,7 @@ TEST(AndroidExternalViewEmbedder, PlatformViewRectChangedParams) {
|
||||
ASSERT_EQ(SkRect::MakeXYWH(75, 90, 105, 120), embedder->GetViewRect(view_id));
|
||||
}
|
||||
|
||||
TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
TEST(AndroidExternalViewEmbedder, SubmitFlutterView) {
|
||||
auto jni_mock = std::make_shared<JNIMock>();
|
||||
auto android_context =
|
||||
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
|
||||
@ -313,7 +316,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
// Submits frame if no Android view in the current frame.
|
||||
EXPECT_TRUE(did_submit_frame);
|
||||
// Doesn't resubmit frame.
|
||||
@ -327,7 +331,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
// ------------------ Second frame ------------------ //
|
||||
{
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
// Add an Android view.
|
||||
MutatorsStack stack1;
|
||||
@ -381,7 +386,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
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.
|
||||
@ -395,7 +401,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
// ------------------ Third frame ------------------ //
|
||||
{
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
// Add an Android view.
|
||||
MutatorsStack stack1;
|
||||
@ -446,7 +453,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) {
|
||||
return true;
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
// Submits frame if there are Android views in the previous frame.
|
||||
EXPECT_TRUE(did_submit_frame);
|
||||
// Doesn't resubmit frame.
|
||||
@ -499,7 +507,8 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) {
|
||||
auto raster_thread_merger = GetThreadMergerFromPlatformThread();
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
{
|
||||
// Add first Android view.
|
||||
@ -553,7 +562,8 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) {
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -597,7 +607,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
|
||||
auto raster_thread_merger = GetThreadMergerFromPlatformThread();
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
{
|
||||
// Add first Android view.
|
||||
@ -656,7 +667,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) {
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -700,7 +712,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) {
|
||||
auto raster_thread_merger = GetThreadMergerFromPlatformThread();
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
{
|
||||
// Add Android view.
|
||||
@ -724,7 +737,8 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) {
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -743,8 +757,8 @@ TEST(AndroidExternalViewEmbedder, DoesNotCallJNIPlatformThreadOnlyMethods) {
|
||||
auto raster_thread_merger = GetThreadMergerFromRasterThread(&platform_thread);
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
|
||||
embedder->BeginFrame(SkISize::Make(10, 20), nullptr, 1.0,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(10, 20), 1.0);
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame()).Times(0);
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -792,7 +806,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
|
||||
// ------------------ First frame ------------------ //
|
||||
{
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
// Add an Android view.
|
||||
MutatorsStack stack1;
|
||||
@ -825,7 +840,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
|
||||
return true;
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -834,8 +850,8 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) {
|
||||
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces());
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
// Change the frame size.
|
||||
embedder->BeginFrame(SkISize::Make(30, 40), nullptr, 1.0,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(30, 40), 1.0);
|
||||
}
|
||||
|
||||
TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
|
||||
@ -880,7 +896,8 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
|
||||
auto raster_thread_merger =
|
||||
GetThreadMergerFromPlatformThread(&rasterizer_thread);
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame());
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
// Add an Android view.
|
||||
MutatorsStack stack1;
|
||||
@ -912,7 +929,8 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
|
||||
return true;
|
||||
},
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewEndFrame());
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
@ -922,8 +940,9 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) {
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
|
||||
|
||||
fml::Thread platform_thread("platform");
|
||||
embedder->BeginFrame(SkISize::Make(30, 40), nullptr, 1.0,
|
||||
embedder->BeginFrame(nullptr,
|
||||
GetThreadMergerFromRasterThread(&platform_thread));
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(30, 40), 1.0);
|
||||
}
|
||||
|
||||
TEST(AndroidExternalViewEmbedder, SupportsDynamicThreadMerging) {
|
||||
@ -949,8 +968,8 @@ TEST(AndroidExternalViewEmbedder, DisableThreadMerger) {
|
||||
|
||||
EXPECT_CALL(*jni_mock, FlutterViewBeginFrame()).Times(0);
|
||||
|
||||
embedder->BeginFrame(SkISize::Make(10, 20), nullptr, 1.0,
|
||||
raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, SkISize::Make(10, 20), 1.0);
|
||||
// Push a platform view.
|
||||
embedder->PrerollCompositeEmbeddedView(
|
||||
0, std::make_unique<EmbeddedViewParams>());
|
||||
@ -999,7 +1018,8 @@ TEST(AndroidExternalViewEmbedder, Teardown) {
|
||||
auto raster_thread_merger =
|
||||
GetThreadMergerFromPlatformThread(&rasterizer_thread);
|
||||
|
||||
embedder->BeginFrame(frame_size, nullptr, 1.5, raster_thread_merger);
|
||||
embedder->BeginFrame(nullptr, raster_thread_merger);
|
||||
embedder->PrepareFlutterView(kImplicitViewId, frame_size, 1.5);
|
||||
|
||||
// Add an Android view.
|
||||
MutatorsStack stack;
|
||||
@ -1023,7 +1043,8 @@ TEST(AndroidExternalViewEmbedder, Teardown) {
|
||||
SkSurfaces::Null(1000, 1000), framebuffer_info,
|
||||
[](const SurfaceFrame& surface_frame, DlCanvas* canvas) { return true; },
|
||||
/*frame_size=*/SkISize::Make(800, 600));
|
||||
embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame));
|
||||
embedder->SubmitFlutterView(gr_context.get(), nullptr,
|
||||
std::move(surface_frame));
|
||||
|
||||
embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger);
|
||||
|
||||
|
||||
@ -31,12 +31,15 @@ class IOSExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
void CancelFrame() override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
@ -51,9 +54,10 @@ class IOSExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
DlCanvas* CompositeEmbeddedView(int64_t view_id) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void EndFrame(bool should_resubmit_frame,
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#import "flutter/shell/platform/darwin/ios/ios_external_view_embedder.h"
|
||||
|
||||
#include "flutter/common/constants.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
IOSExternalViewEmbedder::IOSExternalViewEmbedder(
|
||||
@ -31,11 +33,16 @@ void IOSExternalViewEmbedder::CancelFrame() {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void IOSExternalViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
|
||||
TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::BeginFrame");
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void IOSExternalViewEmbedder::PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {
|
||||
// TODO(dkwingsmt): This class only supports rendering into the implicit view.
|
||||
// Properly support multi-view in the future.
|
||||
FML_DCHECK(flutter_view_id == kFlutterImplicitViewId);
|
||||
FML_CHECK(platform_views_controller_);
|
||||
platform_views_controller_->BeginFrame(frame_size);
|
||||
}
|
||||
@ -66,11 +73,11 @@ DlCanvas* IOSExternalViewEmbedder::CompositeEmbeddedView(int64_t view_id) {
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void IOSExternalViewEmbedder::SubmitFrame(
|
||||
void IOSExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::SubmitFrame");
|
||||
TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::SubmitFlutterView");
|
||||
FML_CHECK(platform_views_controller_);
|
||||
platform_views_controller_->SubmitFrame(context, ios_context_, std::move(frame));
|
||||
TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::DidSubmitFrame");
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/common/constants.h"
|
||||
#include "flutter/shell/platform/embedder/embedder_layers.h"
|
||||
#include "flutter/shell/platform/embedder/embedder_render_target.h"
|
||||
#include "third_party/skia/include/gpu/GrDirectContext.h"
|
||||
@ -53,10 +54,18 @@ void EmbedderExternalViewEmbedder::CancelFrame() {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void EmbedderExternalViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void EmbedderExternalViewEmbedder::PrepareFlutterView(
|
||||
int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {
|
||||
// TODO(dkwingsmt): This class only supports rendering into the implicit
|
||||
// view. Properly support multi-view in the future.
|
||||
// https://github.com/flutter/flutter/issues/135530 item 4
|
||||
FML_DCHECK(flutter_view_id == kFlutterImplicitViewId);
|
||||
Reset();
|
||||
|
||||
pending_frame_size_ = frame_size;
|
||||
@ -407,7 +416,7 @@ class LayerBuilder {
|
||||
|
||||
}; // namespace
|
||||
|
||||
void EmbedderExternalViewEmbedder::SubmitFrame(
|
||||
void EmbedderExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
@ -436,15 +445,15 @@ void EmbedderExternalViewEmbedder::SubmitFrame(
|
||||
return create_render_target_callback_(context, aiks_context, config);
|
||||
});
|
||||
|
||||
// This is where unused render targets will be collected. Control may flow to
|
||||
// the embedder. Here, the embedder has the opportunity to trample on the
|
||||
// This is where unused render targets will be collected. Control may flow
|
||||
// to the embedder. Here, the embedder has the opportunity to trample on the
|
||||
// OpenGL context.
|
||||
//
|
||||
// For optimum performance, we should tell the render target cache to clear
|
||||
// its unused entries before allocating new ones. This collection step before
|
||||
// allocating new render targets ameliorates peak memory usage within the
|
||||
// frame. But, this causes an issue in a known internal embedder. To work
|
||||
// around this issue while that embedder migrates, collection of render
|
||||
// its unused entries before allocating new ones. This collection step
|
||||
// before allocating new render targets ameliorates peak memory usage within
|
||||
// the frame. But, this causes an issue in a known internal embedder. To
|
||||
// work around this issue while that embedder migrates, collection of render
|
||||
// targets is deferred after the presentation.
|
||||
//
|
||||
// @warning: Embedder may trample on our OpenGL context here.
|
||||
@ -460,9 +469,9 @@ void EmbedderExternalViewEmbedder::SubmitFrame(
|
||||
|
||||
builder.Render();
|
||||
|
||||
// We are going to be transferring control back over to the embedder there the
|
||||
// context may be trampled upon again. Flush all operations to the underlying
|
||||
// rendering API.
|
||||
// We are going to be transferring control back over to the embedder there
|
||||
// the context may be trampled upon again. Flush all operations to the
|
||||
// underlying rendering API.
|
||||
//
|
||||
// @warning: Embedder may trample on our OpenGL context here.
|
||||
if (context) {
|
||||
@ -482,7 +491,8 @@ void EmbedderExternalViewEmbedder::SubmitFrame(
|
||||
presented_layers.InvokePresentCallback(present_callback_);
|
||||
}
|
||||
|
||||
// See why this is necessary in the comment where this collection in realized.
|
||||
// See why this is necessary in the comment where this collection in
|
||||
// realized.
|
||||
//
|
||||
// @warning: Embedder may trample on our OpenGL context here.
|
||||
deferred_cleanup_render_targets.clear();
|
||||
|
||||
@ -81,12 +81,15 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
void CancelFrame() override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
@ -96,9 +99,10 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
DlCanvas* CompositeEmbeddedView(int64_t view_id) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
DlCanvas* GetRootCanvas() override;
|
||||
|
||||
@ -108,13 +108,14 @@ flutter::PostPrerollResult ExternalViewEmbedder::PostPrerollAction(
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::BeginFrame(
|
||||
SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
|
||||
TRACE_EVENT0("flutter", "ExternalViewEmbedder::BeginFrame");
|
||||
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
|
||||
|
||||
// Reset for new frame.
|
||||
// |ExternalViewEmbedder|
|
||||
void ExternalViewEmbedder::PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) {
|
||||
// Reset for new view.
|
||||
Reset();
|
||||
frame_size_ = frame_size;
|
||||
frame_dpr_ = device_pixel_ratio;
|
||||
@ -132,11 +133,11 @@ void ExternalViewEmbedder::EndFrame(
|
||||
TRACE_EVENT0("flutter", "ExternalViewEmbedder::EndFrame");
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::SubmitFrame(
|
||||
void ExternalViewEmbedder::SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "ExternalViewEmbedder::SubmitFrame");
|
||||
TRACE_EVENT0("flutter", "ExternalViewEmbedder::SubmitFlutterView");
|
||||
std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
|
||||
std::unordered_map<EmbedderLayerId, size_t> frame_surface_indices;
|
||||
|
||||
|
||||
@ -72,21 +72,25 @@ class ExternalViewEmbedder final : public flutter::ExternalViewEmbedder {
|
||||
override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void EndFrame(bool should_resubmit_frame,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override;
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void CancelFrame() override { Reset(); }
|
||||
|
||||
@ -58,6 +58,7 @@ constexpr static fuchsia::ui::composition::BlendMode kFirstLayerBlendMode{
|
||||
fuchsia::ui::composition::BlendMode::SRC};
|
||||
constexpr static fuchsia::ui::composition::BlendMode kUpperLayerBlendMode{
|
||||
fuchsia::ui::composition::BlendMode::SRC_OVER};
|
||||
constexpr static int64_t kImplicitViewId = 0;
|
||||
|
||||
class FakeSurfaceProducerSurface : public SurfaceProducerSurface {
|
||||
public:
|
||||
@ -326,7 +327,9 @@ void DrawSimpleFrame(ExternalViewEmbedder& external_view_embedder,
|
||||
SkISize frame_size,
|
||||
float frame_dpr,
|
||||
std::function<void(flutter::DlCanvas*)> draw_callback) {
|
||||
external_view_embedder.BeginFrame(frame_size, nullptr, frame_dpr, nullptr);
|
||||
external_view_embedder.BeginFrame(nullptr, nullptr);
|
||||
external_view_embedder.PrepareFlutterView(kImplicitViewId, frame_size,
|
||||
frame_dpr);
|
||||
{
|
||||
flutter::DlCanvas* root_canvas = external_view_embedder.GetRootCanvas();
|
||||
external_view_embedder.PostPrerollAction(nullptr);
|
||||
@ -335,7 +338,7 @@ void DrawSimpleFrame(ExternalViewEmbedder& external_view_embedder,
|
||||
external_view_embedder.EndFrame(false, nullptr);
|
||||
flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
|
||||
framebuffer_info.supports_readback = true;
|
||||
external_view_embedder.SubmitFrame(
|
||||
external_view_embedder.SubmitFlutterView(
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
nullptr, std::move(framebuffer_info),
|
||||
@ -352,7 +355,9 @@ void DrawFrameWithView(
|
||||
flutter::EmbeddedViewParams& view_params,
|
||||
std::function<void(flutter::DlCanvas*)> background_draw_callback,
|
||||
std::function<void(flutter::DlCanvas*)> overlay_draw_callback) {
|
||||
external_view_embedder.BeginFrame(frame_size, nullptr, frame_dpr, nullptr);
|
||||
external_view_embedder.BeginFrame(nullptr, nullptr);
|
||||
external_view_embedder.PrepareFlutterView(kImplicitViewId, frame_size,
|
||||
frame_dpr);
|
||||
{
|
||||
flutter::DlCanvas* root_canvas = external_view_embedder.GetRootCanvas();
|
||||
external_view_embedder.PrerollCompositeEmbeddedView(
|
||||
@ -366,7 +371,7 @@ void DrawFrameWithView(
|
||||
external_view_embedder.EndFrame(false, nullptr);
|
||||
flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
|
||||
framebuffer_info.supports_readback = true;
|
||||
external_view_embedder.SubmitFrame(
|
||||
external_view_embedder.SubmitFlutterView(
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
nullptr, std::move(framebuffer_info),
|
||||
|
||||
@ -45,15 +45,18 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
|
||||
flutter::DlCanvas* GetRootCanvas() override { return nullptr; }
|
||||
|
||||
void CancelFrame() override {}
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override {}
|
||||
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override {}
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override {}
|
||||
|
||||
void SubmitFlutterView(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override {}
|
||||
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
|
||||
@ -138,12 +138,15 @@ class TesterExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
void CancelFrame() override {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void BeginFrame(SkISize frame_size,
|
||||
GrDirectContext* context,
|
||||
double device_pixel_ratio,
|
||||
void BeginFrame(GrDirectContext* context,
|
||||
const fml::RefPtr<fml::RasterThreadMerger>&
|
||||
raster_thread_merger) override {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrepareFlutterView(int64_t flutter_view_id,
|
||||
SkISize frame_size,
|
||||
double device_pixel_ratio) override {}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void PrerollCompositeEmbeddedView(
|
||||
int64_t view_id,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user