<commit_before>use core::cmp::min;
use core::mem::size_of;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4*1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024*1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4*1024; // Of 4 K chunks

struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

unsafe fn cluster(number: usize) -> usize{
    if number < CLUSTER_COUNT {
        return *((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize);
    }else{
        return 0;
    }
}

unsafe fn set_cluster(number: usize, address: usize){
    if number < CLUSTER_COUNT {
        *((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize) = address;
    }
}

unsafe fn address_to_cluster(address: usize) -> usize {
    return (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>())/CLUSTER_SIZE;
}

unsafe fn cluster_to_address(number: usize) -> usize {
    return CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number*CLUSTER_SIZE;
}

pub unsafe fn cluster_init(){
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x7B00 - 0x500)/size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address >= entry.base as usize && (address + CLUSTER_SIZE) <= (entry.base + entry.len) as usize {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize{
    if size > 0 {
        let mut number = 0;
        let mut count = 0;
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count*CLUSTER_SIZE > size {
                    break;
                }
            }else{
                count = 0;
            }
        }
        if count*CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            return address;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

pub unsafe fn alloc_aligned(size: usize, alignment: usize) -> usize{
    if size > 0 {
        let mut number = 0;
        let mut count = 0;
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    if cluster_to_address(i) % alignment == 0 {
                        number = i;
                    }else{
                        continue;
                    }
                }
                count += 1;
                if count*CLUSTER_SIZE > size {
                    break;
                }
            }else{
                count = 0;
            }
        }
        if count*CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            return address;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            }
        }
    }

    return size;
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
        return 0;
    }

    let old_size = alloc_size(ptr);
    if size <= old_size {
        return ptr;
    }else{
        let new = alloc(size);
        if ptr > 0 {
            if new > 0 {
                let copy_size = min(old_size, size);

                let mut i = 0;
                while i < copy_size - size_of::<usize>() {
                    *(new as *mut usize).offset(i as isize) = *(ptr as *const usize).offset(i as isize);
                    i += size_of::<usize>();
                }
                while i < copy_size {
                    *(new as *mut u8).offset(i as isize) = *(ptr as *const u8).offset(i as isize);
                    i += size_of::<u8>();
                }
            }
            unalloc(ptr);
        }
        return new;
    }
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        return size;
    }else{
        return old_size;
    }
}

pub unsafe fn unalloc(ptr: usize){
    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            }
        }
    }
}

pub fn memory_used() -> usize{
    let mut ret = 0;
    unsafe{
        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }
    }
    return ret;
}

pub fn memory_free() -> usize{
    let mut ret = 0;
    unsafe{
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }
    }
    return ret;
}
<commit_msg>Fix for large memory systems<commit_after>use core::cmp::min;
use core::mem::size_of;

pub const PAGE_DIRECTORY: usize = 0x300000;
pub const PAGE_TABLE_SIZE: usize = 1024;
pub const PAGE_TABLES: usize = PAGE_DIRECTORY + PAGE_TABLE_SIZE * 4;
pub const PAGE_SIZE: usize = 4*1024;

pub const CLUSTER_ADDRESS: usize = PAGE_TABLES + PAGE_TABLE_SIZE * PAGE_TABLE_SIZE * 4 ;
pub const CLUSTER_COUNT: usize = 1024*1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4*1024; // Of 4 K chunks

struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

unsafe fn cluster(number: usize) -> usize{
    if number < CLUSTER_COUNT {
        return *((CLUSTER_ADDRESS + number * size_of::<usize>()) as *const usize);
    }else{
        return 0;
    }
}

unsafe fn set_cluster(number: usize, address: usize){
    if number < CLUSTER_COUNT {
        *((CLUSTER_ADDRESS + number * size_of::<usize>()) as *mut usize) = address;
    }
}

unsafe fn address_to_cluster(address: usize) -> usize {
    return (address - CLUSTER_ADDRESS - CLUSTER_COUNT * size_of::<usize>())/CLUSTER_SIZE;
}

unsafe fn cluster_to_address(number: usize) -> usize {
    return CLUSTER_ADDRESS + CLUSTER_COUNT * size_of::<usize>() + number*CLUSTER_SIZE;
}

pub unsafe fn cluster_init(){
    //First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    //Next, set all valid clusters to the free value
    //TODO: Optimize this function
    for i in 0..((0x7B00 - 0x500)/size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base && (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

pub unsafe fn alloc(size: usize) -> usize{
    if size > 0 {
        let mut number = 0;
        let mut count = 0;
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count*CLUSTER_SIZE > size {
                    break;
                }
            }else{
                count = 0;
            }
        }
        if count*CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            return address;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

pub unsafe fn alloc_aligned(size: usize, alignment: usize) -> usize{
    if size > 0 {
        let mut number = 0;
        let mut count = 0;
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    if cluster_to_address(i) % alignment == 0 {
                        number = i;
                    }else{
                        continue;
                    }
                }
                count += 1;
                if count*CLUSTER_SIZE > size {
                    break;
                }
            }else{
                count = 0;
            }
        }
        if count*CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            return address;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            }
        }
    }

    return size;
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
        return 0;
    }

    let old_size = alloc_size(ptr);
    if size <= old_size {
        return ptr;
    }else{
        let new = alloc(size);
        if ptr > 0 {
            if new > 0 {
                let copy_size = min(old_size, size);

                let mut i = 0;
                while i < copy_size - size_of::<usize>() {
                    *(new as *mut usize).offset(i as isize) = *(ptr as *const usize).offset(i as isize);
                    i += size_of::<usize>();
                }
                while i < copy_size {
                    *(new as *mut u8).offset(i as isize) = *(ptr as *const u8).offset(i as isize);
                    i += size_of::<u8>();
                }
            }
            unalloc(ptr);
        }
        return new;
    }
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        return size;
    }else{
        return old_size;
    }
}

pub unsafe fn unalloc(ptr: usize){
    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            }
        }
    }
}

pub fn memory_used() -> usize{
    let mut ret = 0;
    unsafe{
        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }
    }
    return ret;
}

pub fn memory_free() -> usize{
    let mut ret = 0;
    unsafe{
        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }
    }
    return ret;
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::{gl, Texture, Sampler};
use super::gl::types::{GLenum, GLuint, GLint, GLfloat, GLsizei, GLvoid};
use tex::*;
use Blob;

fn kind_to_gl(t: ::tex::TextureKind) -> GLenum {
    match t {
        Texture1D => gl::TEXTURE_1D,
        Texture1DArray => gl::TEXTURE_1D_ARRAY,
        Texture2D => gl::TEXTURE_2D,
        Texture2DArray => gl::TEXTURE_2D_ARRAY,
        TextureCube => gl::TEXTURE_CUBE_MAP,
        Texture3D => gl::TEXTURE_3D,
    }
}

fn format_to_gl(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 => gl::RGB8,
        RGBA8 => gl::RGBA8,
    }
}

fn format_to_glpixel(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 => gl::RGB,
        RGBA8 => gl::RGBA
    }
}

fn format_to_gltype(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 | RGBA8 => gl::UNSIGNED_BYTE,
    }
}

/// Create a texture, assuming TexStorage* isn't available.
pub fn make_without_storage(info: ::tex::TextureInfo) -> Texture {
    let name = make_texture(info);

    let fmt = format_to_gl(info.format) as GLint;
    let pix = format_to_glpixel(info.format);
    let typ = format_to_gltype(info.format);

    let kind = kind_to_gl(info.kind);

    unsafe {
        match info.kind {
            Texture1D => {
                gl::TexImage1D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            Texture1DArray => {
                gl::TexImage2D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            Texture2D => {
                gl::TexImage2D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            TextureCube => unimplemented!(),
            Texture2DArray | Texture3D => {
                gl::TexImage3D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    info.depth as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
        }
    }

    name
}

/// Create a texture, assuming TexStorage is available.
pub fn make_with_storage(info: ::tex::TextureInfo) -> Texture {
    use std::cmp::max;

    fn min(a: u8, b: u8) -> GLint {
        ::std::cmp::min(a, b) as GLint
    }

    fn mip_level1(w: u16) -> u8 {
        ((w as f32).log2() + 1.0) as u8
    }

    fn mip_level2(w: u16, h: u16) -> u8 {
        ((max(w, h) as f32).log2() + 1.0) as u8
    }

    fn mip_level3(w: u16, h: u16, d: u16) -> u8 {
        ((max(w, max(h, d)) as f32).log2() + 1.0) as u8
    }

    let name = make_texture(info);

    let fmt = format_to_gl(info.format);
    let kind = kind_to_gl(info.kind);

    match info.kind {
        Texture1D => {
            gl::TexStorage1D(
                kind,
                min(info.mipmap_range.val1(), mip_level1(info.width)),
                fmt,
                info.width as GLsizei
            );
        },
        Texture1DArray => {
            gl::TexStorage2D(
                kind,
                min(info.mipmap_range.val1(), mip_level1(info.width)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
            );
        },
        Texture2D => {
            gl::TexStorage2D(
                kind,
                min(info.mipmap_range.val1(), mip_level2(info.width, info.height)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
            );
        },
        TextureCube => unimplemented!(),
        Texture2DArray => {
            gl::TexStorage3D(
                kind,
                min(info.mipmap_range.val1(), mip_level2(info.width, info.height)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
                info.depth as GLsizei,
            );
        },
        Texture3D => {
            gl::TexStorage3D(
                kind,
                min(info.mipmap_range.val1(), mip_level3(info.width, info.height, info.depth)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
                info.depth as GLsizei,
            );
        },
    }

    name
}

/// Bind a texture + sampler to a given slot.
pub fn bind_texture(loc: GLuint, tex: Texture, sam: Sampler, info: ::tex::TextureInfo) {
    gl::ActiveTexture(gl::TEXTURE0 + loc as GLenum);
    gl::BindSampler(loc, sam);
    gl::BindTexture(kind_to_gl(info.kind), tex);
}

pub fn update_texture(tex: Texture, img: ::tex::ImageInfo, tex_info: ::tex::TextureInfo,
                      data: Box<Blob + Send>) {
    let data = data.get_address() as *const GLvoid;
    let pix = format_to_glpixel(tex_info.format);
    let typ = format_to_gltype(tex_info.format);

    gl::BindTexture(kind_to_gl(tex_info.kind), tex);

    unsafe {
        match tex_info.kind {
            Texture1D => {
                gl::TexSubImage1D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.width as GLint,
                    pix,
                    typ,
                    data,
                );
            },
            Texture1DArray | Texture2D => {
                gl::TexSubImage2D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.yoffset as GLint,
                    img.width as GLint,
                    img.height as GLint,
                    pix,
                    typ,
                    data,
                );
            },
            TextureCube => unimplemented!(),
            Texture2DArray | Texture3D => {
                gl::TexSubImage3D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.yoffset as GLint,
                    img.zoffset as GLint,
                    img.width as GLint,
                    img.height as GLint,
                    img.depth as GLint,
                    pix,
                    typ,
                    data,
                );
            }
        }
    }
}

/// Common texture creation routine, just binds and sets mipmap ranges.
fn make_texture(info: ::tex::TextureInfo) -> Texture {
    let mut name = 0 as Texture;
    unsafe {
        gl::GenTextures(1, &mut name);
    }

    let k = kind_to_gl(info.kind);
    gl::BindTexture(k, name);

    let (base, max) = info.mipmap_range;
    gl::TexParameteri(k, gl::TEXTURE_BASE_LEVEL, base as GLint);
    gl::TexParameteri(k, gl::TEXTURE_MAX_LEVEL, max as GLint);

    name
}

fn wrap_to_gl(w: WrapMode) -> GLenum {
    match w {
        Tile => gl::REPEAT,
        Mirror => gl::MIRRORED_REPEAT,
        Clamp => gl::CLAMP_TO_EDGE
    }
}

pub fn make_sampler(info: ::tex::SamplerInfo) -> Sampler {
    let mut name = 0 as Sampler;
    unsafe {
        gl::GenSamplers(1, &mut name);
    }

    fn tup<T: Copy>(v: T) -> (T, T) { (v, v) }

    let (min, mag) = match info.filtering {
        Scale => tup(gl::NEAREST),
        Mipmap => tup(gl::NEAREST_MIPMAP_NEAREST),
        Bilinear => tup(gl::LINEAR_MIPMAP_NEAREST),
        Trilinear => tup(gl::LINEAR_MIPMAP_LINEAR),
        Anisotropic(fac) => {
            gl::SamplerParameterf(name, gl::TEXTURE_MAX_ANISOTROPY_EXT, fac as GLfloat);
            tup(gl::LINEAR_MIPMAP_LINEAR)
        }
    };

    gl::SamplerParameteri(name, gl::TEXTURE_MIN_FILTER, min as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_MAG_FILTER, mag as GLint);

    let (s, t, r) = info.wrap_mode;
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_S, wrap_to_gl(s) as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_T, wrap_to_gl(t) as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_R, wrap_to_gl(r) as GLint);

    gl::SamplerParameteri(name, gl::TEXTURE_LOD_BIAS, info.lod_bias as GLint);

    let (base, max) = info.mipmap_range;
    gl::SamplerParameteri(name, gl::TEXTURE_BASE_LEVEL, base as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_MAX_LEVEL, max as GLint);

    name
}
<commit_msg>Fix mag filter<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::{gl, Texture, Sampler};
use super::gl::types::{GLenum, GLuint, GLint, GLfloat, GLsizei, GLvoid};
use tex::*;
use Blob;

fn kind_to_gl(t: ::tex::TextureKind) -> GLenum {
    match t {
        Texture1D => gl::TEXTURE_1D,
        Texture1DArray => gl::TEXTURE_1D_ARRAY,
        Texture2D => gl::TEXTURE_2D,
        Texture2DArray => gl::TEXTURE_2D_ARRAY,
        TextureCube => gl::TEXTURE_CUBE_MAP,
        Texture3D => gl::TEXTURE_3D,
    }
}

fn format_to_gl(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 => gl::RGB8,
        RGBA8 => gl::RGBA8,
    }
}

fn format_to_glpixel(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 => gl::RGB,
        RGBA8 => gl::RGBA
    }
}

fn format_to_gltype(t: ::tex::TextureFormat) -> GLenum {
    match t {
        RGB8 | RGBA8 => gl::UNSIGNED_BYTE,
    }
}

/// Create a texture, assuming TexStorage* isn't available.
pub fn make_without_storage(info: ::tex::TextureInfo) -> Texture {
    let name = make_texture(info);

    let fmt = format_to_gl(info.format) as GLint;
    let pix = format_to_glpixel(info.format);
    let typ = format_to_gltype(info.format);

    let kind = kind_to_gl(info.kind);

    unsafe {
        match info.kind {
            Texture1D => {
                gl::TexImage1D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            Texture1DArray => {
                gl::TexImage2D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            Texture2D => {
                gl::TexImage2D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
            TextureCube => unimplemented!(),
            Texture2DArray | Texture3D => {
                gl::TexImage3D(
                    kind,
                    0,
                    fmt,
                    info.width as GLsizei,
                    info.height as GLsizei,
                    info.depth as GLsizei,
                    0,
                    pix,
                    typ,
                    ::std::ptr::null(),
                );
            },
        }
    }

    name
}

/// Create a texture, assuming TexStorage is available.
pub fn make_with_storage(info: ::tex::TextureInfo) -> Texture {
    use std::cmp::max;

    fn min(a: u8, b: u8) -> GLint {
        ::std::cmp::min(a, b) as GLint
    }

    fn mip_level1(w: u16) -> u8 {
        ((w as f32).log2() + 1.0) as u8
    }

    fn mip_level2(w: u16, h: u16) -> u8 {
        ((max(w, h) as f32).log2() + 1.0) as u8
    }

    fn mip_level3(w: u16, h: u16, d: u16) -> u8 {
        ((max(w, max(h, d)) as f32).log2() + 1.0) as u8
    }

    let name = make_texture(info);

    let fmt = format_to_gl(info.format);
    let kind = kind_to_gl(info.kind);

    match info.kind {
        Texture1D => {
            gl::TexStorage1D(
                kind,
                min(info.mipmap_range.val1(), mip_level1(info.width)),
                fmt,
                info.width as GLsizei
            );
        },
        Texture1DArray => {
            gl::TexStorage2D(
                kind,
                min(info.mipmap_range.val1(), mip_level1(info.width)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
            );
        },
        Texture2D => {
            gl::TexStorage2D(
                kind,
                min(info.mipmap_range.val1(), mip_level2(info.width, info.height)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
            );
        },
        TextureCube => unimplemented!(),
        Texture2DArray => {
            gl::TexStorage3D(
                kind,
                min(info.mipmap_range.val1(), mip_level2(info.width, info.height)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
                info.depth as GLsizei,
            );
        },
        Texture3D => {
            gl::TexStorage3D(
                kind,
                min(info.mipmap_range.val1(), mip_level3(info.width, info.height, info.depth)),
                fmt,
                info.width as GLsizei,
                info.height as GLsizei,
                info.depth as GLsizei,
            );
        },
    }

    name
}

/// Bind a texture + sampler to a given slot.
pub fn bind_texture(loc: GLuint, tex: Texture, sam: Sampler, info: ::tex::TextureInfo) {
    gl::ActiveTexture(gl::TEXTURE0 + loc as GLenum);
    gl::BindSampler(loc, sam);
    gl::BindTexture(kind_to_gl(info.kind), tex);
}

pub fn update_texture(tex: Texture, img: ::tex::ImageInfo, tex_info: ::tex::TextureInfo,
                      data: Box<Blob + Send>) {
    let data = data.get_address() as *const GLvoid;
    let pix = format_to_glpixel(tex_info.format);
    let typ = format_to_gltype(tex_info.format);

    gl::BindTexture(kind_to_gl(tex_info.kind), tex);

    unsafe {
        match tex_info.kind {
            Texture1D => {
                gl::TexSubImage1D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.width as GLint,
                    pix,
                    typ,
                    data,
                );
            },
            Texture1DArray | Texture2D => {
                gl::TexSubImage2D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.yoffset as GLint,
                    img.width as GLint,
                    img.height as GLint,
                    pix,
                    typ,
                    data,
                );
            },
            TextureCube => unimplemented!(),
            Texture2DArray | Texture3D => {
                gl::TexSubImage3D(
                    kind_to_gl(tex_info.kind),
                    img.mipmap as GLint,
                    img.xoffset as GLint,
                    img.yoffset as GLint,
                    img.zoffset as GLint,
                    img.width as GLint,
                    img.height as GLint,
                    img.depth as GLint,
                    pix,
                    typ,
                    data,
                );
            }
        }
    }
}

/// Common texture creation routine, just binds and sets mipmap ranges.
fn make_texture(info: ::tex::TextureInfo) -> Texture {
    let mut name = 0 as Texture;
    unsafe {
        gl::GenTextures(1, &mut name);
    }

    let k = kind_to_gl(info.kind);
    gl::BindTexture(k, name);

    let (base, max) = info.mipmap_range;
    gl::TexParameteri(k, gl::TEXTURE_BASE_LEVEL, base as GLint);
    gl::TexParameteri(k, gl::TEXTURE_MAX_LEVEL, max as GLint);

    name
}

fn wrap_to_gl(w: WrapMode) -> GLenum {
    match w {
        Tile => gl::REPEAT,
        Mirror => gl::MIRRORED_REPEAT,
        Clamp => gl::CLAMP_TO_EDGE
    }
}

pub fn make_sampler(info: ::tex::SamplerInfo) -> Sampler {
    let mut name = 0 as Sampler;
    unsafe {
        gl::GenSamplers(1, &mut name);
    }

    let (min, mag) = match info.filtering {
        Scale => (gl::NEAREST, gl::NEAREST),
        Mipmap => (gl::NEAREST_MIPMAP_NEAREST, gl::NEAREST),
        Bilinear => (gl::LINEAR_MIPMAP_NEAREST, gl::LINEAR),
        Trilinear => (gl::LINEAR_MIPMAP_LINEAR, gl::LINEAR),
        Anisotropic(fac) => {
            gl::SamplerParameterf(name, gl::TEXTURE_MAX_ANISOTROPY_EXT, fac as GLfloat);
            (gl::LINEAR_MIPMAP_LINEAR, gl::LINEAR)
        }
    };

    gl::SamplerParameteri(name, gl::TEXTURE_MIN_FILTER, min as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_MAG_FILTER, mag as GLint);

    let (s, t, r) = info.wrap_mode;
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_S, wrap_to_gl(s) as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_T, wrap_to_gl(t) as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_WRAP_R, wrap_to_gl(r) as GLint);

    gl::SamplerParameteri(name, gl::TEXTURE_LOD_BIAS, info.lod_bias as GLint);

    let (base, max) = info.mipmap_range;
    gl::SamplerParameteri(name, gl::TEXTURE_BASE_LEVEL, base as GLint);
    gl::SamplerParameteri(name, gl::TEXTURE_MAX_LEVEL, max as GLint);

    name
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::io;

use externalfiles::ExternalHtml;

#[deriving(Clone)]
pub struct Layout {
    pub logo: String,
    pub favicon: String,
    pub external_html: ExternalHtml,
    pub krate: String,
    pub playground_url: String,
}

pub struct Page<'a> {
    pub title: &'a str,
    pub ty: &'a str,
    pub root_path: &'a str,
    pub description: &'a str,
    pub keywords: &'a str
}

pub fn render<T: fmt::Show, S: fmt::Show>(
    dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
    -> io::IoResult<()>
{
    write!(dst,
r##"<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <meta name="description" content="{description}">
    <meta name="keywords" content="{keywords}">

    <title>{title}</title>

    <link rel="stylesheet" type="text/css" href="{root_path}main.css">

    {favicon}
    {in_header}

    {before_content}

        {logo}
        {sidebar}

        <form class="search-form js-only">

                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Click or press 'S' to search, '?' for more options..."
                       type="search">

        </form>

{content}

Keyboard shortcuts

?

Show this help dialog

S

Focus the search field

⇤

Move up in search results

⇥

Move down in search results

⏎

Go to active search result

Search tricks

                Prefix searches with a type followed by a colon (e.g.
                fn:) to restrict the search to a given type.

                Accepted types are: fn, mod,
                struct, enum,
                trait, typedef (or
                tdef).

    {after_content}

    {play_js}

"##,
    content   = *t,
    root_path = page.root_path,
    ty        = page.ty,
    logo      = if layout.logo.len() == 0 {
        "".to_string()
    } else {
        format!("\
                 ",
                page.root_path, layout.krate,
                layout.logo)
    },
    title     = page.title,
    description = page.description,
    keywords = page.keywords,
    favicon   = if layout.favicon.len() == 0 {
        "".to_string()
    } else {
        format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
    },
    in_header = layout.external_html.in_header,
    before_content = layout.external_html.before_content,
    after_content = layout.external_html.after_content,
    sidebar   = *sidebar,
    krate     = layout.krate,
    play_url  = layout.playground_url,
    play_js   = if layout.playground_url.len() == 0 {
        "".to_string()
    } else {
        format!(r#""#, page.root_path)
    },
    )
}

pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
    write!(dst,
r##"<!DOCTYPE html>

    <meta http-equiv="refresh" content="0;URL={url}">

"##,
    url = url,
    )
}
<commit_msg>rollup merge of #19513: lifthrasiir/rustdoc-fat-redirect<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::io;

use externalfiles::ExternalHtml;

#[deriving(Clone)]
pub struct Layout {
    pub logo: String,
    pub favicon: String,
    pub external_html: ExternalHtml,
    pub krate: String,
    pub playground_url: String,
}

pub struct Page<'a> {
    pub title: &'a str,
    pub ty: &'a str,
    pub root_path: &'a str,
    pub description: &'a str,
    pub keywords: &'a str
}

pub fn render<T: fmt::Show, S: fmt::Show>(
    dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
    -> io::IoResult<()>
{
    write!(dst,
r##"<!DOCTYPE html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <meta name="description" content="{description}">
    <meta name="keywords" content="{keywords}">

    <title>{title}</title>

    <link rel="stylesheet" type="text/css" href="{root_path}main.css">

    {favicon}
    {in_header}

    {before_content}

        {logo}
        {sidebar}

        <form class="search-form js-only">

                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Click or press 'S' to search, '?' for more options..."
                       type="search">

        </form>

{content}

Keyboard shortcuts

?

Show this help dialog

S

Focus the search field

⇤

Move up in search results

⇥

Move down in search results

⏎

Go to active search result

Search tricks

                Prefix searches with a type followed by a colon (e.g.
                fn:) to restrict the search to a given type.

                Accepted types are: fn, mod,
                struct, enum,
                trait, typedef (or
                tdef).

    {after_content}

    {play_js}

"##,
    content   = *t,
    root_path = page.root_path,
    ty        = page.ty,
    logo      = if layout.logo.len() == 0 {
        "".to_string()
    } else {
        format!("\
                 ",
                page.root_path, layout.krate,
                layout.logo)
    },
    title     = page.title,
    description = page.description,
    keywords = page.keywords,
    favicon   = if layout.favicon.len() == 0 {
        "".to_string()
    } else {
        format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
    },
    in_header = layout.external_html.in_header,
    before_content = layout.external_html.before_content,
    after_content = layout.external_html.after_content,
    sidebar   = *sidebar,
    krate     = layout.krate,
    play_url  = layout.playground_url,
    play_js   = if layout.playground_url.len() == 0 {
        "".to_string()
    } else {
        format!(r#""#, page.root_path)
    },
    )
}

pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
    //

"##,
    url = url,
    )
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

use core::prelude::*;

use cmp;
use ffi::CString;
use io;
use libc::consts::os::posix01::PTHREAD_STACK_MIN;
use libc;
use mem;
use ptr;
use sys::os;
use thunk::Thunk;
use time::Duration;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "bitrig"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> usize { 0 }
    pub unsafe fn main() -> usize { 0 }
    pub unsafe fn init() {}
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "bitrig",
          target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
    use libc::{self, pthread_t};
    use libc::funcs::posix88::mman::mmap;
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};
    use mem;
    use ptr;
    use super::{pthread_self, pthread_attr_destroy};
    use sys::os;

    // These are initialized in init() and only read from after
    static mut GUARD_PAGE: usize = 0;

    #[cfg(any(target_os = "macos",
              target_os = "bitrig",
              target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);
        stackaddr
    }

    pub unsafe fn init() {
        let psize = os::page_size();
        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % psize;
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + psize - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          psize as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {2} else {1};

        GUARD_PAGE = stackaddr as usize + offset * psize;
    }

    pub unsafe fn main() -> usize {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> usize {
        extern {
            fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
            fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
        }
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as usize
    }

    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
    pub unsafe fn current() -> usize {
        #[repr(C)]
        struct stack_t {
            ss_sp: *mut libc::c_void,
            ss_size: libc::size_t,
            ss_flags: libc::c_int,
        }
        extern {
            fn pthread_main_np() -> libc::c_uint;
            fn pthread_stackseg_np(thread: pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        }

        let mut current_stack: stack_t = mem::zeroed();
        assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);

        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
        } else {
            // new thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> usize {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut guardsize = 0;
        assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut size = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);

        stackaddr as usize + guardsize as usize
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    extern {
        fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
        fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
    }
}

pub unsafe fn create(stack: usize, p: Thunk) -> io::Result<rust_thread> {
    let p = box p;
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as usize);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {}
        n => {
            assert_eq!(n, libc::EINVAL);
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = os::page_size();
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as isize - 1) as usize - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr,
                                                 stack_size as libc::size_t), 0);
        }
    };

    let ret = pthread_create(&mut native, &attr, thread_start,
                             &*p as *const _ as *mut _);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    return if ret != 0 {
        Err(io::Error::from_os_error(ret))
    } else {
        mem::forget(p); // ownership passed to pthread_create
        Ok(native)
    };

    #[no_stack_check]
    extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
        start_thread(main);
        0 as *mut _
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since glibc 2.12
    // availability autodetected via weak linkage
    type F = unsafe extern fn(libc::pthread_t, *const libc::c_char)
                              -> libc::c_int;
    extern {
        #[linkage = "extern_weak"]
        static pthread_setname_np: *const ();
    }
    if !pthread_setname_np.is_null() {
        let cname = CString::new(name).unwrap();
        mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(),
                                                           cname.as_ptr());
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
    }
    let cname = CString::new(name).unwrap();
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
    }
    let cname = CString::new(name).unwrap();
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() {
    assert_eq!(sched_yield(), 0);
}

pub fn sleep(dur: Duration) {
    unsafe {
        if dur < Duration::zero() {
            return yield_now()
        }
        let seconds = dur.num_seconds();
        let ns = dur - Duration::seconds(seconds);
        let mut ts = libc::timespec {
            tv_sec: seconds as libc::time_t,
            tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long,
        };
        // If we're awoken with a signal then the return value will be -1 and
        // nanosleep will fill in `ts` with the remaining time.
        while dosleep(&mut ts) == -1 {
            assert_eq!(os::errno(), libc::EINTR);
        }
    }

    #[cfg(target_os = "linux")]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        extern {
            fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int,
                               request: *const libc::timespec,
                               remain: *mut libc::timespec) -> libc::c_int;
        }
        clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts)
    }
    #[cfg(not(target_os = "linux"))]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        libc::nanosleep(ts, ts)
    }
}

// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Link weakly to the symbol for compatibility with older versions of glibc.
// Assumes that we've been dynamically linked to libpthread but that is
// currently always the case.  Note that you need to check that the symbol
// is non-null before calling it!
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    extern {
        #[linkage = "extern_weak"]
        static __pthread_get_minstack: *const ();
    }
    if __pthread_get_minstack.is_null() {
        PTHREAD_STACK_MIN
    } else {
        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
    }
}

// __pthread_get_minstack() is marked as weak but extern_weak linkage is
// not supported on OS X, hence this kludge...
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

extern {
    fn pthread_self() -> libc::pthread_t;
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: extern fn(*mut libc::c_void) -> *mut libc::c_void,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<commit_msg>prctl instead of pthread on linux for name setup<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

use core::prelude::*;

use cmp;
use ffi::CString;
use io;
use libc::consts::os::posix01::PTHREAD_STACK_MIN;
use libc;
use mem;
use ptr;
use sys::os;
use thunk::Thunk;
use time::Duration;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "bitrig"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> usize { 0 }
    pub unsafe fn main() -> usize { 0 }
    pub unsafe fn init() {}
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "bitrig",
          target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
    use libc::{self, pthread_t};
    use libc::funcs::posix88::mman::mmap;
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};
    use mem;
    use ptr;
    use super::{pthread_self, pthread_attr_destroy};
    use sys::os;

    // These are initialized in init() and only read from after
    static mut GUARD_PAGE: usize = 0;

    #[cfg(any(target_os = "macos",
              target_os = "bitrig",
              target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);
        stackaddr
    }

    pub unsafe fn init() {
        let psize = os::page_size();
        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % psize;
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + psize - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          psize as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {2} else {1};

        GUARD_PAGE = stackaddr as usize + offset * psize;
    }

    pub unsafe fn main() -> usize {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> usize {
        extern {
            fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
            fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
        }
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as usize
    }

    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
    pub unsafe fn current() -> usize {
        #[repr(C)]
        struct stack_t {
            ss_sp: *mut libc::c_void,
            ss_size: libc::size_t,
            ss_flags: libc::c_int,
        }
        extern {
            fn pthread_main_np() -> libc::c_uint;
            fn pthread_stackseg_np(thread: pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        }

        let mut current_stack: stack_t = mem::zeroed();
        assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);

        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
        } else {
            // new thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> usize {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut guardsize = 0;
        assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut size = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);

        stackaddr as usize + guardsize as usize
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    extern {
        fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
        fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
    }
}

pub unsafe fn create(stack: usize, p: Thunk) -> io::Result<rust_thread> {
    let p = box p;
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as usize);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {}
        n => {
            assert_eq!(n, libc::EINVAL);
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = os::page_size();
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as isize - 1) as usize - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr,
                                                 stack_size as libc::size_t), 0);
        }
    };

    let ret = pthread_create(&mut native, &attr, thread_start,
                             &*p as *const _ as *mut _);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    return if ret != 0 {
        Err(io::Error::from_os_error(ret))
    } else {
        mem::forget(p); // ownership passed to pthread_create
        Ok(native)
    };

    #[no_stack_check]
    extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
        start_thread(main);
        0 as *mut _
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread wrapper only appeared in glibc 2.12, so we use syscall directly.
    extern {
        fn prctl(option: libc::c_int, arg2: libc::c_ulong, arg3: libc::c_ulong,
                 arg4: libc::c_ulong, arg5: libc::c_ulong) -> libc::c_int;
    }
    const PR_SET_NAME: libc::c_int = 15;
    let cname = CString::new(name).unwrap_or_else(|_| {
        panic!("thread name may not contain interior null bytes")
    });
    prctl(PR_SET_NAME, cname.as_ptr() as libc::c_ulong, 0, 0, 0);
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
    }
    let cname = CString::new(name).unwrap();
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
    }
    let cname = CString::new(name).unwrap();
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() {
    assert_eq!(sched_yield(), 0);
}

pub fn sleep(dur: Duration) {
    unsafe {
        if dur < Duration::zero() {
            return yield_now()
        }
        let seconds = dur.num_seconds();
        let ns = dur - Duration::seconds(seconds);
        let mut ts = libc::timespec {
            tv_sec: seconds as libc::time_t,
            tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long,
        };
        // If we're awoken with a signal then the return value will be -1 and
        // nanosleep will fill in `ts` with the remaining time.
        while dosleep(&mut ts) == -1 {
            assert_eq!(os::errno(), libc::EINTR);
        }
    }

    #[cfg(target_os = "linux")]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        extern {
            fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int,
                               request: *const libc::timespec,
                               remain: *mut libc::timespec) -> libc::c_int;
        }
        clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts)
    }
    #[cfg(not(target_os = "linux"))]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        libc::nanosleep(ts, ts)
    }
}

// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Link weakly to the symbol for compatibility with older versions of glibc.
// Assumes that we've been dynamically linked to libpthread but that is
// currently always the case.  Note that you need to check that the symbol
// is non-null before calling it!
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    extern {
        #[linkage = "extern_weak"]
        static __pthread_get_minstack: *const ();
    }
    if __pthread_get_minstack.is_null() {
        PTHREAD_STACK_MIN
    } else {
        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
    }
}

// __pthread_get_minstack() is marked as weak but extern_weak linkage is
// not supported on OS X, hence this kludge...
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

extern {
    fn pthread_self() -> libc::pthread_t;
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: extern fn(*mut libc::c_void) -> *mut libc::c_void,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<|endoftext|>


<commit_before><commit_msg>alternate version of coerce-match test that avoids box syntax.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

// Check that coercions are propagated through match and if expressions.

use std::boxed::Box;

pub fn main() {
    let _: Box<[int]> = if true { Box::new([1i, 2, 3]) } else { Box::new([1i]) };

    let _: Box<[int]> = match true { true => Box::new([1i, 2, 3]), false => Box::new([1i]) };

    // Check we don't get over-keen at propagating coercions in the case of casts.
    let x = if true { 42 } else { 42u8 } as u16;
    let x = match true { true => 42, false => 42u8 } as u16;
}
<|endoftext|>


<commit_before><commit_msg>binary search<commit_after><|endoftext|>


<commit_before>#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate glutin;

use std::io::{self, Write};

mod support;

#[cfg(target_os = "android")]
android_start!(main);

fn main() {
    // enumerating monitors
    let monitor = {
        for (num, monitor) in glutin::get_available_monitors().enumerate() {
            println!("Monitor #{}: {:?}", num, monitor.get_name());
        }

        print!("Please write the number of the monitor to use: ");
        io::stdout().flush().unwrap();

        let mut num = String::new();
        io::stdin().read_line(&mut num).unwrap();
        let num = num.trim().parse().ok().expect("Please enter a number");
        let monitor = glutin::get_available_monitors().nth(num).expect("Please enter a valid ID");

        println!("Using {:?}", monitor.get_name());

        monitor
    };

    let window = glutin::WindowBuilder::new()
        .with_title("Hello world!".to_string())
        .with_fullscreen(monitor)
        .build()
        .unwrap();

    let _ = unsafe { window.make_current() };

    let context = support::load(&window);

    for event in window.wait_events() {
        context.draw_frame((0.0, 1.0, 0.0, 1.0));
        let _ = window.swap_buffers();

        println!("{:?}", event);

        match event {
            glutin::Event::Closed => break,
            _ => ()
        }
    }
}
<commit_msg>Fix issue #543<commit_after>#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;

extern crate glutin;

use std::io::{self, Write};

mod support;

#[cfg(target_os = "android")]
android_start!(main);

fn main() {
    // enumerating monitors
    let monitor = {
        for (num, monitor) in glutin::get_available_monitors().enumerate() {
            println!("Monitor #{}: {:?}", num, monitor.get_name());
        }

        print!("Please write the number of the monitor to use: ");
        io::stdout().flush().unwrap();

        let mut num = String::new();
        io::stdin().read_line(&mut num).unwrap();
        let num = num.trim().parse().ok().expect("Please enter a number");
        let monitor = glutin::get_available_monitors().nth(num).expect("Please enter a valid ID");

        println!("Using {:?}", monitor.get_name());

        monitor
    };

    let window = glutin::WindowBuilder::new()
        .with_title("Hello world!".to_string())
        .with_fullscreen(monitor)
        .build()
        .unwrap();

    let _ = unsafe { window.make_current() };

    let context = support::load(&window);

    for event in window.wait_events() {
        context.draw_frame((0.0, 1.0, 0.0, 1.0));
        let _ = window.swap_buffers();

        println!("{:?}", event);

        match event {
            glutin::Event::Closed => break,
            glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) => break,
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Temporarily fix a syntax issue.<commit_after><|endoftext|>


<commit_before><commit_msg>practice<commit_after>fn main() {
    let n = 5;

    if  n < 0 {
        println!("{} is negative", n);
    }else if n > 0 {
        println!("{} is positive", n);
    }else {
        println!("{} is zero", n);
    }

    let big_n =
        if n < 10 && n > - 10 {
            println!(", and is a small number, increase ten-fold");
            10 * n
        } else {
            println!(", and is a big number, reduce by two");
            n / 2
        };
    println!("{} -> {}", n, big_n)
}
<|endoftext|>


<commit_before><commit_msg>update constructur param type<commit_after><|endoftext|>


<commit_before><commit_msg>Increase block size<commit_after><|endoftext|>


<commit_before>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;
extern crate shader_version;
extern crate glutin_window;

use glutin_window::GlutinWindow;
pub use shader_version::OpenGL;
pub use graphics::*;
pub use piston::window::*;
pub use piston::event::*;
pub use piston::input::*;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use piston::{ event, window };
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };

/// Actual gfx::Stream implementation carried by the window.
pub type GfxStream = gfx::OwnedStream<gfx_device_gl::Device, gfx_device_gl::Output>;
/// Glyph cache.
type Glyphs = gfx_graphics::GlyphCache<gfx_device_gl::Resources, gfx_device_gl::Factory>;
/// 2D graphics.
type G2d<'a> = GfxGraphics<'a, gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, gfx_device_gl::Output>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: window::Window = GlutinWindow, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX stream.
    pub stream: Rc<RefCell<GfxStream>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<event::WindowEvents<W, event::Event<W::Event>>>>,
    /// The event.
    pub event: Option<event::Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
    /// The factory that was created along with the device.
    pub factory: Rc<RefCell<gfx_device_gl::Factory>>,
}

impl<T> From<WindowSettings> for PistonWindow<T>
    where T: Window + OpenGLWindow + From<WindowSettings>,
          T::Event: GenericEvent
{
    fn from(settings: WindowSettings) -> PistonWindow<T> {
        PistonWindow::new(Rc::new(RefCell::new(settings.into())), empty_app())
    }
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: window::Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            stream: self.stream.clone(),
            device: self.device.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
            factory: self.factory.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: window::OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (device, mut factory) =
            gfx_device_gl::create(|s| window.borrow_mut().get_proc_address(s));

        let draw_size = window.borrow().draw_size();
        let output = factory.make_fake_output(draw_size.width as u16, draw_size.height as u16);

        let g2d = Gfx2d::new(&mut factory);

        let stream = factory.create_stream(output);

        PistonWindow {
            window: window.clone(),
            stream: Rc::new(RefCell::new(stream)),
            device: Rc::new(RefCell::new(device)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
            factory: Rc::new(RefCell::new(factory)),
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            stream: self.stream,
            device: self.device,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
            factory: self.factory,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                {
                    let (renderer, output) = stream.access();
                    self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                }
                stream.flush(&mut *self.device.borrow_mut());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F) where
        F: FnMut(&mut GfxStream)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                f(&mut *stream);
                stream.flush(&mut *self.device.borrow_mut())
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            if let Some(_) = e.resize_args() {
                let mut stream = self.stream.borrow_mut();
                let draw_size = self.window.borrow().draw_size();
                stream.out.width = draw_size.width as u16;
                stream.out.height = draw_size.height as u16;
            }

            Some(PistonWindow {
                window: self.window.clone(),
                stream: self.stream.clone(),
                device: self.device.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
                factory: self.factory.clone(),
            })
        } else { None }
    }
}

impl<W, T> event::GenericEvent for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    fn event_id(&self) -> event::EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => event::EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: event::EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match event::GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        stream: old_event.stream.clone(),
                        device: old_event.device.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                        factory: old_event.factory.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> window::Window for PistonWindow<W, T>
    where W: window::Window
{
    type Event = <W as window::Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> window::Size { self.window.borrow().size() }
    fn draw_size(&self) -> window::Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        window::Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> window::AdvancedWindow for PistonWindow<W, T>
    where W: window::AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<commit_msg>Some cleanup<commit_after>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;
extern crate shader_version;
extern crate glutin_window;

use glutin_window::GlutinWindow;
pub use shader_version::OpenGL;
pub use graphics::*;
pub use piston::window::*;
pub use piston::event::*;
pub use piston::input::*;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };

/// Actual gfx::Stream implementation carried by the window.
pub type GfxStream = gfx::OwnedStream<gfx_device_gl::Device, gfx_device_gl::Output>;
/// Glyph cache.
type Glyphs = gfx_graphics::GlyphCache<gfx_device_gl::Resources, gfx_device_gl::Factory>;
/// 2D graphics.
type G2d<'a> = GfxGraphics<'a, gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, gfx_device_gl::Output>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: Window = GlutinWindow, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX stream.
    pub stream: Rc<RefCell<GfxStream>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<WindowEvents<W, Event<W::Event>>>>,
    /// The event.
    pub event: Option<Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
    /// The factory that was created along with the device.
    pub factory: Rc<RefCell<gfx_device_gl::Factory>>,
}

impl<T> From<WindowSettings> for PistonWindow<T>
    where T: Window + OpenGLWindow + From<WindowSettings>,
          T::Event: GenericEvent
{
    fn from(settings: WindowSettings) -> PistonWindow<T> {
        PistonWindow::new(Rc::new(RefCell::new(settings.into())), empty_app())
    }
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            stream: self.stream.clone(),
            device: self.device.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
            factory: self.factory.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: Window, W::Event: GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (device, mut factory) =
            gfx_device_gl::create(|s| window.borrow_mut().get_proc_address(s));

        let draw_size = window.borrow().draw_size();
        let output = factory.make_fake_output(draw_size.width as u16, draw_size.height as u16);

        let g2d = Gfx2d::new(&mut factory);

        let stream = factory.create_stream(output);

        PistonWindow {
            window: window.clone(),
            stream: Rc::new(RefCell::new(stream)),
            device: Rc::new(RefCell::new(device)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
            factory: Rc::new(RefCell::new(factory)),
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            stream: self.stream,
            device: self.device,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
            factory: self.factory,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                {
                    let (renderer, output) = stream.access();
                    self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                }
                stream.flush(&mut *self.device.borrow_mut());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F) where
        F: FnMut(&mut GfxStream)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                f(&mut *stream);
                stream.flush(&mut *self.device.borrow_mut())
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: Window, W::Event: GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            if let Some(_) = e.resize_args() {
                let mut stream = self.stream.borrow_mut();
                let draw_size = self.window.borrow().draw_size();
                stream.out.width = draw_size.width as u16;
                stream.out.height = draw_size.height as u16;
            }

            Some(PistonWindow {
                window: self.window.clone(),
                stream: self.stream.clone(),
                device: self.device.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
                factory: self.factory.clone(),
            })
        } else { None }
    }
}

impl<W, T> GenericEvent for PistonWindow<W, T>
    where W: Window, W::Event: GenericEvent
{
    fn event_id(&self) -> EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        stream: old_event.stream.clone(),
                        device: old_event.device.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                        factory: old_event.factory.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> Window for PistonWindow<W, T>
    where W: Window
{
    type Event = <W as Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> Size { self.window.borrow().size() }
    fn draw_size(&self) -> Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> AdvancedWindow for PistonWindow<W, T>
    where W: AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<|endoftext|>


<commit_before><commit_msg>Do not lie in the comments<commit_after><|endoftext|>


<commit_before><commit_msg>Removing palette restrictions.<commit_after><|endoftext|>


<commit_before><commit_msg>fix ref<commit_after><|endoftext|>


<commit_before><commit_msg>Increase insertion sort cutoff<commit_after><|endoftext|>