From e565bfeb1372b885f8cced6a42596b731cb382b2 Mon Sep 17 00:00:00 2001 From: Tomaka17 Date: Sat, 4 Oct 2014 19:17:02 +0200 Subject: Implement headless rendering --- src/win32/init.rs | 40 +++++++++++++++++++++++++--------------- src/win32/mod.rs | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 17 deletions(-) (limited to 'src/win32') diff --git a/src/win32/init.rs b/src/win32/init.rs index 7ad4dca..740bc02 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -6,7 +6,7 @@ use std::sync::atomics::AtomicBool; use std::ptr; use super::{event, ffi}; use super::Window; -use {Event, WindowBuilder}; +use Event; /// Stores the current window and its events dispatcher. /// @@ -14,12 +14,16 @@ use {Event, WindowBuilder}; /// receive an event for another window. local_data_key!(WINDOW: (ffi::HWND, Sender)) -pub fn new_window(builder: WindowBuilder) -> Result { +pub fn new_window(builder_dimensions: Option<(uint, uint)>, builder_title: String, + builder_monitor: Option, + builder_gl_version: Option<(uint, uint)>, + builder_headless: bool) -> Result +{ use std::mem; use std::os; // initializing variables to be sent to the task - let title = builder.title.as_slice().utf16_units() + let title = builder_title.as_slice().utf16_units() .collect::>().append_one(0); // title to utf16 //let hints = hints.clone(); let (tx, rx) = channel(); @@ -59,15 +63,15 @@ pub fn new_window(builder: WindowBuilder) -> Result { // building a RECT object with coordinates let mut rect = ffi::RECT { - left: 0, right: builder.dimensions.unwrap_or((1024, 768)).val0() as ffi::LONG, - top: 0, bottom: builder.dimensions.unwrap_or((1024, 768)).val1() as ffi::LONG, + left: 0, right: builder_dimensions.unwrap_or((1024, 768)).val0() as ffi::LONG, + top: 0, bottom: builder_dimensions.unwrap_or((1024, 768)).val1() as ffi::LONG, }; // switching to fullscreen if necessary // this means adjusting the window's position so that it overlaps the right monitor, // and change the monitor's resolution if necessary - if builder.monitor.is_some() { - let monitor = builder.monitor.as_ref().unwrap(); + if builder_monitor.is_some() { + let monitor = builder_monitor.as_ref().unwrap(); // adjusting the rect { @@ -96,7 +100,7 @@ pub fn new_window(builder: WindowBuilder) -> Result { } // computing the style and extended style of the window - let (ex_style, style) = if builder.monitor.is_some() { + let (ex_style, style) = if builder_monitor.is_some() { (ffi::WS_EX_APPWINDOW, ffi::WS_POPUP | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN) } else { (ffi::WS_EX_APPWINDOW | ffi::WS_EX_WINDOWEDGE, @@ -227,17 +231,23 @@ pub fn new_window(builder: WindowBuilder) -> Result { // creating the real window this time let real_window = unsafe { - let (width, height) = if builder.monitor.is_some() || builder.dimensions.is_some() { + let (width, height) = if builder_monitor.is_some() || builder_dimensions.is_some() { (Some(rect.right - rect.left), Some(rect.bottom - rect.top)) } else { (None, None) }; + let style = if builder_headless { + style + } else { + style | ffi::WS_VISIBLE + }; + let handle = ffi::CreateWindowExW(ex_style, class_name.as_ptr(), title.as_ptr() as ffi::LPCWSTR, - style | ffi::WS_VISIBLE | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN, - if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, - if builder.monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, + style | ffi::WS_CLIPSIBLINGS | ffi::WS_CLIPCHILDREN, + if builder_monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, + if builder_monitor.is_some() { 0 } else { ffi::CW_USEDEFAULT }, width.unwrap_or(ffi::CW_USEDEFAULT), height.unwrap_or(ffi::CW_USEDEFAULT), ptr::null(), ptr::null(), ffi::GetModuleHandleW(ptr::null()), ptr::null_mut()); @@ -280,8 +290,8 @@ pub fn new_window(builder: WindowBuilder) -> Result { let mut attributes = Vec::new(); - if builder.gl_version.is_some() { - let version = builder.gl_version.as_ref().unwrap(); + if builder_gl_version.is_some() { + let version = builder_gl_version.as_ref().unwrap(); attributes.push(ffi::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); attributes.push(version.val0() as libc::c_int); attributes.push(ffi::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); @@ -310,7 +320,7 @@ pub fn new_window(builder: WindowBuilder) -> Result { }; // calling SetForegroundWindow if fullscreen - if builder.monitor.is_some() { + if builder_monitor.is_some() { unsafe { ffi::SetForegroundWindow(real_window) }; } diff --git a/src/win32/mod.rs b/src/win32/mod.rs index faff374..af28011 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -1,6 +1,12 @@ use std::sync::atomics::AtomicBool; use std::ptr; -use {Event, WindowBuilder}; +use Event; + +#[cfg(feature = "window")] +use WindowBuilder; + +#[cfg(feature = "headless")] +use HeadlessRendererBuilder; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -9,6 +15,30 @@ mod ffi; mod init; mod monitor; +/// +#[cfg(feature = "headless")] +pub struct HeadlessContext(Window); + +#[cfg(feature = "headless")] +impl HeadlessContext { + /// See the docs in the crate root file. + pub fn new(builder: HeadlessRendererBuilder) -> Result { + let HeadlessRendererBuilder { dimensions, gl_version } = builder; + init::new_window(Some(dimensions), "".to_string(), None, gl_version, true) + .map(|w| HeadlessContext(w)) + } + + /// See the docs in the crate root file. + pub unsafe fn make_current(&self) { + self.0.make_current() + } + + /// See the docs in the crate root file. + pub fn get_proc_address(&self, addr: &str) -> *const () { + self.0.get_proc_address(addr) + } +} + /// The Win32 implementation of the main `Window` object. pub struct Window { /// Main handle for the window. @@ -33,12 +63,16 @@ pub struct Window { is_closed: AtomicBool, } +#[cfg(feature = "window")] impl Window { /// See the docs in the crate root file. pub fn new(builder: WindowBuilder) -> Result { - init::new_window(builder) + let WindowBuilder { dimensions, title, monitor, gl_version } = builder; + init::new_window(dimensions, title, monitor, gl_version, false) } +} +impl Window { /// See the docs in the crate root file. pub fn is_closed(&self) -> bool { use std::sync::atomics::Relaxed; @@ -200,6 +234,7 @@ impl Window { } } +#[cfg(feature = "window")] #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { -- cgit v1.2.3