<commit_before>use layers::{ARGB32Format, ContainerLayerKind, Image, ImageLayerKind, RGB24Format};
use layers::{TiledImageLayerKind};
use scene::Scene;

use geom::matrix::{Matrix4, ortho};
use geom::size::Size2D;
use opengles::gl2;
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, CLAMP_TO_EDGE, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINEAR, LINK_STATUS, NEAREST, NO_ERROR, REPEAT, RGB, RGBA,
                      BGRA};
use opengles::gl2::{STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, TEXTURE_WRAP_T};
use opengles::gl2::{TRIANGLE_STRIP, UNPACK_ALIGNMENT, UNPACK_CLIENT_STORAGE_APPLE, UNSIGNED_BYTE};
use opengles::gl2::{UNPACK_ROW_LENGTH, UNSIGNED_BYTE, UNSIGNED_INT_8_8_8_8_REV, VERTEX_SHADER};
use opengles::gl2::{GLclampf, GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{bind_texture, buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays, enable};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
use opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv};
use opengles::gl2::{get_uniform_location, link_program, pixel_store_i, shader_source};
use opengles::gl2::{tex_image_2d, tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
use opengles::gl2::{vertex_attrib_pointer_f32, viewport};

use io::println;
use libc::c_int;
use str::to_bytes;

pub fn FRAGMENT_SHADER_SOURCE() -> ~str {
    ~"
        #ifdef GLES2
            precision mediump float;
        #endif

        varying vec2 vTextureCoord;

        uniform sampler2DRect uSampler;

        void main(void) {
            gl_FragColor = texture2DRect(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        }
    "
}

pub fn VERTEX_SHADER_SOURCE() -> ~str {
    ~"
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        varying vec2 vTextureCoord;

        void main(void) {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }
    "
}

pub fn load_shader(source_string: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[ to_bytes(source_string) ]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(#fmt("shader info log: %s", get_shader_info_log(shader_id)));
        fail ~"failed to compile shader";
    }

    return shader_id;
}

pub struct RenderContext {
    program: GLuint,
    vertex_position_attr: c_int,
    texture_coord_attr: c_int,
    modelview_uniform: c_int,
    projection_uniform: c_int,
    sampler_uniform: c_int,
    vertex_buffer: GLuint,
    texture_coord_buffer: GLuint,
}

pub fn RenderContext(program: GLuint) -> RenderContext {
    let (vertex_buffer, texture_coord_buffer) = init_buffers();
    let rc = RenderContext {
        program: program,
        vertex_position_attr: get_attrib_location(program, ~"aVertexPosition"),
        texture_coord_attr: get_attrib_location(program, ~"aTextureCoord"),
        modelview_uniform: get_uniform_location(program, ~"uMVMatrix"),
        projection_uniform: get_uniform_location(program, ~"uPMatrix"),
        sampler_uniform: get_uniform_location(program, ~"uSampler"),
        vertex_buffer: vertex_buffer,
        texture_coord_buffer: texture_coord_buffer,
    };

    enable_vertex_attrib_array(rc.vertex_position_attr as GLuint);
    enable_vertex_attrib_array(rc.texture_coord_attr as GLuint);

    rc
}

pub fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE(), VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE(), FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    enable(TEXTURE_2D);
    enable(TEXTURE_RECTANGLE_ARB);

    return RenderContext(program);
}

pub fn init_buffers() -> (GLuint, GLuint) {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);

    let (_0, _1) = (0.0f32, 1.0f32);
    let vertices = ~[
        _0, _0, _0,
        _0, _1, _0,
        _1, _0, _0,
        _1, _1, _0
    ];

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    let texture_coord_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, texture_coord_buffer);

    return (triangle_vertex_buffer, texture_coord_buffer);
}

pub fn create_texture_for_image_if_necessary(image: @Image) {
    match image.texture {
        None => {}
        Some(_) => { return; /* Nothing to do. */ }
    }

    let texture = gen_textures(1 as GLsizei)[0];

    debug!("making texture, id=%d, format=%?", texture as int, image.data.format());

    bind_texture(TEXTURE_RECTANGLE_ARB, texture);

    // FIXME: This makes the lifetime requirements somewhat complex...
    pixel_store_i(UNPACK_CLIENT_STORAGE_APPLE, 1);

    let size = image.data.size();
    let stride = image.data.stride() as GLsizei;

    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MAG_FILTER, NEAREST as GLint);
    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MIN_FILTER, NEAREST as GLint);

    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, CLAMP_TO_EDGE as GLint);
    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_T, CLAMP_TO_EDGE as GLint);

    // These two are needed for DMA on the Mac. Don't touch them unless you know what you're doing!
    pixel_store_i(UNPACK_ALIGNMENT, 4);
    pixel_store_i(UNPACK_ROW_LENGTH, stride);
    if stride % 32 != 0 {
        info!("rust-layers: suggest using stride multiples of 32 for DMA on the Mac");
    }

    debug!("rust-layers stride is %u", stride as uint);

    match image.data.format() {
        RGB24Format => {
            do image.data.with_data |data| {
                tex_image_2d(TEXTURE_RECTANGLE_ARB, 0 as GLint, RGB as GLint,
                             size.width as GLsizei, size.height as GLsizei, 0 as GLint, RGB,
                             UNSIGNED_BYTE, Some(data));
            }
        }
        ARGB32Format => {
            do image.data.with_data |data| {
                debug!("(rust-layers) data size=%u expected size=%u",
                      data.len(), ((stride as uint) * size.height * 4) as uint);

                tex_parameter_i(TEXTURE_RECTANGLE_ARB, gl2::TEXTURE_STORAGE_HINT_APPLE,
                                gl2::STORAGE_CACHED_APPLE as GLint);

                tex_image_2d(TEXTURE_RECTANGLE_ARB, 0 as GLint, RGBA as GLint,
                             size.width as GLsizei, size.height as GLsizei, 0 as GLint, BGRA,
                             UNSIGNED_INT_8_8_8_8_REV, Some(data));
            }
        }
    }

    bind_texture(TEXTURE_RECTANGLE_ARB, 0);

    image.texture = Some(texture);
}

pub fn bind_and_render_quad(render_context: RenderContext, size: Size2D<uint>, texture: GLuint) {
    bind_texture(TEXTURE_RECTANGLE_ARB, texture);

    uniform_1i(render_context.sampler_uniform, 0);

    bind_buffer(ARRAY_BUFFER, render_context.vertex_buffer);
    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3, false, 0, 0);

    // Create the texture coordinate array.
    bind_buffer(ARRAY_BUFFER, render_context.texture_coord_buffer);

    let (width, height) = (size.width as f32, size.height as f32);
    let vertices = [
        0.0f32, 0.0f32,
        0.0f32, height,
        width,  0.0f32,
        width,  height
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2, false, 0, 0);

    draw_arrays(TRIANGLE_STRIP, 0, 4);

    bind_texture(TEXTURE_RECTANGLE_ARB, 0);
}

// Layer rendering

pub trait Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>);
}

impl @layers::ContainerLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        for self.each_child |child| {
            render_layer(render_context, transform, child);
        }
    }
}

impl @layers::ImageLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        create_texture_for_image_if_necessary(self.image);

        let transform = transform.mul(&self.common.transform);
        uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());

        bind_and_render_quad(
            render_context, self.image.data.size(), option::get(self.image.texture));
    }
}

impl @layers::TiledImageLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        let tiles_down = self.tiles.len() / self.tiles_across;
        for self.tiles.eachi |i, tile| {
            create_texture_for_image_if_necessary(*tile);

            let x = ((i % self.tiles_across) as f32);
            let y = ((i / self.tiles_across) as f32);

            let transform = transform.mul(&self.common.transform);
            let transform = transform.scale(&(1.0f32 / (self.tiles_across as f32)),
                                            &(1.0f32 / (tiles_down as f32)),
                                            &1.0f32);
            let transform = transform.translate(&(x * 1.0f32), &(y * 1.0f32), &0.0f32);

            uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());

            bind_and_render_quad(render_context, tile.data.size(), option::get(tile.texture));
        }
    }
}

fn render_layer(render_context: RenderContext, transform: Matrix4<f32>, layer: layers::Layer) {
    match layer {
        ContainerLayerKind(container_layer) => {
            container_layer.render(render_context, transform);
        }
        ImageLayerKind(image_layer) => {
            image_layer.render(render_context, transform);
        }
        TiledImageLayerKind(tiled_image_layer) => {
            tiled_image_layer.render(render_context, transform);
        }
    }
}

pub fn render_scene(render_context: RenderContext, scene: &Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    // Clear the screen.
    clear_color(0.38f32, 0.36f32, 0.36f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    // Set the projection matrix.
    let projection_matrix = ortho(0.0f32, copy scene.size.width, copy scene.size.height, 0.0f32,
                                  -10.0f32, 10.0f32);
    uniform_matrix_4fv(render_context.projection_uniform, false, projection_matrix.to_array());

    // Set up the initial modelview matrix.
    let transform = scene.transform;

    // Render the root layer.
    render_layer(render_context, transform, scene.root);
}

<commit_msg>Update for language changes<commit_after>use layers::{ARGB32Format, ContainerLayerKind, Image, ImageLayerKind, RGB24Format};
use layers::{TiledImageLayerKind};
use scene::Scene;

use geom::matrix::{Matrix4, ortho};
use geom::size::Size2D;
use opengles::gl2;
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, CLAMP_TO_EDGE, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINEAR, LINK_STATUS, NEAREST, NO_ERROR, REPEAT, RGB, RGBA,
                      BGRA};
