Fix multi-window example for Glutin on MacOS
This commit is contained in:
parent
f43419d475
commit
1944e98f82
3 changed files with 90 additions and 75 deletions
|
|
@ -24,8 +24,6 @@ version = "0.4"
|
||||||
|
|
||||||
[dependencies.glutin]
|
[dependencies.glutin]
|
||||||
version = "0.30"
|
version = "0.30"
|
||||||
git = "https://github.com/derezzedex/glutin"
|
|
||||||
rev = "2a2a97209c49929027beced68e1989b8486bdec9"
|
|
||||||
|
|
||||||
[dependencies.iced_native]
|
[dependencies.iced_native]
|
||||||
version = "0.7"
|
version = "0.7"
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,11 @@ use glutin::config::{
|
||||||
};
|
};
|
||||||
use glutin::context::{
|
use glutin::context::{
|
||||||
ContextApi, ContextAttributesBuilder, NotCurrentContext,
|
ContextApi, ContextAttributesBuilder, NotCurrentContext,
|
||||||
NotCurrentGlContextSurfaceAccessor,
|
NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext,
|
||||||
PossiblyCurrentContextGlSurfaceAccessor, PossiblyCurrentGlContext,
|
|
||||||
};
|
};
|
||||||
use glutin::display::{Display, DisplayApiPreference, GlDisplay};
|
use glutin::display::{Display, DisplayApiPreference, GlDisplay};
|
||||||
use glutin::surface::{
|
use glutin::surface::{
|
||||||
GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface,
|
GlSurface, Surface, SurfaceAttributesBuilder, SwapInterval, WindowSurface,
|
||||||
};
|
};
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||||
|
|
||||||
|
|
@ -240,42 +239,19 @@ where
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let (width, height) = window.inner_size().into();
|
let surface = gl_surface(&display, configuration.as_ref(), &window);
|
||||||
let surface_attributes =
|
|
||||||
SurfaceAttributesBuilder::<WindowSurface>::new()
|
|
||||||
.with_srgb(Some(true))
|
|
||||||
.build(
|
|
||||||
window_handle,
|
|
||||||
NonZeroU32::new(width).unwrap_or(ONE),
|
|
||||||
NonZeroU32::new(height).unwrap_or(ONE),
|
|
||||||
);
|
|
||||||
|
|
||||||
let surface = display
|
|
||||||
.create_window_surface(configuration.as_ref(), &surface_attributes)
|
|
||||||
.map_err(|error| {
|
|
||||||
Error::GraphicsCreationFailed(
|
|
||||||
iced_graphics::Error::BackendError(format!(
|
|
||||||
"failed to create surface: {error}"
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let context = {
|
|
||||||
context
|
|
||||||
.make_current(&surface)
|
|
||||||
.expect("make context current")
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(error) = surface.set_swap_interval(
|
|
||||||
&context,
|
|
||||||
glutin::surface::SwapInterval::Wait(ONE),
|
|
||||||
) {
|
|
||||||
log::error!("set swap interval failed: {}", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
(display, window, configuration.0, surface, context)
|
(display, window, configuration.0, surface, context)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let windows: HashMap<window::Id, winit::window::Window> =
|
||||||
|
HashMap::from([(window::Id::MAIN, window)]);
|
||||||
|
|
||||||
|
// need to make context current before trying to load GL functions
|
||||||
|
let context = context
|
||||||
|
.make_current(&surface)
|
||||||
|
.expect("Make context current.");
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
let (compositor, renderer) = unsafe {
|
let (compositor, renderer) = unsafe {
|
||||||
C::new(compositor_settings, |address| {
|
C::new(compositor_settings, |address| {
|
||||||
|
|
@ -284,7 +260,7 @@ where
|
||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
|
|
||||||
let context = { context.make_not_current().expect("make context current") };
|
let context = context.make_not_current().expect("Make not current.");
|
||||||
|
|
||||||
let (mut sender, receiver) = mpsc::unbounded();
|
let (mut sender, receiver) = mpsc::unbounded();
|
||||||
|
|
||||||
|
|
@ -297,9 +273,8 @@ where
|
||||||
debug,
|
debug,
|
||||||
receiver,
|
receiver,
|
||||||
display,
|
display,
|
||||||
window,
|
windows,
|
||||||
configuration,
|
configuration,
|
||||||
surface,
|
|
||||||
context,
|
context,
|
||||||
init_command,
|
init_command,
|
||||||
settings.exit_on_close_request,
|
settings.exit_on_close_request,
|
||||||
|
|
@ -370,10 +345,9 @@ async fn run_instance<A, E, C>(
|
||||||
winit::event::Event<'_, Event<A::Message>>,
|
winit::event::Event<'_, Event<A::Message>>,
|
||||||
>,
|
>,
|
||||||
display: Display,
|
display: Display,
|
||||||
window: winit::window::Window,
|
mut windows: HashMap<window::Id, winit::window::Window>,
|
||||||
configuration: Config,
|
configuration: Config,
|
||||||
surface: Surface<WindowSurface>,
|
mut context: NotCurrentContext,
|
||||||
context: NotCurrentContext,
|
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
_exit_on_close_request: bool,
|
_exit_on_close_request: bool,
|
||||||
) where
|
) where
|
||||||
|
|
@ -385,34 +359,48 @@ async fn run_instance<A, E, C>(
|
||||||
use iced_winit::futures::stream::StreamExt;
|
use iced_winit::futures::stream::StreamExt;
|
||||||
use winit::event;
|
use winit::event;
|
||||||
|
|
||||||
let context = {
|
let mut clipboard =
|
||||||
context
|
Clipboard::connect(windows.values().next().expect("No window found"));
|
||||||
.make_current(&surface)
|
|
||||||
.expect("make context current")
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut clipboard = Clipboard::connect(&window);
|
|
||||||
let mut cache = user_interface::Cache::default();
|
let mut cache = user_interface::Cache::default();
|
||||||
let state = State::new(&application, &window);
|
let mut current_context_window = None;
|
||||||
let user_interface = multi_window::build_user_interface(
|
let mut window_ids: HashMap<_, _> = windows
|
||||||
&application,
|
.iter()
|
||||||
user_interface::Cache::default(),
|
.map(|(&id, window)| (window.id(), id))
|
||||||
&mut renderer,
|
.collect();
|
||||||
state.logical_size(),
|
let mut states = HashMap::new();
|
||||||
&mut debug,
|
let mut surfaces = HashMap::new();
|
||||||
window::Id::MAIN,
|
let mut interfaces = ManuallyDrop::new(HashMap::new());
|
||||||
);
|
|
||||||
|
|
||||||
let mut current_context_window = window.id();
|
for (&id, window) in windows.keys().zip(windows.values()) {
|
||||||
let mut window_ids = HashMap::from([(window.id(), window::Id::MAIN)]);
|
let surface = gl_surface(&display, &configuration, &window);
|
||||||
let mut windows = HashMap::from([(window::Id::MAIN, window)]);
|
let current_context = context.make_current(&surface).expect("Make current.");
|
||||||
let mut surfaces = HashMap::from([(window::Id::MAIN, surface)]);
|
let state = State::new(&application, &window);
|
||||||
let mut states = HashMap::from([(window::Id::MAIN, state)]);
|
let physical_size = state.physical_size();
|
||||||
let mut interfaces =
|
|
||||||
ManuallyDrop::new(HashMap::from([(window::Id::MAIN, user_interface)]));
|
surface.resize(
|
||||||
|
¤t_context,
|
||||||
|
NonZeroU32::new(physical_size.width).unwrap_or(ONE),
|
||||||
|
NonZeroU32::new(physical_size.height).unwrap_or(ONE),
|
||||||
|
);
|
||||||
|
|
||||||
|
let user_interface = multi_window::build_user_interface(
|
||||||
|
&application,
|
||||||
|
user_interface::Cache::default(),
|
||||||
|
&mut renderer,
|
||||||
|
state.logical_size(),
|
||||||
|
&mut debug,
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
|
||||||
|
context = current_context.make_not_current().expect("Make not current.");
|
||||||
|
|
||||||
|
let _ = states.insert(id, state);
|
||||||
|
let _ = surfaces.insert(id, surface);
|
||||||
|
let _ = interfaces.insert(id, user_interface);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let state = states.get(&window::Id::MAIN).unwrap();
|
let state = states.values().next().expect("No state found.");
|
||||||
|
|
||||||
run_command(
|
run_command(
|
||||||
&application,
|
&application,
|
||||||
|
|
@ -653,12 +641,11 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
debug.render_started();
|
debug.render_started();
|
||||||
|
|
||||||
if current_context_window != id {
|
let current_context =
|
||||||
context
|
context.make_current(&surface).expect("Make current.");
|
||||||
.make_current(&surface)
|
|
||||||
.expect("Make OpenGL context current");
|
|
||||||
|
|
||||||
current_context_window = id;
|
if current_context_window != Some(id) {
|
||||||
|
current_context_window = Some(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.viewport_changed() {
|
if state.viewport_changed() {
|
||||||
|
|
@ -695,11 +682,17 @@ async fn run_instance<A, E, C>(
|
||||||
}
|
}
|
||||||
|
|
||||||
surface.resize(
|
surface.resize(
|
||||||
&context,
|
¤t_context,
|
||||||
NonZeroU32::new(physical_size.width).unwrap_or(ONE),
|
NonZeroU32::new(physical_size.width).unwrap_or(ONE),
|
||||||
NonZeroU32::new(physical_size.height).unwrap_or(ONE),
|
NonZeroU32::new(physical_size.height).unwrap_or(ONE),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Err(error) =
|
||||||
|
surface.set_swap_interval(¤t_context, SwapInterval::Wait(ONE))
|
||||||
|
{
|
||||||
|
log::error!("Could not set swap interval for surface attached to window id: {:?}", id);
|
||||||
|
}
|
||||||
|
|
||||||
compositor.resize_viewport(physical_size);
|
compositor.resize_viewport(physical_size);
|
||||||
|
|
||||||
let _ = interfaces
|
let _ = interfaces
|
||||||
|
|
@ -713,10 +706,10 @@ async fn run_instance<A, E, C>(
|
||||||
&debug.overlay(),
|
&debug.overlay(),
|
||||||
);
|
);
|
||||||
|
|
||||||
surface.swap_buffers(&context).expect("Swap buffers");
|
surface.swap_buffers(¤t_context).expect("Swap buffers");
|
||||||
|
|
||||||
|
context = current_context.make_not_current().expect("Make not current.");
|
||||||
debug.render_finished();
|
debug.render_finished();
|
||||||
|
|
||||||
// TODO: Handle animations!
|
// TODO: Handle animations!
|
||||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||||
}
|
}
|
||||||
|
|
@ -1038,3 +1031,26 @@ where
|
||||||
|
|
||||||
interfaces
|
interfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn gl_surface(
|
||||||
|
display: &Display,
|
||||||
|
gl_config: &Config,
|
||||||
|
window: &winit::window::Window,
|
||||||
|
) -> Surface<WindowSurface> {
|
||||||
|
let (width, height) = window.inner_size().into();
|
||||||
|
|
||||||
|
let surface_attributes = SurfaceAttributesBuilder::<WindowSurface>::new()
|
||||||
|
.with_srgb(Some(true))
|
||||||
|
.build(
|
||||||
|
window.raw_window_handle(),
|
||||||
|
NonZeroU32::new(width).unwrap_or(ONE),
|
||||||
|
NonZeroU32::new(height).unwrap_or(ONE),
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
display
|
||||||
|
.create_window_surface(gl_config, &surface_attributes)
|
||||||
|
.expect("failed to create surface")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,7 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
for (&id, window) in windows.keys().zip(windows.values()) {
|
for (&id, window) in windows.keys().zip(windows.values()) {
|
||||||
let mut surface = compositor.create_surface(window);
|
let mut surface = compositor.create_surface(window);
|
||||||
|
println!("Creating surface for window: {:?}", window);
|
||||||
|
|
||||||
let state = State::new(&application, window);
|
let state = State::new(&application, window);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue