<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use api::{FontKey, FontRenderMode, GlyphDimensions};
use api::{NativeFontHandle, GlyphOptions};
use api::{GlyphKey};

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error};

use std::{cmp, mem, ptr, slice};
use std::collections::HashMap;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

// FreeType resources are safe to move between threads as long as they
// are not concurrently accessed. In our case, everything is hidden inside
// a given FontContext so it is safe to move the latter between threads.
unsafe impl Send for FontContext {}

pub struct RasterizedGlyph {
    pub top: f32,
    pub left: f32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

fn float_to_fixed(before: usize, f: f64) -> i32 {
    ((1i32 << before) as f64 * f) as i32
}

fn float_to_fixed_ft(f: f64) -> i32 {
    float_to_fixed(6, f)
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
            }
        }

        FontContext {
            lib,
            faces: HashMap::new(),
        }
    }

    pub fn has_font(&self, font_key: &FontKey) -> bool {
        self.faces.contains_key(font_key)
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font_key: FontKey,
                  size: Au,
                  character: u32) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font_key));
        let face = self.faces.get(&font_key).unwrap();
        let char_size = float_to_fixed_ft(size.to_f64_px());

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face, character as FT_UInt, 0)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());
            Some(slot)
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                character, size, font_key, result);
            None
        }
    }

    fn get_glyph_dimensions_impl(slot: FT_GlyphSlot) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };
        if metrics.width == 0 || metrics.height == 0 {
            None
        } else {
            let left = metrics.horiBearingX >> 6;
            let top = metrics.horiBearingY >> 6;
            let right = (metrics.horiBearingX + metrics.width + 0x3f) >> 6;
            let bottom = (metrics.horiBearingY + metrics.height + 0x3f) >> 6;
            Some(GlyphDimensions {
                left: left as i32,
                top: top as i32,
                width: (right - left) as u32,
                height: (bottom - top) as u32,
            })
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        self.load_glyph(key.font_key, key.size, key.index)
            .and_then(Self::get_glyph_dimensions_impl)
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           _glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(key.font_key, key.size, key.index) {
            Some(slot) => slot,
            None => return None,
        };
        let render_mode = match render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let dimensions = match Self::get_glyph_dimensions_impl(slot) {
            Some(val) => val,
            None => return None,
        };

        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);
        // we may be filling only a part of the buffer, so initialize the whole thing with 0
        let mut final_buffer = Vec::with_capacity(dimensions.width as usize *
                                                  dimensions.height as usize *
                                                  4);

        let offset_x = dimensions.left - unsafe { (*slot).bitmap_left };
        let src_pixel_width = match pixel_mode {
            FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                assert!(bitmap.width % 3 == 0);
                bitmap.width / 3
            },
            _ => bitmap.width,
        };
        // determine the destination range of texels that `bitmap` provides data for
        let dst_start = cmp::max(0, -offset_x);
        let dst_end = cmp::min(dimensions.width as i32, src_pixel_width as i32 - offset_x);

        for y in 0 .. dimensions.height {
            let src_y = y as i32 - dimensions.top + unsafe { (*slot).bitmap_top };
            if src_y < 0 || src_y >= bitmap.rows as i32 {
                for _x in 0 .. dimensions.width {
                    final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
                }
                continue
            }
            let base = unsafe {
                bitmap.buffer.offset((src_y * bitmap.pitch) as isize)
            };
            for _x in 0 .. dst_start {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            match pixel_mode {
                FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                    for x in dst_start .. dst_end {
                        let src_x = x + offset_x;
                        let mask = 0x80 >> (src_x & 0x7);
                        let byte = unsafe {
                            *base.offset((src_x >> 3) as isize)
                        };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                    for x in dst_start .. dst_end {
                        let alpha = unsafe {
                            *base.offset((x + offset_x) as isize)
                        };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                    for x in dst_start .. dst_end {
                        let src_x = ((x + offset_x) * 3) as isize;
                        assert!(src_x+2 < bitmap.pitch as isize);
                        let t = unsafe {
                            slice::from_raw_parts(base.offset(src_x), 3)
                        };
                        final_buffer.extend_from_slice(&[t[2], t[1], t[0], 0xff]);
                    }
                }
                _ => panic!("Unsupported {:?}", pixel_mode)
            }
            for _x in dst_end .. dimensions.width as i32 {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            assert_eq!(final_buffer.len(), ((y+1) * dimensions.width * 4) as usize);
        }

        Some(RasterizedGlyph {
            left: dimensions.left as f32,
            top: dimensions.top as f32,
            width: dimensions.width as u32,
            height: dimensions.height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<commit_msg>Auto merge of #1457 - glennw:hinting, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use api::{FontKey, FontRenderMode, GlyphDimensions};
use api::{NativeFontHandle, GlyphOptions};
use api::{GlyphKey};

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
use freetype::freetype::{FT_Library, FT_Set_Char_Size};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error, FT_Int32};

use std::{cmp, mem, ptr, slice};
use std::collections::HashMap;

// This constant is not present in the freetype
// bindings due to bindgen not handling the way
// the macro is defined.
const FT_LOAD_TARGET_LIGHT: FT_Int32 = 1 << 16;

// Default to slight hinting, which is what most
// Linux distros use by default, and is a better
// default than no hinting.
// TODO(gw): Make this configurable.
const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_TARGET_LIGHT;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: HashMap<FontKey, Face>,
}

// FreeType resources are safe to move between threads as long as they
// are not concurrently accessed. In our case, everything is hidden inside
// a given FontContext so it is safe to move the latter between threads.
unsafe impl Send for FontContext {}

pub struct RasterizedGlyph {
    pub top: f32,
    pub left: f32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();
        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);
            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
            }
        }

        FontContext {
            lib,
            faces: HashMap::new(),
        }
    }

    pub fn has_font(&self, font_key: &FontKey) -> bool {
        self.faces.contains_key(font_key)
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font_key: FontKey,
                  size: Au,
                  character: u32) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font_key));
        let face = self.faces.get(&font_key).unwrap();
        let char_size = size.to_f64_px() * 64.0 + 0.5;

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face,
                          character as FT_UInt,
                          GLYPH_LOAD_FLAGS)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());
            Some(slot)
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                character, size, font_key, result);
            None
        }
    }

    fn get_glyph_dimensions_impl(slot: FT_GlyphSlot) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };
        if metrics.width == 0 || metrics.height == 0 {
            None
        } else {
            let left = metrics.horiBearingX >> 6;
            let top = metrics.horiBearingY >> 6;
            let right = (metrics.horiBearingX + metrics.width + 0x3f) >> 6;
            let bottom = (metrics.horiBearingY + metrics.height + 0x3f) >> 6;
            Some(GlyphDimensions {
                left: left as i32,
                top: top as i32,
                width: (right - left) as u32,
                height: (bottom - top) as u32,
            })
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        self.load_glyph(key.font_key, key.size, key.index)
            .and_then(Self::get_glyph_dimensions_impl)
    }

    pub fn rasterize_glyph(&mut self,
                           key: &GlyphKey,
                           render_mode: FontRenderMode,
                           _glyph_options: Option<GlyphOptions>)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(key.font_key, key.size, key.index) {
            Some(slot) => slot,
            None => return None,
        };
        let render_mode = match render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let dimensions = match Self::get_glyph_dimensions_impl(slot) {
            Some(val) => val,
            None => return None,
        };

        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);
        // we may be filling only a part of the buffer, so initialize the whole thing with 0
        let mut final_buffer = Vec::with_capacity(dimensions.width as usize *
                                                  dimensions.height as usize *
                                                  4);

        let offset_x = dimensions.left - unsafe { (*slot).bitmap_left };
        let src_pixel_width = match pixel_mode {
            FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                assert!(bitmap.width % 3 == 0);
                bitmap.width / 3
            },
            _ => bitmap.width,
        };
        // determine the destination range of texels that `bitmap` provides data for
        let dst_start = cmp::max(0, -offset_x);
        let dst_end = cmp::min(dimensions.width as i32, src_pixel_width as i32 - offset_x);

        for y in 0 .. dimensions.height {
            let src_y = y as i32 - dimensions.top + unsafe { (*slot).bitmap_top };
            if src_y < 0 || src_y >= bitmap.rows as i32 {
                for _x in 0 .. dimensions.width {
                    final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
                }
                continue
            }
            let base = unsafe {
                bitmap.buffer.offset((src_y * bitmap.pitch) as isize)
            };
            for _x in 0 .. dst_start {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            match pixel_mode {
                FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                    for x in dst_start .. dst_end {
                        let src_x = x + offset_x;
                        let mask = 0x80 >> (src_x & 0x7);
                        let byte = unsafe {
                            *base.offset((src_x >> 3) as isize)
                        };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                    for x in dst_start .. dst_end {
                        let alpha = unsafe {
                            *base.offset((x + offset_x) as isize)
                        };
                        final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, alpha]);
                    }
                }
                FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                    for x in dst_start .. dst_end {
                        let src_x = ((x + offset_x) * 3) as isize;
                        assert!(src_x+2 < bitmap.pitch as isize);
                        let t = unsafe {
                            slice::from_raw_parts(base.offset(src_x), 3)
                        };
                        final_buffer.extend_from_slice(&[t[2], t[1], t[0], 0xff]);
                    }
                }
                _ => panic!("Unsupported {:?}", pixel_mode)
            }
            for _x in dst_end .. dimensions.width as i32 {
                final_buffer.extend_from_slice(&[0xff, 0xff, 0xff, 0]);
            }
            assert_eq!(final_buffer.len(), ((y+1) * dimensions.width * 4) as usize);
        }

        Some(RasterizedGlyph {
            left: dimensions.left as f32,
            top: dimensions.top as f32,
            width: dimensions.width as u32,
            height: dimensions.height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<|endoftext|>


<commit_before>/*
 *
 * Computer-graphics specific implementations.
 * Currently, it is mostly implemented for homogeneous matrices in 2- and 3-space.
 *
 */

use num::One;

use base::allocator::Allocator;
use base::dimension::{DimName, DimNameDiff, DimNameSub, U1};
use base::storage::{Storage, StorageMut};
use base::{
    DefaultAllocator, Matrix3, Matrix4, MatrixN, Scalar, SquareMatrix, Unit, Vector, Vector3,
    VectorN,
};
use geometry::{
    Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3,
};

use alga::general::{Real, Ring};
use alga::linear::Transformation;

impl<N, D: DimName> MatrixN<N, D>
where
    N: Scalar + Ring,
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Creates a new homogeneous matrix that applies the same scaling factor on each dimension.
    #[inline]
    pub fn new_scaling(scaling: N) -> Self {
        let mut res = Self::from_diagonal_element(scaling);
        res[(D::dim() - 1, D::dim() - 1)] = N::one();

        res
    }

    /// Creates a new homogeneous matrix that applies a distinct scaling factor for each dimension.
    #[inline]
    pub fn new_nonuniform_scaling<SB>(scaling: &Vector<N, DimNameDiff<D, U1>, SB>) -> Self
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        let mut res = Self::one();
        for i in 0..scaling.len() {
            res[(i, i)] = scaling[i];
        }

        res
    }

    /// Creates a new homogeneous matrix that applies a pure translation.
    #[inline]
    pub fn new_translation<SB>(translation: &Vector<N, DimNameDiff<D, U1>, SB>) -> Self
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        let mut res = Self::one();
        res.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1)
            .copy_from(translation);

        res
    }
}

impl<N: Real> Matrix3<N> {
    /// Builds a 2 dimensional homogeneous rotation matrix from an angle in radian.
    #[inline]
    pub fn new_rotation(angle: N) -> Self {
        Rotation2::new(angle).to_homogeneous()
    }
}

impl<N: Real> Matrix4<N> {
    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    #[inline]
    pub fn new_rotation(axisangle: Vector3<N>) -> Self {
        Rotation3::new(axisangle).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    #[inline]
    pub fn new_rotation_wrt_point(axisangle: Vector3<N>, pt: Point3<N>) -> Self {
        let rot = Rotation3::from_scaled_axis(axisangle);
        Isometry::rotation_wrt_point(rot, pt).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    /// This is identical to `Self::new_rotation`.
    #[inline]
    pub fn from_scaled_axis(axisangle: Vector3<N>) -> Self {
        Rotation3::from_scaled_axis(axisangle).to_homogeneous()
    }

    /// Creates a new rotation from Euler angles.
    ///
    /// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
    pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Self {
        Rotation3::from_euler_angles(roll, pitch, yaw).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and a rotation angle.
    pub fn from_axis_angle(axis: &Unit<Vector3<N>>, angle: N) -> Self {
        Rotation3::from_axis_angle(axis, angle).to_homogeneous()
    }

    /// Creates a new homogeneous matrix for an orthographic projection.
    #[inline]
    pub fn new_orthographic(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> Self {
        Orthographic3::new(left, right, bottom, top, znear, zfar).unwrap()
    }

    /// Creates a new homogeneous matrix for a perspective projection.
    #[inline]
    pub fn new_perspective(aspect: N, fovy: N, znear: N, zfar: N) -> Self {
        Perspective3::new(aspect, fovy, znear, zfar).unwrap()
    }

    /// Creates an isometry that corresponds to the local frame of an observer standing at the
    /// point `eye` and looking toward `target`.
    ///
    /// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
    /// `eye`.
    #[inline]
    pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::new_observer_frame(eye, target, up).to_homogeneous()
    }

    /// Builds a right-handed look-at view matrix.
    #[inline]
    pub fn look_at_rh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::look_at_rh(eye, target, up).to_homogeneous()
    }

    /// Builds a left-handed look-at view matrix.
    #[inline]
    pub fn look_at_lh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::look_at_lh(eye, target, up).to_homogeneous()
    }
}

impl<N: Scalar + Ring, D: DimName, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
    /// Computes the transformation equal to `self` followed by an uniform scaling factor.
    #[inline]
    pub fn append_scaling(&self, scaling: N) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to an uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_scaling(&self, scaling: N) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.prepend_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to `self` followed by a non-uniform scaling factor.
    #[inline]
    pub fn append_nonuniform_scaling<SB>(
        &self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_nonuniform_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to a non-uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_nonuniform_scaling<SB>(
        &self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.prepend_nonuniform_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to `self` followed by a translation.
    #[inline]
    pub fn append_translation<SB>(&self, shift: &Vector<N, DimNameDiff<D, U1>, SB>) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_translation_mut(shift);
        res
    }

    /// Computes the transformation equal to a translation followed by `self`.
    #[inline]
    pub fn prepend_translation<SB>(
        &self,
        shift: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimNameDiff<D, U1>>,
    {
        let mut res = self.clone_owned();
        res.prepend_translation_mut(shift);
        res
    }
}

impl<N: Scalar + Ring, D: DimName, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
    /// Computes in-place the transformation equal to `self` followed by an uniform scaling factor.
    #[inline]
    pub fn append_scaling_mut(&mut self, scaling: N)
    where D: DimNameSub<U1> {
        let mut to_scale = self.fixed_rows_mut::<DimNameDiff<D, U1>>(0);
        to_scale *= scaling;
    }

    /// Computes in-place the transformation equal to an uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_scaling_mut(&mut self, scaling: N)
    where D: DimNameSub<U1> {
        let mut to_scale = self.fixed_columns_mut::<DimNameDiff<D, U1>>(0);
        to_scale *= scaling;
    }

    /// Computes in-place the transformation equal to `self` followed by a non-uniform scaling factor.
    #[inline]
    pub fn append_nonuniform_scaling_mut<SB>(&mut self, scaling: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..scaling.len() {
            let mut to_scale = self.fixed_rows_mut::<U1>(i);
            to_scale *= scaling[i];
        }
    }

    /// Computes in-place the transformation equal to a non-uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_nonuniform_scaling_mut<SB>(
        &mut self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..scaling.len() {
            let mut to_scale = self.fixed_columns_mut::<U1>(i);
            to_scale *= scaling[i];
        }
    }

    /// Computes the transformation equal to `self` followed by a translation.
    #[inline]
    pub fn append_translation_mut<SB>(&mut self, shift: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..D::dim() {
            for j in 0..D::dim() - 1 {
                self[(j, i)] += shift[j] * self[(D::dim() - 1, i)];
            }
        }
    }

    /// Computes the transformation equal to a translation followed by `self`.
    #[inline]
    pub fn prepend_translation_mut<SB>(&mut self, shift: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, DimNameDiff<D, U1>>,
    {
        let scale = self
            .fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0)
            .tr_dot(&shift);
        let post_translation =
            self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0) * shift;

        self[(D::dim() - 1, D::dim() - 1)] += scale;

        let mut translation = self.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1);
        translation += post_translation;
    }
}

impl<N: Real, D: DimNameSub<U1>> Transformation<Point<N, DimNameDiff<D, U1>>> for MatrixN<N, D>
where DefaultAllocator: Allocator<N, D, D>
        + Allocator<N, DimNameDiff<D, U1>>
        + Allocator<N, DimNameDiff<D, U1>, DimNameDiff<D, U1>>
{
    #[inline]
    fn transform_vector(
        &self,
        v: &VectorN<N, DimNameDiff<D, U1>>,
    ) -> VectorN<N, DimNameDiff<D, U1>>
    {
        let transform = self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0);
        let normalizer = self.fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0);
        let n = normalizer.tr_dot(&v);

        if !n.is_zero() {
            return transform * (v / n);
        }

        transform * v
    }

    #[inline]
    fn transform_point(&self, pt: &Point<N, DimNameDiff<D, U1>>) -> Point<N, DimNameDiff<D, U1>> {
        let transform = self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0);
        let translation = self.fixed_slice::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1);
        let normalizer = self.fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0);
        let n = normalizer.tr_dot(&pt.coords)
            + unsafe { *self.get_unchecked(D::dim() - 1, D::dim() - 1) };

        if !n.is_zero() {
            return transform * (pt / n) + translation;
        }

        transform * pt + translation
    }
}
<commit_msg>Make MatrixN::{transform_vector, transform_point} inherent methods.<commit_after>/*
 *
 * Computer-graphics specific implementations.
 * Currently, it is mostly implemented for homogeneous matrices in 2- and 3-space.
 *
 */

use num::One;

use base::allocator::Allocator;
use base::dimension::{DimName, DimNameDiff, DimNameSub, U1};
use base::storage::{Storage, StorageMut};
use base::{
    DefaultAllocator, Matrix3, Matrix4, MatrixN, Scalar, SquareMatrix, Unit, Vector, Vector3,
    VectorN,
};
use geometry::{
    Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3,
};

use alga::general::{Real, Ring};
use alga::linear::Transformation;

impl<N, D: DimName> MatrixN<N, D>
where
    N: Scalar + Ring,
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Creates a new homogeneous matrix that applies the same scaling factor on each dimension.
    #[inline]
    pub fn new_scaling(scaling: N) -> Self {
        let mut res = Self::from_diagonal_element(scaling);
        res[(D::dim() - 1, D::dim() - 1)] = N::one();

        res
    }

    /// Creates a new homogeneous matrix that applies a distinct scaling factor for each dimension.
    #[inline]
    pub fn new_nonuniform_scaling<SB>(scaling: &Vector<N, DimNameDiff<D, U1>, SB>) -> Self
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        let mut res = Self::one();
        for i in 0..scaling.len() {
            res[(i, i)] = scaling[i];
        }

        res
    }

    /// Creates a new homogeneous matrix that applies a pure translation.
    #[inline]
    pub fn new_translation<SB>(translation: &Vector<N, DimNameDiff<D, U1>, SB>) -> Self
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        let mut res = Self::one();
        res.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1)
            .copy_from(translation);

        res
    }
}

impl<N: Real> Matrix3<N> {
    /// Builds a 2 dimensional homogeneous rotation matrix from an angle in radian.
    #[inline]
    pub fn new_rotation(angle: N) -> Self {
        Rotation2::new(angle).to_homogeneous()
    }
}

impl<N: Real> Matrix4<N> {
    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    #[inline]
    pub fn new_rotation(axisangle: Vector3<N>) -> Self {
        Rotation3::new(axisangle).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    #[inline]
    pub fn new_rotation_wrt_point(axisangle: Vector3<N>, pt: Point3<N>) -> Self {
        let rot = Rotation3::from_scaled_axis(axisangle);
        Isometry::rotation_wrt_point(rot, pt).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together).
    ///
    /// Returns the identity matrix if the given argument is zero.
    /// This is identical to `Self::new_rotation`.
    #[inline]
    pub fn from_scaled_axis(axisangle: Vector3<N>) -> Self {
        Rotation3::from_scaled_axis(axisangle).to_homogeneous()
    }

    /// Creates a new rotation from Euler angles.
    ///
    /// The primitive rotations are applied in order: 1 roll − 2 pitch − 3 yaw.
    pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Self {
        Rotation3::from_euler_angles(roll, pitch, yaw).to_homogeneous()
    }

    /// Builds a 3D homogeneous rotation matrix from an axis and a rotation angle.
    pub fn from_axis_angle(axis: &Unit<Vector3<N>>, angle: N) -> Self {
        Rotation3::from_axis_angle(axis, angle).to_homogeneous()
    }

    /// Creates a new homogeneous matrix for an orthographic projection.
    #[inline]
    pub fn new_orthographic(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> Self {
        Orthographic3::new(left, right, bottom, top, znear, zfar).unwrap()
    }

    /// Creates a new homogeneous matrix for a perspective projection.
    #[inline]
    pub fn new_perspective(aspect: N, fovy: N, znear: N, zfar: N) -> Self {
        Perspective3::new(aspect, fovy, znear, zfar).unwrap()
    }

    /// Creates an isometry that corresponds to the local frame of an observer standing at the
    /// point `eye` and looking toward `target`.
    ///
    /// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
    /// `eye`.
    #[inline]
    pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::new_observer_frame(eye, target, up).to_homogeneous()
    }

    /// Builds a right-handed look-at view matrix.
    #[inline]
    pub fn look_at_rh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::look_at_rh(eye, target, up).to_homogeneous()
    }

    /// Builds a left-handed look-at view matrix.
    #[inline]
    pub fn look_at_lh(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
        IsometryMatrix3::look_at_lh(eye, target, up).to_homogeneous()
    }
}

impl<N: Scalar + Ring, D: DimName, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
    /// Computes the transformation equal to `self` followed by an uniform scaling factor.
    #[inline]
    pub fn append_scaling(&self, scaling: N) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to an uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_scaling(&self, scaling: N) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.prepend_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to `self` followed by a non-uniform scaling factor.
    #[inline]
    pub fn append_nonuniform_scaling<SB>(
        &self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_nonuniform_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to a non-uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_nonuniform_scaling<SB>(
        &self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.prepend_nonuniform_scaling_mut(scaling);
        res
    }

    /// Computes the transformation equal to `self` followed by a translation.
    #[inline]
    pub fn append_translation<SB>(&self, shift: &Vector<N, DimNameDiff<D, U1>, SB>) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D>,
    {
        let mut res = self.clone_owned();
        res.append_translation_mut(shift);
        res
    }

    /// Computes the transformation equal to a translation followed by `self`.
    #[inline]
    pub fn prepend_translation<SB>(
        &self,
        shift: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) -> MatrixN<N, D>
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimNameDiff<D, U1>>,
    {
        let mut res = self.clone_owned();
        res.prepend_translation_mut(shift);
        res
    }
}

impl<N: Scalar + Ring, D: DimName, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
    /// Computes in-place the transformation equal to `self` followed by an uniform scaling factor.
    #[inline]
    pub fn append_scaling_mut(&mut self, scaling: N)
    where D: DimNameSub<U1> {
        let mut to_scale = self.fixed_rows_mut::<DimNameDiff<D, U1>>(0);
        to_scale *= scaling;
    }

    /// Computes in-place the transformation equal to an uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_scaling_mut(&mut self, scaling: N)
    where D: DimNameSub<U1> {
        let mut to_scale = self.fixed_columns_mut::<DimNameDiff<D, U1>>(0);
        to_scale *= scaling;
    }

    /// Computes in-place the transformation equal to `self` followed by a non-uniform scaling factor.
    #[inline]
    pub fn append_nonuniform_scaling_mut<SB>(&mut self, scaling: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..scaling.len() {
            let mut to_scale = self.fixed_rows_mut::<U1>(i);
            to_scale *= scaling[i];
        }
    }

    /// Computes in-place the transformation equal to a non-uniform scaling factor followed by `self`.
    #[inline]
    pub fn prepend_nonuniform_scaling_mut<SB>(
        &mut self,
        scaling: &Vector<N, DimNameDiff<D, U1>, SB>,
    ) where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..scaling.len() {
            let mut to_scale = self.fixed_columns_mut::<U1>(i);
            to_scale *= scaling[i];
        }
    }

    /// Computes the transformation equal to `self` followed by a translation.
    #[inline]
    pub fn append_translation_mut<SB>(&mut self, shift: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
    {
        for i in 0..D::dim() {
            for j in 0..D::dim() - 1 {
                self[(j, i)] += shift[j] * self[(D::dim() - 1, i)];
            }
        }
    }

    /// Computes the transformation equal to a translation followed by `self`.
    #[inline]
    pub fn prepend_translation_mut<SB>(&mut self, shift: &Vector<N, DimNameDiff<D, U1>, SB>)
    where
        D: DimNameSub<U1>,
        SB: Storage<N, DimNameDiff<D, U1>>,
        DefaultAllocator: Allocator<N, DimNameDiff<D, U1>>,
    {
        let scale = self
            .fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0)
            .tr_dot(&shift);
        let post_translation =
            self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0) * shift;

        self[(D::dim() - 1, D::dim() - 1)] += scale;

        let mut translation = self.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1);
        translation += post_translation;
    }
}

impl<N: Real, D: DimNameSub<U1>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
where DefaultAllocator: Allocator<N, D, D>
        + Allocator<N, DimNameDiff<D, U1>>
        + Allocator<N, DimNameDiff<D, U1>, DimNameDiff<D, U1>>
{
    /// Transforms the given vector, assuming the matirx `self` uses homogeneous coordinates.
    #[inline]
    fn transform_vector(
        &self,
        v: &VectorN<N, DimNameDiff<D, U1>>,
    ) -> VectorN<N, DimNameDiff<D, U1>>
    {
        let transform = self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0);
        let normalizer = self.fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0);
        let n = normalizer.tr_dot(&v);

        if !n.is_zero() {
            return transform * (v / n);
        }

        transform * v
    }

    /// Transforms the given point, assuming the matrix `self` uses homogeneous coordinates.
    #[inline]
    fn transform_point(&self, pt: &Point<N, DimNameDiff<D, U1>>) -> Point<N, DimNameDiff<D, U1>> {
        let transform = self.fixed_slice::<DimNameDiff<D, U1>, DimNameDiff<D, U1>>(0, 0);
        let translation = self.fixed_slice::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1);
        let normalizer = self.fixed_slice::<U1, DimNameDiff<D, U1>>(D::dim() - 1, 0);
        let n = normalizer.tr_dot(&pt.coords)
            + unsafe { *self.get_unchecked(D::dim() - 1, D::dim() - 1) };

        if !n.is_zero() {
            return transform * (pt / n) + translation;
        }

        transform * pt + translation
    }
}

impl<N: Real, D: DimNameSub<U1>> Transformation<Point<N, DimNameDiff<D, U1>>> for MatrixN<N, D>
where DefaultAllocator: Allocator<N, D, D>
        + Allocator<N, DimNameDiff<D, U1>>
        + Allocator<N, DimNameDiff<D, U1>, DimNameDiff<D, U1>>
{
    #[inline]
    fn transform_vector(
        &self,
        v: &VectorN<N, DimNameDiff<D, U1>>,
    ) -> VectorN<N, DimNameDiff<D, U1>>
    {
        self.transform_vector(v)
    }

    #[inline]
    fn transform_point(&self, pt: &Point<N, DimNameDiff<D, U1>>) -> Point<N, DimNameDiff<D, U1>> {
        self.transform_point(pt)
    }
}
<|endoftext|>


<commit_before>use crate::gateway::InterMessage;
use std::collections::HashMap;
use std::sync::mpsc::Sender as MpscSender;
use crate::model::id::{ChannelId, GuildId, UserId};
use crate::voice::{Handler, Manager};
use crate::utils;

pub struct ClientVoiceManager {
    managers: HashMap<u64, Manager>,
    shard_count: u64,
    user_id: UserId,
}

impl ClientVoiceManager {
    pub fn new(shard_count: u64, user_id: UserId) -> Self {
        Self {
            managers: HashMap::default(),
            shard_count,
            user_id,
        }
    }

    pub fn get<G: Into<GuildId>>(&self, guild_id: G) -> Option<&Handler> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get(&sid)?.get(gid)
    }

    pub fn get_mut<G: Into<GuildId>>(&mut self, guild_id: G)
        -> Option<&mut Handler> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid)?.get_mut(gid)
    }

    /// Refer to [`Manager::join`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `join` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::join`]: ../../../voice/struct.Manager.html#method.join
    pub fn join<C, G>(&mut self, guild_id: G, channel_id: C)
        -> Option<&mut Handler> where C: Into<ChannelId>, G: Into<GuildId> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.join(gid, channel_id))
    }

    /// Refer to [`Manager::leave`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `leave` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::leave`]: ../../../voice/struct.Manager.html#method.leave
    pub fn leave<G: Into<GuildId>>(&mut self, guild_id: G) -> Option<()> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.leave(gid))
    }

    /// Refer to [`Manager::remove`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `remove` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::remove`]: ../../../voice/struct.Manager.html#method.remove
    pub fn remove<G: Into<GuildId>>(&mut self, guild_id: G) -> Option<()> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.leave(gid))
    }

    pub fn set(&mut self, shard_id: u64, sender: MpscSender<InterMessage>) {
        self.managers.insert(shard_id, Manager::new(sender, self.user_id));
    }

    /// Sets the number of shards for the voice manager to use when calculating
    /// guilds' shard numbers.
    ///
    /// You probably should not call this.
    #[doc(hidden)]
    pub fn set_shard_count(&mut self, shard_count: u64) {
        self.shard_count = shard_count;
    }

    /// Sets the ID of the user for the voice manager.
    ///
    /// You probably _really_ should not call this.
    ///
    /// But it's there if you need it. For some reason.
    #[doc(hidden)]
    pub fn set_user_id(&mut self, user_id: UserId) {
        self.user_id = user_id;
    }

    pub fn manager_get(&self, shard_id: u64) -> Option<&Manager> {
        self.managers.get(&shard_id)
    }

    pub fn manager_get_mut(&mut self, shard_id: u64) -> Option<&mut Manager> {
        self.managers.get_mut(&shard_id)
    }

    pub fn manager_remove(&mut self, shard_id: u64) -> Option<Manager> {
        self.managers.remove(&shard_id)
    }

    fn manager_info<G: Into<GuildId>>(&self, guild_id: G) -> (GuildId, u64) {
        let guild_id = guild_id.into();
        let shard_id = utils::shard_id(guild_id.0, self.shard_count);

        (guild_id, shard_id)
    }
}
<commit_msg>Fix `ClientVoiceManager::remove` to actually call `Manager::remove` (#730)<commit_after>use crate::gateway::InterMessage;
use std::collections::HashMap;
use std::sync::mpsc::Sender as MpscSender;
use crate::model::id::{ChannelId, GuildId, UserId};
use crate::voice::{Handler, Manager};
use crate::utils;

pub struct ClientVoiceManager {
    managers: HashMap<u64, Manager>,
    shard_count: u64,
    user_id: UserId,
}

impl ClientVoiceManager {
    pub fn new(shard_count: u64, user_id: UserId) -> Self {
        Self {
            managers: HashMap::default(),
            shard_count,
            user_id,
        }
    }

    pub fn get<G: Into<GuildId>>(&self, guild_id: G) -> Option<&Handler> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get(&sid)?.get(gid)
    }

    pub fn get_mut<G: Into<GuildId>>(&mut self, guild_id: G)
        -> Option<&mut Handler> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid)?.get_mut(gid)
    }

    /// Refer to [`Manager::join`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `join` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::join`]: ../../../voice/struct.Manager.html#method.join
    pub fn join<C, G>(&mut self, guild_id: G, channel_id: C)
        -> Option<&mut Handler> where C: Into<ChannelId>, G: Into<GuildId> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.join(gid, channel_id))
    }

    /// Refer to [`Manager::leave`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `leave` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::leave`]: ../../../voice/struct.Manager.html#method.leave
    pub fn leave<G: Into<GuildId>>(&mut self, guild_id: G) -> Option<()> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.leave(gid))
    }

    /// Refer to [`Manager::remove`].
    ///
    /// This is a shortcut to retrieving the inner [`Manager`] and then calling
    /// its `remove` method.
    ///
    /// [`Manager`]: ../../../voice/struct.Manager.html
    /// [`Manager::remove`]: ../../../voice/struct.Manager.html#method.remove
    pub fn remove<G: Into<GuildId>>(&mut self, guild_id: G) -> Option<()> {
        let (gid, sid) = self.manager_info(guild_id);

        self.managers.get_mut(&sid).map(|manager| manager.remove(gid))
    }

    pub fn set(&mut self, shard_id: u64, sender: MpscSender<InterMessage>) {
        self.managers.insert(shard_id, Manager::new(sender, self.user_id));
    }

    /// Sets the number of shards for the voice manager to use when calculating
    /// guilds' shard numbers.
    ///
    /// You probably should not call this.
    #[doc(hidden)]
    pub fn set_shard_count(&mut self, shard_count: u64) {
        self.shard_count = shard_count;
    }

    /// Sets the ID of the user for the voice manager.
    ///
    /// You probably _really_ should not call this.
    ///
    /// But it's there if you need it. For some reason.
    #[doc(hidden)]
    pub fn set_user_id(&mut self, user_id: UserId) {
        self.user_id = user_id;
    }

    pub fn manager_get(&self, shard_id: u64) -> Option<&Manager> {
        self.managers.get(&shard_id)
    }

    pub fn manager_get_mut(&mut self, shard_id: u64) -> Option<&mut Manager> {
        self.managers.get_mut(&shard_id)
    }

    pub fn manager_remove(&mut self, shard_id: u64) -> Option<Manager> {
        self.managers.remove(&shard_id)
    }

    fn manager_info<G: Into<GuildId>>(&self, guild_id: G) -> (GuildId, u64) {
        let guild_id = guild_id.into();
        let shard_id = utils::shard_id(guild_id.0, self.shard_count);

        (guild_id, shard_id)
    }
}
<|endoftext|>


