Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiwindow Example #10

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ core-foundation = "0.9.1"

[dev-dependencies]
gl = "0.14.0"
winit = "0.22.2"
winit = "0.24"
sdl2 = { version = "0.34", features = ["raw-window-handle", "bundled"] }
62 changes: 62 additions & 0 deletions examples/multiwindow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use raw_gl_context::{GlConfig, GlContext};

use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;

fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
let window2 = WindowBuilder::new().build(&event_loop).unwrap();

let context = GlContext::create(&window, GlConfig::default(), None).unwrap();
let context2 = GlContext::create(&window2, GlConfig::default(), Some(&context)).unwrap();

context.make_current();

gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);

let now = std::time::Instant::now();

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;

match event {
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
winit::event::Event::MainEventsCleared => {
window.request_redraw();
}
winit::event::Event::RedrawRequested(_) => {
context.make_current();

unsafe {
gl::ClearColor(now.elapsed().as_secs_f32().sin() * 0.5 + 0.5, 0.0, 1.0, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
}

context.swap_buffers();
context.make_not_current();

context2.make_current();

unsafe {
gl::ClearColor(
1.0 - (now.elapsed().as_secs_f32().sin() * 0.5 + 0.5),
0.0,
1.0,
1.0,
);
gl::Clear(gl::COLOR_BUFFER_BIT);
}

context2.swap_buffers();
context2.make_not_current();
}
_ => {}
}
});
}
55 changes: 55 additions & 0 deletions examples/sdl2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use raw_gl_context::{GlConfig, GlContext};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub fn main() {
// Setup SDL
let sdl2_context = sdl2::init().expect("Failed to initialize sdl2");
let video_subsystem = sdl2_context
.video()
.expect("Failed to create sdl video subsystem");

// Create the window
let window = video_subsystem
.window("SDL2 GL Example", 900, 600)
.position_centered()
.allow_highdpi()
.resizable()
.build()
.expect("Failed to create window");

let mut event_pump = sdl2_context
.event_pump()
.expect("Could not create sdl event pump");

let gl_context = GlContext::create(&window, GlConfig::default(), None).unwrap();

gl_context.make_current();

gl::load_with(|symbol| gl_context.get_proc_address(symbol) as *const _);

let now = std::time::Instant::now();

'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. } => break 'running,
Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'running,
_ => {}
}
}

gl_context.make_current();

unsafe {
gl::ClearColor(now.elapsed().as_secs_f32().sin() * 0.5 + 0.5, 0.0, 1.0, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
}

gl_context.swap_buffers();
gl_context.make_not_current();
}
}
11 changes: 8 additions & 3 deletions examples/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();

let context = GlContext::create(&window, GlConfig::default()).unwrap();
let context = GlContext::create(&window, GlConfig::default(), None).unwrap();

context.make_current();

gl::load_with(|symbol| context.get_proc_address(symbol) as *const _);

let now = std::time::Instant::now();

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
*control_flow = ControlFlow::Poll;