use opengles::gl2::{STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, TEXTURE_WRAP_T};
use opengles::gl2::{TRIANGLE_STRIP, UNPACK_ALIGNMENT, UNPACK_CLIENT_STORAGE_APPLE, UNSIGNED_BYTE};
use opengles::gl2::{UNPACK_ROW_LENGTH, UNSIGNED_BYTE, UNSIGNED_INT_8_8_8_8_REV, VERTEX_SHADER};
use opengles::gl2::{GLclampf, GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{bind_texture, buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays, enable};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
use opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv};
use opengles::gl2::{get_uniform_location, link_program, pixel_store_i, shader_source};
use opengles::gl2::{tex_image_2d, tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
use opengles::gl2::{vertex_attrib_pointer_f32, viewport};

use io::println;
use libc::c_int;
use str::to_bytes;

pub fn FRAGMENT_SHADER_SOURCE() -> ~str {
    ~"
        #ifdef GLES2
            precision mediump float;
        #endif

        varying vec2 vTextureCoord;

        uniform sampler2DRect uSampler;

        void main(void) {
            gl_FragColor = texture2DRect(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        }
    "
}

pub fn VERTEX_SHADER_SOURCE() -> ~str {
    ~"
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        varying vec2 vTextureCoord;

        void main(void) {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }
    "
}

pub fn load_shader(source_string: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[ to_bytes(source_string) ]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(fmt!("error: %d", get_error() as int));
        fail ~"failed to compile shader";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(fmt!("shader info log: %s", get_shader_info_log(shader_id)));
        fail ~"failed to compile shader";
    }

    return shader_id;
}

pub struct RenderContext {
    program: GLuint,
    vertex_position_attr: c_int,
    texture_coord_attr: c_int,
    modelview_uniform: c_int,
    projection_uniform: c_int,
    sampler_uniform: c_int,
    vertex_buffer: GLuint,
    texture_coord_buffer: GLuint,
}

pub fn RenderContext(program: GLuint) -> RenderContext {
    let (vertex_buffer, texture_coord_buffer) = init_buffers();
    let rc = RenderContext {
        program: program,
        vertex_position_attr: get_attrib_location(program, ~"aVertexPosition"),
        texture_coord_attr: get_attrib_location(program, ~"aTextureCoord"),
        modelview_uniform: get_uniform_location(program, ~"uMVMatrix"),
        projection_uniform: get_uniform_location(program, ~"uPMatrix"),
        sampler_uniform: get_uniform_location(program, ~"uSampler"),
        vertex_buffer: vertex_buffer,
        texture_coord_buffer: texture_coord_buffer,
    };

    enable_vertex_attrib_array(rc.vertex_position_attr as GLuint);
    enable_vertex_attrib_array(rc.texture_coord_attr as GLuint);

    rc
}

pub fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE(), VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE(), FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    enable(TEXTURE_2D);
    enable(TEXTURE_RECTANGLE_ARB);

    return RenderContext(program);
}

pub fn init_buffers() -> (GLuint, GLuint) {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);

    let (_0, _1) = (0.0f32, 1.0f32);
    let vertices = ~[
        _0, _0, _0,
        _0, _1, _0,
        _1, _0, _0,
        _1, _1, _0
    ];

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    let texture_coord_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, texture_coord_buffer);

    return (triangle_vertex_buffer, texture_coord_buffer);
}

pub fn create_texture_for_image_if_necessary(image: @Image) {
    match image.texture {
        None => {}
        Some(_) => { return; /* Nothing to do. */ }
    }

    let texture = gen_textures(1 as GLsizei)[0];

    debug!("making texture, id=%d, format=%?", texture as int, image.data.format());

    bind_texture(TEXTURE_RECTANGLE_ARB, texture);

    // FIXME: This makes the lifetime requirements somewhat complex...
    pixel_store_i(UNPACK_CLIENT_STORAGE_APPLE, 1);

    let size = image.data.size();
    let stride = image.data.stride() as GLsizei;

    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MAG_FILTER, NEAREST as GLint);
    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MIN_FILTER, NEAREST as GLint);

    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, CLAMP_TO_EDGE as GLint);
    tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_T, CLAMP_TO_EDGE as GLint);

    // These two are needed for DMA on the Mac. Don't touch them unless you know what you're doing!
    pixel_store_i(UNPACK_ALIGNMENT, 4);
    pixel_store_i(UNPACK_ROW_LENGTH, stride);
    if stride % 32 != 0 {
        info!("rust-layers: suggest using stride multiples of 32 for DMA on the Mac");
    }

    debug!("rust-layers stride is %u", stride as uint);

    match image.data.format() {
        RGB24Format => {
            do image.data.with_data |data| {
                tex_image_2d(TEXTURE_RECTANGLE_ARB, 0 as GLint, RGB as GLint,
                             size.width as GLsizei, size.height as GLsizei, 0 as GLint, RGB,
                             UNSIGNED_BYTE, Some(data));
            }
        }
        ARGB32Format => {
            do image.data.with_data |data| {
                debug!("(rust-layers) data size=%u expected size=%u",
                      data.len(), ((stride as uint) * size.height * 4) as uint);

                tex_parameter_i(TEXTURE_RECTANGLE_ARB, gl2::TEXTURE_STORAGE_HINT_APPLE,
                                gl2::STORAGE_CACHED_APPLE as GLint);

                tex_image_2d(TEXTURE_RECTANGLE_ARB, 0 as GLint, RGBA as GLint,
                             size.width as GLsizei, size.height as GLsizei, 0 as GLint, BGRA,
                             UNSIGNED_INT_8_8_8_8_REV, Some(data));
            }
        }
    }

    bind_texture(TEXTURE_RECTANGLE_ARB, 0);

    image.texture = Some(texture);
}

pub fn bind_and_render_quad(render_context: RenderContext, size: Size2D<uint>, texture: GLuint) {
    bind_texture(TEXTURE_RECTANGLE_ARB, texture);

    uniform_1i(render_context.sampler_uniform, 0);

    bind_buffer(ARRAY_BUFFER, render_context.vertex_buffer);
    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3, false, 0, 0);

    // Create the texture coordinate array.
    bind_buffer(ARRAY_BUFFER, render_context.texture_coord_buffer);

    let (width, height) = (size.width as f32, size.height as f32);
    let vertices = [
        0.0f32, 0.0f32,
        0.0f32, height,
        width,  0.0f32,
        width,  height
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2, false, 0, 0);

    draw_arrays(TRIANGLE_STRIP, 0, 4);

    bind_texture(TEXTURE_RECTANGLE_ARB, 0);
}

// Layer rendering

pub trait Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>);
}

impl @layers::ContainerLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        for self.each_child |child| {
            render_layer(render_context, transform, child);
        }
    }
}

impl @layers::ImageLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        create_texture_for_image_if_necessary(self.image);

        let transform = transform.mul(&self.common.transform);
        uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());

        bind_and_render_quad(
            render_context, self.image.data.size(), option::get(self.image.texture));
    }
}

impl @layers::TiledImageLayer : Render {
    fn render(render_context: RenderContext, transform: Matrix4<f32>) {
        let tiles_down = self.tiles.len() / self.tiles_across;
        for self.tiles.eachi |i, tile| {
            create_texture_for_image_if_necessary(*tile);

            let x = ((i % self.tiles_across) as f32);
            let y = ((i / self.tiles_across) as f32);

            let transform = transform.mul(&self.common.transform);
            let transform = transform.scale(&(1.0f32 / (self.tiles_across as f32)),
                                            &(1.0f32 / (tiles_down as f32)),
                                            &1.0f32);
            let transform = transform.translate(&(x * 1.0f32), &(y * 1.0f32), &0.0f32);

            uniform_matrix_4fv(render_context.modelview_uniform, false, transform.to_array());

            bind_and_render_quad(render_context, tile.data.size(), option::get(tile.texture));
        }
    }
}

fn render_layer(render_context: RenderContext, transform: Matrix4<f32>, layer: layers::Layer) {
    match layer {
        ContainerLayerKind(container_layer) => {
            container_layer.render(render_context, transform);
        }
        ImageLayerKind(image_layer) => {
            image_layer.render(render_context, transform);
        }
        TiledImageLayerKind(tiled_image_layer) => {
            tiled_image_layer.render(render_context, transform);
        }
    }
}

pub fn render_scene(render_context: RenderContext, scene: &Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    // Clear the screen.
    clear_color(0.38f32, 0.36f32, 0.36f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    // Set the projection matrix.
    let projection_matrix = ortho(0.0f32, copy scene.size.width, copy scene.size.height, 0.0f32,
                                  -10.0f32, 10.0f32);
    uniform_matrix_4fv(render_context.projection_uniform, false, projection_matrix.to_array());

    // Set up the initial modelview matrix.
    let transform = scene.transform;

    // Render the root layer.
    render_layer(render_context, transform, scene.root);
}

<|endoftext|>


<commit_before><commit_msg>Add CpuBufferPool example (#1352)<commit_after>// Copyright (c) 2020 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.

// BufferPool Example
//
// Modified triangle example to show BufferPool
// Using a pool allows multiple buffers to be "in-flight" simultaneously
//  and is suited to highly dynamic, similar sized chunks of data
//
// NOTE:(jdnewman85) ATM (5/4/2020) CpuBufferPool.next() and .chunk() have identical documentation
//      I was unable to get next() to work. The compiler complained that the resulting buffer
//      didn't implement VertexSource. Similar issues have been reported.
//      See: https://github.com/vulkano-rs/vulkano/issues/1221
//      Finally, I have not profiled CpuBufferPool against CpuAccessibleBuffer

use vulkano::buffer::CpuBufferPool;
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::{Device, DeviceExtensions};
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract, Subpass};
use vulkano::image::SwapchainImage;
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::pipeline::viewport::Viewport;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::swapchain;
use vulkano::swapchain::{
    AcquireError, ColorSpace, FullscreenExclusive, PresentMode, SurfaceTransform, Swapchain,
    SwapchainCreationError,
};
use vulkano::sync;
use vulkano::sync::{FlushError, GpuFuture};

use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};

use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Default, Debug, Clone)]
struct Vertex {
    position: [f32; 2],
}
vulkano::impl_vertex!(Vertex, position);

fn main() {
    let required_extensions = vulkano_win::required_extensions();
    let instance = Instance::new(None, &required_extensions, None).unwrap();
    let physical = PhysicalDevice::enumerate(&instance).next().unwrap();

    println!(
        "Using device: {} (type: {:?})",
        physical.name(),
        physical.ty()
    );

    let event_loop = EventLoop::new();
    let surface = WindowBuilder::new()
        .build_vk_surface(&event_loop, instance.clone()).unwrap();

    let queue_family = physical
        .queue_families()
        .find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false)).unwrap();

    let device_ext = DeviceExtensions {
        khr_swapchain: true,
        ..DeviceExtensions::none()
    };
    let (device, mut queues) = Device::new(
        physical,
        physical.supported_features(),
        &device_ext,
        [(queue_family, 0.5)].iter().cloned(),
    ).unwrap();

    let queue = queues.next().unwrap();

    let (mut swapchain, images) = {
        let caps = surface.capabilities(physical).unwrap();
        let usage = caps.supported_usage_flags;

        let alpha = caps.supported_composite_alpha.iter().next().unwrap();
        let format = caps.supported_formats[0].0;
        let dimensions: [u32; 2] = surface.window().inner_size().into();

        Swapchain::new(
            device.clone(),
            surface.clone(),
            caps.min_image_count,
            format,
            dimensions,
            1,
            usage,
            &queue,
            SurfaceTransform::Identity,
            alpha,
            PresentMode::Fifo,
            FullscreenExclusive::Default,
            true,
            ColorSpace::SrgbNonLinear,
        ).unwrap()
    };

    // Vertex Buffer Pool
    let buffer_pool: CpuBufferPool<Vertex> = CpuBufferPool::vertex_buffer(device.clone());

    mod vs {
        vulkano_shaders::shader! {
            ty: "vertex",
            src: "
				#version 450

				layout(location = 0) in vec2 position;

				void main() {
					gl_Position = vec4(position, 0.0, 1.0);
				}
			"
        }
    }

    mod fs {
        vulkano_shaders::shader! {
            ty: "fragment",
            src: "
				#version 450

				layout(location = 0) out vec4 f_color;

				void main() {
					f_color = vec4(1.0, 0.0, 0.0, 1.0);
				}
			"
        }
    }

    let vs = vs::Shader::load(device.clone()).unwrap();
    let fs = fs::Shader::load(device.clone()).unwrap();

    let render_pass = Arc::new(
        vulkano::single_pass_renderpass!(
            device.clone(),
            attachments: {
                color: {
                    load: Clear,
                    store: Store,
                    format: swapchain.format(),
                    samples: 1,
                }
            },
            pass: {
                color: [color],
                depth_stencil: {}
            }
        ).unwrap(),
    );

    let pipeline = Arc::new(
        GraphicsPipeline::start()
            .vertex_input_single_buffer()
            .vertex_shader(vs.main_entry_point(), ())
            .triangle_list()
            .viewports_dynamic_scissors_irrelevant(1)
            .fragment_shader(fs.main_entry_point(), ())
            .render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
            .build(device.clone()).unwrap(),
    );

    let mut dynamic_state = DynamicState {
        line_width: None,
        viewports: None,
        scissors: None,
        compare_mask: None,
        write_mask: None,
        reference: None,
    };
    let mut framebuffers =
        window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
    let mut recreate_swapchain = false;
    let mut previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<dyn GpuFuture>);

    event_loop.run(move |event, _, control_flow| {
        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => {
                *control_flow = ControlFlow::Exit;
            }
            Event::WindowEvent {
                event: WindowEvent::Resized(_),
                ..
            } => {
                recreate_swapchain = true;
            }
            Event::RedrawEventsCleared => {
                previous_frame_end.as_mut().unwrap().cleanup_finished();

                if recreate_swapchain {
                    let dimensions: [u32; 2] = surface.window().inner_size().into();
                    let (new_swapchain, new_images) =
                        match swapchain.recreate_with_dimensions(dimensions) {
                            Ok(r) => r,
                            Err(SwapchainCreationError::UnsupportedDimensions) => return,
                            Err(e) => panic!("Failed to recreate swapchain: {:?}", e),
                        };

                    swapchain = new_swapchain;
                    framebuffers = window_size_dependent_setup(
                        &new_images,
                        render_pass.clone(),
                        &mut dynamic_state,
                    );
                    recreate_swapchain = false;
                }

                let (image_num, suboptimal, acquire_future) =
                    match swapchain::acquire_next_image(swapchain.clone(), None) {
                        Ok(r) => r,
                        Err(AcquireError::OutOfDate) => {
                            recreate_swapchain = true;
                            return;
                        }
                        Err(e) => panic!("Failed to acquire next image: {:?}", e),
                    };

                if suboptimal {
                    recreate_swapchain = true;
                }

                let clear_values = vec![[0.0, 0.0, 1.0, 1.0].into()];

                // Rotate once (PI*2) every 5 seconds
                let elapsed = SystemTime::now()
                    .duration_since(UNIX_EPOCH).unwrap()
                    .as_secs_f64();
                const DURATION: f64 = 5.0;
                let remainder = elapsed.rem_euclid(DURATION);
                let delta = (remainder / DURATION) as f32;
                let angle = delta * std::f32::consts::PI * 2.0;
                const RADIUS: f32 = 0.5;
                // 120Degree offset in radians
                const ANGLE_OFFSET: f32 = (std::f32::consts::PI * 2.0) / 3.0;
                // Calculate vertices
                let data = [
                    Vertex {
                        position: [angle.cos() * RADIUS, angle.sin() * RADIUS],
                    },
                    Vertex {
                        position: [
                            (angle + ANGLE_OFFSET).cos() * RADIUS,
                            (angle + ANGLE_OFFSET).sin() * RADIUS,
                        ],
                    },
                    Vertex {
                        position: [
                            (angle - ANGLE_OFFSET).cos() * RADIUS,
                            (angle - ANGLE_OFFSET).sin() * RADIUS,
                        ],
                    },
                ];

                // Allocate a new chunk from buffer_pool
                let buffer = buffer_pool.chunk(data.to_vec()).unwrap();
                let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(
                    device.clone(),
                    queue.family(),
                ).unwrap()
                .begin_render_pass(framebuffers[image_num].clone(), false, clear_values).unwrap()
                // Draw our buffer
                .draw(pipeline.clone(), &dynamic_state, buffer, (), ()).unwrap()
                .end_render_pass().unwrap()
                .build().unwrap();

                let future = previous_frame_end
                    .take().unwrap()
                    .join(acquire_future)
                    .then_execute(queue.clone(), command_buffer).unwrap()
                    .then_swapchain_present(queue.clone(), swapchain.clone(), image_num)
                    .then_signal_fence_and_flush();

                match future {
                    Ok(future) => {
                        previous_frame_end = Some(Box::new(future) as Box<_>);
                    }
                    Err(FlushError::OutOfDate) => {
                        recreate_swapchain = true;
                        previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<_>);
                    }
                    Err(e) => {
                        println!("Failed to flush future: {:?}", e);
                        previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<_>);
                    }
                }
            }
            _ => (),
        }
    });
}

/// This method is called once during initialization, then again whenever the window is resized
fn window_size_dependent_setup(
    images: &[Arc<SwapchainImage<Window>>],
    render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
    dynamic_state: &mut DynamicState,
) -> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
    let dimensions = images[0].dimensions();

    let viewport = Viewport {
        origin: [0.0, 0.0],
        dimensions: [dimensions[0] as f32, dimensions[1] as f32],
        depth_range: 0.0..1.0,
    };
    dynamic_state.viewports = Some(vec![viewport]);

    images
        .iter()
        .map(|image| {
            Arc::new(
                Framebuffer::start(render_pass.clone())
                    .add(image.clone()).unwrap()
                    .build().unwrap(),
            ) as Arc<dyn FramebufferAbstract + Send + Sync>
        })
        .collect::<Vec<_>>()
}
<|endoftext|>


<commit_before><commit_msg>Add chat server example<commit_after>/// An example of a chat web application server
extern crate ws;
use ws::{listen, Handler, Message, Request, Response, Result, Sender};

// This can be read from a file
static INDEX_HTML: &'static [u8] = br#"
<!DOCTYPE html>

		<meta charset="utf-8">

			<form id="form">
				<input type="text" id="msg">
				<input type="submit" value="Send">
			</form>

    "#;

// Server web application handler
struct Server {
  out: Sender,
}

impl Handler for Server {
  //
  fn on_request(&mut self, req: &Request) -> Result<(Response)> {
    // Using multiple handlers is better (see router example)
    match req.resource() {
      // The default trait implementation
      "/ws" => Response::from_request(req),

      // Create a custom response
      "/" => Ok(Response::new(200, "OK", INDEX_HTML.to_vec())),

      _ => Ok(Response::new(404, "Not Found", b"404 - Not Found".to_vec())),
    }
  }

  // Handle messages recieved in the websocket (in this case, only on /ws)
  fn on_message(&mut self, msg: Message) -> Result<()> {
    // Broadcast to all connections
    self.out.broadcast(msg)
  }
}

fn main() {
  // Listen on an address and call the closure for each connection
  listen("127.0.0.1:8000", |out| Server { out }).unwrap()
}
<|endoftext|>


<commit_before><commit_msg>Forgot to return the vector at the end<commit_after><|endoftext|>


