Unverified Commit 30a4f469 authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub

Merge pull request #45 from robbycerantola/over

Image:  parallel rendering  and window overwriting
parents 0a9588f3 06e7cbab
......@@ -15,6 +15,7 @@ keywords = [
[dependencies]
time = "*"
rayon = "1.0"
[features]
default = []
......
......@@ -3,7 +3,7 @@ extern crate time;
use orbclient::{Color, Window, Renderer, EventOption};
const TIMES:i32 = 100;
const TIMES:i32 = 10;
fn main() {
//let (width, height) = orbclient::get_display_size().unwrap();
......@@ -20,39 +20,48 @@ fn main() {
//create image data : a green square
let data = vec![Color::rgba(100,200,10,20);412500];
let data2 = vec![Color::rgba(200,100,10,20);412500];
let data3 = vec![Color::rgba(10,100,200,20);800];
let data3 = vec![Color::rgba(10,100,100,20);412500];
let data4 = vec![Color::rgba(10,100,200,20);480000];
//draw image benchmarking
println!("Benchmarking implementations to draw an image on window:");
let mut t = time::now();
for _i in 0..TIMES {
window.image_over(50, &data4[..360000]);
}
let mut t2 = time::now();
let dt4 = (t2-t)/TIMES;
println!("image_over {:?}",dt4);
t = time::now();
for _i in 0..TIMES {
window.image_legacy(10,10,750,550, &data[..]);
}
let mut t2 = time::now();
t2 = time::now();
let dt = (t2-t)/TIMES;
println!("image_legacy {:?}",dt );
println!("image_legacy {:?}",dt );
t = time::now();
for _i in 0..TIMES {
window.image_fast(140,240,750,550, &data2[..]);
window.image_fast(20,20,750,550, &data2[..]);
}
t2 = time::now();
let dt2 = (t2-t)/TIMES;
println!("image_fast {:?}",dt2);
println!("-------------------------");
println!("difference {:?}", dt-dt2);
println!("image_fast {:?}",dt2);
t = time::now();
for _i in 0..TIMES {
window.image(0,0,800,1, &data3[..]);
window.image(30,30,750,550, &data3[..]);
}
t2 = time::now();
let dt3 = (t2-t)/TIMES;
println!("image wrapper {:?}",dt3);
println!("image_parallel {:?}",dt3);
//println!("difference {:?}", dt-dt3);
println!("-------------------------");
window.sync();
......
......@@ -59,9 +59,7 @@ fn main() {
window.char(200, 200, '═', Color::rgb(0, 0, 0));
window.char(208, 200, '═', Color::rgb(0, 0, 0));
// testing for non existent x,y position : does not panic but returns Color(0,0,0,0)
let _non_existent_pixel = window.getpixel(width as i32 +10,height as i32 +10);
......
extern crate rayon;
use core::cmp;
use FONT;
......@@ -298,7 +300,7 @@ pub trait Renderer {
//check if image is inside window
if (w + start_x as u32) > self.width() {
self.image_legacy(start_x, start_y, w, h, data);
}else{
} else {
self.image_fast(start_x, start_y, w, h, data);
}
}
......@@ -316,6 +318,17 @@ pub trait Renderer {
}
}
///Display an image overwriting a portion of window starting at given line : very quick!!
fn image_over (&mut self, start: i32, image_data: &[Color]) {
let start = start as usize * self.width() as usize;
let window_data = self.data_mut();
let stop = cmp::min(start + image_data.len(), window_data.len());
let end = cmp::min(image_data.len(), window_data.len() - start);
window_data[start..stop].copy_from_slice(&image_data[..end]);
}
// Speed improved, but image has to be all inside of window boundary
fn image_fast (&mut self, start_x: i32, start_y: i32, w: u32, h: u32, image_data: &[Color]) {
let window_w = self.width() as usize;
......@@ -356,6 +369,70 @@ pub trait Renderer {
}
}
///Render an image using parallel threads if possible
//Works in Linux but not in Redox !
fn image_parallel(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, image_data: &[Color]) {
let start_x = start_x as usize;
let start_y = start_y as usize;
let h_hi = (h / 2) as usize;
let h_lo = h as usize - h_hi;
let w = w as usize;
let mid = image_data.len() / 2;
let width = self.width() as usize;
let window_data = self.data_mut();
let hi_start = start_x + start_y * width;
let hi_stop = width * (h_hi + start_y);
let lo_start = hi_stop + start_x;
let lo_stop = cmp::min(width * (start_y + h_lo + h_hi), window_data.len());
let mut window_lo = vec![Color::rgba(0,0,0,0); lo_stop - lo_start];
{
window_lo.copy_from_slice(&window_data[lo_start..lo_stop]);
let window_hi = &mut window_data[hi_start..hi_stop];
rayon::join(|| blit(width, window_hi, w, h_hi, &image_data[..mid]),
|| blit(width, &mut window_lo, w, h_lo, &image_data[mid..]),
);
}
window_data[lo_start..lo_stop].copy_from_slice(&window_lo);
fn blit(window_w: usize, window_data: &mut[Color], w: usize, h: usize, image_data: &[Color]){
let window_len = window_data.len();
for i in 0..(w * h) {
let y= i / w;
let x = i - (y * w);
let window_index = y * window_w + x;
if window_index < window_len && i < image_data.len(){
let new = image_data[i].data;
let alpha = (new >> 24) & 0xFF;
if alpha > 0 {
let old = unsafe{ &mut window_data[window_index].data};
if alpha >= 255 {
*old = new;
} else {
let n_r = (((new >> 16) & 0xFF) * alpha) >> 8;
let n_g = (((new >> 8) & 0xFF) * alpha) >> 8;
let n_b = ((new & 0xFF) * alpha) >> 8;
let n_alpha = 255 - alpha;
let o_a = (((*old >> 24) & 0xFF) * n_alpha) >> 8;
let o_r = (((*old >> 16) & 0xFF) * n_alpha) >> 8;
let o_g = (((*old >> 8) & 0xFF) * n_alpha) >> 8;
let o_b = ((*old & 0xFF) * n_alpha) >> 8;
*old = ((o_a << 24) | (o_r << 16) | (o_g << 8) | o_b) + ((alpha << 24) | (n_r << 16) | (n_g << 8) | n_b);
}
}
}
}
}
}
/// Draw a linear gradient in a rectangular region
#[cfg(not(feature="no_std"))]
fn linear_gradient(&mut self, rect_x: i32, rect_y: i32, rect_width: u32, rect_height:u32, start_x: i32, start_y: i32, end_x: i32, end_y: i32, start_color: Color, end_color: Color) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment