From a68c78cef5fb2112617de095efd4e64cba1587eb Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Thu, 21 Jan 2021 13:19:58 +0000 Subject: [PATCH] Use raw-window-handle --- Cargo.toml | 18 ++++++++++--- crates/bevy_wgpu/Cargo.toml | 2 -- crates/bevy_wgpu/src/wgpu_renderer.rs | 21 ++++++---------- crates/bevy_window/Cargo.toml | 1 + crates/bevy_window/src/lib.rs | 3 ++- crates/bevy_window/src/windows.rs | 35 +++++++++++++++++++++++--- crates/bevy_winit/Cargo.toml | 1 + crates/bevy_winit/src/lib.rs | 21 ++++++---------- crates/bevy_winit/src/winit_windows.rs | 22 ++++++++++------ 9 files changed, 80 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ef33fd568e39..36d7ef1c3aaee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,13 @@ default = [ dynamic = ["bevy_dylib"] # Rendering support -render = ["bevy_internal/bevy_pbr", "bevy_internal/bevy_render", "bevy_internal/bevy_sprite", "bevy_internal/bevy_text", "bevy_internal/bevy_ui"] +render = [ + "bevy_internal/bevy_pbr", + "bevy_internal/bevy_render", + "bevy_internal/bevy_sprite", + "bevy_internal/bevy_text", + "bevy_internal/bevy_ui", +] # Optional bevy crates bevy_audio = ["bevy_internal/bevy_audio"] @@ -76,14 +82,14 @@ x11 = ["bevy_internal/x11"] subpixel_glyph_atlas = ["bevy_internal/subpixel_glyph_atlas"] [dependencies] -bevy_dylib = {path = "crates/bevy_dylib", version = "0.4.0", default-features = false, optional = true} -bevy_internal = {path = "crates/bevy_internal", version = "0.4.0", default-features = false} +bevy_dylib = { path = "crates/bevy_dylib", version = "0.4.0", default-features = false, optional = true } +bevy_internal = { path = "crates/bevy_internal", version = "0.4.0", default-features = false } [dev-dependencies] anyhow = "1.0" rand = "0.8.0" ron = "0.6.2" -serde = {version = "1", features = ["derive"]} +serde = { version = "1", features = ["derive"] } [[example]] name = "hello_world" @@ -406,3 +412,7 @@ icon = "@mipmap/ic_launcher" build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"] min_sdk_version = 16 target_sdk_version = 29 + +[patch.crates-io] +# Latest commit breaks the entire ecosystem +raw-window-handle = { git = "https://github.com/rust-windowing/raw-window-handle", rev = "31d91a932c03b81dc0f3e05e4c11aa7a727b799b" } diff --git a/crates/bevy_wgpu/Cargo.toml b/crates/bevy_wgpu/Cargo.toml index 31d9cc1d92698..b859854fb88e2 100644 --- a/crates/bevy_wgpu/Cargo.toml +++ b/crates/bevy_wgpu/Cargo.toml @@ -13,7 +13,6 @@ license = "MIT" keywords = ["bevy"] [features] -default = ["bevy_winit"] trace = ["wgpu/trace"] [dependencies] @@ -25,7 +24,6 @@ bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.4.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" } bevy_render = { path = "../bevy_render", version = "0.4.0" } bevy_window = { path = "../bevy_window", version = "0.4.0" } -bevy_winit = { path = "../bevy_winit", optional = true, version = "0.4.0" } bevy_utils = { path = "../bevy_utils", version = "0.4.0" } # other diff --git a/crates/bevy_wgpu/src/wgpu_renderer.rs b/crates/bevy_wgpu/src/wgpu_renderer.rs index d10fa9a0cafc2..a7bd51f5436b7 100644 --- a/crates/bevy_wgpu/src/wgpu_renderer.rs +++ b/crates/bevy_wgpu/src/wgpu_renderer.rs @@ -8,8 +8,8 @@ use bevy_render::{ render_graph::{DependentNodeStager, RenderGraph, RenderGraphStager}, renderer::RenderResourceContext, }; -use bevy_window::{WindowCreated, WindowResized, Windows}; -use std::{ops::Deref, sync::Arc}; +use bevy_window::{WindowCreated, WindowHandles, WindowResized}; +use std::sync::Arc; pub struct WgpuRenderer { pub instance: wgpu::Instance, @@ -79,22 +79,17 @@ impl WgpuRenderer { let render_resource_context = render_resource_context .downcast_mut::() .unwrap(); - let windows = resources.get::().unwrap(); + let handles = resources.get_thread_local::().unwrap(); let window_created_events = resources.get::>().unwrap(); - for window_created_event in self + for WindowCreated { id } in self .window_created_event_reader .iter(&window_created_events) { - let window = windows - .get(window_created_event.id) + let handle = handles + .get(*id) .expect("Received window created event for non-existent window."); - #[cfg(feature = "bevy_winit")] - { - let winit_windows = resources.get::().unwrap(); - let winit_window = winit_windows.get_window(window.id()).unwrap(); - let surface = unsafe { self.instance.create_surface(winit_window.deref()) }; - render_resource_context.set_window_surface(window.id(), surface); - } + let surface = unsafe { self.instance.create_surface(handle) }; + render_resource_context.set_window_surface(*id, surface); } } diff --git a/crates/bevy_window/Cargo.toml b/crates/bevy_window/Cargo.toml index 6c340562decfe..cb9b8ab3f5f3d 100644 --- a/crates/bevy_window/Cargo.toml +++ b/crates/bevy_window/Cargo.toml @@ -18,6 +18,7 @@ bevy_app = { path = "../bevy_app", version = "0.4.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" } bevy_math = { path = "../bevy_math", version = "0.4.0" } bevy_utils = { path = "../bevy_utils", version = "0.4.0" } +raw-window-handle = "0.3.3" # other diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index 55c46bef8fd6f..16bc0261348be 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -47,7 +47,8 @@ impl Plugin for WindowPlugin { .add_event::() .add_event::() .add_event::() - .init_resource::(); + .init_resource::() + .init_thread_local_resource::(); if self.add_primary_window { let resources = app.resources(); diff --git a/crates/bevy_window/src/windows.rs b/crates/bevy_window/src/windows.rs index a669799b572f9..58348def86695 100644 --- a/crates/bevy_window/src/windows.rs +++ b/crates/bevy_window/src/windows.rs @@ -1,5 +1,6 @@ use super::{Window, WindowId}; use bevy_utils::HashMap; +pub use raw_window_handle::TrustedWindowHandle; #[derive(Debug, Default)] pub struct Windows { @@ -7,10 +8,6 @@ pub struct Windows { } impl Windows { - pub fn add(&mut self, window: Window) { - self.windows.insert(window.id(), window); - } - pub fn get(&self, id: WindowId) -> Option<&Window> { self.windows.get(&id) } @@ -35,3 +32,33 @@ impl Windows { self.windows.values_mut() } } + +#[derive(Default)] +/// A map from [`WindowId`] to [`TrustedWindowHandle`], stored as a thread_local_resource on the main thread. +/// +/// Accessed by graphics backends to allow them to create surfaces for their windows +pub struct WindowHandles { + handles: HashMap, +} + +impl WindowHandles { + pub fn get(&self, id: WindowId) -> Option<&TrustedWindowHandle> { + self.handles.get(&id) + } +} + +// This is the only way to add to windows, which ensures handles and Windows are kept in sync +/// Add a window to the `bevy` windowing system. +/// In general, this should only called by the windowing backend (which is by default provided by `bevy_winit`) +/// +/// To create a window in a bevy application, send a [`crate::CreateWindow`] `Event`. +pub fn create_window( + windows: &mut Windows, + window: Window, + handles: &mut WindowHandles, + handle: TrustedWindowHandle, +) { + let id = window.id(); + windows.windows.insert(id, window); + handles.handles.insert(id, handle); +} diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index f9ef5394d147a..5d21d530fa6a7 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -27,6 +27,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.4.0" } # other winit = { version = "0.24.0", default-features = false } +raw-window-handle = "0.3.3" [target.'cfg(target_arch = "wasm32")'.dependencies] winit = { version = "0.24.0", features = ["web-sys"], default-features = false } diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index f41b1186b6a91..e0eb326565698 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -15,9 +15,9 @@ use bevy_ecs::{IntoSystem, Resources, World}; use bevy_math::Vec2; use bevy_utils::tracing::{error, trace, warn}; use bevy_window::{ - CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter, - WindowBackendScaleFactorChanged, WindowCloseRequested, WindowCreated, WindowFocused, - WindowResized, WindowScaleFactorChanged, Windows, + create_window, CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, + ReceivedCharacter, WindowBackendScaleFactorChanged, WindowCloseRequested, WindowCreated, + WindowFocused, WindowHandles, WindowResized, WindowScaleFactorChanged, Windows, }; use winit::{ event::{self, DeviceEvent, Event, WindowEvent}, @@ -461,17 +461,12 @@ fn handle_create_window_events( ) { let mut winit_windows = resources.get_mut::().unwrap(); let mut windows = resources.get_mut::().unwrap(); + let mut handles = resources.get_thread_local_mut::().unwrap(); let create_window_events = resources.get::>().unwrap(); let mut window_created_events = resources.get_mut::>().unwrap(); - for create_window_event in create_window_event_reader.iter(&create_window_events) { - let window = winit_windows.create_window( - event_loop, - create_window_event.id, - &create_window_event.descriptor, - ); - windows.add(window); - window_created_events.send(WindowCreated { - id: create_window_event.id, - }); + for CreateWindow { id, descriptor } in create_window_event_reader.iter(&create_window_events) { + let (window, handle) = winit_windows.create_window(event_loop, *id, descriptor); + create_window(&mut *windows, window, &mut *handles, handle); + window_created_events.send(WindowCreated { id: *id }); } } diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index d32b4d2e41233..836ebda4d42af 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -1,5 +1,6 @@ use bevy_utils::HashMap; use bevy_window::{Window, WindowDescriptor, WindowId, WindowMode}; +use raw_window_handle::{HasRawWindowHandle, TrustedWindowHandle}; #[derive(Debug, Default)] pub struct WinitWindows { @@ -14,7 +15,7 @@ impl WinitWindows { event_loop: &winit::event_loop::EventLoopWindowTarget<()>, window_id: WindowId, window_descriptor: &WindowDescriptor, - ) -> Window { + ) -> (Window, TrustedWindowHandle) { #[cfg(target_os = "windows")] let mut winit_window_builder = { use winit::platform::windows::WindowBuilderExtWindows; @@ -112,14 +113,21 @@ impl WinitWindows { let inner_size = winit_window.inner_size(); let scale_factor = winit_window.scale_factor(); + // Safety: Winit returns a valid raw window handle + let handle = unsafe { + raw_window_handle::TrustedWindowHandle::new(winit_window.raw_window_handle()) + }; self.windows.insert(winit_window.id(), winit_window); - Window::new( - window_id, - &window_descriptor, - inner_size.width, - inner_size.height, - scale_factor, + ( + Window::new( + window_id, + &window_descriptor, + inner_size.width, + inner_size.height, + scale_factor, + ), + handle, ) }