aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs53
-rw-r--r--src/win32/init.rs82
2 files changed, 110 insertions, 25 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b251a7a..1bd29bb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -170,6 +170,21 @@ pub enum MouseCursor {
RowResize,
}
+/// Describes a possible format. Unused.
+#[allow(missing_docs)]
+pub struct PixelFormat {
+ pub red_bits: u8,
+ pub green_bits: u8,
+ pub blue_bits: u8,
+ pub alpha_bits: u8,
+ pub depth_bits: u8,
+ pub stencil_bits: u8,
+ pub stereoscopy: bool,
+ pub double_buffer: bool,
+ pub multisampling: Option<u16>,
+ pub srgb: bool,
+}
+
/// Attributes
struct BuilderAttribs<'a> {
#[allow(dead_code)]
@@ -239,5 +254,41 @@ impl<'a> BuilderAttribs<'a> {
(new_attribs, sharing)
}
-}
+ fn choose_pixel_format<T, I>(&self, iter: I) -> (T, PixelFormat)
+ where I: Iterator<Item=(T, PixelFormat)>, T: Clone
+ {
+ let mut current_result = None;
+
+ // 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) {
+ continue;
+ }
+
+ if format.alpha_bits < self.alpha_bits.unwrap_or(0) {
+ continue;
+ }
+
+ if format.depth_bits < self.depth_bits.unwrap_or(0) {
+ continue;
+ }
+
+ if format.stencil_bits < self.stencil_bits.unwrap_or(0) {
+ continue;
+ }
+
+ if !format.stereoscopy && self.stereoscopy {
+ continue;
+ }
+
+ if self.multisampling.is_some() && format.multisampling.is_none() {
+ continue;
+ }
+
+ current_result = Some((id, format));
+ }
+
+ current_result.expect("Could not find compliant pixel format")
+ }
+}
diff --git a/src/win32/init.rs b/src/win32/init.rs
index fcb23f5..357b87d 100644
--- a/src/win32/init.rs
+++ b/src/win32/init.rs
@@ -8,6 +8,7 @@ use super::MonitorID;
use BuilderAttribs;
use CreationError;
use CreationError::OsError;
+use PixelFormat;
use std::ffi::CString;
use std::sync::mpsc::channel;
@@ -130,31 +131,11 @@ fn init(title: Vec<u16>, builder: BuilderAttribs<'static>, builder_sharelists: O
// getting the pixel format that we will use
let pixel_format = {
- // initializing a PIXELFORMATDESCRIPTOR that indicates what we want
- let mut output: winapi::PIXELFORMATDESCRIPTOR = unsafe { mem::zeroed() };
- output.nSize = mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as winapi::WORD;
- output.nVersion = 1;
- output.dwFlags = winapi::PFD_DRAW_TO_WINDOW | winapi::PFD_DOUBLEBUFFER |
- winapi::PFD_SUPPORT_OPENGL | winapi::PFD_GENERIC_ACCELERATED;
- output.iPixelType = winapi::PFD_TYPE_RGBA;
- output.cColorBits = 24;
- output.cAlphaBits = 8;
- output.cAccumBits = 0;
- output.cDepthBits = 24;
- output.cStencilBits = 8;
- output.cAuxBuffers = 0;
- output.iLayerType = winapi::PFD_MAIN_PLANE;
-
- let pf_index = unsafe { gdi32::ChoosePixelFormat(dummy_hdc, &output) };
-
- if pf_index == 0 {
- let err = Err(OsError(format!("ChoosePixelFormat function failed: {}",
- os::error_string(os::errno() as usize))));
- unsafe { user32::DestroyWindow(dummy_window); }
- return err;
- }
+ let formats = enumerate_native_pixel_formats(dummy_hdc);
+ let (id, _) = builder.choose_pixel_format(formats.into_iter().map(|(a, b)| (b, a)));
- if unsafe { gdi32::DescribePixelFormat(dummy_hdc, pf_index,
+ let mut output: winapi::PIXELFORMATDESCRIPTOR = unsafe { mem::zeroed() };
+ if unsafe { gdi32::DescribePixelFormat(dummy_hdc, id,
mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as winapi::UINT, &mut output) } == 0
{
let err = Err(OsError(format!("DescribePixelFormat function failed: {}",
@@ -475,3 +456,56 @@ fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'static>)>
Ok(ctxt as winapi::HGLRC)
}
+
+fn enumerate_native_pixel_formats(hdc: winapi::HDC) -> Vec<(PixelFormat, libc::c_int)> {
+ let size_of_pxfmtdescr = mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u32;
+ let num = unsafe { gdi32::DescribePixelFormat(hdc, 1, size_of_pxfmtdescr, ptr::null_mut()) };
+
+ let mut result = Vec::new();
+
+ for index in (0 .. num) {
+ let mut output: winapi::PIXELFORMATDESCRIPTOR = unsafe { mem::zeroed() };
+
+ if unsafe { gdi32::DescribePixelFormat(hdc, index, size_of_pxfmtdescr,
+ &mut output) } == 0
+ {
+ continue;
+ }
+
+ if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 {
+ continue;
+ }
+ if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 {
+ continue;
+ }
+
+ if (output.dwFlags & winapi::PFD_GENERIC_ACCELERATED) == 0 &&
+ (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0
+ {
+ continue;
+ }
+
+ if output.iPixelType != winapi::PFD_TYPE_RGBA {
+ continue;
+ }
+
+ result.push((PixelFormat {
+ red_bits: output.cRedBits,
+ green_bits: output.cGreenBits,
+ blue_bits: output.cBlueBits,
+ alpha_bits: output.cAlphaBits,
+ depth_bits: output.cDepthBits,
+ stencil_bits: output.cStencilBits,
+ stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0,
+ double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0,
+ multisampling: None,
+ srgb: false,
+ }, index));
+ }
+
+ result
+}
+
+fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, hdc: winapi::HDC) -> Vec<PixelFormat> {
+ unimplemented!()
+}