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

Android Support #1633

Closed
rib opened this issue May 17, 2022 · 1 comment · Fixed by #1634
Closed

Android Support #1633

rib opened this issue May 17, 2022 · 1 comment · Fixed by #1634
Labels
bug Something is broken

Comments

@rib
Copy link
Contributor

rib commented May 17, 2022

It's currently tricky to run egui natively on Android due to some general assumptions that it's possible to create a winit Window and immediately use that to create a graphics context and surface for rendering.

Unlike other winit platforms the native windows on Android are given to the application via lifecycle events and the application will be notified of a new window for each Resumed event and the native window will be invalidated by the next Paused event. (The winit backend on Android will panic if the app does anything that depends on dereferencing the .native_window() for a winit window while the app is paused).

The changes required to support this aren't too complicated but it generally means:

  • Splitting up surface creation/configuration from graphics context setup
  • Deferring graphics context / render state setup until we have our first (native) window (since device selection is technically dependent on being compatible with a given surface)
  • On Android: the graphics context should only be lazily initialized when the application is first Resumed.
  • On Android: for each Resumed event a new surface should be created, and then dropped on the next Paused event.

Problem areas currently are with the ::new() constructors for apis like egui_winit::State egui_wgpu::winit::Painter, epi::EpiIntegration and EguiGlium which currently all tend to assume that they have a valid native window and can immediately initialize all required render state.

proposal

It will require some small API changes to the above constructors but it shouldn't be too tricky to remove this assumption and instead allow for deferred initialization on graphics state on platforms where that's needed (i.e. Android).

For example egui_wgpu::Painter::new() might only take arguments for a power preference, present mode and msaa sample count and could have a set_window() method for asynchronously associating (or disassociating) the painter with a native window. For platforms other than Android this could be called immediately if a window has already been created, but on Android it would be called when handling Resumed and Paused events. Internally the set_window() method would handle deferring the creation of all render state until the first time set_window() is called, and thereafter would handle just creating a new surface (since the render state should remain valid/reusable).

In the case of egui_winit::State::new() it wouldn't be assumed that max_texture_side or pixels_per_point are known up front and instead there would be setters for both of these that would allow for the max_texture_side to be initialized whenever the gpu context gets (lazily) initialized and pixels_per_point can be explicitly set each time a new native window is created.

The epi and glium apis would then just need updating in line with those lower-level changes.

For reference I have a branch with the above proposed egui_wgpu::Painter and egui_winit::State changes which I've tested on Android (and also on Windows) which I can use to open a draft PR. So far I haven't looked at the epi/glium changes required to really support Android, I just made minimal changes to work with the updated Painter/State APIs.

@rib rib added the bug Something is broken label May 17, 2022
@rib
Copy link
Contributor Author

rib commented May 17, 2022

In case it's helpful to reference here, I've recently pushed an example Android app based on these changes here: https://github.com/rib/agdk-rust/tree/main/examples/agdk-egui

(Note the example is also using a modified Android backend for winit to work with a different 'glue' layer than ndk-glue, but that doesn't affect how native windows are only valid between resume/paused events)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant