1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-27 23:13:13 -04:00

egui_winit/wgpu: enable Android support (#1634)

* 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.
This commit is contained in:
Robert Bragg
2022-05-22 19:24:41 +01:00
committed by GitHub
parent fff2008255
commit a5076d4cc4
14 changed files with 300 additions and 109 deletions

View File

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

View File

@@ -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,
@@ -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")]
@@ -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) => {