Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[windows/linux] add ability to enable Impeller on windows and linux desktop. #162684

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

jonahwilliams
Copy link
Member

@jonahwilliams jonahwilliams commented Feb 4, 2025

Currently the --enable-impeller runtime flag works but there is no compile time option for desktop. This adds a flag that can be enabled via modifying the project source.

For Linux:

fl_dart_project_set_enable_impeller(project, true);

For windows:

DartProject project = ...
project.set_enable_impeller(true);

@github-actions github-actions bot added engine flutter/engine repository. See also e: labels. platform-windows Building on or for Windows specifically a: desktop Running on desktop platform-macos labels Feb 4, 2025
@github-actions github-actions bot added the platform-linux Building on or for Linux specifically label Feb 4, 2025
@jonahwilliams jonahwilliams changed the title [windows] add ability to enable Impeller on windows desktop. [windows] add ability to enable Impeller on windows and linux desktop. Feb 4, 2025
@jonahwilliams jonahwilliams changed the title [windows] add ability to enable Impeller on windows and linux desktop. [windows/linux] add ability to enable Impeller on windows and linux desktop. Feb 5, 2025
@jonahwilliams jonahwilliams marked this pull request as ready for review February 5, 2025 21:24
///
/// When not provided, this value is treated as false. In a future release,
/// this setting will become a no-op when the Skia backend is fully removed.
bool enable_impeller;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that in flutter/engine#42639 (comment) this was rejected; I didn't realize that when I proposed it.

I had also forgotten that command_line_argv is explicitly set up to control things like this in embedder.h, and that for the desktop embedders we explicitly disconnected actual command line arguments from what embedder.h unfortunately calls command line arguments.

Runtime command line arguments passed to a desktop app are actually piped through dart_entrypoint_arg*, which becomes the command line arguments that would be seen by Dart main. What the engine (unfortunately, but we can't change it without breaking the world) calls command_line_arg* is actually "engine flags", not anything related to what any Flutter dev would think of as command line arguments.

So I led you astray. Having paged all of this back in, we shouldn't need to change embedder.h at all, instead we can have the embedders turn whatever higher-level API we add into engine switches, which they are already set up to do. Going a step further, if we don't want to expose future-dead things in the embedding structs, we could instead expose the actual switches system, and have people use that along with the magic string. It looks like Windows already has SetString, so we would just have to expose that in the C++ wrapper. For Linux it looks like we haven't plumber switches up to that level, but we could, and it would avoid the same issue (just one level up) raised in the earlier embedder.h review that we don't want to permanently have explicit APIs for something that will become meaningless.

Copy link
Member

@loic-sharma loic-sharma Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stuart's suggestion is excellent, but I'm not sure that avoiding future-dead things in the embedding structs is currently worth the effort for Windows/Linux. I'd personally rather we spend our time on iOS/Android/web improvements. I'd be OK with having a no-op setting on Windows.

That said, +1 for avoiding a future-dead embedder API if possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that avoiding future-dead things in the embedding structs is currently worth the effort for Windows/Linux

If we plumb through the ability to set arbitrary engine flags, it won't be future-dead, it'll be available for whatever the next experimental engine features are.

Copy link
Member

@loic-sharma loic-sharma Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that avoiding future-dead things in the embedding structs is currently worth the effort for Windows/Linux

If we plumb through the ability to set arbitrary engine flags, it won't be future-dead, it'll be available for whatever the next experimental engine features are.

Right. By "future-dead things in the embedding structs", I was referring to set_enable_impeller and get_enable_impeller - I'd be OK adding those future-dead APIs if that's easier for Jonah.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I somehow read "avoiding" as "adding" in the first sentence, which is why my comment doesn't make sense :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this PR so that there is no change in embedder API, instead --enable-impeller is passed via embedder switches.

@@ -601,9 +601,10 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
std::vector<std::string> switches = self.switches;

// Enable Impeller only if specifically asked for from the project or cmdline arguments.
bool enable_impeller = false;
if (_project.enableImpeller ||
std::find(switches.begin(), switches.end(), "--enable-impeller=true") != switches.end()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope to fix in this specific PR, but this seems like a pretty bad idea to me. Capturing from my comments in the Discord discussion about this PR, I don't think we want to allow end users of Flutter-built software to change the rendering engine. That seems like a decision that should be up to the developer, at the time they build their app, just as it is (IIUC) on Android and iOS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, we explicitly say not to do this in embedder.h.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this code but even on iOS/Andorid, embedder switches is how we've handled the opt in.

@robert-ancell
Copy link
Contributor

The Linux changes look good; no opinion on the correct structure for this feature, I'll leave that to the other reviewers.

@jonahwilliams jonahwilliams marked this pull request as draft February 26, 2025 19:39
@jonahwilliams jonahwilliams marked this pull request as ready for review March 3, 2025 19:29
Copy link
Member

@loic-sharma loic-sharma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

void set_enable_impeller(bool value) { enable_impeller_ = value; }

// Whether the Impeller rendering engine is enabled.
bool get_enable_impeller() const { return enable_impeller_; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be called enable_impeller; it's more idiomatic for Google C++ style, and it's consistent with the other APIs in this class.

@@ -70,6 +70,9 @@ class FlutterProjectBundle {
return dart_entrypoint_arguments_;
}

// Whether the Impeller rendering engine is enabled.
bool ImpellerEnabled() const { return impeller_enabled_; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

impeller_enabled() since it's a trivial getter.

const bool has_impeller_flag =
std::find_if(
switches.begin(), switches.end(), [](std::string_view value) {
return value.rfind("--enable-impeller=", 0) != std::string::npos;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why rfind instead of find for a substring that should be at the start of the string?

// become a no-op when the Skia backend is fully removed.
void set_enable_impeller(bool value) { enable_impeller_ = value; }

// Whether the Impeller rendering engine is enabled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the flag-override behavior—and, importantly, the fact that this getter will not work correctly when there is a runtime flag—needs to be documented on these methods.

const bool has_impeller_flag =
std::find_if(
switches.begin(), switches.end(), [](std::string_view value) {
return value.rfind("--enable-impeller=", 0) != std::string::npos;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here about rfind.

@@ -70,6 +70,9 @@ class FlutterProjectBundle {
return dart_entrypoint_arguments_;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the setter?

@@ -70,6 +70,9 @@ class FlutterProjectBundle {
return dart_entrypoint_arguments_;
}

// Whether the Impeller rendering engine is enabled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment on this comment; this file should explain the interaction with the runtime flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: desktop Running on desktop engine flutter/engine repository. See also e: labels. platform-linux Building on or for Linux specifically platform-windows Building on or for Windows specifically
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants