Skip to content

Commit

Permalink
keep Bevy window, only recreate Winit window and wgpu surface
Browse files Browse the repository at this point in the history
  • Loading branch information
mockersf committed Sep 29, 2023
1 parent 523ea85 commit 0330fed
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
14 changes: 14 additions & 0 deletions crates/bevy_render/src/view/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ fn extract_windows(
screenshot_manager: Extract<Res<ScreenshotManager>>,
mut closed: Extract<EventReader<WindowClosed>>,
windows: Extract<Query<(Entity, &Window, &RawHandleWrapper, Option<&PrimaryWindow>)>>,
mut removed: Extract<RemovedComponents<RawHandleWrapper>>,
mut window_surfaces: ResMut<WindowSurfaces>,
) {
for (entity, window, handle, primary) in windows.iter() {
if primary.is_some() {
Expand Down Expand Up @@ -163,6 +165,11 @@ fn extract_windows(

for closed_window in closed.read() {
extracted_windows.remove(&closed_window.window);
window_surfaces.remove(&closed_window.window);
}
for removed_window in removed.read() {
extracted_windows.remove(&removed_window);
window_surfaces.remove(&removed_window);
}
// This lock will never block because `callbacks` is `pub(crate)` and this is the singular callsite where it's locked.
// Even if a user had multiple copies of this system, since the system has a mutable resource access the two systems would never run
Expand All @@ -187,6 +194,13 @@ pub struct WindowSurfaces {
configured_windows: HashSet<Entity>,
}

impl WindowSurfaces {
fn remove(&mut self, window: &Entity) {
self.surfaces.remove(window);
self.configured_windows.remove(window);
}
}

/// Creates and (re)configures window surfaces, and obtains a swapchain texture for rendering.
///
/// NOTE: `get_current_texture` in `prepare_windows` can take a long time if the GPU workload is
Expand Down
50 changes: 41 additions & 9 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,6 @@ pub fn winit_runner(mut app: App) {

let mut runner_state = WinitAppRunnerState::default();

#[cfg(target_os = "android")]
let mut primary_window = None;

// prepare structures to access data in the world
let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
let mut redraw_event_reader = ManualEventReader::<RequestRedraw>::default();
Expand Down Expand Up @@ -669,19 +666,54 @@ pub fn winit_runner(mut app: App) {
runner_state.is_active = false;
#[cfg(target_os = "android")]
{
let mut query = app.world.query::<(Entity, &Window)>();
let (entity, window) = query.single(&app.world);
primary_window = Some(window.clone());
app.world.despawn(entity);
// Remove the `RawHandleWrapper` from the primary window.
// This will trigger the surface destruction.
let mut query = app.world.query_filtered::<Entity, With<PrimaryWindow>>();
let entity = query.single(&app.world);
app.world
.entity_mut(entity)
.remove::<bevy_window::RawHandleWrapper>();
*control_flow = ControlFlow::Wait;
}
}
event::Event::Resumed => {
runner_state.is_active = true;
#[cfg(target_os = "android")]
{
if let Some(window) = primary_window.take() {
app.world.spawn((window, PrimaryWindow));
// Get windows that are cached but without raw handles. Those window were already created, but got their
// handle wrapper removed when the app was suspended.
let mut query = app
.world
.query_filtered::<(Entity, &Window), (With<CachedWindow>, Without<bevy_window::RawHandleWrapper>)>();
if let Ok((entity, window)) = query.get_single(&app.world) {
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
let window = window.clone();

let (
_,
_,
_,
mut winit_windows,
mut adapters,
mut handlers,
accessibility_requested,
) = create_window_system_state.get_mut(&mut app.world);

let winit_window = winit_windows.create_window(
event_loop,
entity,
&window,
&mut adapters,
&mut handlers,
&accessibility_requested,
);

let wrapper = bevy_window::RawHandleWrapper {
window_handle: winit_window.raw_window_handle(),
display_handle: winit_window.raw_display_handle(),
};

app.world.entity_mut(entity).insert(wrapper);
}
*control_flow = ControlFlow::Poll;
}
Expand Down
3 changes: 0 additions & 3 deletions examples/mobile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ use bevy::{input::touch::TouchPhase, prelude::*, window::WindowMode};
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins.set(WindowPlugin {
// On Android, the entity with this window will be despawned when the application is suspended
// and respawned when it is resumed. The entity will change each time, and any extra component
// will be lost.
primary_window: Some(Window {
resizable: false,
mode: WindowMode::BorderlessFullscreen,
Expand Down

0 comments on commit 0330fed

Please sign in to comment.