Skip to content

Commit

Permalink
egui_winit/wgpu: enable Android support (#1634)
Browse files Browse the repository at this point in the history
* egui-winit: don't assume window available at init

On Android in particular we can only initialize render state once we
have a native window, after a 'Resumed' lifecycle event. It's still
practical to be able to initialize an egui_winit::State early on
so this adds setters for the max_texture_side and pixels_per_point
that can be called once we have a valid Window and have initialized
a graphics context.

On Wayland, where we need to access the Display for clipboard handling
we now get the Display from the event loop instead of a window.

* egui-wgpu: lazily initialize render + surface state

Enable the renderer and surface state initialization to be deferred
until we know that any winit window we created has a valid native window
and enable the surface state to be updated in case the native window
changes.

In particular these changes help with running on Android where winit
windows will only have a valid native window associated with them
between Resumed and Paused lifecycle events, and so surface creation
(and render state initialization) needs to wait until the first
Resumed event, and the surface needs to be dropped/recreated based on
Paused/Resumed events.
  • Loading branch information
rib authored May 22, 2022
1 parent fff2008 commit a5076d4
Show file tree
Hide file tree
Showing 14 changed files with 300 additions and 109 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ screen_reader = [
]

# Use WGPU as the backend instead of glow
wgpu = ["egui-wgpu"]
wgpu = ["dep:wgpu", "egui-wgpu"]


[dependencies]
Expand All @@ -68,6 +68,7 @@ egui-wgpu = { version = "0.18.0", path = "../egui-wgpu", optional = true, featur
glow = { version = "0.11", optional = true }
ron = { version = "0.7", optional = true }
serde = { version = "1", optional = true, features = ["derive"] }
wgpu = { version = "0.12", optional = true }

# -------------------------------------------
# native:
Expand Down
11 changes: 9 additions & 2 deletions eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{epi, WindowInfo};
use egui_winit::{native_pixels_per_point, WindowSettings};
use winit::event_loop::EventLoopWindowTarget;

pub fn points_to_size(points: egui::Vec2) -> winit::dpi::LogicalSize<f64> {
winit::dpi::LogicalSize {
Expand Down Expand Up @@ -181,7 +182,8 @@ pub struct EpiIntegration {
}

impl EpiIntegration {
pub fn new(
pub fn new<E>(
event_loop: &EventLoopWindowTarget<E>,
max_texture_side: usize,
window: &winit::window::Window,
storage: Option<Box<dyn epi::Storage>>,
Expand Down Expand Up @@ -213,11 +215,16 @@ impl EpiIntegration {
egui_ctx.set_visuals(egui::Visuals::light());
}

let mut egui_winit = egui_winit::State::new(event_loop);
egui_winit.set_max_texture_side(max_texture_side);
let pixels_per_point = window.scale_factor() as f32;
egui_winit.set_pixels_per_point(pixels_per_point);

Self {
frame,
last_auto_save: std::time::Instant::now(),
egui_ctx,
egui_winit: egui_winit::State::new(max_texture_side, window),
egui_winit,
pending_full_output: Default::default(),
quit: false,
can_drag_window: false,
Expand Down
28 changes: 26 additions & 2 deletions eframe/src/native/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub fn run_glow(
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));

let mut integration = epi_integration::EpiIntegration::new(
&event_loop,
painter.max_texture_side(),
gl_window.window(),
storage,
Expand Down Expand Up @@ -213,11 +214,25 @@ pub fn run_wgpu(
// SAFETY: `window` must outlive `painter`.
#[allow(unsafe_code)]
let mut painter = unsafe {
egui_wgpu::winit::Painter::new(&window, native_options.multisampling.max(1) as _)
let mut painter = egui_wgpu::winit::Painter::new(
wgpu::Backends::PRIMARY | wgpu::Backends::GL,
wgpu::PowerPreference::HighPerformance,
wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::default(),
limits: wgpu::Limits::default(),
},
wgpu::PresentMode::Fifo,
native_options.multisampling.max(1) as _,
);
#[cfg(not(target_os = "android"))]
painter.set_window(Some(&window));
painter
};

let mut integration = epi_integration::EpiIntegration::new(
painter.max_texture_side(),
&event_loop,
painter.max_texture_side().unwrap_or(2048),
&window,
storage,
#[cfg(feature = "glow")]
Expand Down Expand Up @@ -303,6 +318,15 @@ pub fn run_wgpu(
winit::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),

#[cfg(target_os = "android")]
winit::event::Event::Resumed => unsafe {
painter.set_window(Some(&window));
},
#[cfg(target_os = "android")]
winit::event::Event::Paused => unsafe {
painter.set_window(None);
},

winit::event::Event::WindowEvent { event, .. } => {
match &event {
winit::event::WindowEvent::Focused(new_focused) => {
Expand Down
2 changes: 1 addition & 1 deletion egui-wgpu/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ All notable changes to the `egui-wgpu` integration will be noted in this file.


## Unreleased

Enables deferred render + surface state initialization for Android ([#1634](https://github.com/emilk/egui/pull/1634))

## 0.18.0 - 2022-05-15
First published version since moving the code into the `egui` repository from <https://github.com/LU15W1R7H/eww>.
Loading

0 comments on commit a5076d4

Please sign in to comment.