<commit_before>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;

#[macro_use]
extern crate vulkano;

use std::sync::Arc;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    // The first step of any vulkan program is to create an instance.
    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &["VK_LAYER_LUNARG_draw_state"]).expect("failed to create instance");

    // We then choose which physical device to use.
    //
    // In a real application, there are three things to take into consideration:
    //
    // - Some devices support some optional features that may be required by your application.
    //   You should filter out the devices that don't support your app.
    //
    // - Not all devices can draw to a certain surface. Once you create your window, you have to
    //   choose a device that is capable of drawing to it.
    //
    // - You probably want to leave the choice between the remaining devices to the user.
    //
    // Here we are just going to use the first device.
    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    // The objective of this example is to draw a triangle on a window. To do so, we first have to
    // create the window in a platform-specific way. Then we create a `Surface` object from it.
    //
    // Surface objects are cross-platform. Once you have a `Surface` everything is the same again.
    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    // The next step is to choose which queue will execute our draw commands.
    //
    // Devices can provide multiple queues to run things in parallel (for example a draw queue and
    // a compute queue). This is something you have to have to manage manually in Vulkan.
    //
    // We have to specify which queues you are going to use when we create the device, therefore
    // we need to choose that now.
    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    // Now initializing the device.
    //
    // We have to pass a list of optional Vulkan features that must be enabled. TODO: explain this
    //
    // We also have to pass a list of queues to create and their priorities relative to each other.
    // Since we create one queue, we don't really care about the priority and just pass `0.5`.
    // The list of created queues is returned by the function alongside with the device.
    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(),
                                                        &["VK_LAYER_LUNARG_draw_state"])
                                                                .expect("failed to create device");

    // Since we can request multiple queues, the `queues` variable is a `Vec`. Our actual queue
    // is the first element.
    let queue = queues.into_iter().next().unwrap();

    // Before we can draw on the surface, we have to create what is called a swapchain. Creating
    // a swapchain allocates the color buffers that will contain the image that will ultimately
    // be visible on the screen. These images are returned alongside with the swapchain.
    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    // We now create a buffer that will store the shape of our triangle.
    //
    // The first parameter is the device to use, and the second parameter is how the buffer will
    // be used on the GPU side. This is a vertex buffer, and we need to tell this to the
    // implementation.
    //
    // The third parameter is where to get the memory where the buffer will be stored. It is very
    // important as it also determines the way you are going to access and modify your buffer.
    // Here we just ask for a basic host visible memory.
    //
    // Note that to store immutable data, the best way is to create two buffers. One buffer on
    // the CPU and one buffer on the GPU. We then write our data to the buffer on the CPU and
    // ask the GPU to copy it to the real buffer. This way the data is located on the most
    // efficient memory possible.
    let vertex_buffer = vulkano::buffer::Buffer::<[Vertex; 3], _>
                               ::new(&device, &vulkano::buffer::Usage::all(),
                                     vulkano::memory::HostVisible, &queue)
                               .expect("failed to create buffer");
    struct Vertex { position: [f32; 2] }
    impl_vertex!(Vertex, position);

    // The buffer that we created contains uninitialized data.
    // In order to fill it with data, we have to *map* it.
    {
        // The `try_write` function would return `None` if the buffer was in use by the GPU. This
        // obviously can't happen here, since we haven't ask the GPU to do anything yet.
        let mut mapping = vertex_buffer.try_write().unwrap();
        mapping[0].position = [-0.5, -0.25];
        mapping[1].position = [0.0, 0.5];
        mapping[2].position = [0.25, -0.1];
    }

    // The next step is to create the shaders.
    //
    // The shader creation API provided by the vulkano library is unsafe, for various reasons.
    //
    // Instead, in our build script we used the `vulkano-shaders` crate to parse our shaders at
    // compile time and provide a safe wrapper over vulkano's API. You can find the shaders'
    // source code in the `triangle_fs.glsl` and `triangle_vs.glsl` files.
    //
    // The code generated by the build script created a struct named `TriangleShader`, which we
    // can now use to load the shader.
    //
    // Because of some restrictions with the `include!` macro, we need to use a module.
    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_vs.rs")} }
    let vs = vs::TriangleShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_fs.rs")} }
    let fs = fs::TriangleShader::load(&device).expect("failed to create shader module");

    // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
    // implicitely does a lot of computation whenever you draw. In Vulkan, you have to do all this
    // manually.

    // We are going to create a command buffer below. Command buffers need to be allocated
    // from a *command buffer pool*, so we create the pool.
    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    // We are going to draw on the images returned when creating the swapchain. To do so, we must
    // convert them into *image views*. TODO: explain more
    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    // The next step is to create a *renderpass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(), &vulkano::descriptor_set::PipelineLayout::new(&device, Default::default(), ()).unwrap(),
                                                 &renderpass.subpass(0).unwrap()).unwrap()
    };

    // The renderpass we created above only describes the layout of our framebuffers. We also need
    // to create the actual framebuffers.
    //
    // Since we need to draw to multiple images, we are going to create a different framebuffer for
    // each image.
    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    // The final initialization step is to create a command buffer.
    //
    // A command buffer contains a list of commands that the GPU must execute. This can include
    // transfers between buffers, clearing images or attachments, etc. and draw commands. Here we
    // create a command buffer with a single command: drawing the triangle. The color attachment
    // is also cleared at the start.
    //
    // Since we have several images to draw on, we are also going to create one command buffer for
    // each image.
    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none(), ())
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    // Initialization is finally finished!

    // Note that the only thing we need now are the `command_buffers` and `swapchain` variables.
    // Everything else is kept alive internally with `Arc`s (even the vertex buffer for example),
    // so the only variable that we need is this one.

    loop {
        // Before we can draw on the output, we have to *acquire* an image from the swapchain.
        // This operation returns the index of the image that we are allowed to draw upon..
        let image_num = swapchain.acquire_next_image(1000000).unwrap();

        // Our queue is wrapped around a `Mutex`, so we have to lock it.
        let mut queue = queue.lock().unwrap();

        // In order to draw, all we need to do is submit the command buffer to the queue.
        command_buffers[image_num].submit(&mut queue).unwrap();

        // The color output should now contain our triangle. But in order to show it on the
        // screen, we have to *present* the image. Depending on the presentation mode, this may
        // be shown immediatly or on the next redraw.
        swapchain.present(&mut queue, image_num).unwrap();

        // In a real application we want to submit things to the same queue in parallel, so we
        // shouldn't keep it locked too long.
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<commit_msg>Fix triangle example<commit_after>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;

#[macro_use]
extern crate vulkano;

use std::sync::Arc;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    // The first step of any vulkan program is to create an instance.
    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &["VK_LAYER_LUNARG_draw_state"]).expect("failed to create instance");

    // We then choose which physical device to use.
    //
    // In a real application, there are three things to take into consideration:
    //
    // - Some devices support some optional features that may be required by your application.
    //   You should filter out the devices that don't support your app.
    //
    // - Not all devices can draw to a certain surface. Once you create your window, you have to
    //   choose a device that is capable of drawing to it.
    //
    // - You probably want to leave the choice between the remaining devices to the user.
    //
    // Here we are just going to use the first device.
    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    // The objective of this example is to draw a triangle on a window. To do so, we first have to
    // create the window in a platform-specific way. Then we create a `Surface` object from it.
    //
    // Surface objects are cross-platform. Once you have a `Surface` everything is the same again.
    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    // The next step is to choose which queue will execute our draw commands.
    //
    // Devices can provide multiple queues to run things in parallel (for example a draw queue and
    // a compute queue). This is something you have to have to manage manually in Vulkan.
    //
    // We have to specify which queues you are going to use when we create the device, therefore
    // we need to choose that now.
    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    // Now initializing the device.
    //
    // We have to pass a list of optional Vulkan features that must be enabled. TODO: explain this
    //
    // We also have to pass a list of queues to create and their priorities relative to each other.
    // Since we create one queue, we don't really care about the priority and just pass `0.5`.
    // The list of created queues is returned by the function alongside with the device.
    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(),
                                                        &["VK_LAYER_LUNARG_draw_state"])
                                                                .expect("failed to create device");

    // Since we can request multiple queues, the `queues` variable is a `Vec`. Our actual queue
    // is the first element.
    let queue = queues.into_iter().next().unwrap();

    // Before we can draw on the surface, we have to create what is called a swapchain. Creating
    // a swapchain allocates the color buffers that will contain the image that will ultimately
    // be visible on the screen. These images are returned alongside with the swapchain.
    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    // We now create a buffer that will store the shape of our triangle.
    //
    // The first parameter is the device to use, and the second parameter is how the buffer will
    // be used on the GPU side. This is a vertex buffer, and we need to tell this to the
    // implementation.
    //
    // The third parameter is where to get the memory where the buffer will be stored. It is very
    // important as it also determines the way you are going to access and modify your buffer.
    // Here we just ask for a basic host visible memory.
    //
    // Note that to store immutable data, the best way is to create two buffers. One buffer on
    // the CPU and one buffer on the GPU. We then write our data to the buffer on the CPU and
    // ask the GPU to copy it to the real buffer. This way the data is located on the most
    // efficient memory possible.
    let vertex_buffer = vulkano::buffer::Buffer::<[Vertex; 3], _>
                               ::new(&device, &vulkano::buffer::Usage::all(),
                                     vulkano::memory::HostVisible, &queue)
                               .expect("failed to create buffer");
    struct Vertex { position: [f32; 2] }
    impl_vertex!(Vertex, position);

    // The buffer that we created contains uninitialized data.
    // In order to fill it with data, we have to *map* it.
    {
        // The `try_write` function would return `None` if the buffer was in use by the GPU. This
        // obviously can't happen here, since we haven't ask the GPU to do anything yet.
        let mut mapping = vertex_buffer.try_write().unwrap();
        mapping[0].position = [-0.5, -0.25];
        mapping[1].position = [0.0, 0.5];
        mapping[2].position = [0.25, -0.1];
    }

    // The next step is to create the shaders.
    //
    // The shader creation API provided by the vulkano library is unsafe, for various reasons.
    //
    // Instead, in our build script we used the `vulkano-shaders` crate to parse our shaders at
    // compile time and provide a safe wrapper over vulkano's API. You can find the shaders'
    // source code in the `triangle_fs.glsl` and `triangle_vs.glsl` files.
    //
    // The code generated by the build script created a struct named `TriangleShader`, which we
    // can now use to load the shader.
    //
    // Because of some restrictions with the `include!` macro, we need to use a module.
    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_vs.rs")} }
    let vs = vs::TriangleShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_fs.rs")} }
    let fs = fs::TriangleShader::load(&device).expect("failed to create shader module");

    // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
    // implicitely does a lot of computation whenever you draw. In Vulkan, you have to do all this
    // manually.

    // We are going to create a command buffer below. Command buffers need to be allocated
    // from a *command buffer pool*, so we create the pool.
    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    // We are going to draw on the images returned when creating the swapchain. To do so, we must
    // convert them into *image views*. TODO: explain more
    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    // The next step is to create a *renderpass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let pipeline = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(), &vulkano::descriptor_set::PipelineLayout::new(&device, Default::default(), ((), ())).unwrap(),
                                                 &renderpass.subpass(0).unwrap()).unwrap()
    };

    // The renderpass we created above only describes the layout of our framebuffers. We also need
    // to create the actual framebuffers.
    //
    // Since we need to draw to multiple images, we are going to create a different framebuffer for
    // each image.
    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    // The final initialization step is to create a command buffer.
    //
    // A command buffer contains a list of commands that the GPU must execute. This can include
    // transfers between buffers, clearing images or attachments, etc. and draw commands. Here we
    // create a command buffer with a single command: drawing the triangle. The color attachment
    // is also cleared at the start.
    //
    // Since we have several images to draw on, we are also going to create one command buffer for
    // each image.
    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none(), ((), ()))
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    // Initialization is finally finished!

    // Note that the only thing we need now are the `command_buffers` and `swapchain` variables.
    // Everything else is kept alive internally with `Arc`s (even the vertex buffer for example),
    // so the only variable that we need is this one.

    loop {
        // Before we can draw on the output, we have to *acquire* an image from the swapchain.
        // This operation returns the index of the image that we are allowed to draw upon..
        let image_num = swapchain.acquire_next_image(1000000).unwrap();

        // Our queue is wrapped around a `Mutex`, so we have to lock it.
        let mut queue = queue.lock().unwrap();

        // In order to draw, all we need to do is submit the command buffer to the queue.
        command_buffers[image_num].submit(&mut queue).unwrap();

        // The color output should now contain our triangle. But in order to show it on the
        // screen, we have to *present* the image. Depending on the presentation mode, this may
        // be shown immediatly or on the next redraw.
        swapchain.present(&mut queue, image_num).unwrap();

        // In a real application we want to submit things to the same queue in parallel, so we
        // shouldn't keep it locked too long.
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<|endoftext|>


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

//! Link between Vulkan and a window and/or the screen.
//!
//! Before you can draw on the screen or a window, you have to create two objects:
//!
//! - Create a `Surface` object that represents the location where the image will show up (either
//!   a window or a monitor).
//! - Create a `Swapchain` that uses that `Surface`.
//!
//! Creating a surface can be done with only an `Instance` object. However creating a swapchain
//! requires a `Device` object.
//!
//! Once you have a swapchain, you can retrieve `Image` objects from it and draw to them just like
//! you would draw on any other image.
//!
//! # Surfaces
//!
//! A surface is an object that represents a location where to render. It can be created from an
//! instance and either a window handle (in a platform-specific way) or a monitor.
//!
//! In order to use surfaces, you will have to enable the `VK_KHR_surface` extension on the
//! instance. See the `instance` module for more information about how to enable extensions.
//!
//! ## Creating a surface from a window
//!
//! There are 6 extensions that each allow you to create a surface from a type of window:
//!
//! - `VK_KHR_xlib_surface`
//! - `VK_KHR_xcb_surface`
//! - `VK_KHR_wayland_surface`
//! - `VK_KHR_mir_surface`
//! - `VK_KHR_android_surface`
//! - `VK_KHR_win32_surface`
//!
//! For example if you want to create a surface from an Android surface, you will have to enable
//! the `VK_KHR_android_surface` extension and use `Surface::from_anativewindow`.
//! See the documentation of `Surface` for all the possible constructors.
//!
//! Trying to use one of these functions without enabling the proper extension will result in an
//! error.
//!
//! **Note that the `Surface` object is unsafe**. It is your responsibility to keep the window
//! alive for at least as long as the surface exists.
//!
//! ### Example
//!
//! ```no_run
//! use std::ptr;
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::swapchain::Surface;
//!
//! let instance = {
//!     let extensions = InstanceExtensions {
//!         khr_surface: true,
//!         khr_win32_surface: true,        // If you don't enable this, `from_hwnd` will fail.
//!         .. InstanceExtensions::none()
//!     };
//!
//!      match Instance::new(None, &extensions, None) {
//!         Ok(i) => i,
//!         Err(err) => panic!("Couldn't build instance: {:?}", err)
//!     }
//! };
//!
//! # fn build_window() -> *const u32 { ptr::null() }
//! let window = build_window();
//! let _surface = unsafe { Surface::from_hwnd(&instance, ptr::null(), window).unwrap() };
//! ```
//!
//! ## Creating a surface from a monitor
//!
//! Currently no system provides the `VK_KHR_display` extension that contains this feature.
//! This feature is still a work-in-progress in vulkano and will reside in the `display` module.
//!
//! # Swapchains
//!
//! A surface represents a location on the screen and can be created from an instance. Once you
//! have a surface, the next step is to create a swapchain. Creating a swapchain requires a device,
//! and allocates the resources that will be used to display images on the screen.
//!
//! A swapchain is composed of one or multiple images. Each image of the swapchain is presented in
//! turn on the screen, one after another. More information below.
//!
//! Swapchains have several properties:
//!
//!  - The number of images that will cycle on the screen.
//!  - The format of the images.
//!  - The 2D dimensions of the images, plus a number of layers, for a total of three dimensions.
//!  - The usage of the images, similar to creating other images.
//!  - The queue families that are going to use the images, similar to creating other images.
//!  - An additional transformation (rotation or mirroring) to perform on the final output.
//!  - How the alpha of the final output will be interpreted.
//!  - How to perform the cycling between images in regard to vsync.
//!
//! You can query the supported values of all these properties with `Surface::get_capabilities()`.
//!
//! ## Creating a swapchain
//!
//! In order to create a swapchain, you will first have to enable the `VK_KHR_swapchain` extension
//! on the device (and not on the instance like `VK_KHR_surface`).
//!
//! Then, you should query the capabilities of the surface with `Surface::get_capabilities()` and
//! choose which values you are going to use. Then, call `Swapchain::new`.
//!
//! TODO: add example here
//!
//! Creating a swapchain not only returns the swapchain object, but also all the images that belong
//! to it.
//!
//! ## Acquiring and presenting images
//!
//! Once you created a swapchain and retreived all the images that belong to it (see previous
//! section), you can draw on it. This is done in three steps:
//!
//!  - Call `Swapchain::acquire_next_image`. This function will return the index of the image
//!    (within the list returned by `Swapchain::new`) that is available to draw.
//!  - Draw on that image just like you would draw to any other image (see the documentation of
//!    the `pipeline` module).
//!  - Call `Swapchain::present` with the same index in order to tell the implementation that you
//!    are finished drawing to the image and that it can queue a command to present the image on
//!    the screen after the draw operations are finished.
//!
//! TODO: add example here
//! loop {
//!     let index = swapchain.acquire_next_image(Duration::from_millis(500)).unwrap();
//!     draw(images[index]);
//!     swapchain.present(queue, index).unwrap();
//! }
//!
//! ## Recreating a swapchain
//!
//! In some situations, the swapchain will become invalid by itself. This includes for example when
//! the window is resized (as the images of the swapchain will no longer match the window's) or,
//! on Android, when the application went to the background and goes back to the foreground.
//!
//! In this situation, acquiring a swapchain image or presenting it will return an error. Rendering
//! to an image of that swapchain will not produce any error, but may or may not work. To continue
//! rendering, you will need to *recreate* the swapchain by creating a new swapchain and passing
//! as last parameter the old swapchain.
//!
//! TODO: add example here
//!

use std::sync::atomic::AtomicBool;

pub use self::surface::Capabilities;
pub use self::surface::Surface;
pub use self::surface::PresentMode;
pub use self::surface::SurfaceTransform;
pub use self::surface::CompositeAlpha;
pub use self::surface::ColorSpace;
pub use self::surface::SurfaceCreationError;
pub use self::swapchain::Swapchain;
pub use self::swapchain::AcquireError;
pub use self::swapchain::PresentError;

pub mod display;
mod surface;
mod swapchain;

/// Internal trait so that creating/destroying a swapchain can access the surface's "has_swapchain"
/// flag.
unsafe trait SurfaceSwapchainLock {
    fn flag(&self) -> &AtomicBool;
}
<commit_msg>Fix swapchain doctest<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Link between Vulkan and a window and/or the screen.
//!
//! Before you can draw on the screen or a window, you have to create two objects:
//!
//! - Create a `Surface` object that represents the location where the image will show up (either
//!   a window or a monitor).
//! - Create a `Swapchain` that uses that `Surface`.
//!
//! Creating a surface can be done with only an `Instance` object. However creating a swapchain
//! requires a `Device` object.
//!
//! Once you have a swapchain, you can retrieve `Image` objects from it and draw to them just like
//! you would draw on any other image.
//!
//! # Surfaces
//!
//! A surface is an object that represents a location where to render. It can be created from an
//! instance and either a window handle (in a platform-specific way) or a monitor.
//!
//! In order to use surfaces, you will have to enable the `VK_KHR_surface` extension on the
//! instance. See the `instance` module for more information about how to enable extensions.
//!
//! ## Creating a surface from a window
//!
//! There are 6 extensions that each allow you to create a surface from a type of window:
//!
//! - `VK_KHR_xlib_surface`
//! - `VK_KHR_xcb_surface`
//! - `VK_KHR_wayland_surface`
//! - `VK_KHR_mir_surface`
//! - `VK_KHR_android_surface`
//! - `VK_KHR_win32_surface`
//!
//! For example if you want to create a surface from an Android surface, you will have to enable
//! the `VK_KHR_android_surface` extension and use `Surface::from_anativewindow`.
//! See the documentation of `Surface` for all the possible constructors.
//!
//! Trying to use one of these functions without enabling the proper extension will result in an
//! error.
//!
//! **Note that the `Surface` object is unsafe**. It is your responsibility to keep the window
//! alive for at least as long as the surface exists.
//!
//! ### Example
//!
//! ```no_run
//! use std::ptr;
//! use vulkano::instance::Instance;
//! use vulkano::instance::InstanceExtensions;
//! use vulkano::swapchain::Surface;
//!
//! let instance = {
//!     let extensions = InstanceExtensions {
//!         khr_surface: true,
//!         khr_win32_surface: true,        // If you don't enable this, `from_hwnd` will fail.
//!         .. InstanceExtensions::none()
//!     };
//!
//!      match Instance::new(None, &extensions, None) {
//!         Ok(i) => i,
//!         Err(err) => panic!("Couldn't build instance: {:?}", err)
//!     }
//! };
//!
//! # fn build_window() -> *const u32 { ptr::null() }
//! let window = build_window();
//! let _surface = unsafe {
//!     let hinstance: *const () = ptr::null();     // Windows-specific object
//!     Surface::from_hwnd(&instance, hinstance, window).unwrap()
//! };
//! ```
//!
//! ## Creating a surface from a monitor
//!
//! Currently no system provides the `VK_KHR_display` extension that contains this feature.
//! This feature is still a work-in-progress in vulkano and will reside in the `display` module.
//!
//! # Swapchains
//!
//! A surface represents a location on the screen and can be created from an instance. Once you
//! have a surface, the next step is to create a swapchain. Creating a swapchain requires a device,
//! and allocates the resources that will be used to display images on the screen.
//!
//! A swapchain is composed of one or multiple images. Each image of the swapchain is presented in
//! turn on the screen, one after another. More information below.
//!
//! Swapchains have several properties:
//!
//!  - The number of images that will cycle on the screen.
//!  - The format of the images.
//!  - The 2D dimensions of the images, plus a number of layers, for a total of three dimensions.
//!  - The usage of the images, similar to creating other images.
//!  - The queue families that are going to use the images, similar to creating other images.
//!  - An additional transformation (rotation or mirroring) to perform on the final output.
//!  - How the alpha of the final output will be interpreted.
//!  - How to perform the cycling between images in regard to vsync.
//!
//! You can query the supported values of all these properties with `Surface::get_capabilities()`.
//!
//! ## Creating a swapchain
//!
//! In order to create a swapchain, you will first have to enable the `VK_KHR_swapchain` extension
//! on the device (and not on the instance like `VK_KHR_surface`).
//!
//! Then, you should query the capabilities of the surface with `Surface::get_capabilities()` and
//! choose which values you are going to use. Then, call `Swapchain::new`.
//!
//! TODO: add example here
//!
//! Creating a swapchain not only returns the swapchain object, but also all the images that belong
//! to it.
//!
//! ## Acquiring and presenting images
//!
//! Once you created a swapchain and retreived all the images that belong to it (see previous
//! section), you can draw on it. This is done in three steps:
//!
//!  - Call `Swapchain::acquire_next_image`. This function will return the index of the image
//!    (within the list returned by `Swapchain::new`) that is available to draw.
//!  - Draw on that image just like you would draw to any other image (see the documentation of
//!    the `pipeline` module).
//!  - Call `Swapchain::present` with the same index in order to tell the implementation that you
//!    are finished drawing to the image and that it can queue a command to present the image on
//!    the screen after the draw operations are finished.
//!
//! TODO: add example here
//! loop {
//!     let index = swapchain.acquire_next_image(Duration::from_millis(500)).unwrap();
//!     draw(images[index]);
//!     swapchain.present(queue, index).unwrap();
//! }
//!
//! ## Recreating a swapchain
//!
//! In some situations, the swapchain will become invalid by itself. This includes for example when
//! the window is resized (as the images of the swapchain will no longer match the window's) or,
//! on Android, when the application went to the background and goes back to the foreground.
//!
//! In this situation, acquiring a swapchain image or presenting it will return an error. Rendering
//! to an image of that swapchain will not produce any error, but may or may not work. To continue
//! rendering, you will need to *recreate* the swapchain by creating a new swapchain and passing
//! as last parameter the old swapchain.
//!
//! TODO: add example here
//!

use std::sync::atomic::AtomicBool;

pub use self::surface::Capabilities;
pub use self::surface::Surface;
pub use self::surface::PresentMode;
pub use self::surface::SurfaceTransform;
pub use self::surface::CompositeAlpha;
pub use self::surface::ColorSpace;
pub use self::surface::SurfaceCreationError;
pub use self::swapchain::Swapchain;
pub use self::swapchain::AcquireError;
pub use self::swapchain::PresentError;

pub mod display;
mod surface;
mod swapchain;

/// Internal trait so that creating/destroying a swapchain can access the surface's "has_swapchain"
/// flag.
unsafe trait SurfaceSwapchainLock {
    fn flag(&self) -> &AtomicBool;
}
<|endoftext|>


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

use crate::frame_builder::FrameBuildingContext;
use crate::internal_types::FastHashMap;
use crate::prim_store::PictureIndex;
use crate::picture::{PicturePrimitive, SurfaceIndex, ROOT_SURFACE_INDEX, SurfaceInfo};
use crate::picture::{TileCacheInstance, SliceId};
use crate::render_backend::DataStores;
use smallvec::SmallVec;

#[derive(Debug)]
pub struct PictureInfo {
    pub update_pass: Option<usize>,
    pub surface_index: SurfaceIndex,
    pub parent: Option<PictureIndex>,
}

/// A graph of picture dependencies, allowing updates to be processed without recursion
/// by building a list of passes.
pub struct PictureGraph {
    roots: Vec<PictureIndex>,
    pic_info: Vec<PictureInfo>,
    update_passes: Vec<Vec<PictureIndex>>,
}

impl PictureGraph {
    pub fn new() -> Self {
        PictureGraph {
            roots: Vec::new(),
            pic_info: Vec::new(),
            update_passes: Vec::new(),
        }
    }

    /// Add a root picture to the graph
    pub fn add_root(
        &mut self,
        pic_index: PictureIndex,
    ) {
        self.roots.push(pic_index);
    }

    /// Build a list of update passes based on the dependencies between pictures
    pub fn build_update_passes(
        &mut self,
        pictures: &mut [PicturePrimitive],
        frame_context: &FrameBuildingContext
    ) {
        self.pic_info.clear();
        self.pic_info.reserve(pictures.len());

        for _ in 0 .. pictures.len() {
            self.pic_info.push(PictureInfo {
                update_pass: None,
                parent: None,
                surface_index: ROOT_SURFACE_INDEX,
            })
        };

        let mut max_pass_index = 0;

        for pic_index in &self.roots {
            assign_update_pass(
                *pic_index,
                None,
                0,
                pictures,
                &mut self.pic_info,
                &mut max_pass_index,
                frame_context,
            );
        }

        let pass_count = max_pass_index + 1;

        self.update_passes.resize_with(pass_count, Vec::new);

        for (pic_index, info) in self.pic_info.iter().enumerate() {
            if let Some(update_pass) = info.update_pass {
                let pass = &mut self.update_passes[update_pass];
                pass.push(PictureIndex(pic_index));
            }
        }
    }

    /// Assign surfaces and scale factors to each picture (root -> leaf ordered pass)
    pub fn assign_surfaces(
        &mut self,
        pictures: &mut [PicturePrimitive],
        surfaces: &mut Vec<SurfaceInfo>,
        tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
        frame_context: &FrameBuildingContext,
    ) {
        for pass in &self.update_passes {
            for pic_index in pass {
                let parent = self.pic_info[pic_index.0].parent;

                let parent_surface_index = parent.map_or(ROOT_SURFACE_INDEX, |parent| {
                    self.pic_info[parent.0].surface_index
                });

                let info = &mut self.pic_info[pic_index.0];

                info.surface_index = pictures[pic_index.0].assign_surface(
                    frame_context,
                    tile_caches,
                    parent_surface_index,
                    surfaces,
                );
            }
        }
    }

    /// Propegate bounding rects from pictures to parents (leaf -> root ordered pass)
    pub fn propagate_bounding_rects(
        &mut self,
        pictures: &mut [PicturePrimitive],
        surfaces: &mut [SurfaceInfo],
        frame_context: &FrameBuildingContext,
        data_stores: &mut DataStores,
    ) {
        for pass in self.update_passes.iter().rev() {
            for pic_index in pass {
                let parent = self.pic_info[pic_index.0].parent;

                let surface_index = self.pic_info[pic_index.0].surface_index;

                let parent_surface_index = parent.map_or(ROOT_SURFACE_INDEX, |parent| {
                    self.pic_info[parent.0].surface_index
                });

                pictures[pic_index.0].propagate_bounding_rect(
                    surface_index,
                    parent_surface_index,
                    surfaces,
                    frame_context,
                    data_stores,
                );
            }
        }
    }
}

/// Recursive function that assigns pictures to the earliest pass possible that they
/// can be processed in, while maintaining dependency ordering.
fn assign_update_pass(
    pic_index: PictureIndex,
    parent_pic_index: Option<PictureIndex>,
    pass: usize,
    pictures: &mut [PicturePrimitive],
    pic_info: &mut [PictureInfo],
    max_pass_index: &mut usize,
    frame_context: &FrameBuildingContext
) {
    let pic = &mut pictures[pic_index.0];
    let info = &mut pic_info[pic_index.0];

    info.parent = parent_pic_index;

    let can_be_drawn = match info.update_pass {
        Some(update_pass) => {
            // No point in recursing into paths in the graph if this picture already
            // has been set to update after this pass.
            if update_pass > pass {
                return;
            }

            true
        }
        None => {
            // Check if this picture can be dropped from the graph we're building this frame
            pic.pre_update_visibility_check(frame_context)
        }
    };

    if can_be_drawn {
        info.update_pass = Some(pass);

        *max_pass_index = pass.max(*max_pass_index);

        let mut child_pictures: SmallVec<[PictureIndex; 8]> = SmallVec::new();
        child_pictures.extend_from_slice(&pic.prim_list.child_pictures);

        for child_pic_index in child_pictures {
            assign_update_pass(
                child_pic_index,
                Some(pic_index),
                pass + 1,
                pictures,
                pic_info,
                max_pass_index,
                frame_context,
            );
        }
    }
}
<commit_msg>Auto merge of #4436 - moz-gfx:github-sync, r=auto<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::frame_builder::FrameBuildingContext;
use crate::internal_types::FastHashMap;
use crate::prim_store::PictureIndex;
use crate::picture::{PicturePrimitive, SurfaceIndex, ROOT_SURFACE_INDEX, SurfaceInfo};
use crate::picture::{TileCacheInstance, SliceId};
use crate::render_backend::DataStores;
use smallvec::SmallVec;

#[derive(Debug)]
pub struct PictureInfo {
    pub update_pass: Option<usize>,
    pub surface_index: SurfaceIndex,
    pub parent: Option<PictureIndex>,
}

/// A graph of picture dependencies, allowing updates to be processed without recursion
/// by building a list of passes.
pub struct PictureGraph {
    roots: Vec<PictureIndex>,
    pic_info: Vec<PictureInfo>,
    update_passes: Vec<Vec<PictureIndex>>,
}

impl PictureGraph {
    pub fn new() -> Self {
        PictureGraph {
            roots: Vec::new(),
            pic_info: Vec::new(),
            update_passes: Vec::new(),
        }
    }

    /// Add a root picture to the graph
    pub fn add_root(
        &mut self,
        pic_index: PictureIndex,
    ) {
        self.roots.push(pic_index);
    }

    /// Build a list of update passes based on the dependencies between pictures
    pub fn build_update_passes(
        &mut self,
        pictures: &mut [PicturePrimitive],
        frame_context: &FrameBuildingContext
    ) {
        self.pic_info.clear();
        self.pic_info.reserve(pictures.len());

        for _ in 0 .. pictures.len() {
            self.pic_info.push(PictureInfo {
                update_pass: None,
                parent: None,
                surface_index: ROOT_SURFACE_INDEX,
            })
        };

        let mut max_pass_index = 0;

        for pic_index in &self.roots {
            assign_update_pass(
                *pic_index,
                None,
                0,
                pictures,
                &mut self.pic_info,
                &mut max_pass_index,
                frame_context,
            );
        }

        let pass_count = max_pass_index + 1;

        self.update_passes.clear();
        self.update_passes.resize_with(pass_count, Vec::new);

        for (pic_index, info) in self.pic_info.iter().enumerate() {
            if let Some(update_pass) = info.update_pass {
                let pass = &mut self.update_passes[update_pass];
                pass.push(PictureIndex(pic_index));
            }
        }
    }

    /// Assign surfaces and scale factors to each picture (root -> leaf ordered pass)
    pub fn assign_surfaces(
        &mut self,
        pictures: &mut [PicturePrimitive],
        surfaces: &mut Vec<SurfaceInfo>,
        tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
        frame_context: &FrameBuildingContext,
    ) {
        for pass in &self.update_passes {
            for pic_index in pass {
                let parent = self.pic_info[pic_index.0].parent;

                let parent_surface_index = parent.map_or(ROOT_SURFACE_INDEX, |parent| {
                    self.pic_info[parent.0].surface_index
                });

                let info = &mut self.pic_info[pic_index.0];

                info.surface_index = pictures[pic_index.0].assign_surface(
                    frame_context,
                    tile_caches,
                    parent_surface_index,
                    surfaces,
                );
            }
        }
    }

    /// Propegate bounding rects from pictures to parents (leaf -> root ordered pass)
    pub fn propagate_bounding_rects(
        &mut self,
        pictures: &mut [PicturePrimitive],
        surfaces: &mut [SurfaceInfo],
        frame_context: &FrameBuildingContext,
        data_stores: &mut DataStores,
    ) {
        for pass in self.update_passes.iter().rev() {
            for pic_index in pass {
                let parent = self.pic_info[pic_index.0].parent;

                let surface_index = self.pic_info[pic_index.0].surface_index;

                let parent_surface_index = parent.map_or(ROOT_SURFACE_INDEX, |parent| {
                    self.pic_info[parent.0].surface_index
                });

                pictures[pic_index.0].propagate_bounding_rect(
                    surface_index,
                    parent_surface_index,
                    surfaces,
                    frame_context,
                    data_stores,
                );
            }
        }
    }
}

/// Recursive function that assigns pictures to the earliest pass possible that they
/// can be processed in, while maintaining dependency ordering.
fn assign_update_pass(
    pic_index: PictureIndex,
    parent_pic_index: Option<PictureIndex>,
    pass: usize,
    pictures: &mut [PicturePrimitive],
    pic_info: &mut [PictureInfo],
    max_pass_index: &mut usize,
    frame_context: &FrameBuildingContext
) {
    let pic = &mut pictures[pic_index.0];
    let info = &mut pic_info[pic_index.0];

    info.parent = parent_pic_index;

    let can_be_drawn = match info.update_pass {
        Some(update_pass) => {
            // No point in recursing into paths in the graph if this picture already
            // has been set to update after this pass.
            if update_pass > pass {
                return;
            }

            true
        }
        None => {
            // Check if this picture can be dropped from the graph we're building this frame
            pic.pre_update_visibility_check(frame_context)
        }
    };

    if can_be_drawn {
        info.update_pass = Some(pass);

        *max_pass_index = pass.max(*max_pass_index);

        let mut child_pictures: SmallVec<[PictureIndex; 8]> = SmallVec::new();
        child_pictures.extend_from_slice(&pic.prim_list.child_pictures);

        for child_pic_index in child_pictures {
            assign_update_pass(
                child_pic_index,
                Some(pic_index),
                pass + 1,
                pictures,
                pic_info,
                max_pass_index,
                frame_context,
            );
        }
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
///
/// The [`unreachable!()`] macro is the safe counterpart of this function, which
/// will panic instead when executed.
///
/// [`unreachable!()`]: ../macro.unreachable.html
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, std::u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
pub unsafe fn unreachable_unchecked() -> ! {
    intrinsics::unreachable()
}

/// Save power or switch hyperthreads in a busy-wait spin-loop.
///
/// This function is deliberately more primitive than
/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
/// does not directly yield to the system's scheduler.
/// In some cases it might be useful to use a combination of both functions.
/// Careful benchmarking is advised.
///
/// On some platforms this function may not do anything at all.
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(
        all(
            any(target_arch = "x86", target_arch = "x86_64"),
            target_feature = "sse2"
        )
    )] {
        #[cfg(target_arch = "x86")] {
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")] {
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(
        any(
            target_arch = "aarch64",
            all(target_arch = "arm", target_feature = "v6")
        )
    )] {
        #[cfg(target_arch = "aarch64")] {
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")] {
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// A function that is opaque to the optimizer, to allow benchmarks to
/// pretend to use outputs to assist in avoiding dead-code
/// elimination.
///
/// This function is a no-op, and does not even read from `dummy`.
#[unstable(feature = "test", issue = "27812")]
pub fn black_box<T>(dummy: T) -> T {
    #[cfg(not(target_arch = "asmjs"))] {
        // we need to "use" the argument in some way LLVM can't
        // introspect.
        unsafe { asm!("" : : "r"(&dummy)) }
        dummy
    }
    #[cfg(target_arch = "asmjs")] {
        unsafe {
            let ret = crate::ptr::read_volatile(&dummy);
            crate::mem::forget(dummy);
            ret
        }
    }
}
<commit_msg>Use fallback on emscripten targets<commit_after>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
///
/// The [`unreachable!()`] macro is the safe counterpart of this function, which
/// will panic instead when executed.
///
/// [`unreachable!()`]: ../macro.unreachable.html
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, std::u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
pub unsafe fn unreachable_unchecked() -> ! {
    intrinsics::unreachable()
}

/// Save power or switch hyperthreads in a busy-wait spin-loop.
///
/// This function is deliberately more primitive than
/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
/// does not directly yield to the system's scheduler.
/// In some cases it might be useful to use a combination of both functions.
/// Careful benchmarking is advised.
///
/// On some platforms this function may not do anything at all.
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(
        all(
            any(target_arch = "x86", target_arch = "x86_64"),
            target_feature = "sse2"
        )
    )] {
        #[cfg(target_arch = "x86")] {
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")] {
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(
        any(
            target_arch = "aarch64",
            all(target_arch = "arm", target_feature = "v6")
        )
    )] {
        #[cfg(target_arch = "aarch64")] {
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")] {
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// A function that is opaque to the optimizer, to allow benchmarks to
/// pretend to use outputs to assist in avoiding dead-code
/// elimination.
///
/// This function is a no-op, and does not even read from `dummy`.
#[unstable(feature = "test", issue = "27812")]
pub fn black_box<T>(dummy: T) -> T {
    #[cfg(not(
        any(
            target_arch = "asmjs",
            all(
                target_arch = "wasm32",
                target_os = "emscripten"
            )
        )
    ))] {
        // we need to "use" the argument in some way LLVM can't
        // introspect.
        unsafe { asm!("" : : "r"(&dummy)) }
        dummy
    }
    #[cfg(
        any(
            target_arch = "asmjs",
            all(
                target_arch = "wasm32",
                target_os = "emscripten"
            )
        )
    )] {
        unsafe {
            let ret = crate::ptr::read_volatile(&dummy);
            crate::mem::forget(dummy);
            ret
        }
    }
}
<|endoftext|>


<commit_before>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;
export xorshift, seeded_xorshift;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> ~[u8] {
        vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: ~[T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: ~[T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : ~[weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: ~[weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: ~[weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each {|item|
            for uint::range(0u, item.weight) {|_i|
                vec::push(r, item.item);
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: ~[T]) -> ~[T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&&values: ~[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

class rand_res {
    let c: *rctx;
    new(c: *rctx) { self.c = c; }
    drop { rustrt::rand_free(self.c); }
}

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next((*self).c); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: ~[u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

type xorshift_state = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl of rng for xorshift_state {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        #error("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose(~[1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option(~[]) == none::<int>;
        assert r.choose_option(~[1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option(~[]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Eliminate usages of old sugared call syntax<commit_after>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;
export xorshift, seeded_xorshift;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: ~[T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: ~[T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : ~[weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: ~[weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: ~[weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each {|item|
            for uint::range(0u, item.weight) {|_i|
                vec::push(r, item.item);
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: ~[T]) -> ~[T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&&values: ~[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

class rand_res {
    let c: *rctx;
    new(c: *rctx) { self.c = c; }
    drop { rustrt::rand_free(self.c); }
}

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next((*self).c); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: ~[u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

type xorshift_state = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl of rng for xorshift_state {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        #error("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose(~[1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option(~[]) == none::<int>;
        assert r.choose_option(~[1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option(~[]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>