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:
Tong Mu 2023-12-04 12:29:49 -08:00 committed by GitHub
parent 2b37d51467
commit 673fca77cf
21 changed files with 383 additions and 175 deletions

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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();

View File

@ -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 =

View File

@ -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) {

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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");

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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(); }

View File

@ -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),

View File

@ -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,

View File

@ -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,