match event {
winit::event::Event::WindowEvent {
Expand All @@ -23,11 +25,14 @@ fn main() {
} => {
*control_flow = ControlFlow::Exit;
}
winit::event::Event::MainEventsCleared => {
window.request_redraw();
}
winit::event::Event::RedrawRequested(_) => {
context.make_current();

unsafe {
gl::ClearColor(1.0, 0.0, 1.0, 1.0);
gl::ClearColor(now.elapsed().as_secs_f32().sin() * 0.5 + 0.5, 0.0, 1.0, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
}

Expand Down
11 changes: 7 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,15 @@ pub struct GlContext {

impl GlContext {
pub fn create(
parent: &impl HasRawWindowHandle,
parent: &dyn HasRawWindowHandle,
config: GlConfig,
share: Option<&GlContext>,
) -> Result<GlContext, GlError> {
platform::GlContext::create(parent, config).map(|context| GlContext {
context,
phantom: PhantomData,
platform::GlContext::create(parent, config, share.map(|x| &x.context)).map(|context| {
GlContext {
context,
phantom: PhantomData,
}
})
}

Expand Down
49 changes: 29 additions & 20 deletions src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use cocoa::appkit::{
NSOpenGLPFAColorSize, NSOpenGLPFADepthSize, NSOpenGLPFADoubleBuffer, NSOpenGLPFAMultisample,
NSOpenGLPFAOpenGLProfile, NSOpenGLPFASampleBuffers, NSOpenGLPFASamples, NSOpenGLPFAStencilSize,
NSOpenGLPixelFormat, NSOpenGLProfileVersion3_2Core, NSOpenGLProfileVersion4_1Core,
NSOpenGLProfileVersionLegacy, NSOpenGLView, NSView,
NSOpenGLProfileVersionLegacy,
};
use cocoa::base::{id, nil, YES};
use cocoa::base::{id, nil};

use core_foundation::base::TCFType;
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
Expand All @@ -19,28 +19,38 @@ use core_foundation::string::CFString;
use objc::{msg_send, sel, sel_impl};

use crate::{GlConfig, GlError, Profile};
use cocoa::foundation::NSAutoreleasePool;
use objc::runtime::Object;

pub struct GlContext {
view: id,
context: id,
}

impl GlContext {
pub fn create(
parent: &impl HasRawWindowHandle,
parent: &dyn HasRawWindowHandle,
config: GlConfig,
shared_context: Option<&GlContext>,
) -> Result<GlContext, GlError> {
let handle = if let RawWindowHandle::MacOS(handle) = parent.raw_window_handle() {
handle
} else {
return Err(GlError::InvalidWindowHandle);
};

if handle.ns_view.is_null() {
let ns_view = if !handle.ns_view.is_null() {
Ok(handle.ns_view as id)
} else if !handle.ns_window.is_null() {
let ns_window = handle.ns_window as *mut Object;
let ns_view: *mut c_void = unsafe { msg_send![ns_window, contentView] };

assert!(!ns_view.is_null());
Ok(ns_view as id)
} else {
return Err(GlError::InvalidWindowHandle);
}
}?;

let parent_view = handle.ns_view as id;
let parent_view = ns_view as id;

unsafe {
let version = if config.version < (3, 2) && config.profile == Profile::Compatibility {
Expand Down Expand Up @@ -84,28 +94,27 @@ impl GlContext {
return Err(GlError::CreationFailed);
}

let view = NSOpenGLView::alloc(nil)
.initWithFrame_pixelFormat_(parent_view.frame(), pixel_format);
let shared_context = shared_context.map(|x| x.context).unwrap_or(nil);

if view == nil {
let gl_context = NSOpenGLContext::alloc(nil)
.initWithFormat_shareContext_(pixel_format, shared_context);

if gl_context == nil {
return Err(GlError::CreationFailed);
}

let () = msg_send![view, retain];
NSOpenGLView::display_(view);
parent_view.addSubview_(view);

let context: id = msg_send![view, openGLContext];
let () = msg_send![context, retain];
gl_context.setView_(parent_view);

context.setValues_forParameter_(
gl_context.setValues_forParameter_(
&(config.vsync as i32),
NSOpenGLContextParameter::NSOpenGLCPSwapInterval,
);

let () = msg_send![pixel_format, release];

Ok(GlContext { view, context })
Ok(GlContext {
context: gl_context,
})
}
}

Expand Down Expand Up @@ -134,8 +143,9 @@ impl GlContext {

pub fn swap_buffers(&self) {
unsafe {
let pool = NSAutoreleasePool::new(nil);
self.context.flushBuffer();
let () = msg_send![self.view, setNeedsDisplay: YES];
let _: () = msg_send![pool, release];
}
}
}
Expand All @@ -144,7 +154,6 @@ impl Drop for GlContext {
fn drop(&mut self) {
unsafe {
let () = msg_send![self.context, release];
let () = msg_send![self.view, release];
}
}
}
8 changes: 6 additions & 2 deletions src/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ pub struct GlContext {

impl GlContext {
pub fn create(
parent: &impl HasRawWindowHandle,
parent: &dyn HasRawWindowHandle,
config: GlConfig,
shared_context: Option<&GlContext>,
) -> Result<GlContext, GlError> {
let handle = if let RawWindowHandle::Windows(handle) = parent.raw_window_handle() {
handle
Expand Down Expand Up @@ -242,7 +243,10 @@ impl GlContext {
0
];

let hglrc = wglCreateContextAttribsARB(hdc, std::ptr::null_mut(), ctx_attribs.as_ptr());
let shared_context = shared_context
.map(|x| x.hglrc)
.unwrap_or(std::ptr::null_mut());
let hglrc = wglCreateContextAttribsARB(hdc, shared_context, ctx_attribs.as_ptr());
if hglrc == std::ptr::null_mut() {
return Err(GlError::CreationFailed);
}
Expand Down
14 changes: 6 additions & 8 deletions src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ pub struct GlContext {

impl GlContext {
pub fn create(
parent: &impl HasRawWindowHandle,
parent: &dyn HasRawWindowHandle,
config: GlConfig,
shared_context: Option<&GlContext>,
) -> Result<GlContext, GlError> {
let handle = if let RawWindowHandle::Xlib(handle) = parent.raw_window_handle() {
handle
Expand Down Expand Up @@ -123,14 +124,11 @@ impl GlContext {
0,
];

let shared_context = shared_context
.map(|x| x.context)
.unwrap_or(std::ptr::null_mut());
let context = unsafe {
glXCreateContextAttribsARB(
display,
*fb_config,
std::ptr::null_mut(),
1,
ctx_attribs.as_ptr(),
)
glXCreateContextAttribsARB(display, *fb_config, shared_context, 1, ctx_attribs.as_ptr())
};

if context.is_null() {
Expand Down