<commit_before>use liquid;

use error::*;
use super::FrontmatterBuilder;
use super::slug;

#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub enum SortOrder {
    None,
    Asc,
    Desc,
}

impl Default for SortOrder {
    fn default() -> SortOrder {
        SortOrder::Desc
    }
}

#[derive(Clone, Default, Debug, PartialEq)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct CollectionBuilder {
    pub title: Option<String>,
    pub slug: Option<String>,
    pub description: Option<String>,
    pub dir: Option<String>,
    pub drafts_dir: Option<String>,
    pub include_drafts: bool,
    pub template_extensions: Vec<String>,
    pub ignore: Vec<String>,
    pub order: SortOrder,
    pub rss: Option<String>,
    pub jsonfeed: Option<String>,
    pub base_url: Option<String>,
    pub default: FrontmatterBuilder,
}

impl CollectionBuilder {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn merge_frontmatter(mut self, secondary: FrontmatterBuilder) -> Self {
        self.default = self.default.merge(secondary);
        self
    }

    pub fn build(self) -> Result<Collection> {
        let CollectionBuilder {
            title,
            slug,
            description,
            dir,
            drafts_dir,
            include_drafts,
            template_extensions,
            ignore,
            order,
            rss,
            jsonfeed,
            base_url,
            default,
        } = self;

        let title = title.ok_or("Collection is missing a `title`")?;
        let slug = slug.unwrap_or_else(|| slug::slugify(&title));
        let dir = dir.unwrap_or_else(|| slug.clone());

        if dir.starts_with('/') {
            bail!("Collection {}: dir {} must be a relative path", title, dir)
        }
        if let Some(ref drafts_dir) = drafts_dir {
            if drafts_dir.starts_with('/') {
                bail!("Collection {}: dir {} must be a relative path",
                      title,
                      drafts_dir)
            }
        }

        let mut attributes: liquid::Object =
            vec![("title".to_owned(), liquid::Value::scalar(&title)),
                 ("slug".to_owned(), liquid::Value::scalar(&slug)),
                 ("description".to_owned(),
                  liquid::Value::scalar(description.clone().unwrap_or_else(|| "".to_owned())))]
                .into_iter()
                .collect();
        if let Some(ref rss) = rss {
            attributes.insert("rss".to_owned(), liquid::Value::scalar(rss));
        }
        if let Some(ref jsonfeed) = jsonfeed {
            attributes.insert("jsonfeed".to_owned(), liquid::Value::scalar(jsonfeed));
        }

        let default = default.set_collection(slug.clone());

        let new = Collection {
            title,
            slug,
            description,
            dir,
            drafts_dir,
            include_drafts,
            template_extensions,
            ignore,
            order,
            rss,
            jsonfeed,
            base_url,
            default,
            attributes,
        };
        Ok(new)
    }
}

#[derive(Clone, Default, Debug, PartialEq)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Collection {
    pub title: String,
    pub slug: String,
    pub description: Option<String>,
    pub dir: String,
    pub drafts_dir: Option<String>,
    pub include_drafts: bool,
    pub template_extensions: Vec<String>,
    pub ignore: Vec<String>,
    pub order: SortOrder,
    pub rss: Option<String>,
    pub jsonfeed: Option<String>,
    pub base_url: Option<String>,
    pub default: FrontmatterBuilder,
    pub attributes: liquid::Object,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_build_dir_rel() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.dir = Some("rel".to_owned());
        let collection = collection.build().unwrap();
        assert_eq!(collection.dir, "rel".to_owned());
    }

    #[test]
    fn test_build_dir_abs() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.dir = Some("/root".to_owned());
        let collection = collection.build();
        assert!(collection.is_err());
    }

    #[test]
    fn test_build_drafts_rel() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.drafts_dir = Some("rel".to_owned());
        let collection = collection.build().unwrap();
        assert_eq!(collection.drafts_dir, Some("rel".to_owned()));
    }

    #[test]
    fn test_build_drafts_abs() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.drafts_dir = Some("/root".to_owned());
        let collection = collection.build();
        assert!(collection.is_err());
    }
}
<commit_msg>refactor(drafts): Auto-disable dir if drafts disabled<commit_after>use liquid;

use error::*;
use super::FrontmatterBuilder;
use super::slug;

#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub enum SortOrder {
    None,
    Asc,
    Desc,
}

impl Default for SortOrder {
    fn default() -> SortOrder {
        SortOrder::Desc
    }
}

#[derive(Clone, Default, Debug, PartialEq)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct CollectionBuilder {
    pub title: Option<String>,
    pub slug: Option<String>,
    pub description: Option<String>,
    pub dir: Option<String>,
    pub drafts_dir: Option<String>,
    pub include_drafts: bool,
    pub template_extensions: Vec<String>,
    pub ignore: Vec<String>,
    pub order: SortOrder,
    pub rss: Option<String>,
    pub jsonfeed: Option<String>,
    pub base_url: Option<String>,
    pub default: FrontmatterBuilder,
}

impl CollectionBuilder {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn merge_frontmatter(mut self, secondary: FrontmatterBuilder) -> Self {
        self.default = self.default.merge(secondary);
        self
    }

    pub fn build(self) -> Result<Collection> {
        let CollectionBuilder {
            title,
            slug,
            description,
            dir,
            drafts_dir,
            include_drafts,
            template_extensions,
            ignore,
            order,
            rss,
            jsonfeed,
            base_url,
            default,
        } = self;

        let title = title.ok_or("Collection is missing a `title`")?;
        let slug = slug.unwrap_or_else(|| slug::slugify(&title));
        let dir = dir.unwrap_or_else(|| slug.clone());

        if dir.starts_with('/') {
            bail!("Collection {}: dir {} must be a relative path", title, dir)
        }
        if let Some(ref drafts_dir) = drafts_dir {
            if drafts_dir.starts_with('/') {
                bail!("Collection {}: dir {} must be a relative path",
                      title,
                      drafts_dir)
            }
        }
        let drafts_dir = if include_drafts { drafts_dir } else { None };

        let mut attributes: liquid::Object =
            vec![("title".to_owned(), liquid::Value::scalar(&title)),
                 ("slug".to_owned(), liquid::Value::scalar(&slug)),
                 ("description".to_owned(),
                  liquid::Value::scalar(description.clone().unwrap_or_else(|| "".to_owned())))]
                .into_iter()
                .collect();
        if let Some(ref rss) = rss {
            attributes.insert("rss".to_owned(), liquid::Value::scalar(rss));
        }
        if let Some(ref jsonfeed) = jsonfeed {
            attributes.insert("jsonfeed".to_owned(), liquid::Value::scalar(jsonfeed));
        }

        let default = default.set_collection(slug.clone());

        let new = Collection {
            title,
            slug,
            description,
            dir,
            drafts_dir,
            include_drafts,
            template_extensions,
            ignore,
            order,
            rss,
            jsonfeed,
            base_url,
            default,
            attributes,
        };
        Ok(new)
    }
}

#[derive(Clone, Default, Debug, PartialEq)]
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Collection {
    pub title: String,
    pub slug: String,
    pub description: Option<String>,
    pub dir: String,
    pub drafts_dir: Option<String>,
    pub include_drafts: bool,
    pub template_extensions: Vec<String>,
    pub ignore: Vec<String>,
    pub order: SortOrder,
    pub rss: Option<String>,
    pub jsonfeed: Option<String>,
    pub base_url: Option<String>,
    pub default: FrontmatterBuilder,
    pub attributes: liquid::Object,
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_build_dir_rel() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.dir = Some("rel".to_owned());
        let collection = collection.build().unwrap();
        assert_eq!(collection.dir, "rel".to_owned());
    }

    #[test]
    fn test_build_dir_abs() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.dir = Some("/root".to_owned());
        let collection = collection.build();
        assert!(collection.is_err());
    }

    #[test]
    fn test_build_drafts_rel() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.drafts_dir = Some("rel".to_owned());
        collection.include_drafts = true;
        let collection = collection.build().unwrap();
        assert_eq!(collection.drafts_dir, Some("rel".to_owned()));
    }

    #[test]
    fn test_build_drafts_abs() {
        let mut collection = CollectionBuilder::default();
        collection.title = Some("title".to_owned());
        collection.drafts_dir = Some("/root".to_owned());
        collection.include_drafts = true;
        let collection = collection.build();
        assert!(collection.is_err());
    }
}
<|endoftext|>


<commit_before>/// Machine configuration specifics

use std::io;
use std::path::PathBuf;

use clap::ArgMatches;

pub struct MachineCfg {
    pub kernel_path: Option<PathBuf>,
    pub kernel_cmdline: Option<String>,
}

impl MachineCfg {
    pub fn new() -> Self {
        MachineCfg {
            kernel_path: None,
            kernel_cmdline: Some(String::from(
                "console=ttyS0,115200n8 init=/init tsc=reliable no_timer_check cryptomgr.notests",
            )),
        }
    }

    pub fn populate(&mut self, matches: ArgMatches) -> io::Result<()> {
        if let Some(value) = matches.value_of("kernel_path") {
            self.kernel_path = Some(PathBuf::from(value));
        }

        if let Some(value) = matches.value_of("kernel_cmdline") {
            self.kernel_cmdline = Some(String::from(value));
        }

        Ok(())
    }
}
<commit_msg>vmm: update kernel cmdline to a working one<commit_after>/// Machine configuration specifics

use std::io;
use std::path::PathBuf;

use clap::ArgMatches;

pub struct MachineCfg {
    pub kernel_path: Option<PathBuf>,
    pub kernel_cmdline: Option<String>,
}

impl MachineCfg {
    pub fn new() -> Self {
        MachineCfg {
            kernel_path: None,
            kernel_cmdline: Some(String::from(
                "console=ttyS0 noapic noacpi reboot=k panic=1 pci=off",
            )),
        }
    }

    pub fn populate(&mut self, matches: ArgMatches) -> io::Result<()> {
        if let Some(value) = matches.value_of("kernel_path") {
            self.kernel_path = Some(PathBuf::from(value));
        }

        if let Some(value) = matches.value_of("kernel_cmdline") {
            self.kernel_cmdline = Some(String::from(value));
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//!
//! # Brief summary of Vulkan
//!
//! - The `Instance` object is the API entry point. It is the first object you must create before
//!   starting to use Vulkan.
//!
//! - The `PhysicalDevice` object represents an implementation of Vulkan available on the system
//!   (eg. a graphics card, a CPU implementation, multiple graphics card working together, etc.).
//!   Physical devices can be enumerated from an instance with `PhysicalDevice::enumerate()`.
//!
//! - Once you have chosen a physical device to use, you must a `Device` object from it. The
//!   `Device` is another very important object, as it represents an open channel of
//!   communicaton with the physical device.
//!
//! - `Buffer`s and `Image`s can be used to store data on memory accessible from the GPU (or
//!   Vulkan implementation). Buffers are usually used to store vertices, lights, etc. or
//!   arbitrary data, while images are used to store textures or multi-dimensional data.
//!
//! - In order to show something on the screen, you need a `Swapchain`. A `Swapchain` contains a
//!   special `Image` that corresponds to the content of the window or the monitor. When you
//!   *present* a swapchain, the content of that special image is shown on the screen.
//!
//! - `ComputePipeline`s and `GraphicsPipeline`s describe the way the GPU must perform a certain
//!   operation. `Shader`s are programs that the GPU will execute as part of a pipeline.
//!
//! - `RenderPass`es and `Framebuffer`s describe on which attachments the implementation must draw
//!   on. They are only used for graphical operations.
//!
//! - In order to ask the GPU to do something, you must create a `CommandBuffer`. A `CommandBuffer`
//!   contains a list of commands that the GPU must perform. This can include copies between
//!   buffers, compute operations, or graphics operations. For the work to start, the
//!   `CommandBuffer` must then be submitted to a `Queue`, which is obtained when you create
//!   the `Device`.
//!

//#![warn(missing_docs)]        // TODO: activate
#![allow(dead_code)]            // TODO: remove
#![allow(unused_variables)]     // TODO: remove

extern crate crossbeam;
#[macro_use]
extern crate lazy_static;
extern crate shared_library;
extern crate smallvec;

#[macro_use]
mod tests;

mod features;
mod version;

pub mod buffer;
pub mod command_buffer;
pub mod descriptor_set;
pub mod device;
pub mod format;
pub mod framebuffer;
pub mod image;
pub mod instance;
pub mod memory;
pub mod pipeline;
//pub mod query;
pub mod sampler;
pub mod swapchain;
pub mod sync;

use std::error;
use std::fmt;
use std::mem;
use std::path::Path;
use std::sync::MutexGuard;

mod vk {
    #![allow(dead_code)]
    #![allow(non_upper_case_globals)]
    #![allow(non_snake_case)]
    #![allow(non_camel_case_types)]
    include!(concat!(env!("OUT_DIR"), "/vk_bindings.rs"));
}

lazy_static! {
    static ref VK_LIB: shared_library::dynamic_library::DynamicLibrary = {
        #[cfg(windows)] fn get_path() -> &'static Path { Path::new("vulkan-1.dll") }
        #[cfg(unix)] fn get_path() -> &'static Path { Path::new("libvulkan-1.so") }
        let path = get_path();
        shared_library::dynamic_library::DynamicLibrary::open(Some(path)).unwrap()
    };

    static ref VK_STATIC: vk::Static = {
        vk::Static::load(|name| unsafe {
            VK_LIB.symbol(name.to_str().unwrap()).unwrap()      // TODO: error handling
        })
    };

    static ref VK_ENTRY: vk::EntryPoints = {
        vk::EntryPoints::load(|name| unsafe {
            mem::transmute(VK_STATIC.GetInstanceProcAddr(0, name.as_ptr()))
        })
    };
}

/// Gives access to the internal identifier of an object.
pub unsafe trait VulkanObject {
    /// The type of the object.
    type Object;

    /// Returns a reference to the object.
    fn internal_object(&self) -> Self::Object;
}

/// Gives access to the internal identifier of an object.
pub unsafe trait SynchronizedVulkanObject {
    /// The type of the object.
    type Object;

    /// Returns a reference to the object.
    fn internal_object_guard(&self) -> MutexGuard<Self::Object>;
}

// TODO: remove eventually
// https://github.com/rust-lang/rust/issues/29328
pub unsafe trait VulkanObjectU64 { fn internal_object(&self) -> u64; }
unsafe impl<T> VulkanObjectU64 for T where T: VulkanObject<Object = u64> {
    #[inline]
    fn internal_object(&self) -> u64 { VulkanObject::internal_object(self) }
}
// TODO: remove eventually
// https://github.com/rust-lang/rust/issues/29328
pub unsafe trait VulkanObjectUsize { fn internal_object(&self) -> usize; }
unsafe impl<T> VulkanObjectUsize for T where T: VulkanObject<Object = usize> {
    #[inline]
    fn internal_object(&self) -> usize { VulkanObject::internal_object(self) }
}

/// Gives access to the Vulkan function pointers stored in this object.
trait VulkanPointers {
    /// The struct that provides access to the function pointers.
    type Pointers;

    // Returns a reference to the pointers.
    fn pointers(&self) -> &Self::Pointers;
}

/// Error type returned by most Vulkan functions.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OomError {
    /// There is no memory available on the host (ie. the CPU, RAM, etc.).
    OutOfHostMemory,
    /// There is no memory available on the device (ie. video memory).
    OutOfDeviceMemory,
}

impl error::Error for OomError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            OomError::OutOfHostMemory => "no memory available on the host",
            OomError::OutOfDeviceMemory => "no memory available on the graphical device",
        }
    }
}

impl fmt::Display for OomError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<Error> for OomError {
    #[inline]
    fn from(err: Error) -> OomError {
        match err {
            Error::OutOfHostMemory => OomError::OutOfHostMemory,
            Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory,
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// All possible success codes returned by any Vulkan function.
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
enum Success {
    Success = vk::SUCCESS,
    NotReady = vk::NOT_READY,
    Timeout = vk::TIMEOUT,
    EventSet = vk::EVENT_SET,
    EventReset = vk::EVENT_RESET,
    Incomplete = vk::INCOMPLETE,
    Suboptimal = vk::SUBOPTIMAL_KHR,
}

/// All possible errors returned by any Vulkan function.
///
/// This type is not public. Instead all public error types should implement `From<Error>` and
/// panic for error code that arent supposed to happen.
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
#[doc(hidden)]      // TODO: this is necessary because of the stupid visibility rules in rustc
pub enum Error {
    OutOfHostMemory = vk::ERROR_OUT_OF_HOST_MEMORY,
    OutOfDeviceMemory = vk::ERROR_OUT_OF_DEVICE_MEMORY,
    InitializationFailed = vk::ERROR_INITIALIZATION_FAILED,
    DeviceLost = vk::ERROR_DEVICE_LOST,
    MemoryMapFailed = vk::ERROR_MEMORY_MAP_FAILED,
    LayerNotPresent = vk::ERROR_LAYER_NOT_PRESENT,
    ExtensionNotPresent = vk::ERROR_EXTENSION_NOT_PRESENT,
    FeatureNotPresent = vk::ERROR_FEATURE_NOT_PRESENT,
    IncompatibleDriver = vk::ERROR_INCOMPATIBLE_DRIVER,
    TooManyObjects = vk::ERROR_TOO_MANY_OBJECTS,
    FormatNotSupported = vk::ERROR_FORMAT_NOT_SUPPORTED,
    SurfaceLost = vk::ERROR_SURFACE_LOST_KHR,
    NativeWindowInUse = vk::ERROR_NATIVE_WINDOW_IN_USE_KHR,
    OutOfDate = vk::ERROR_OUT_OF_DATE_KHR,
    IncompatibleDisplay = vk::ERROR_INCOMPATIBLE_DISPLAY_KHR,
    ValidationFailed = vk::ERROR_VALIDATION_FAILED_EXT,
}

/// Checks whether the result returned correctly.
fn check_errors(result: vk::Result) -> Result<Success, Error> {
    match result {
        vk::SUCCESS => Ok(Success::Success),
        vk::NOT_READY => Ok(Success::NotReady),
        vk::TIMEOUT => Ok(Success::Timeout),
        vk::EVENT_SET => Ok(Success::EventSet),
        vk::EVENT_RESET => Ok(Success::EventReset),
        vk::INCOMPLETE => Ok(Success::Incomplete),
        vk::ERROR_OUT_OF_HOST_MEMORY => Err(Error::OutOfHostMemory),
        vk::ERROR_OUT_OF_DEVICE_MEMORY => Err(Error::OutOfDeviceMemory),
        vk::ERROR_INITIALIZATION_FAILED => Err(Error::InitializationFailed),
        vk::ERROR_DEVICE_LOST => Err(Error::DeviceLost),
        vk::ERROR_MEMORY_MAP_FAILED => Err(Error::MemoryMapFailed),
        vk::ERROR_LAYER_NOT_PRESENT => Err(Error::LayerNotPresent),
        vk::ERROR_EXTENSION_NOT_PRESENT => Err(Error::ExtensionNotPresent),
        vk::ERROR_FEATURE_NOT_PRESENT => Err(Error::FeatureNotPresent),
        vk::ERROR_INCOMPATIBLE_DRIVER => Err(Error::IncompatibleDriver),
        vk::ERROR_TOO_MANY_OBJECTS => Err(Error::TooManyObjects),
        vk::ERROR_FORMAT_NOT_SUPPORTED => Err(Error::FormatNotSupported),
        vk::ERROR_SURFACE_LOST_KHR => Err(Error::SurfaceLost),
        vk::ERROR_NATIVE_WINDOW_IN_USE_KHR => Err(Error::NativeWindowInUse),
        vk::SUBOPTIMAL_KHR => Ok(Success::Suboptimal),
        vk::ERROR_OUT_OF_DATE_KHR => Err(Error::OutOfDate),
        vk::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay),
        vk::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed),
        c => unreachable!("Unexpected error code returned by Vulkan: {}", c)
    }
}
<commit_msg>Fix linux library name<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//!
//! # Brief summary of Vulkan
//!
//! - The `Instance` object is the API entry point. It is the first object you must create before
//!   starting to use Vulkan.
//!
//! - The `PhysicalDevice` object represents an implementation of Vulkan available on the system
//!   (eg. a graphics card, a CPU implementation, multiple graphics card working together, etc.).
//!   Physical devices can be enumerated from an instance with `PhysicalDevice::enumerate()`.
//!
//! - Once you have chosen a physical device to use, you must a `Device` object from it. The
//!   `Device` is another very important object, as it represents an open channel of
//!   communicaton with the physical device.
//!
//! - `Buffer`s and `Image`s can be used to store data on memory accessible from the GPU (or
//!   Vulkan implementation). Buffers are usually used to store vertices, lights, etc. or
//!   arbitrary data, while images are used to store textures or multi-dimensional data.
//!
//! - In order to show something on the screen, you need a `Swapchain`. A `Swapchain` contains a
//!   special `Image` that corresponds to the content of the window or the monitor. When you
//!   *present* a swapchain, the content of that special image is shown on the screen.
//!
//! - `ComputePipeline`s and `GraphicsPipeline`s describe the way the GPU must perform a certain
//!   operation. `Shader`s are programs that the GPU will execute as part of a pipeline.
//!
//! - `RenderPass`es and `Framebuffer`s describe on which attachments the implementation must draw
//!   on. They are only used for graphical operations.
//!
//! - In order to ask the GPU to do something, you must create a `CommandBuffer`. A `CommandBuffer`
//!   contains a list of commands that the GPU must perform. This can include copies between
//!   buffers, compute operations, or graphics operations. For the work to start, the
//!   `CommandBuffer` must then be submitted to a `Queue`, which is obtained when you create
//!   the `Device`.
//!

//#![warn(missing_docs)]        // TODO: activate
#![allow(dead_code)]            // TODO: remove
#![allow(unused_variables)]     // TODO: remove

extern crate crossbeam;
#[macro_use]
extern crate lazy_static;
extern crate shared_library;
extern crate smallvec;

#[macro_use]
mod tests;

mod features;
mod version;

pub mod buffer;
pub mod command_buffer;
pub mod descriptor_set;
pub mod device;
pub mod format;
pub mod framebuffer;
pub mod image;
pub mod instance;
pub mod memory;
pub mod pipeline;
//pub mod query;
pub mod sampler;
pub mod swapchain;
pub mod sync;

use std::error;
use std::fmt;
use std::mem;
use std::path::Path;
use std::sync::MutexGuard;

mod vk {
    #![allow(dead_code)]
    #![allow(non_upper_case_globals)]
    #![allow(non_snake_case)]
    #![allow(non_camel_case_types)]
    include!(concat!(env!("OUT_DIR"), "/vk_bindings.rs"));
}

lazy_static! {
    static ref VK_LIB: shared_library::dynamic_library::DynamicLibrary = {
        #[cfg(windows)] fn get_path() -> &'static Path { Path::new("vulkan-1.dll") }
        #[cfg(unix)] fn get_path() -> &'static Path { Path::new("libvulkan.so.1") }
        let path = get_path();
        shared_library::dynamic_library::DynamicLibrary::open(Some(path)).unwrap()
    };

    static ref VK_STATIC: vk::Static = {
        vk::Static::load(|name| unsafe {
            VK_LIB.symbol(name.to_str().unwrap()).unwrap()      // TODO: error handling
        })
    };

    static ref VK_ENTRY: vk::EntryPoints = {
        vk::EntryPoints::load(|name| unsafe {
            mem::transmute(VK_STATIC.GetInstanceProcAddr(0, name.as_ptr()))
        })
    };
}

/// Gives access to the internal identifier of an object.
pub unsafe trait VulkanObject {
    /// The type of the object.
    type Object;

    /// Returns a reference to the object.
    fn internal_object(&self) -> Self::Object;
}

/// Gives access to the internal identifier of an object.
pub unsafe trait SynchronizedVulkanObject {
    /// The type of the object.
    type Object;

    /// Returns a reference to the object.
    fn internal_object_guard(&self) -> MutexGuard<Self::Object>;
}

// TODO: remove eventually
// https://github.com/rust-lang/rust/issues/29328
pub unsafe trait VulkanObjectU64 { fn internal_object(&self) -> u64; }
unsafe impl<T> VulkanObjectU64 for T where T: VulkanObject<Object = u64> {
    #[inline]
    fn internal_object(&self) -> u64 { VulkanObject::internal_object(self) }
}
// TODO: remove eventually
// https://github.com/rust-lang/rust/issues/29328
pub unsafe trait VulkanObjectUsize { fn internal_object(&self) -> usize; }
unsafe impl<T> VulkanObjectUsize for T where T: VulkanObject<Object = usize> {
    #[inline]
    fn internal_object(&self) -> usize { VulkanObject::internal_object(self) }
}

/// Gives access to the Vulkan function pointers stored in this object.
trait VulkanPointers {
    /// The struct that provides access to the function pointers.
    type Pointers;

    // Returns a reference to the pointers.
    fn pointers(&self) -> &Self::Pointers;
}

/// Error type returned by most Vulkan functions.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum OomError {
    /// There is no memory available on the host (ie. the CPU, RAM, etc.).
    OutOfHostMemory,
    /// There is no memory available on the device (ie. video memory).
    OutOfDeviceMemory,
}

impl error::Error for OomError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            OomError::OutOfHostMemory => "no memory available on the host",
            OomError::OutOfDeviceMemory => "no memory available on the graphical device",
        }
    }
}

impl fmt::Display for OomError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<Error> for OomError {
    #[inline]
    fn from(err: Error) -> OomError {
        match err {
            Error::OutOfHostMemory => OomError::OutOfHostMemory,
            Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory,
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

/// All possible success codes returned by any Vulkan function.
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
enum Success {
    Success = vk::SUCCESS,
    NotReady = vk::NOT_READY,
    Timeout = vk::TIMEOUT,
    EventSet = vk::EVENT_SET,
    EventReset = vk::EVENT_RESET,
    Incomplete = vk::INCOMPLETE,
    Suboptimal = vk::SUBOPTIMAL_KHR,
}

/// All possible errors returned by any Vulkan function.
///
/// This type is not public. Instead all public error types should implement `From<Error>` and
/// panic for error code that arent supposed to happen.
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
#[doc(hidden)]      // TODO: this is necessary because of the stupid visibility rules in rustc
pub enum Error {
    OutOfHostMemory = vk::ERROR_OUT_OF_HOST_MEMORY,
    OutOfDeviceMemory = vk::ERROR_OUT_OF_DEVICE_MEMORY,
    InitializationFailed = vk::ERROR_INITIALIZATION_FAILED,
    DeviceLost = vk::ERROR_DEVICE_LOST,
    MemoryMapFailed = vk::ERROR_MEMORY_MAP_FAILED,
    LayerNotPresent = vk::ERROR_LAYER_NOT_PRESENT,
    ExtensionNotPresent = vk::ERROR_EXTENSION_NOT_PRESENT,
    FeatureNotPresent = vk::ERROR_FEATURE_NOT_PRESENT,
    IncompatibleDriver = vk::ERROR_INCOMPATIBLE_DRIVER,
    TooManyObjects = vk::ERROR_TOO_MANY_OBJECTS,
    FormatNotSupported = vk::ERROR_FORMAT_NOT_SUPPORTED,
    SurfaceLost = vk::ERROR_SURFACE_LOST_KHR,
    NativeWindowInUse = vk::ERROR_NATIVE_WINDOW_IN_USE_KHR,
    OutOfDate = vk::ERROR_OUT_OF_DATE_KHR,
    IncompatibleDisplay = vk::ERROR_INCOMPATIBLE_DISPLAY_KHR,
    ValidationFailed = vk::ERROR_VALIDATION_FAILED_EXT,
}

/// Checks whether the result returned correctly.
fn check_errors(result: vk::Result) -> Result<Success, Error> {
    match result {
        vk::SUCCESS => Ok(Success::Success),
        vk::NOT_READY => Ok(Success::NotReady),
        vk::TIMEOUT => Ok(Success::Timeout),
        vk::EVENT_SET => Ok(Success::EventSet),
        vk::EVENT_RESET => Ok(Success::EventReset),
        vk::INCOMPLETE => Ok(Success::Incomplete),
        vk::ERROR_OUT_OF_HOST_MEMORY => Err(Error::OutOfHostMemory),
        vk::ERROR_OUT_OF_DEVICE_MEMORY => Err(Error::OutOfDeviceMemory),
        vk::ERROR_INITIALIZATION_FAILED => Err(Error::InitializationFailed),
        vk::ERROR_DEVICE_LOST => Err(Error::DeviceLost),
        vk::ERROR_MEMORY_MAP_FAILED => Err(Error::MemoryMapFailed),
        vk::ERROR_LAYER_NOT_PRESENT => Err(Error::LayerNotPresent),
        vk::ERROR_EXTENSION_NOT_PRESENT => Err(Error::ExtensionNotPresent),
        vk::ERROR_FEATURE_NOT_PRESENT => Err(Error::FeatureNotPresent),
        vk::ERROR_INCOMPATIBLE_DRIVER => Err(Error::IncompatibleDriver),
        vk::ERROR_TOO_MANY_OBJECTS => Err(Error::TooManyObjects),
        vk::ERROR_FORMAT_NOT_SUPPORTED => Err(Error::FormatNotSupported),
        vk::ERROR_SURFACE_LOST_KHR => Err(Error::SurfaceLost),
        vk::ERROR_NATIVE_WINDOW_IN_USE_KHR => Err(Error::NativeWindowInUse),
        vk::SUBOPTIMAL_KHR => Ok(Success::Suboptimal),
        vk::ERROR_OUT_OF_DATE_KHR => Err(Error::OutOfDate),
        vk::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay),
        vk::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed),
        c => unreachable!("Unexpected error code returned by Vulkan: {}", c)
    }
}
<|endoftext|>