aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/osx/headless.rs109
-rw-r--r--src/osx/mod.rs25
2 files changed, 115 insertions, 19 deletions
diff --git a/src/osx/headless.rs b/src/osx/headless.rs
new file mode 100644
index 0000000..bbe3d9f
--- /dev/null
+++ b/src/osx/headless.rs
@@ -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);
+ }
+ }
+}
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
index 8ab3efd..0cb4553 100644
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -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();