<commit_before><commit_msg>fileinfo structs<commit_after>#[derive(Debug)]
pub enum FileInformation{
    FileInformationV17,
    FileInformationV23,
    FileInformationV26,
    FileInformationV30
}
#[derive(Debug)]
pub struct FileInformationV17{
    pub metrics_array_offset: u32, //The offset is relative to the start of the file
    pub metrics_entry_count: u32,
    pub trace_array_offset: u32,  //The offset is relative to the start of the file
    pub trace_entry_count: u32,
    pub filename_offset: u32,
    pub filename_length: u32,
    pub volume_info_offset: u32,
    pub volume_info_count: u32,
    pub volume_info_size: u32,
    pub last_run_time: u64,
    // pub unknown1: [u8; 16],
    pub run_count: u32,
    pub unknown2: u32
}
#[derive(Debug)]
pub struct FileInformationV23{
    pub metrics_array_offset: u32, //The offset is relative to the start of the file
    pub metrics_entry_count: u32,
    pub trace_array_offset: u32,  //The offset is relative to the start of the file
    pub trace_entry_count: u32,
    pub filename_offset: u32,
    pub filename_length: u32,
    pub volume_info_offset: u32,
    pub volume_info_count: u32,
    pub volume_info_size: u32,
    pub unknown3: u64,
    pub last_run_time: u64,
    // pub unknown1: [u8; 16],
    pub run_count: u32,
    pub unknown2: u32,
    // pub unknown4: [u8; 80]
}
#[derive(Debug)]
pub struct FileInformationV26{
    pub metrics_array_offset: u32, //The offset is relative to the start of the file
    pub metrics_entry_count: u32,
    pub trace_array_offset: u32,  //The offset is relative to the start of the file
    pub trace_entry_count: u32,
    pub filename_offset: u32,
    pub filename_length: u32,
    pub volume_info_offset: u32,
    pub volume_info_count: u32,
    pub volume_info_size: u32,
    pub unknown3: u64,
    // pub last_run_time: [u64;8],
    // pub unknown1: [u8; 16],
    pub run_count: u32,
    pub unknown2: u32,
    pub unknown5: u32,
    pub unknown6: u32,
    // pub unknown4: [u8; 88]
}
#[derive(Debug)]
pub struct FileInformationV30{
    pub metrics_array_offset: u32, //The offset is relative to the start of the file
    pub metrics_entry_count: u32,
    pub trace_array_offset: u32,  //The offset is relative to the start of the file
    pub trace_entry_count: u32,
    pub filename_offset: u32,
    pub filename_length: u32,
    pub volume_info_offset: u32,
    pub volume_info_count: u32,
    pub volume_info_size: u32,
    pub unknown3: u64,
    // pub last_run_time: [u64;8],
    // pub unknown1: [u8; 16],
    pub run_count: u32,
    pub unknown2: u32,
    pub unknown5: u32,
    pub unknown6: u32,
    // pub unknown4: [u8; 88]
}
<|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.

//! Batches are structures containing all the data required for the draw call,
//! except for the target frame. Here we define the `Batch` trait as well as
//! `RefBatch` and `OwnedBatch` implementations.

use std::fmt;
use std::num::from_uint;
use std::cmp::Ordering;
use device::{PrimitiveType, ProgramHandle};
use device::shade::ProgramInfo;
use mesh;
use mesh::ToSlice;
use shade::{ParameterError, ShaderParam};
use state::DrawState;

/// An error with a defined Mesh.
#[derive(Clone, Show)]
pub enum MeshError {
    /// A required attribute was missing.
    AttributeMissing(String),
    /// An attribute's type from the vertex format differed from the type used in the shader.
    AttributeType,
    /// Internal error due to mesh link limitations
    MeshLink(mesh::LinkError),
}

/// An error occurring at batch creation
#[derive(Clone, Show)]
pub enum BatchError {
    /// Error connecting mesh attributes
    Mesh(MeshError),
    /// Error connecting shader parameters
    Parameters(ParameterError),
    /// Error context is full
    ContextFull,
}

/// Match mesh attributes against shader inputs, produce a mesh link.
/// Exposed to public to allow external `Batch` implementations to use it.
pub fn link_mesh(mesh: &mesh::Mesh, pinfo: &ProgramInfo) -> Result<mesh::Link, MeshError> {
    let mut indices = Vec::new();
    for sat in pinfo.attributes.iter() {
        match mesh.attributes.iter().enumerate()
                  .find(|&(_, a)| a.name == sat.name) {
            Some((attrib_id, vat)) => match vat.format.elem_type.is_compatible(sat.base_type) {
                Ok(_) => indices.push(attrib_id),
                Err(_) => return Err(MeshError::AttributeType),
            },
            None => return Err(MeshError::AttributeMissing(sat.name.clone())),
        }
    }
    mesh::Link::from_iter(indices.into_iter())
        .map_err(|e| MeshError::MeshLink(e))
}

/// Abstract batch trait
pub trait Batch {
    /// Obtain information about the mesh, program, and state
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState);
    /// Fill shader parameter values
    fn fill_params(&self, ::shade::ParamValues);
}

/// Owned batch - self-contained, but has heap-allocated data
pub struct OwnedBatch<L, T> {
    mesh: mesh::Mesh,
    mesh_link: mesh::Link,
    /// Mesh slice
    pub slice: mesh::Slice,
    /// Parameter data.
    pub param: T,
    program: ProgramHandle,
    param_link: L,
    /// Draw state
    pub state: DrawState,
}

impl<L, T: ShaderParam<L>> OwnedBatch<L, T> {
    /// Create a new owned batch
    pub fn new(mesh: mesh::Mesh, program: ProgramHandle, param: T)
           -> Result<OwnedBatch<L, T>, BatchError> {
        let slice = mesh.to_slice(PrimitiveType::TriangleList);
        let mesh_link = match link_mesh(&mesh, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Mesh(e)),
        };
        let param_link = match ShaderParam::create_link(None::<&T>, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Parameters(e)),
        };
        Ok(OwnedBatch {
            mesh: mesh,
            mesh_link: mesh_link,
            slice: slice,
            program: program,
            param: param,
            param_link: param_link,
            state: DrawState::new(),
        })
    }
}

impl<L, T: ShaderParam<L>> Batch for OwnedBatch<L, T> {
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) {
        (&self.mesh, &self.mesh_link, &self.slice, &self.program, &self.state)
    }

    fn fill_params(&self, values: ::shade::ParamValues) {
        self.param.fill_params(&self.param_link, values);
    }
}

type Index = u16;

//#[derive(PartialEq, Eq, PartialOrd, Ord, Show)]
struct Id<T>(Index);

impl<T> Copy for Id<T> {}

impl<T> Id<T> {
    fn unwrap(&self) -> Index {
        let Id(i) = *self;
        i
    }
}

impl<T> fmt::Show for Id<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Id(i) = *self;
        write!(f, "Id({})", i)
    }
}

impl<T> PartialEq for Id<T> {
    fn eq(&self, other: &Id<T>) -> bool {
        self.unwrap() == other.unwrap()
    }
}

impl<T> Eq for Id<T> {}

impl<T> PartialOrd for Id<T> {
    fn partial_cmp(&self, other: &Id<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T> Ord for Id<T> {
    fn cmp(&self, other: &Id<T>) -> Ordering {
        self.unwrap().cmp(&other.unwrap())
    }
}

struct Array<T> {
    data: Vec<T>,
    //generation: u16,
}

impl<T> Array<T> {
    fn new() -> Array<T> {
        Array {
            data: Vec::new(),
            //generation: 0,
        }
    }

    fn get(&self, id: Id<T>) -> &T {
        let Id(i) = id;
        &self.data[i as usize]
    }
}

impl<T: Clone + PartialEq> Array<T> {
    fn find_or_insert(&mut self, value: &T) -> Option<Id<T>> {
        match self.data.iter().position(|v| v == value) {
            Some(i) => from_uint::<Index>(i).map(|id| Id(id)),
            None => {
                from_uint::<Index>(self.data.len()).map(|id| {
                    self.data.push(value.clone());
                    Id(id)
                })
            },
        }
    }
}

/// Ref batch - copyable and smaller, but depends on the `Context`.
/// It has references to the resources (mesh, program, state), that are held
/// by the context that created the batch, so these have to be used together.
pub struct RefBatch<L, T> {
    mesh_id: Id<mesh::Mesh>,
    mesh_link: mesh::Link,
    /// Mesh slice
    pub slice: mesh::Slice,
    program_id: Id<ProgramHandle>,
    param_link: L,
    state_id: Id<DrawState>,
}

impl<L, T> fmt::Show for RefBatch<L, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RefBatch(mesh: {:?}, slice: {:?}, program: {:?}, state: {:?})",
            self.mesh_id, self.slice, self.program_id, self.state_id)
    }
}

impl<L, T> PartialEq for RefBatch<L, T> {
    fn eq(&self, other: &RefBatch<L, T>) -> bool {
        self.program_id == other.program_id &&
        self.state_id == other.state_id &&
        self.mesh_id == other.mesh_id
    }
}

impl<L, T> Eq for RefBatch<L, T> {}

impl<L, T> PartialOrd for RefBatch<L, T> {
    fn partial_cmp(&self, other: &RefBatch<L, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<L, T> Ord for RefBatch<L, T> {
    fn cmp(&self, other: &RefBatch<L, T>) -> Ordering {
        (&self.program_id, &self.state_id, &self.mesh_id).cmp(
        &(&other.program_id, &other.state_id, &other.mesh_id))
    }
}

/// Factory of ref batches, required to always be used with them.
pub struct Context {
    meshes: Array<mesh::Mesh>,
    programs: Array<ProgramHandle>,
    states: Array<DrawState>,
}

impl Context {
    /// Create a new empty `Context`
    pub fn new() -> Context {
        Context {
            meshes: Array::new(),
            programs: Array::new(),
            states: Array::new(),
        }
    }
}

impl Context {
    /// Produce a new ref batch
    pub fn make_batch<L, T: ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &mesh::Mesh,
                      slice: mesh::Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, BatchError> {
        let mesh_link = match link_mesh(mesh, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Mesh(e)),
        };
        let link = match ShaderParam::create_link(None::<&T>, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Parameters(e))
        };
        let mesh_id = match self.meshes.find_or_insert(mesh) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };
        let program_id = match self.programs.find_or_insert(program) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };
        let state_id = match self.states.find_or_insert(state) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };

        Ok(RefBatch {
            mesh_id: mesh_id,
            mesh_link: mesh_link,
            slice: slice,
            program_id: program_id,
            param_link: link,
            state_id: state_id,
        })
    }
}

impl<'a, L, T: ShaderParam<L>> Batch for (&'a RefBatch<L, T>, &'a T, &'a Context) {
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) {
        let (b, _, ctx) = *self;
        (ctx.meshes.get(b.mesh_id),
         &b.mesh_link,
         &b.slice,
         ctx.programs.get(b.program_id),
         ctx.states.get(b.state_id))
    }

    fn fill_params(&self, values: ::shade::ParamValues) {
        let (b, data, _) = *self;
        data.fill_params(&b.param_link, values);
    }
}
<commit_msg>Derive Copy for RefBatch<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.

//! Batches are structures containing all the data required for the draw call,
//! except for the target frame. Here we define the `Batch` trait as well as
//! `RefBatch` and `OwnedBatch` implementations.

use std::fmt;
use std::num::from_uint;
use std::cmp::Ordering;
use device::{PrimitiveType, ProgramHandle};
use device::shade::ProgramInfo;
use mesh;
use mesh::ToSlice;
use shade::{ParameterError, ShaderParam};
use state::DrawState;

/// An error with a defined Mesh.
#[derive(Clone, Show)]
pub enum MeshError {
    /// A required attribute was missing.
    AttributeMissing(String),
    /// An attribute's type from the vertex format differed from the type used in the shader.
    AttributeType,
    /// Internal error due to mesh link limitations
    MeshLink(mesh::LinkError),
}

/// An error occurring at batch creation
#[derive(Clone, Show)]
pub enum BatchError {
    /// Error connecting mesh attributes
    Mesh(MeshError),
    /// Error connecting shader parameters
    Parameters(ParameterError),
    /// Error context is full
    ContextFull,
}

/// Match mesh attributes against shader inputs, produce a mesh link.
/// Exposed to public to allow external `Batch` implementations to use it.
pub fn link_mesh(mesh: &mesh::Mesh, pinfo: &ProgramInfo) -> Result<mesh::Link, MeshError> {
    let mut indices = Vec::new();
    for sat in pinfo.attributes.iter() {
        match mesh.attributes.iter().enumerate()
                  .find(|&(_, a)| a.name == sat.name) {
            Some((attrib_id, vat)) => match vat.format.elem_type.is_compatible(sat.base_type) {
                Ok(_) => indices.push(attrib_id),
                Err(_) => return Err(MeshError::AttributeType),
            },
            None => return Err(MeshError::AttributeMissing(sat.name.clone())),
        }
    }
    mesh::Link::from_iter(indices.into_iter())
        .map_err(|e| MeshError::MeshLink(e))
}

/// Abstract batch trait
pub trait Batch {
    /// Obtain information about the mesh, program, and state
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState);
    /// Fill shader parameter values
    fn fill_params(&self, ::shade::ParamValues);
}

/// Owned batch - self-contained, but has heap-allocated data
pub struct OwnedBatch<L, T> {
    mesh: mesh::Mesh,
    mesh_link: mesh::Link,
    /// Mesh slice
    pub slice: mesh::Slice,
    /// Parameter data.
    pub param: T,
    program: ProgramHandle,
    param_link: L,
    /// Draw state
    pub state: DrawState,
}

impl<L, T: ShaderParam<L>> OwnedBatch<L, T> {
    /// Create a new owned batch
    pub fn new(mesh: mesh::Mesh, program: ProgramHandle, param: T)
           -> Result<OwnedBatch<L, T>, BatchError> {
        let slice = mesh.to_slice(PrimitiveType::TriangleList);
        let mesh_link = match link_mesh(&mesh, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Mesh(e)),
        };
        let param_link = match ShaderParam::create_link(None::<&T>, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Parameters(e)),
        };
        Ok(OwnedBatch {
            mesh: mesh,
            mesh_link: mesh_link,
            slice: slice,
            program: program,
            param: param,
            param_link: param_link,
            state: DrawState::new(),
        })
    }
}

impl<L, T: ShaderParam<L>> Batch for OwnedBatch<L, T> {
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) {
        (&self.mesh, &self.mesh_link, &self.slice, &self.program, &self.state)
    }

    fn fill_params(&self, values: ::shade::ParamValues) {
        self.param.fill_params(&self.param_link, values);
    }
}

type Index = u16;

//#[derive(PartialEq, Eq, PartialOrd, Ord, Show)]
struct Id<T>(Index);

impl<T> Copy for Id<T> {}

impl<T> Id<T> {
    fn unwrap(&self) -> Index {
        let Id(i) = *self;
        i
    }
}

impl<T> fmt::Show for Id<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Id(i) = *self;
        write!(f, "Id({})", i)
    }
}

impl<T> PartialEq for Id<T> {
    fn eq(&self, other: &Id<T>) -> bool {
        self.unwrap() == other.unwrap()
    }
}

impl<T> Eq for Id<T> {}

impl<T> PartialOrd for Id<T> {
    fn partial_cmp(&self, other: &Id<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T> Ord for Id<T> {
    fn cmp(&self, other: &Id<T>) -> Ordering {
        self.unwrap().cmp(&other.unwrap())
    }
}

struct Array<T> {
    data: Vec<T>,
    //generation: u16,
}

impl<T> Array<T> {
    fn new() -> Array<T> {
        Array {
            data: Vec::new(),
            //generation: 0,
        }
    }

    fn get(&self, id: Id<T>) -> &T {
        let Id(i) = id;
        &self.data[i as usize]
    }
}

impl<T: Clone + PartialEq> Array<T> {
    fn find_or_insert(&mut self, value: &T) -> Option<Id<T>> {
        match self.data.iter().position(|v| v == value) {
            Some(i) => from_uint::<Index>(i).map(|id| Id(id)),
            None => {
                from_uint::<Index>(self.data.len()).map(|id| {
                    self.data.push(value.clone());
                    Id(id)
                })
            },
        }
    }
}

/// Ref batch - copyable and smaller, but depends on the `Context`.
/// It has references to the resources (mesh, program, state), that are held
/// by the context that created the batch, so these have to be used together.
#[derive(Copy)]
pub struct RefBatch<L, T> {
    mesh_id: Id<mesh::Mesh>,
    mesh_link: mesh::Link,
    /// Mesh slice
    pub slice: mesh::Slice,
    program_id: Id<ProgramHandle>,
    param_link: L,
    state_id: Id<DrawState>,
}

impl<L, T> fmt::Show for RefBatch<L, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RefBatch(mesh: {:?}, slice: {:?}, program: {:?}, state: {:?})",
            self.mesh_id, self.slice, self.program_id, self.state_id)
    }
}

impl<L, T> PartialEq for RefBatch<L, T> {
    fn eq(&self, other: &RefBatch<L, T>) -> bool {
        self.program_id == other.program_id &&
        self.state_id == other.state_id &&
        self.mesh_id == other.mesh_id
    }
}

impl<L, T> Eq for RefBatch<L, T> {}

impl<L, T> PartialOrd for RefBatch<L, T> {
    fn partial_cmp(&self, other: &RefBatch<L, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<L, T> Ord for RefBatch<L, T> {
    fn cmp(&self, other: &RefBatch<L, T>) -> Ordering {
        (&self.program_id, &self.state_id, &self.mesh_id).cmp(
        &(&other.program_id, &other.state_id, &other.mesh_id))
    }
}

/// Factory of ref batches, required to always be used with them.
pub struct Context {
    meshes: Array<mesh::Mesh>,
    programs: Array<ProgramHandle>,
    states: Array<DrawState>,
}

impl Context {
    /// Create a new empty `Context`
    pub fn new() -> Context {
        Context {
            meshes: Array::new(),
            programs: Array::new(),
            states: Array::new(),
        }
    }
}

impl Context {
    /// Produce a new ref batch
    pub fn make_batch<L, T: ShaderParam<L>>(&mut self,
                      program: &ProgramHandle,
                      mesh: &mesh::Mesh,
                      slice: mesh::Slice,
                      state: &DrawState)
                      -> Result<RefBatch<L, T>, BatchError> {
        let mesh_link = match link_mesh(mesh, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Mesh(e)),
        };
        let link = match ShaderParam::create_link(None::<&T>, program.get_info()) {
            Ok(l) => l,
            Err(e) => return Err(BatchError::Parameters(e))
        };
        let mesh_id = match self.meshes.find_or_insert(mesh) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };
        let program_id = match self.programs.find_or_insert(program) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };
        let state_id = match self.states.find_or_insert(state) {
            Some(id) => id,
            None => return Err(BatchError::ContextFull),
        };

        Ok(RefBatch {
            mesh_id: mesh_id,
            mesh_link: mesh_link,
            slice: slice,
            program_id: program_id,
            param_link: link,
            state_id: state_id,
        })
    }
}

impl<'a, L, T: ShaderParam<L>> Batch for (&'a RefBatch<L, T>, &'a T, &'a Context) {
    fn get_data(&self) -> (&mesh::Mesh, &mesh::Link, &mesh::Slice, &ProgramHandle, &DrawState) {
        let (b, _, ctx) = *self;
        (ctx.meshes.get(b.mesh_id),
         &b.mesh_link,
         &b.slice,
         ctx.programs.get(b.program_id),
         ctx.states.get(b.state_id))
    }

    fn fill_params(&self, values: ::shade::ParamValues) {
        let (b, data, _) = *self;
        data.fill_params(&b.param_link, values);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add compile fail test for issue 27675<commit_after>/// The compiler previously did not properly check the bound of `From` when it was used from type
/// of the dyn trait object (use in `copy_any` below). Since the associated type is under user
/// control in this usage, the compiler could be tricked to believe any type implemented any trait.
/// This would ICE, except for pure marker traits like `Copy`. It did not require providing an
/// instance of the dyn trait type, only name said type.
trait Setup {
    type From: Copy;
}

fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
    *from
}

pub fn copy_any<T>(t: &T) -> T {
    copy::<dyn Setup<From=T>>(t)
    //~^ ERROR the trait bound `T: Copy` is not satisfied
}

fn main() {}
<|endoftext|>


<commit_before>use core::ptr::{read, write};

use common::debug;

use drivers::pciconfig::*;

use programs::session::SessionItem;

#[repr(packed)]
struct SETUP {
    request_type: u8,
    request: u8,
    value: u16,
    index: u16,
    len: u16,
}

#[repr(packed)]
struct QTD {
    next: u32,
    next_alt: u32,
    token: u32,
    buffers: [u32; 5],
}

#[repr(packed)]
struct QueueHead {
    next: u32,
    characteristics: u32,
    capabilities: u32,
    qtd_ptr: u32,
    qtd: QTD,
}

pub struct EHCI {
    pub pci: PCIConfig,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8,
}

impl SessionItem for EHCI {
    #[allow(non_snake_case)]
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            //debug::d("EHCI handle");

            unsafe {
                let CAPLENGTH = self.base as *mut u8;

                let opbase = self.base + read(CAPLENGTH) as usize;

                let USBSTS = (opbase + 4) as *mut u32;
                //debug::d(" USBSTS ");
                //debug::dh(*USBSTS as usize);

                write(USBSTS, 0b111111);

                //debug::d(" USBSTS ");
                //debug::dh(*USBSTS as usize);

                //let FRINDEX = (opbase + 0xC) as *mut u32;
                //debug::d(" FRINDEX ");
                //debug::dh(*FRINDEX as usize);
            }

            //debug::dl();
        }
    }
}

impl EHCI {
    #[allow(non_snake_case)]
    pub unsafe fn init(&mut self) {
        debug::d("EHCI on: ");
        debug::dh(self.base);
        if self.memory_mapped {
            debug::d(" memory mapped");
        } else {
            debug::d(" port mapped");
        }
        debug::d(" IRQ: ");
        debug::dbh(self.irq);

        return;

        /*

        let pci = &mut self.pci;

        pci.flag(4, 4, true); // Bus master

        let CAPLENGTH = self.base as *mut u8;
        let HCSPARAMS = (self.base + 4) as *mut u32;
        let HCCPARAMS = (self.base + 8) as *mut u32;

        debug::d(" CAPLENGTH ");
        debug::dd(read(CAPLENGTH) as usize);

        debug::d(" HCSPARAMS ");
        debug::dh(read(HCSPARAMS) as usize);

        debug::d(" HCCPARAMS ");
        debug::dh(read(HCCPARAMS) as usize);

        let ports = (read(HCSPARAMS) & 0b1111) as usize;
        debug::d(" PORTS ");
        debug::dd(ports);

        let eecp = ((read(HCCPARAMS) >> 8) & 0xFF) as u8;
        debug::d(" EECP ");
        debug::dh(eecp as usize);

        debug::dl();

        if eecp > 0 {
            if pci.read(eecp) & ((1 << 24) | (1 << 16)) == (1 << 16) {
                debug::d("Taking Ownership");
                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);

                pci.flag(eecp, 1 << 24, true);

                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);
                debug::dl();

                debug::d("Waiting");
                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);

                loop {
                    if pci.read(eecp) & ((1 << 24) | (1 << 16)) == (1 << 24) {
                        break;
                    }
                }

                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);
                debug::dl();
            }
        }

        let opbase = self.base + *CAPLENGTH as usize;

        let USBCMD = opbase as *mut u32;
        let USBSTS = (opbase + 4) as *mut u32;
        let USBINTR = (opbase + 8) as *mut u32;
        let FRINDEX = (opbase + 0xC) as *mut u32;
        let CTRLDSSEGMENT = (opbase + 0x10) as *mut u32;
        let PERIODICLISTBASE = (opbase + 0x14) as *mut u32;
        let ASYNCLISTADDR = (opbase + 0x18) as *mut u32;
        let CONFIGFLAG = (opbase + 0x40) as *mut u32;
        let PORTSC = (opbase + 0x44) as *mut u32;

        if read(USBSTS) & (1 << 12) == 0 {
            debug::d("Halting");
            debug::d(" CMD ");
            debug::dh(read(USBCMD) as usize);

            debug::d(" STS ");
            debug::dh(read(USBSTS) as usize);

            write(USBCMD, read(USBCMD) & 0xFFFFFFF0);

            debug::d(" CMD ");
            debug::dh(*USBCMD as usize);

            debug::d(" STS ");
            debug::dh(*USBSTS as usize);
            debug::dl();

            debug::d("Waiting");
            loop {
                if volatile_load(USBSTS) & (1 << 12) == (1 << 12) {
                    break;
                }
            }

            debug::d(" CMD ");
            debug::dh(read(USBCMD) as usize);

            debug::d(" STS ");
            debug::dh(read(USBSTS) as usize);
            debug::dl();
        }

        debug::d("Resetting");
        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);

        write(USBCMD, read(USBCMD) | (1 << 1));

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Waiting");
        loop {
            if volatile_load(USBCMD) & (1 << 1) == 0 {
                break;
            }
        }

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Enabling");
        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);

        write(USBINTR, 0b111111);

        write(USBCMD, read(USBCMD) | 1);
        write(CONFIGFLAG, 1);

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Waiting");
        loop {
            if volatile_load(USBSTS) & (1 << 12) == 0 {
                break;
            }
        }

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        let disable = scheduler::start_ints();
        Duration::new(0, 100 * time::NANOS_PER_MILLI).sleep();
        scheduler::end_ints(disable);

        for i in 0..ports as isize {
            debug::dd(i as usize);
            debug::d(": ");
            debug::dh(read(PORTSC.offset(i)) as usize);
            debug::dl();

            if read(PORTSC.offset(i)) & 1 == 1 {
                debug::d("Device on port ");
                debug::dd(i as usize);
                debug::d(" ");
                debug::dh(read(PORTSC.offset(i)) as usize);
                debug::dl();

                if read(PORTSC.offset(i)) & (1 << 1) == (1 << 1) {
                    debug::d("Connection Change");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i), read(PORTSC.offset(i)) | (1 << 1));

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();
                }

                if read(PORTSC.offset(i)) & (1 << 2) == 0 {
                    debug::d("Reset");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i), read(PORTSC.offset(i)) | (1 << 8));

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i),
                          read(PORTSC.offset(i)) & 0xFFFFFEFF);

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();

                    debug::d("Wait");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    loop {
                        if volatile_load(PORTSC.offset(i)) & (1 << 8) == 0 {
                            break;
                        } else {
                            volatile_store(PORTSC.offset(i),
                                           volatile_load(PORTSC.offset(i)) & 0xFFFFFEFF);
                        }
                    }

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();
                }

                if read(PORTSC.offset(i)) & (1 << 2) == (1 << 2) {
                    debug::d("Port Enabled ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();

                    /*
                    let out_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(out_qtd, QTD {
                        next: 1,
                        next_alt: 1,
                        token: (1 << 31) | (0b11 << 10) | 0x80,
                        buffers: [0, 0, 0, 0, 0]
                    });

                    let in_data = alloc(64) as *mut u8;
                    for i in 0..64 {
                        *in_data.offset(i) = 0;
                    }

                    let in_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(in_qtd, QTD {
                        next: out_qtd as u32,
                        next_alt: 1,
                        token: (1 << 31) | (64 << 16) | (0b11 << 10) | (0b01 << 8) | 0x80,
                        buffers: [in_data as u32, 0, 0, 0, 0]
                    });

                    let setup_packet = alloc(size_of::<SETUP>()) as *mut SETUP;
                    ptr::write(setup_packet, SETUP {
                        request_type: 0b10000000,
                        request: 6,
                        value: 1 << 8,
                        index: 0,
                        len: 64
                    });

                    let setup_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(setup_qtd, QTD {
                        next: in_qtd as u32,
                        next_alt: 1,
                        token: ((size_of::<SETUP>() as u32) << 16) | (0b11 << 10) | (0b10 << 8) | 0x80,
                        buffers: [setup_packet as u32, 0, 0, 0, 0]
                    });

                    let queuehead = alloc(size_of::<QueueHead>()) as *mut QueueHead;
                    ptr::write(queuehead, QueueHead {
                        next: 1,
                        characteristics: (64 << 16) | (1 << 15) | (1 << 14) | (0b10 << 12),
                        capabilities: (0b11 << 30),
                        qtd_ptr: setup_qtd as u32,
                        qtd: ptr::read(setup_qtd)
                    });

                    debug::d("Prepare");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" PTR ");
                        debug::dh(queuehead as usize);
                    debug::dl();

                    debug::d("Send");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *ASYNCLISTADDR = queuehead as u32;

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD |= (1 << 5);

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD |= 1;

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    debug::d("Wait");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                        debug::dl();

                        loop {
                            if *USBSTS & 0xA000  == 0 {
                                break;
                            }
                        }

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    debug::d("Stop");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD &= 0xFFFFFFFF - (1 << 5);

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    d("Data");
                    for i in 0..64 {
                        debug::d(" ");
                        debug::dbh(*in_data.offset(i));
                    }
                    debug::dl();

                    //Only detect one device for testing
                    break;
                    */
                } else {
                    debug::d("Device not high-speed\n");
                }
            }
        }
        */
    }
}
<commit_msg>Missing newline<commit_after>use core::ptr::{read, write};

use common::debug;

use drivers::pciconfig::*;

use programs::session::SessionItem;

#[repr(packed)]
struct SETUP {
    request_type: u8,
    request: u8,
    value: u16,
    index: u16,
    len: u16,
}

#[repr(packed)]
struct QTD {
    next: u32,
    next_alt: u32,
    token: u32,
    buffers: [u32; 5],
}

#[repr(packed)]
struct QueueHead {
    next: u32,
    characteristics: u32,
    capabilities: u32,
    qtd_ptr: u32,
    qtd: QTD,
}

pub struct EHCI {
    pub pci: PCIConfig,
    pub base: usize,
    pub memory_mapped: bool,
    pub irq: u8,
}

impl SessionItem for EHCI {
    #[allow(non_snake_case)]
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            //debug::d("EHCI handle");

            unsafe {
                let CAPLENGTH = self.base as *mut u8;

                let opbase = self.base + read(CAPLENGTH) as usize;

                let USBSTS = (opbase + 4) as *mut u32;
                //debug::d(" USBSTS ");
                //debug::dh(*USBSTS as usize);

                write(USBSTS, 0b111111);

                //debug::d(" USBSTS ");
                //debug::dh(*USBSTS as usize);

                //let FRINDEX = (opbase + 0xC) as *mut u32;
                //debug::d(" FRINDEX ");
                //debug::dh(*FRINDEX as usize);
            }

            //debug::dl();
        }
    }
}

impl EHCI {
    #[allow(non_snake_case)]
    pub unsafe fn init(&mut self) {
        debug::d("EHCI on: ");
        debug::dh(self.base);
        if self.memory_mapped {
            debug::d(" memory mapped");
        } else {
            debug::d(" port mapped");
        }
        debug::d(" IRQ: ");
        debug::dbh(self.irq);

        debug::dl();
        return;

        /*

        let pci = &mut self.pci;

        pci.flag(4, 4, true); // Bus master

        let CAPLENGTH = self.base as *mut u8;
        let HCSPARAMS = (self.base + 4) as *mut u32;
        let HCCPARAMS = (self.base + 8) as *mut u32;

        debug::d(" CAPLENGTH ");
        debug::dd(read(CAPLENGTH) as usize);

        debug::d(" HCSPARAMS ");
        debug::dh(read(HCSPARAMS) as usize);

        debug::d(" HCCPARAMS ");
        debug::dh(read(HCCPARAMS) as usize);

        let ports = (read(HCSPARAMS) & 0b1111) as usize;
        debug::d(" PORTS ");
        debug::dd(ports);

        let eecp = ((read(HCCPARAMS) >> 8) & 0xFF) as u8;
        debug::d(" EECP ");
        debug::dh(eecp as usize);

        debug::dl();

        if eecp > 0 {
            if pci.read(eecp) & ((1 << 24) | (1 << 16)) == (1 << 16) {
                debug::d("Taking Ownership");
                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);

                pci.flag(eecp, 1 << 24, true);

                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);
                debug::dl();

                debug::d("Waiting");
                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);

                loop {
                    if pci.read(eecp) & ((1 << 24) | (1 << 16)) == (1 << 24) {
                        break;
                    }
                }

                debug::d(" ");
                debug::dh(pci.read(eecp) as usize);
                debug::dl();
            }
        }

        let opbase = self.base + *CAPLENGTH as usize;

        let USBCMD = opbase as *mut u32;
        let USBSTS = (opbase + 4) as *mut u32;
        let USBINTR = (opbase + 8) as *mut u32;
        let FRINDEX = (opbase + 0xC) as *mut u32;
        let CTRLDSSEGMENT = (opbase + 0x10) as *mut u32;
        let PERIODICLISTBASE = (opbase + 0x14) as *mut u32;
        let ASYNCLISTADDR = (opbase + 0x18) as *mut u32;
        let CONFIGFLAG = (opbase + 0x40) as *mut u32;
        let PORTSC = (opbase + 0x44) as *mut u32;

        if read(USBSTS) & (1 << 12) == 0 {
            debug::d("Halting");
            debug::d(" CMD ");
            debug::dh(read(USBCMD) as usize);

            debug::d(" STS ");
            debug::dh(read(USBSTS) as usize);

            write(USBCMD, read(USBCMD) & 0xFFFFFFF0);

            debug::d(" CMD ");
            debug::dh(*USBCMD as usize);

            debug::d(" STS ");
            debug::dh(*USBSTS as usize);
            debug::dl();

            debug::d("Waiting");
            loop {
                if volatile_load(USBSTS) & (1 << 12) == (1 << 12) {
                    break;
                }
            }

            debug::d(" CMD ");
            debug::dh(read(USBCMD) as usize);

            debug::d(" STS ");
            debug::dh(read(USBSTS) as usize);
            debug::dl();
        }

        debug::d("Resetting");
        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);

        write(USBCMD, read(USBCMD) | (1 << 1));

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Waiting");
        loop {
            if volatile_load(USBCMD) & (1 << 1) == 0 {
                break;
            }
        }

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Enabling");
        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);

        write(USBINTR, 0b111111);

        write(USBCMD, read(USBCMD) | 1);
        write(CONFIGFLAG, 1);

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        debug::d("Waiting");
        loop {
            if volatile_load(USBSTS) & (1 << 12) == 0 {
                break;
            }
        }

        debug::d(" CMD ");
        debug::dh(read(USBCMD) as usize);

        debug::d(" STS ");
        debug::dh(read(USBSTS) as usize);
        debug::dl();

        let disable = scheduler::start_ints();
        Duration::new(0, 100 * time::NANOS_PER_MILLI).sleep();
        scheduler::end_ints(disable);

        for i in 0..ports as isize {
            debug::dd(i as usize);
            debug::d(": ");
            debug::dh(read(PORTSC.offset(i)) as usize);
            debug::dl();

            if read(PORTSC.offset(i)) & 1 == 1 {
                debug::d("Device on port ");
                debug::dd(i as usize);
                debug::d(" ");
                debug::dh(read(PORTSC.offset(i)) as usize);
                debug::dl();

                if read(PORTSC.offset(i)) & (1 << 1) == (1 << 1) {
                    debug::d("Connection Change");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i), read(PORTSC.offset(i)) | (1 << 1));

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();
                }

                if read(PORTSC.offset(i)) & (1 << 2) == 0 {
                    debug::d("Reset");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i), read(PORTSC.offset(i)) | (1 << 8));

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    write(PORTSC.offset(i),
                          read(PORTSC.offset(i)) & 0xFFFFFEFF);

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();

                    debug::d("Wait");
                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);

                    loop {
                        if volatile_load(PORTSC.offset(i)) & (1 << 8) == 0 {
                            break;
                        } else {
                            volatile_store(PORTSC.offset(i),
                                           volatile_load(PORTSC.offset(i)) & 0xFFFFFEFF);
                        }
                    }

                    debug::d(" ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();
                }

                if read(PORTSC.offset(i)) & (1 << 2) == (1 << 2) {
                    debug::d("Port Enabled ");
                    debug::dh(read(PORTSC.offset(i)) as usize);
                    debug::dl();

                    /*
                    let out_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(out_qtd, QTD {
                        next: 1,
                        next_alt: 1,
                        token: (1 << 31) | (0b11 << 10) | 0x80,
                        buffers: [0, 0, 0, 0, 0]
                    });

                    let in_data = alloc(64) as *mut u8;
                    for i in 0..64 {
                        *in_data.offset(i) = 0;
                    }

                    let in_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(in_qtd, QTD {
                        next: out_qtd as u32,
                        next_alt: 1,
                        token: (1 << 31) | (64 << 16) | (0b11 << 10) | (0b01 << 8) | 0x80,
                        buffers: [in_data as u32, 0, 0, 0, 0]
                    });

                    let setup_packet = alloc(size_of::<SETUP>()) as *mut SETUP;
                    ptr::write(setup_packet, SETUP {
                        request_type: 0b10000000,
                        request: 6,
                        value: 1 << 8,
                        index: 0,
                        len: 64
                    });

                    let setup_qtd = alloc(size_of::<QTD>()) as *mut QTD;
                    ptr::write(setup_qtd, QTD {
                        next: in_qtd as u32,
                        next_alt: 1,
                        token: ((size_of::<SETUP>() as u32) << 16) | (0b11 << 10) | (0b10 << 8) | 0x80,
                        buffers: [setup_packet as u32, 0, 0, 0, 0]
                    });

                    let queuehead = alloc(size_of::<QueueHead>()) as *mut QueueHead;
                    ptr::write(queuehead, QueueHead {
                        next: 1,
                        characteristics: (64 << 16) | (1 << 15) | (1 << 14) | (0b10 << 12),
                        capabilities: (0b11 << 30),
                        qtd_ptr: setup_qtd as u32,
                        qtd: ptr::read(setup_qtd)
                    });

                    debug::d("Prepare");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" PTR ");
                        debug::dh(queuehead as usize);
                    debug::dl();

                    debug::d("Send");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *ASYNCLISTADDR = queuehead as u32;

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD |= (1 << 5);

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD |= 1;

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    debug::d("Wait");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                        debug::dl();

                        loop {
                            if *USBSTS & 0xA000  == 0 {
                                break;
                            }
                        }

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    debug::d("Stop");
                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);

                        *USBCMD &= 0xFFFFFFFF - (1 << 5);

                        debug::d(" CMD ");
                        debug::dh(*USBCMD as usize);

                        debug::d(" STS ");
                        debug::dh(*USBSTS as usize);
                    debug::dl();

                    d("Data");
                    for i in 0..64 {
                        debug::d(" ");
                        debug::dbh(*in_data.offset(i));
                    }
                    debug::dl();

                    //Only detect one device for testing
                    break;
                    */
                } else {
                    debug::d("Device not high-speed\n");
                }
            }
        }
        */
    }
}
<|endoftext|>


<commit_before><commit_msg>close keeper<commit_after><|endoftext|>


<commit_before><commit_msg>Basic beta state mockup.<commit_after>struct Beta {
	pc:			u32,
	register:	~[u32],
	memory:		~[u8]
}

fn main() {
	let b = Beta { pc: 0u32, register: ~[0u32, ..31], memory: ~[0u8, ..4*1024] };
	println("success");
}
<|endoftext|>


<commit_before><commit_msg>run the initializer from the main method.<commit_after>extern crate getopts;
use std::os;

mod initializer;
mod help;

fn main() {
    let args: Vec<String> = os::args();
    initializer::init(args);
}
<|endoftext|>


<commit_before><commit_msg>lastdocs<commit_after><|endoftext|>


<commit_before><commit_msg>some changes<commit_after><|endoftext|>


<commit_before><commit_msg>small parsing refactor<commit_after><|endoftext|>


<commit_before><commit_msg>:art: Make enable to set optional template message<commit_after><|endoftext|>


<commit_before><commit_msg>Make REPL threads not eat up so much CPU<commit_after><|endoftext|>


<commit_before><commit_msg>push and pop modes<commit_after><|endoftext|>


<commit_before><commit_msg>implement walkdir on -r for cp<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor ls command<commit_after><|endoftext|>


<commit_before><commit_msg>add first version of the code<commit_after>#[crate_id(name="tead", version="1.0.0", author="papanikge")];
//
// George 'papanikge' Papanikolaou 2014
// head + tail = tead
//

extern mod extra;
use extra::getopts::{optopt, optflag, getopts};
use std::io::buffered::BufferedReader;
use std::io::fs::File;
use std::path::Path;

fn usage() {
    println("Usage: tead [options]");
    println("\t-n <number of lines to print>");
    println("\t-h --help");
    println("\t-V --version");
}

// Ideally we would use DoubleEndedIterator but that doesn't work with files,
// since we don't have access to the whole file. So, obviously this is not
// optimized, since we are loading the entire file on memory.
fn tead<T: Reader>(reader: &mut BufferedReader<T>, count: uint) {
    let all: ~[~str] = reader.lines().collect();
    // head
    for line in all.iter().take(count) {
        print(*line);
    }
    // tail
    for line in all.rev_iter().take(count) {
        print(*line);
    }
}

fn main() {
    let args = std::os::args();

    let available = [
        optopt("n"),  // Number of lines to print
        optflag("h"), optflag("help"),
        optflag("V"), optflag("version")
    ];

    // test for the available options upon the provided ones
    let given = match getopts(args.tail(), available) {
        Ok (m) =>  m,
        Err(_) => {
            usage();
            fail!();
        }
    };

    // help and version outta the way
    if given.opt_present("h") || given.opt_present("help") {
        usage();
        return;
    }
    if given.opt_present("V") || given.opt_present("version") {
        println("tead -- version 1.0.0");
        return;
    }

    // let's find out the lines requested and move on
    // Beware: Rust weirdness ahead!
    let lines = match given.opt_str("n") {
        Some(s) => {
            match from_str::<uint>(s) {
                Some(x) => { x }
                None    => { fail!("a string for number of lines, dude?") }
            }
        }
        None    => { 10u }
    };

    // let's go
    let files = given.free;
    if files.is_empty() {
        // No files provided. stdin() is a reader so we can do:
        let mut buffer = BufferedReader::new(std::io::stdin());
        tead(&mut buffer, lines);
    } else {
        for file in files.iter() {
            // the argument below needs to be a ** so we use 'as_slice'
            let path = Path::new(file.as_slice());
            // to avoid all that 'match Some' malarkey we just use 'unwrap'
            let reader = File::open(&path).unwrap();
            // opening the reader
            let mut buffer = BufferedReader::new(reader);
            tead(&mut buffer, lines);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Chore(clippy): fix redundant closures<commit_after><|endoftext|>


<commit_before>use std;
use simd;
use simdext::*;

use simd::x86::sse2::u64x2;

extern "platform-intrinsic" {
    fn x86_mm_testz_si128(x: u64x2, y: u64x2) -> i32;
}

#[inline]
unsafe fn bitcast<T, U>(x: T) -> U {
    debug_assert!(std::mem::size_of::<T>() == std::mem::size_of::<U>());
    std::mem::transmute_copy(&x)
}

#[derive(Clone, Copy)]
pub struct FieldBit {
    m: simd::u16x8,
}

impl FieldBit {
    pub fn new(m: simd::u16x8) -> FieldBit {
        FieldBit {
            m: m,
        }
    }

    pub fn from_values(v1: u16, v2: u16, v3: u16, v4: u16, v5: u16, v6: u16, v7: u16, v8: u16) -> FieldBit {
        FieldBit {
            m: simd::u16x8::new(v1, v2, v3, v4, v5, v6, v7, v8)
        }
    }

    pub fn new_empty() -> FieldBit {
        FieldBit {
            m: simd::u16x8::splat(0)
        }
    }

    pub fn get(&self, x: usize, y: usize) -> bool {
        debug_assert!(FieldBit::check_in_range(x, y));
        unsafe {
            x86_mm_testz_si128(bitcast(FieldBit::onebit(x, y)), bitcast(self.m)) == 0
        }
    }

    pub fn set(&mut self, x: usize, y: usize) {
        debug_assert!(FieldBit::check_in_range(x, y));
        self.m = mm_or_epu16(FieldBit::onebit(x, y), self.m)
    }

    pub fn unset(&mut self, x: usize, y: usize) {
        debug_assert!(FieldBit::check_in_range(x, y));
        self.m = mm_andnot_epu16(FieldBit::onebit(x, y), self.m)
    }

    pub fn as_u16x8(&self) -> simd::u16x8 {
        self.m
    }

    fn check_in_range(x: usize, y: usize) -> bool {
        x < 8 && y < 16
    }

    fn onebit(x: usize, y: usize) -> simd::u16x8 {
        debug_assert!(FieldBit::check_in_range(x, y));

        let shift = ((x << 4) | y) & 0x3F;
        let hi: u64 = (x as u64) >> 2;
        let lo: u64 = hi ^ 1;
        unsafe { bitcast(u64x2::new(lo << shift, hi << shift)) }
    }
}

impl std::fmt::Display for FieldBit {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "({}, {}, {}, {}, {}, {}, {}, {})",
               self.m.extract(0), self.m.extract(1), self.m.extract(2), self.m.extract(3),
               self.m.extract(4), self.m.extract(5), self.m.extract(6), self.m.extract(7))
    }
}

#[cfg(test)]
mod tests {
    use field_bit::FieldBit;

    #[test]
    fn test_empty() {
        let fb = FieldBit::new_empty();
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                assert_eq!(fb.get(x, y), false);
            }
        }
    }

    #[test]
    fn test_from_value() {
        let fb = FieldBit::from_values(1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7);
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                assert_eq!(fb.get(x, y), x == y, "failed at x={}, y={}, fb.get(x, y)={}", x, y, fb.get(x, y));
            }
        }
    }

    #[test]
    fn test_set_get() {
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                let mut fb = FieldBit::new_empty();
                assert!(!fb.get(x, y));
                fb.set(x, y);
                assert!(fb.get(x, y));
                fb.unset(x, y);
                assert!(!fb.get(x, y));
            }
        }
    }
}
<commit_msg>Add FieldBit::masked_field_12 and masked_field_13.<commit_after>use std;
use simd;
use simd::x86::sse2::u64x2;
use simdext::*;

extern "platform-intrinsic" {
    fn x86_mm_testz_si128(x: u64x2, y: u64x2) -> i32;
}

#[inline]
unsafe fn bitcast<T, U>(x: T) -> U {
    debug_assert!(std::mem::size_of::<T>() == std::mem::size_of::<U>());
    std::mem::transmute_copy(&x)
}

#[derive(Clone, Copy)]
pub struct FieldBit {
    m: simd::u16x8,
}

impl FieldBit {
    pub fn new(m: simd::u16x8) -> FieldBit {
        FieldBit {
            m: m,
        }
    }

    pub fn from_values(v1: u16, v2: u16, v3: u16, v4: u16, v5: u16, v6: u16, v7: u16, v8: u16) -> FieldBit {
        FieldBit {
            m: simd::u16x8::new(v1, v2, v3, v4, v5, v6, v7, v8)
        }
    }

    pub fn new_empty() -> FieldBit {
        FieldBit {
            m: simd::u16x8::splat(0)
        }
    }

    pub fn get(&self, x: usize, y: usize) -> bool {
        debug_assert!(FieldBit::check_in_range(x, y));
        unsafe {
            x86_mm_testz_si128(bitcast(FieldBit::onebit(x, y)), bitcast(self.m)) == 0
        }
    }

    pub fn set(&mut self, x: usize, y: usize) {
        debug_assert!(FieldBit::check_in_range(x, y));
        self.m = mm_or_epu16(FieldBit::onebit(x, y), self.m)
    }

    pub fn unset(&mut self, x: usize, y: usize) {
        debug_assert!(FieldBit::check_in_range(x, y));
        self.m = mm_andnot_epu16(FieldBit::onebit(x, y), self.m)
    }

    pub fn masked_field_12(&self) -> FieldBit {
        FieldBit {
            m: self.m & simd::u16x8::new(0, 0x1FFE, 0x1FFE, 0x1FFE, 0x1FFE, 0x1FFE, 0x1FFE, 0)
        }
    }

    pub fn masked_field_13(&self) -> FieldBit {
        FieldBit {
            m: self.m & simd::u16x8::new(0, 0x3FFE, 0x3FFE, 0x3FFE, 0x3FFE, 0x3FFE, 0x3FFE, 0)
        }
    }

    pub fn as_u16x8(&self) -> simd::u16x8 {
        self.m
    }

    fn check_in_range(x: usize, y: usize) -> bool {
        x < 8 && y < 16
    }

    fn onebit(x: usize, y: usize) -> simd::u16x8 {
        debug_assert!(FieldBit::check_in_range(x, y));

        let shift = ((x << 4) | y) & 0x3F;
        let hi: u64 = (x as u64) >> 2;
        let lo: u64 = hi ^ 1;
        unsafe { bitcast(u64x2::new(lo << shift, hi << shift)) }
    }
}

impl std::fmt::Display for FieldBit {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "({}, {}, {}, {}, {}, {}, {}, {})",
               self.m.extract(0), self.m.extract(1), self.m.extract(2), self.m.extract(3),
               self.m.extract(4), self.m.extract(5), self.m.extract(6), self.m.extract(7))
    }
}

#[cfg(test)]
mod tests {
    use field;
    use field_bit::FieldBit;

    #[test]
    fn test_empty() {
        let fb = FieldBit::new_empty();
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                assert_eq!(fb.get(x, y), false);
            }
        }
    }

    #[test]
    fn test_from_value() {
        let fb = FieldBit::from_values(1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7);
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                assert_eq!(fb.get(x, y), x == y, "failed at x={}, y={}, fb.get(x, y)={}", x, y, fb.get(x, y));
            }
        }
    }

    #[test]
    fn test_set_get() {
        for x in 0 .. 8 {
            for y in 0 .. 16 {
                let mut fb = FieldBit::new_empty();
                assert!(!fb.get(x, y));
                fb.set(x, y);
                assert!(fb.get(x, y));
                fb.unset(x, y);
                assert!(!fb.get(x, y));
            }
        }
    }

    #[test]
    fn test_masked_field() {
        let fb = FieldBit::from_values(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
        let fb12 = fb.masked_field_12();
        let fb13 = fb.masked_field_13();

        for x in 0 .. field::MAP_WIDTH {
            for y in 0 .. field::MAP_HEIGHT {
                assert!(fb.get(x, y), "x={}, y={}", x, y);
                assert_eq!(fb12.get(x, y), 1 <= x && x <= 6 && 1 <= y && y <= 12, "x={}, y={}", x, y);
                assert_eq!(fb13.get(x, y), 1 <= x && x <= 6 && 1 <= y && y <= 13, "x={}, y={}", x, y);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Added first unit test<commit_after><|endoftext|>


<commit_before><commit_msg>Replace the c.len_utf8_bytes() hack by a custom string iterator.<commit_after><|endoftext|>