Verified Commit 734dd7be authored by insert's avatar insert

Switch to glutin.

parent 8fcf62bf
......@@ -7,6 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sdl2 = { version = "0.33.0", features = ["bundled", "static-link"] }
gl = "0.14.0"
hashbrown = "0.7.2"
glutin = "0.24.0"
takeable-option = "0.5.0"
gl = "0.14.0"
use byol;
use byol::native::Event;
use byol::render::mesh::MeshData;
use byol::render::shader::{Program, Shader, ShaderType};
use byol::native::Event;
fn main() {
let mut sdl = byol::native::Sdl::new(None).unwrap();
let mut win = sdl.create_window(None).unwrap();
let mut byol = byol::native::Byol::new().unwrap();
let win = byol.create_window(None).unwrap();
let shader = Program::from_shaders(&vec![
Shader::from_string(ShaderType::VERTEX, include_str!("vertex.glsl").to_string()).unwrap(),
......@@ -16,8 +16,34 @@ fn main() {
let mesh = MeshData::new()
.vertex(vec![-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0])
.create();
let win2 = byol.create_window(None).unwrap();
let shader2 = Program::from_shaders(&vec![
Shader::from_string(ShaderType::VERTEX, include_str!("vertex.glsl").to_string()).unwrap(),
Shader::from_string(ShaderType::FRAGMENT, include_str!("frag.glsl").to_string()).unwrap(),
])
.unwrap();
let mesh2 = MeshData::new()
.vertex(vec![-0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, -0.5, 0.0])
.create();
byol.run(move |event| {
match event {
Event::Draw{ window_id, .. } => {
if &window_id == win.id() {
shader.enable();
mesh.draw();
} else if &window_id == win2.id() {
shader2.enable();
mesh2.draw();
}
}
}
});
'main: loop {
/*'main: loop {
while let Some(event) = sdl.take_event() {
match event {
Event::Quit { .. } => break 'main,
......@@ -32,5 +58,5 @@ fn main() {
mesh.draw();
win.swap();
}
}*/
}
use super::window::{Window, WindowOptions};
use super::ct::ContextTracker;
pub use sdl2;
pub use sdl2::event::Event;
pub use sdl2::keyboard::Keycode;
use hashbrown::HashMap;
use glutin::event_loop::EventLoop;
use glutin::event::{WindowEvent};
use glutin::window::WindowId;
pub struct SdlOptions {
pub struct ByolOptions {
swap_after_draw: bool
}
/*pub struct SdlOptions {
gl_context_profile: sdl2::video::GLProfile,
gl_major_version: u8,
gl_minor_version: u8,
......@@ -29,17 +35,32 @@ impl SdlOptions {
self.gl_major_version = minor;
self
}
}*/
use glutin::{PossiblyCurrent};
use super::ct::ContextWrapper;
/*pub struct DrawEvent<'a> {
pub window_id: WindowId,
pub ctx: &'a mut ContextWrapper<PossiblyCurrent>
}*/
pub enum Event<'a> {
Draw {
window_id: WindowId,
ctx: &'a mut ContextWrapper<PossiblyCurrent>
}
}
pub struct Sdl {
sdl: sdl2::Sdl,
pub video: sdl2::VideoSubsystem,
event_pump: sdl2::EventPump,
pub struct Byol {
event_loop: EventLoop<()>,
context_tracker: ContextTracker,
window_context: HashMap<WindowId, usize>
}
impl Sdl {
pub fn new<O: Into<Option<SdlOptions>>>(options: O) -> Result<Sdl, String> {
let options = options.into().unwrap_or(SdlOptions::new());
impl Byol {
pub fn new() -> Result<Byol, String> {
/*let options = options.into().unwrap_or(SdlOptions::new());
let sdl = sdl2::init()?;
let video = sdl.video()?;
......@@ -53,23 +74,73 @@ impl Sdl {
sdl,
video,
event_pump,
})*/
let event_loop = EventLoop::new();
let context_tracker = ContextTracker::default();
let window_context = HashMap::new();
Ok(Byol {
event_loop,
context_tracker,
window_context
})
}
pub fn create_window<O: Into<Option<WindowOptions<'static>>>>(
&self,
&mut self,
options: O,
) -> Result<Window, String> {
Window::new(self, options)
}
pub fn take_event(&mut self) -> Option<Event> {
self.event_pump.poll_event()
pub fn el(&self) -> &EventLoop<()> {
&self.event_loop
}
pub fn ct(&mut self) -> &mut ContextTracker {
&mut self.context_tracker
}
pub fn register_window(&mut self, window: WindowId, ctx_id: usize) {
self.window_context.insert(window, ctx_id);
}
pub fn run<F: FnMut(Event) + 'static>(self, mut func: F) {
let win_ctx = self.window_context;
let mut ctx_tracker = self.context_tracker;
self.event_loop.run(move |event, _, control_flow| {
println!("{:?}", event);
match event {
glutin::event::Event::LoopDestroyed => return,
glutin::event::Event::WindowEvent { event, window_id } => match event {
WindowEvent::Resized(physical_size) => {
//
}
WindowEvent::CloseRequested => {
//
}
_ => (),
},
glutin::event::Event::RedrawRequested(window_id) => {
let ctx_id = win_ctx.get(&window_id).unwrap().clone();
let mut ctx = ctx_tracker.get_current(ctx_id).unwrap();
func(Event::Draw { window_id, ctx });
ctx.windowed().swap_buffers().unwrap();
}
_ => (),
}
});
}
/*pub fn take_event(&mut self) -> Option<Event> {
self.event_pump.poll_event()
}*/
}
impl Drop for Sdl {
/*impl Drop for Sdl {
fn drop(&mut self) {
self.video.gl_unload_library();
}
}
}*/
use glutin::{self, PossiblyCurrent};
pub use self::context_tracker::{ContextCurrentWrapper, ContextId, ContextTracker, ContextWrapper};
mod context_tracker {
use glutin::{
self, Context, ContextCurrentState, ContextError, NotCurrent, PossiblyCurrent,
WindowedContext,
};
use takeable_option::Takeable;
pub enum ContextWrapper<T: ContextCurrentState> {
Headless(Context<T>),
Windowed(WindowedContext<T>),
}
impl<T: ContextCurrentState> ContextWrapper<T> {
pub fn headless(&mut self) -> &mut Context<T> {
match self {
ContextWrapper::Headless(ref mut ctx) => ctx,
_ => panic!(),
}
}
pub fn windowed(&mut self) -> &mut WindowedContext<T> {
match self {
ContextWrapper::Windowed(ref mut ctx) => ctx,
_ => panic!(),
}
}
fn map<T2: ContextCurrentState, FH, FW>(
self,
fh: FH,
fw: FW,
) -> Result<ContextWrapper<T2>, (Self, ContextError)>
where
FH: FnOnce(Context<T>) -> Result<Context<T2>, (Context<T>, ContextError)>,
FW: FnOnce(
WindowedContext<T>,
)
-> Result<WindowedContext<T2>, (WindowedContext<T>, ContextError)>,
{
match self {
ContextWrapper::Headless(ctx) => match fh(ctx) {
Ok(ctx) => Ok(ContextWrapper::Headless(ctx)),
Err((ctx, err)) => Err((ContextWrapper::Headless(ctx), err)),
},
ContextWrapper::Windowed(ctx) => match fw(ctx) {
Ok(ctx) => Ok(ContextWrapper::Windowed(ctx)),
Err((ctx, err)) => Err((ContextWrapper::Windowed(ctx), err)),
},
}
}
}
pub enum ContextCurrentWrapper {
PossiblyCurrent(ContextWrapper<PossiblyCurrent>),
NotCurrent(ContextWrapper<NotCurrent>),
}
impl ContextCurrentWrapper {
fn map_possibly<F>(self, f: F) -> Result<Self, (Self, ContextError)>
where
F: FnOnce(
ContextWrapper<PossiblyCurrent>,
) -> Result<
ContextWrapper<NotCurrent>,
(ContextWrapper<PossiblyCurrent>, ContextError),
>,
{
match self {
ret @ ContextCurrentWrapper::NotCurrent(_) => Ok(ret),
ContextCurrentWrapper::PossiblyCurrent(ctx) => match f(ctx) {
Ok(ctx) => Ok(ContextCurrentWrapper::NotCurrent(ctx)),
Err((ctx, err)) => Err((ContextCurrentWrapper::PossiblyCurrent(ctx), err)),
},
}
}
fn map_not<F>(self, f: F) -> Result<Self, (Self, ContextError)>
where
F: FnOnce(
ContextWrapper<NotCurrent>,
) -> Result<
ContextWrapper<PossiblyCurrent>,
(ContextWrapper<NotCurrent>, ContextError),
>,
{
match self {
ret @ ContextCurrentWrapper::PossiblyCurrent(_) => Ok(ret),
ContextCurrentWrapper::NotCurrent(ctx) => match f(ctx) {
Ok(ctx) => Ok(ContextCurrentWrapper::PossiblyCurrent(ctx)),
Err((ctx, err)) => Err((ContextCurrentWrapper::NotCurrent(ctx), err)),
},
}
}
}
pub type ContextId = usize;
#[derive(Default)]
pub struct ContextTracker {
current: Option<ContextId>,
others: Vec<(ContextId, Takeable<ContextCurrentWrapper>)>,
next_id: ContextId,
}
impl ContextTracker {
pub fn insert(&mut self, ctx: ContextCurrentWrapper) -> ContextId {
let id = self.next_id;
self.next_id += 1;
if let ContextCurrentWrapper::PossiblyCurrent(_) = ctx {
if let Some(old_current) = self.current {
unsafe {
self.modify(old_current, |ctx| {
ctx.map_possibly(|ctx| {
ctx.map(
|ctx| Ok(ctx.treat_as_not_current()),
|ctx| Ok(ctx.treat_as_not_current()),
)
})
})
.unwrap()
}
}
self.current = Some(id);
}
self.others.push((id, Takeable::new(ctx)));
id
}
pub fn remove(&mut self, id: ContextId) -> ContextCurrentWrapper {
if Some(id) == self.current {
self.current.take();
}
let this_index = self
.others
.binary_search_by(|(sid, _)| sid.cmp(&id))
.unwrap();
Takeable::take(&mut self.others.remove(this_index).1)
}
fn modify<F>(&mut self, id: ContextId, f: F) -> Result<(), ContextError>
where
F: FnOnce(
ContextCurrentWrapper,
)
-> Result<ContextCurrentWrapper, (ContextCurrentWrapper, ContextError)>,
{
let this_index = self
.others
.binary_search_by(|(sid, _)| sid.cmp(&id))
.unwrap();
let this_context = Takeable::take(&mut self.others[this_index].1);
match f(this_context) {
Err((ctx, err)) => {
self.others[this_index].1 = Takeable::new(ctx);
Err(err)
}
Ok(ctx) => {
self.others[this_index].1 = Takeable::new(ctx);
Ok(())
}
}
}
pub fn get_current(
&mut self,
id: ContextId,
) -> Result<&mut ContextWrapper<PossiblyCurrent>, ContextError> {
unsafe {
let this_index = self
.others
.binary_search_by(|(sid, _)| sid.cmp(&id))
.unwrap();
if Some(id) != self.current {
let old_current = self.current.take();
if let Err(err) = self.modify(id, |ctx| {
ctx.map_not(|ctx| {
ctx.map(|ctx| ctx.make_current(), |ctx| ctx.make_current())
})
}) {
// Oh noes, something went wrong
// Let's at least make sure that no context is current.
if let Some(old_current) = old_current {
if let Err(err2) = self.modify(old_current, |ctx| {
ctx.map_possibly(|ctx| {
ctx.map(
|ctx| ctx.make_not_current(),
|ctx| ctx.make_not_current(),
)
})
}) {
panic!(
"Could not `make_current` nor `make_not_current`, {:?}, {:?}",
err, err2
);
}
}
if let Err(err2) = self.modify(id, |ctx| {
ctx.map_possibly(|ctx| {
ctx.map(|ctx| ctx.make_not_current(), |ctx| ctx.make_not_current())
})
}) {
panic!(
"Could not `make_current` nor `make_not_current`, {:?}, {:?}",
err, err2
);
}
return Err(err);
}
self.current = Some(id);
if let Some(old_current) = old_current {
self.modify(old_current, |ctx| {
ctx.map_possibly(|ctx| {
ctx.map(
|ctx| Ok(ctx.treat_as_not_current()),
|ctx| Ok(ctx.treat_as_not_current()),
)
})
})
.unwrap();
}
}
match *self.others[this_index].1 {
ContextCurrentWrapper::PossiblyCurrent(ref mut ctx) => Ok(ctx),
ContextCurrentWrapper::NotCurrent(_) => panic!(),
}
}
}
}
}
pub mod sdl;
pub mod ct;
pub mod byol;
pub mod viewport;
pub mod window;
pub use sdl::*;
pub use byol::*;
pub use window::*;
use super::sdl::Sdl;
use super::Byol;
use super::viewport::Viewport;
use super::ct::{ContextCurrentWrapper, ContextWrapper};
use sdl2::video::WindowBuildError;
use glutin::window::{WindowBuilder};
use glutin::ContextBuilder;
use glutin::{self};
use glutin::window::WindowId;
use gl;
pub struct WindowOptions<'a> {
pub title: &'a str,
......@@ -59,19 +65,22 @@ impl<'a> WindowOptions<'a> {
}
pub struct Window {
instance: sdl2::video::Window,
_context: sdl2::video::GLContext,
id: WindowId,
ctx_id: usize,
//ctx: ContextWrapper<PossiblyCurrent, glutin::window::Window>,
//instance: sdl2::video::Window,
//_context: sdl2::video::GLContext,
viewport: Viewport,
}
impl Window {
pub fn new<O: Into<Option<WindowOptions<'static>>>>(
sdl: &Sdl,
byol: &mut Byol,
options: O,
) -> Result<Window, String> {
let options = options.into().unwrap_or(WindowOptions::new());
let mut builder = sdl
/*let mut builder = sdl
.video
.window(options.title, options.width, options.height);
......@@ -104,7 +113,21 @@ impl Window {
};
let _context = instance.gl_create_context()?;
gl::load_with(|s| sdl.video.gl_get_proc_address(s) as *const std::os::raw::c_void);
gl::load_with(|s| sdl.video.gl_get_proc_address(s) as *const std::os::raw::c_void);*/
let wb = WindowBuilder::new().with_title(options.title);
let ctx = ContextBuilder::new().build_windowed(wb, &byol.el()).unwrap();
let ctx = unsafe { ctx.make_current().unwrap() };
let id = ctx.window().id();
let _gl = gl::load_with(|ptr| ctx.context().get_proc_address(ptr) as *const _);
let ctx_id = byol.ct().insert(ContextCurrentWrapper::PossiblyCurrent(
ContextWrapper::Windowed(ctx),
));
byol.register_window(id, ctx_id);
unsafe {
gl::ClearColor(
......@@ -119,13 +142,19 @@ impl Window {
viewport.enable();
Ok(Window {
instance,
_context,
id,
ctx_id,
//instance,
//_context,
viewport,
})
}
pub fn on_event(&mut self, ev: sdl2::event::WindowEvent) {
pub fn id(&self) -> &WindowId {
&self.id
}
/*pub fn on_event(&mut self, ev: sdl2::event::WindowEvent) {
match ev {
sdl2::event::WindowEvent::Resized(w, h) => {
self.viewport.update_size(w, h);
......@@ -133,7 +162,17 @@ impl Window {
}
_ => {}
}
}
}*/
/*pub fn enable(self) -> Result<(), String> {
unsafe {
if let Ok(ctx) = self.ctx.make_current() {
Ok(())
} else {
Err("Failed to switch context.".to_string())
}
}
}*/
pub fn clear(&self) {
unsafe {
......@@ -141,9 +180,10 @@ impl Window {
}
}
pub fn swap(&self) {
self.instance.gl_swap_window();
}
//pub fn swap(&self) -> Result<(), ContextError> {
//self.ctx.swap_buffers()
//self.instance.gl_swap_window();
//}
pub fn enable_viewport(&self) {
self.viewport.enable();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment