未验证 提交 c92613bc 编写于 作者: C Chinmay Garde 提交者: GitHub

Re-land "Custom compositor layers must take into account the device pixel ratio."

This reverts commit 6c2381da and applies iOS fixes.
上级 6a198864
......@@ -208,7 +208,9 @@ class ExternalViewEmbedder {
// sets the stage for the next pre-roll.
virtual void CancelFrame() = 0;
virtual void BeginFrame(SkISize frame_size, GrContext* context) = 0;
virtual void BeginFrame(SkISize frame_size,
GrContext* context,
double device_pixel_ratio) = 0;
virtual void PrerollCompositeEmbeddedView(
int view_id,
......
......@@ -71,8 +71,15 @@ class LayerTree {
checkerboard_offscreen_layers_ = checkerboard;
}
void set_device_pixel_ratio(double device_pixel_ratio) {
device_pixel_ratio_ = device_pixel_ratio;
}
double device_pixel_ratio() const { return device_pixel_ratio_; }
private:
SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels.
double device_pixel_ratio_ = 1.0;
std::shared_ptr<Layer> root_layer_;
fml::TimePoint build_start_;
fml::TimePoint build_finish_;
......
......@@ -438,6 +438,7 @@ void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
return;
layer_tree->set_frame_size(frame_size);
layer_tree->set_device_pixel_ratio(viewport_metrics_.device_pixel_ratio);
animator_->Render(std::move(layer_tree));
}
......
......@@ -230,7 +230,8 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
if (external_view_embedder != nullptr) {
external_view_embedder->BeginFrame(layer_tree.frame_size(),
surface_->GetContext());
surface_->GetContext(),
layer_tree.device_pixel_ratio());
embedder_root_surface = external_view_embedder->GetRootSurface();
}
......
......@@ -60,7 +60,7 @@ class IOSSurfaceGL final : public IOSSurface,
void CancelFrame() override;
// |ExternalViewEmbedder|
void BeginFrame(SkISize frame_size, GrContext* context) override;
void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override;
// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id,
......
......@@ -100,7 +100,7 @@ void IOSSurfaceGL::CancelFrame() {
}
// |ExternalViewEmbedder|
void IOSSurfaceGL::BeginFrame(SkISize frame_size, GrContext* context) {
void IOSSurfaceGL::BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->SetFrameSize(frame_size);
......
......@@ -48,7 +48,7 @@ class IOSSurfaceMetal final : public IOSSurface,
void CancelFrame() override;
// |ExternalViewEmbedder|
void BeginFrame(SkISize frame_size, GrContext* context) override;
void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override;
// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id,
......
......@@ -61,7 +61,9 @@ void IOSSurfaceMetal::CancelFrame() {
[CATransaction commit];
}
void IOSSurfaceMetal::BeginFrame(SkISize frame_size, GrContext* context) {
void IOSSurfaceMetal::BeginFrame(SkISize frame_size,
GrContext* context,
double device_pixel_ratio) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->SetFrameSize(frame_size);
......
......@@ -52,7 +52,7 @@ class IOSSurfaceSoftware final : public IOSSurface,
void CancelFrame() override;
// |ExternalViewEmbedder|
void BeginFrame(SkISize frame_size, GrContext* context) override;
void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override;
// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id,
......
......@@ -150,7 +150,9 @@ void IOSSurfaceSoftware::CancelFrame() {
}
// |ExternalViewEmbedder|
void IOSSurfaceSoftware::BeginFrame(SkISize frame_size, GrContext* context) {
void IOSSurfaceSoftware::BeginFrame(SkISize frame_size,
GrContext* context,
double device_pixel_ratio) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->SetFrameSize(frame_size);
......
......@@ -984,6 +984,12 @@ FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
if (metrics.device_pixel_ratio <= 0.0) {
FML_LOG(ERROR) << "Device pixel ratio invalid: "
<< metrics.device_pixel_ratio;
return LOG_EMBEDDER_ERROR(kInvalidArguments);
}
return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
std::move(metrics))
? kSuccess
......
......@@ -67,9 +67,12 @@ static SkISize TransformedSurfaceSize(const SkISize& size,
// |ExternalViewEmbedder|
void EmbedderExternalViewEmbedder::BeginFrame(SkISize frame_size,
GrContext* context) {
GrContext* context,
double device_pixel_ratio) {
Reset();
pending_frame_size_ = frame_size;
pending_device_pixel_ratio_ = device_pixel_ratio;
pending_surface_transformation_ = GetSurfaceTransformation();
const auto surface_size = TransformedSurfaceSize(
......@@ -155,7 +158,8 @@ SkCanvas* EmbedderExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
static FlutterLayer MakeBackingStoreLayer(
const SkISize& frame_size,
const FlutterBackingStore* store,
const SkMatrix& surface_transformation) {
const SkMatrix& surface_transformation,
double device_pixel_ratio) {
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
......@@ -166,7 +170,9 @@ static FlutterLayer MakeBackingStoreLayer(
SkRect::MakeWH(frame_size.width(), frame_size.height());
const auto transformed_layer_bounds =
surface_transformation.mapRect(layer_bounds);
SkMatrix::Concat(surface_transformation,
SkMatrix::MakeScale(device_pixel_ratio))
.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
......@@ -190,7 +196,8 @@ static FlutterPlatformView MakePlatformView(
static FlutterLayer MakePlatformViewLayer(
const EmbeddedViewParams& params,
const FlutterPlatformView& platform_view,
const SkMatrix& surface_transformation) {
const SkMatrix& surface_transformation,
double device_pixel_ratio) {
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
......@@ -204,7 +211,9 @@ static FlutterLayer MakePlatformViewLayer(
);
const auto transformed_layer_bounds =
surface_transformation.mapRect(layer_bounds);
SkMatrix::Concat(surface_transformation,
SkMatrix::MakeScale(device_pixel_ratio))
.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
......@@ -235,8 +244,11 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
{
// The root surface is expressed as a layer.
presented_layers.push_back(MakeBackingStoreLayer(
pending_frame_size_, root_render_target_->GetBackingStore(),
pending_surface_transformation_));
pending_frame_size_, // frame size
root_render_target_->GetBackingStore(), // backing store
pending_surface_transformation_, // surface transformation
pending_device_pixel_ratio_ // device pixel ratio
));
}
const auto surface_size = TransformedSurfaceSize(
......@@ -262,9 +274,12 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
// The layers presented to the embedder will contain a back pointer to this
// struct. It is safe to deallocate when the embedder callback is done.
presented_platform_views[view_id] = MakePlatformView(view_id);
presented_layers.push_back(
MakePlatformViewLayer(params, presented_platform_views.at(view_id),
pending_surface_transformation_));
presented_layers.push_back(MakePlatformViewLayer(
params, // embedded view params
presented_platform_views.at(view_id), // platform view
pending_surface_transformation_, // surface transformation
pending_device_pixel_ratio_ // device pixel ratio
));
if (!pending_canvas_spies_.at(view_id)->DidDrawIntoCanvas()) {
// Nothing was drawn into the overlay canvas, we don't need to composite
......@@ -312,8 +327,11 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) {
// Indicate a layer for the backing store containing contents rendered by
// Flutter.
presented_layers.push_back(MakeBackingStoreLayer(
pending_frame_size_, render_target->GetBackingStore(),
pending_surface_transformation_));
pending_frame_size_, // frame size
render_target->GetBackingStore(), // backing store
pending_surface_transformation_, // surface transformation
pending_device_pixel_ratio_ // device pixel ratio
));
}
{
......
......@@ -73,7 +73,9 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
void CancelFrame() override;
// |ExternalViewEmbedder|
void BeginFrame(SkISize frame_size, GrContext* context) override;
void BeginFrame(SkISize frame_size,
GrContext* context,
double device_pixel_ratio) override;
// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(
......@@ -127,6 +129,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
RegistryKey::Equal>;
SkISize pending_frame_size_ = SkISize::Make(0, 0);
double pending_device_pixel_ratio_ = 1.0;
SkMatrix pending_surface_transformation_;
std::map<ViewIdentifier, std::unique_ptr<SkPictureRecorder>>
pending_recorders_;
......
......@@ -430,3 +430,16 @@ void verify_b141980393() {
};
window.scheduleFrame();
}
@pragma('vm:entry-point')
void can_display_platform_view_with_pixel_ratio() {
window.onBeginFrame = (Duration duration) {
SceneBuilder builder = SceneBuilder();
builder.pushOffset(0.0, 20.0);
builder.addPlatformView(42, width: 400.0, height: 280.0);
builder.addPicture(Offset(0.0, 0.0), CreateSimplePicture());
builder.pop();
window.render(builder.build());
};
window.scheduleFrame();
}
......@@ -652,6 +652,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLFramebuffer) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -743,6 +744,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLTexture) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -834,6 +836,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToSoftwareBuffer) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1125,6 +1128,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownScene) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1302,6 +1306,7 @@ TEST_F(EmbedderTest,
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1422,6 +1427,7 @@ TEST_F(EmbedderTest, CustomCompositorMustWorkWithCustomTaskRunner) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -1500,6 +1506,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderWithRootLayerOnly) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1612,6 +1619,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderWithPlatformLayerOnBottom) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1795,6 +1803,7 @@ TEST_F(EmbedderTest,
// Flutter still thinks it is 800 x 600. Only the root surface is rotated.
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -1829,6 +1838,7 @@ TEST_F(EmbedderTest, CanRenderSceneWithoutCustomCompositor) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -1871,6 +1881,7 @@ TEST_F(EmbedderTest, CanRenderSceneWithoutCustomCompositorWithTransformation) {
// Flutter still thinks it is 800 x 600.
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -1905,6 +1916,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithoutCompositor) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -1947,6 +1959,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithoutCompositorWithXform) {
// Flutter still thinks it is 800 x 600.
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -1981,6 +1994,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositor) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -2024,6 +2038,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorWithXform) {
// Flutter still thinks it is 800 x 600.
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -2134,6 +2149,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayer) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -2253,6 +2269,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayerWithXform) {
// Flutter still thinks it is 800 x 600.
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
......@@ -2372,7 +2389,7 @@ TEST_F(EmbedderTest, VerifyB141980393) {
// achieved via a root surface transformation.
event.width = flutter_application_rect.width();
event.height = flutter_application_rect.height();
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
......@@ -2425,6 +2442,7 @@ TEST_F(EmbedderTest, CaDeinitializeAnEngine) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kInvalidArguments);
engine.reset();
......@@ -2466,6 +2484,7 @@ TEST_F(EmbedderTest, CanCreateEmbedderWithCustomRenderTaskRunner) {
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
task_latch.Wait();
......@@ -2525,6 +2544,7 @@ TEST_F(EmbedderTest,
event.struct_size = sizeof(event);
event.width = 800;
event.height = 600;
event.pixel_ratio = 1.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
});
......@@ -2555,5 +2575,181 @@ TEST_F(EmbedderTest,
}
}
TEST_F(EmbedderTest,
CompositorMustBeAbleToRenderKnownScenePixelRatioOnSurface) {
auto& context = GetEmbedderContext();
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetDartEntrypoint("can_display_platform_view_with_pixel_ratio");
context.GetCompositor().SetRenderTargetType(
EmbedderTestCompositor::RenderTargetType::kOpenGLTexture);
fml::AutoResetWaitableEvent latch;
context.GetCompositor().SetNextPresentCallback(
[&](const FlutterLayer** layers, size_t layers_count) {
ASSERT_EQ(layers_count, 3u);
// Layer 0 (Root)
{
FlutterBackingStore backing_store = *layers[0]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[0], layer);
}
// Layer 1
{
FlutterPlatformView platform_view = {};
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
layer.size = FlutterSizeMake(800.0, 560.0);
layer.offset = FlutterPointMake(0.0, 40.0);
ASSERT_EQ(*layers[1], layer);
}
// Layer 2
{
FlutterBackingStore backing_store = *layers[2]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(800.0, 600.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[2], layer);
}
latch.Signal();
});
auto engine = builder.LaunchEngine();
// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 400;
event.height = 300;
event.pixel_ratio = 2.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
latch.Wait();
}
TEST_F(
EmbedderTest,
CompositorMustBeAbleToRenderKnownScenePixelRatioOnSurfaceWithRootSurfaceXformation) {
auto& context = GetEmbedderContext();
EmbedderConfigBuilder builder(context);
builder.SetOpenGLRendererConfig(SkISize::Make(600, 800));
builder.SetCompositor();
builder.SetDartEntrypoint("can_display_platform_view_with_pixel_ratio");
context.GetCompositor().SetRenderTargetType(
EmbedderTestCompositor::RenderTargetType::kOpenGLTexture);
const auto root_surface_transformation =
SkMatrix().preTranslate(0, 800).preRotate(-90, 0, 0);
context.SetRootSurfaceTransformation(root_surface_transformation);
fml::AutoResetWaitableEvent latch;
context.GetCompositor().SetNextPresentCallback(
[&](const FlutterLayer** layers, size_t layers_count) {
ASSERT_EQ(layers_count, 3u);
// Layer 0 (Root)
{
FlutterBackingStore backing_store = *layers[0]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(600.0, 800.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[0], layer);
}
// Layer 1
{
FlutterPlatformView platform_view = {};
platform_view.struct_size = sizeof(platform_view);
platform_view.identifier = 42;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = &platform_view;
layer.size = FlutterSizeMake(560.0, 800.0);
layer.offset = FlutterPointMake(40.0, 0.0);
ASSERT_EQ(*layers[1], layer);
}
// Layer 2
{
FlutterBackingStore backing_store = *layers[2]->backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.did_update = true;
backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
FlutterLayer layer = {};
layer.struct_size = sizeof(layer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.size = FlutterSizeMake(600.0, 800.0);
layer.offset = FlutterPointMake(0.0, 0.0);
ASSERT_EQ(*layers[2], layer);
}
latch.Signal();
});
auto engine = builder.LaunchEngine();
// Send a window metrics events so frames may be scheduled.
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = 400;
event.height = 300;
event.pixel_ratio = 2.0;
ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event),
kSuccess);
ASSERT_TRUE(engine.is_valid());
latch.Wait();
}
} // namespace testing
} // namespace flutter
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册