Skip to content

Commit

Permalink
Merge pull request #414 from tomaka/pf-win32
Browse files Browse the repository at this point in the history
Add pixelformat for cocoa and remove individual color components
  • Loading branch information
tomaka committed Apr 30, 2015
2 parents 735df1c + 36de5a5 commit a08388b
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 54 deletions.
140 changes: 102 additions & 38 deletions src/api/cocoa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pub struct Window {
view: IdRef,
window: IdRef,
context: IdRef,
pixel_format: PixelFormat,
delegate: WindowDelegate,
}

Expand Down Expand Up @@ -326,21 +327,23 @@ impl Window {
Some(app) => app,
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
};
let window = match Window::create_window(builder.dimensions.unwrap_or((800, 600)),
&*builder.title,
&builder.monitor)

let window = match Window::create_window(&builder)
{
Some(window) => window,
None => { return Err(OsError(format!("Couldn't create NSWindow"))); },
};

let view = match Window::create_view(*window) {
Some(view) => view,
None => { return Err(OsError(format!("Couldn't create NSView"))); },
};

let context = match Window::create_context(*view, &builder) {
Some(context) => context,
None => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
// TODO: perhaps we should return error from create_context so we can
// determine the cause of failure and possibly recover?
let (context, pf) = match Window::create_context(*view, &builder) {
(Some(context), Some(pf)) => (context, pf),
(_, _) => { return Err(OsError(format!("Couldn't create OpenGL context"))); },
};

unsafe {
Expand All @@ -365,6 +368,7 @@ impl Window {
view: view,
window: window,
context: context,
pixel_format: pf,
delegate: WindowDelegate::new(ds),
};

Expand All @@ -384,9 +388,9 @@ impl Window {
}
}

fn create_window(dimensions: (u32, u32), title: &str, monitor: &Option<MonitorID>) -> Option<IdRef> {
fn create_window(builder: &BuilderAttribs) -> Option<IdRef> {
unsafe {
let screen = match *monitor {
let screen = match builder.monitor {
Some(ref monitor_id) => {
let native_id = match monitor_id.get_native_identifier() {
NativeMonitorId::Numeric(num) => num,
Expand Down Expand Up @@ -418,7 +422,7 @@ impl Window {
let frame = match screen {
Some(screen) => NSScreen::frame(screen),
None => {
let (width, height) = dimensions;
let (width, height) = builder.dimensions.unwrap_or((800, 600));
NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64))
}
};
Expand All @@ -439,7 +443,7 @@ impl Window {
NO,
));
window.non_nil().map(|window| {
let title = IdRef::new(NSString::alloc(nil).init_str(title));
let title = IdRef::new(NSString::alloc(nil).init_str(&builder.title));
window.setTitle_(*title);
window.setAcceptsMouseMovedEvents_(YES);
if screen.is_some() {
Expand All @@ -464,7 +468,7 @@ impl Window {
}
}

fn create_context(view: id, builder: &BuilderAttribs) -> Option<IdRef> {
fn create_context(view: id, builder: &BuilderAttribs) -> (Option<IdRef>, Option<PixelFormat>) {
let profile = match builder.gl_version {
GlRequest::Latest => NSOpenGLProfileVersion4_1Core as u32,
GlRequest::Specific(Api::OpenGl, (1 ... 2, _)) => NSOpenGLProfileVersionLegacy as u32,
Expand All @@ -477,39 +481,99 @@ impl Window {
GlRequest::GlThenGles { opengl_version: (3, 1 ... 2), .. } => NSOpenGLProfileVersion3_2Core as u32,
GlRequest::GlThenGles { .. } => NSOpenGLProfileVersion4_1Core as u32,
};
unsafe {
let mut attributes = vec![
NSOpenGLPFADoubleBuffer as u32,
NSOpenGLPFAClosestPolicy as u32,
NSOpenGLPFAColorSize as u32, 24,
NSOpenGLPFAAlphaSize as u32, 8,
NSOpenGLPFADepthSize as u32, 24,
NSOpenGLPFAStencilSize as u32, 8,
NSOpenGLPFAOpenGLProfile as u32, profile,
];

if let Some(samples) = builder.multisampling {
attributes = attributes + &[
NSOpenGLPFAMultisample as u32,
NSOpenGLPFASampleBuffers as u32, 1,
NSOpenGLPFASamples as u32, samples as u32,
];
}

attributes.push(0);
// NOTE: OS X no longer has the concept of setting individual
// color component's bit size. Instead we can only specify the
// full color size and hope for the best. Another hiccup is that
// `NSOpenGLPFAColorSize` also includes `NSOpenGLPFAAlphaSize`,
// so we have to account for that as well.
let alpha_depth = builder.alpha_bits.unwrap_or(8);
let color_depth = builder.color_bits.unwrap_or(24) + alpha_depth;

let mut attributes = vec![
NSOpenGLPFADoubleBuffer as u32,
NSOpenGLPFAClosestPolicy as u32,
NSOpenGLPFAColorSize as u32, color_depth as u32,
NSOpenGLPFAAlphaSize as u32, alpha_depth as u32,
NSOpenGLPFADepthSize as u32, builder.depth_bits.unwrap_or(24) as u32,
NSOpenGLPFAStencilSize as u32, builder.stencil_bits.unwrap_or(8) as u32,
NSOpenGLPFAOpenGLProfile as u32, profile,
];

// A color depth higher than 64 implies we're using either 16-bit
// floats or 32-bit floats and OS X requires a flag to be set
// accordingly.
if color_depth >= 64 {
attributes.push(NSOpenGLPFAColorFloat as u32);
}

builder.multisampling.map(|samples| {
attributes.push(NSOpenGLPFAMultisample as u32);
attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1);
attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32);
});

// attribute list must be null terminated.
attributes.push(0);

unsafe {
let pixelformat = IdRef::new(NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes));
pixelformat.non_nil().map(|pixelformat| {

if let Some(pixelformat) = pixelformat.non_nil() {

// TODO: Add context sharing
let context = IdRef::new(NSOpenGLContext::alloc(nil).initWithFormat_shareContext_(*pixelformat, nil));
context.non_nil().map(|context| {
context.setView_(view);

if let Some(cxt) = context.non_nil() {
let pf = {
let getValues_forAttribute_forVirtualScreen_ = |fmt: id,
vals: *mut GLint,
attrib: NSOpenGLPixelFormatAttribute,
screen: GLint| -> () {
msg_send![fmt, getValues:vals forAttribute:attrib forVirtualScreen:screen]
};
let get_attr = |attrib: NSOpenGLPixelFormatAttribute| -> i32 {
let mut value = 0;
// TODO: Wait for servo/rust-cocoa/#85 to get merged
/*NSOpenGLPixelFormat::*/getValues_forAttribute_forVirtualScreen_(
*pixelformat,
&mut value,
attrib,
NSOpenGLContext::currentVirtualScreen(*cxt));

value
};

PixelFormat {
hardware_accelerated: get_attr(NSOpenGLPFAAccelerated) != 0,
color_bits: (get_attr(NSOpenGLPFAColorSize) - get_attr(NSOpenGLPFAAlphaSize)) as u8,
alpha_bits: get_attr(NSOpenGLPFAAlphaSize) as u8,
depth_bits: get_attr(NSOpenGLPFADepthSize) as u8,
stencil_bits: get_attr(NSOpenGLPFAStencilSize) as u8,
stereoscopy: get_attr(NSOpenGLPFAStereo) != 0,
double_buffer: get_attr(NSOpenGLPFADoubleBuffer) != 0,
multisampling: if get_attr(NSOpenGLPFAMultisample) > 0 {
Some(get_attr(NSOpenGLPFASamples) as u16)
} else {
None
},
srgb: true,
}
};

cxt.setView_(view);
if builder.vsync {
let value = 1;
context.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
cxt.setValues_forParameter_(&value, NSOpenGLContextParameter::NSOpenGLCPSwapInterval);
}
context
})
}).unwrap_or(None)

(Some(cxt), Some(pf))
} else {
(None, None)
}
} else {
(None, None)
}
}
}

Expand Down Expand Up @@ -654,7 +718,7 @@ impl Window {
}

pub fn get_pixel_format(&self) -> PixelFormat {
unimplemented!();
self.pixel_format.clone()
}

pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
Expand Down
6 changes: 3 additions & 3 deletions src/api/egl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ unsafe fn enumerate_configs(egl: &ffi::egl::Egl, display: ffi::egl::types::EGLDi
result.push((config_id, PixelFormat {
hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT)
!= ffi::egl::SLOW_CONFIG as i32,
red_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8,
green_bits: attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8,
blue_bits: attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8,
color_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8 +
attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 +
attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8,
alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8,
depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8,
stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8,
Expand Down
10 changes: 4 additions & 6 deletions src/api/win32/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,7 @@ unsafe fn enumerate_native_pixel_formats(hdc: &WindowWrapper) -> Vec<(PixelForma

result.push((PixelFormat {
hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0,
red_bits: output.cRedBits,
green_bits: output.cGreenBits,
blue_bits: output.cBlueBits,
color_bits: output.cRedBits + output.cGreenBits + output.cBlueBits,
alpha_bits: output.cAlphaBits,
depth_bits: output.cDepthBits,
stencil_bits: output.cStencilBits,
Expand Down Expand Up @@ -489,9 +487,9 @@ unsafe fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, hdc: &WindowWr

result.push((PixelFormat {
hardware_accelerated: true,
red_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8,
green_bits: get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8,
blue_bits: get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8,
color_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8 +
get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8 +
get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8,
alpha_bits: get_info(index, gl::wgl_extra::ALPHA_BITS_ARB) as u8,
depth_bits: get_info(index, gl::wgl_extra::DEPTH_BITS_ARB) as u8,
stencil_bits: get_info(index, gl::wgl_extra::STENCIL_BITS_ARB) as u8,
Expand Down
6 changes: 3 additions & 3 deletions src/api/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ impl Window {

PixelFormat {
hardware_accelerated: true,
red_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8,
green_bits: get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8,
blue_bits: get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8,
color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8 +
get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8 +
get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8,
alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int) as u8,
depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int) as u8,
stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int) as u8,
Expand Down
6 changes: 2 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,7 @@ pub enum CursorState {
#[derive(Debug, Clone)]
pub struct PixelFormat {
pub hardware_accelerated: bool,
pub red_bits: u8,
pub green_bits: u8,
pub blue_bits: u8,
pub color_bits: u8,
pub alpha_bits: u8,
pub depth_bits: u8,
pub stencil_bits: u8,
Expand Down Expand Up @@ -306,7 +304,7 @@ impl<'a> BuilderAttribs<'a> {

// TODO: do this more properly
for (id, format) in iter {
if format.red_bits + format.green_bits + format.blue_bits < self.color_bits.unwrap_or(0) {
if format.color_bits < self.color_bits.unwrap_or(0) {
continue;
}

Expand Down

0 comments on commit a08388b

Please sign in to comment.