mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Added headless rendering on osx
This commit is contained in:
parent
ef33f19812
commit
f865d9ac01
109
src/osx/headless.rs
Normal file
109
src/osx/headless.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
use CreationError;
|
||||
use CreationError::OsError;
|
||||
use HeadlessRendererBuilder;
|
||||
use libc;
|
||||
use std::ptr;
|
||||
|
||||
use core_foundation::base::TCFType;
|
||||
use core_foundation::string::CFString;
|
||||
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
||||
use cocoa::base::{id, nil};
|
||||
use cocoa::appkit::*;
|
||||
|
||||
mod gl {
|
||||
generate_gl_bindings! {
|
||||
api: "gl",
|
||||
profile: "core",
|
||||
version: "3.2",
|
||||
generator: "global",
|
||||
extensions: ["GL_EXT_framebuffer_object"],
|
||||
}
|
||||
}
|
||||
|
||||
static mut framebuffer: u32 = 0;
|
||||
static mut texture: u32 = 0;
|
||||
|
||||
pub struct HeadlessContext {
|
||||
width: uint,
|
||||
height: uint,
|
||||
context: id,
|
||||
}
|
||||
|
||||
impl HeadlessContext {
|
||||
pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
|
||||
let (width, height) = builder.dimensions;
|
||||
let context = unsafe {
|
||||
let attributes = [
|
||||
NSOpenGLPFADoubleBuffer as uint,
|
||||
NSOpenGLPFAClosestPolicy as uint,
|
||||
NSOpenGLPFAColorSize as uint, 24,
|
||||
NSOpenGLPFAAlphaSize as uint, 8,
|
||||
NSOpenGLPFADepthSize as uint, 24,
|
||||
NSOpenGLPFAStencilSize as uint, 8,
|
||||
NSOpenGLPFAOffScreen as uint,
|
||||
0
|
||||
];
|
||||
|
||||
let pixelformat = NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes);
|
||||
if pixelformat == nil {
|
||||
return Err(OsError(format!("Could not create the pixel format")));
|
||||
}
|
||||
let context = NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(pixelformat, nil);
|
||||
if context == nil {
|
||||
return Err(OsError(format!("Could not create the rendering context")));
|
||||
}
|
||||
context
|
||||
};
|
||||
|
||||
let headless = HeadlessContext {
|
||||
width: width,
|
||||
height: height,
|
||||
context: context,
|
||||
};
|
||||
|
||||
// Load the function pointers as we need them to create the FBO
|
||||
gl::load_with(|s| headless.get_proc_address(s) as *const libc::c_void);
|
||||
|
||||
Ok(headless)
|
||||
}
|
||||
|
||||
pub unsafe fn make_current(&self) {
|
||||
self.context.makeCurrentContext();
|
||||
|
||||
gl::GenFramebuffersEXT(1, &mut framebuffer);
|
||||
gl::BindFramebufferEXT(gl::FRAMEBUFFER_EXT, framebuffer);
|
||||
gl::GenTextures(1, &mut texture);
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture);
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
|
||||
gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA8 as i32, self.width as i32, self.height as i32,
|
||||
0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
|
||||
gl::FramebufferTexture2DEXT(gl::FRAMEBUFFER_EXT, gl::COLOR_ATTACHMENT0_EXT,
|
||||
gl::TEXTURE_2D, texture, 0);
|
||||
let status = gl::CheckFramebufferStatusEXT(gl::FRAMEBUFFER_EXT);
|
||||
if status != gl::FRAMEBUFFER_COMPLETE_EXT {
|
||||
panic!("Error while creating the framebuffer");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_proc_address(&self, _addr: &str) -> *const () {
|
||||
let symbol_name: CFString = from_str(_addr).unwrap();
|
||||
let framework_name: CFString = from_str("com.apple.opengl").unwrap();
|
||||
let framework = unsafe {
|
||||
CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef())
|
||||
};
|
||||
let symbol = unsafe {
|
||||
CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
|
||||
};
|
||||
symbol as *const ()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for HeadlessContext {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
gl::DeleteTextures(1, &texture);
|
||||
gl::DeleteFramebuffersEXT(1, &framebuffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
#[cfg(feature = "headless")]
|
||||
pub use self::headless::HeadlessContext;
|
||||
|
||||
use {CreationError, Event};
|
||||
use CreationError::OsError;
|
||||
use libc;
|
||||
|
@ -5,9 +8,6 @@ use libc;
|
|||
#[cfg(feature = "window")]
|
||||
use WindowBuilder;
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
use HeadlessRendererBuilder;
|
||||
|
||||
use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
|
||||
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
|
||||
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
|
||||
|
@ -33,6 +33,9 @@ pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
|
|||
mod monitor;
|
||||
mod event;
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
mod headless;
|
||||
|
||||
static mut shift_pressed: bool = false;
|
||||
static mut ctrl_pressed: bool = false;
|
||||
static mut win_pressed: bool = false;
|
||||
|
@ -60,14 +63,6 @@ pub struct Window {
|
|||
state: Box<InternalState>,
|
||||
}
|
||||
|
||||
pub struct HeadlessContext(Window);
|
||||
|
||||
impl Deref<Window> for HeadlessContext {
|
||||
fn deref(&self) -> &Window {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "window")]
|
||||
impl Window {
|
||||
pub fn new(builder: WindowBuilder) -> Result<Window, CreationError> {
|
||||
|
@ -79,14 +74,6 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
impl HeadlessContext {
|
||||
pub fn new(builder: HeadlessRendererBuilder) -> Result<HeadlessContext, CreationError> {
|
||||
Window::new_impl(Some(builder.dimensions), "", None, false)
|
||||
.map(|w| HeadlessContext(w))
|
||||
}
|
||||
}
|
||||
|
||||
extern fn window_should_close(this: id, _: id) -> id {
|
||||
unsafe {
|
||||
let mut stored_value = ptr::null_mut();
|
||||
|
|
Loading…
Reference in a new issue