Created
November 22, 2016 18:01
-
-
Save nical/fee1cfecd8fe0ddd6b9fb644cb360559 to your computer and use it in GitHub Desktop.
image off by 1 bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate webrender; | |
extern crate glutin; | |
extern crate gleam; | |
extern crate webrender_traits; | |
extern crate euclid; | |
use euclid::{Size2D, Point2D, Rect, Matrix4D}; | |
use gleam::gl; | |
use std::path::PathBuf; | |
use std::ffi::CStr; | |
use webrender_traits::{AuxiliaryListsBuilder, ColorF, Epoch, GlyphInstance}; | |
use webrender_traits::{ImageData, ImageFormat, PipelineId, RendererKind}; | |
use webrender_traits::{ClipRegion, ImageRendering}; | |
use std::fs::File; | |
use std::io::Read; | |
use std::env; | |
fn _load_file(name: &str) -> Vec<u8> { | |
let mut file = File::open(name).unwrap(); | |
let mut buffer = vec![]; | |
file.read_to_end(&mut buffer).unwrap(); | |
buffer | |
} | |
struct Notifier { | |
window_proxy: glutin::WindowProxy, | |
} | |
impl Notifier { | |
fn new(window_proxy: glutin::WindowProxy) -> Notifier { | |
Notifier { | |
window_proxy: window_proxy, | |
} | |
} | |
} | |
pub struct WebRenderFrameBuilder { | |
pub root_pipeline_id: PipelineId, | |
pub next_scroll_layer_id: usize, | |
} | |
impl webrender_traits::RenderNotifier for Notifier { | |
fn new_frame_ready(&mut self) { | |
self.window_proxy.wakeup_event_loop(); | |
} | |
fn new_scroll_frame_ready(&mut self, _composite_needed: bool) { | |
self.window_proxy.wakeup_event_loop(); | |
} | |
fn pipeline_size_changed(&mut self, | |
_: PipelineId, | |
_: Option<Size2D<f32>>) { | |
} | |
} | |
pub fn rect(x: f32, y: f32, w:f32, h: f32) -> Rect<f32> { | |
Rect::new(Point2D::new(x, y), Size2D::new(w, h)) | |
} | |
pub fn make_image_rgba(w: usize, h: usize, repeat: usize) -> Vec<u8> { | |
let mut data = Vec::with_capacity(w*h*4); | |
let border = repeat / 10; | |
for y in 0..w { | |
for x in 0..h { | |
//if x < border || y < border || x > w - border || y > h - border { | |
// data.push(255); | |
// data.push(255); | |
// data.push(255); | |
//} else { | |
if x == 0 || y == 0 { | |
data.push(255); | |
data.push(255); | |
data.push(255); | |
} else if x == w - 1 || y == h - 1 { | |
data.push(100); | |
data.push(100); | |
data.push(100); | |
} else { | |
data.push(if x % repeat > repeat/2 { 200 } else { 0 }); // b | |
data.push(if (x+y) % repeat > repeat/2 { 128 } else { 0 }); // g | |
data.push(if y % repeat > repeat/2 { 200 } else { 0 }); // r | |
} | |
data.push(255); // a | |
} | |
} | |
return data; | |
} | |
pub fn make_image_a8(w: usize, h: usize, repeat: usize) -> Vec<u8> { | |
let mut data = Vec::with_capacity(w*h); | |
let border = repeat / 10; | |
for y in 0..w { | |
for x in 0..h { | |
if x < border || y < border || x > w -border || y > h - border { | |
data.push(255); | |
} else { | |
data.push(if (x+y) % repeat > repeat/2 { 128 } else { 0 }); | |
} | |
} | |
} | |
return data; | |
} | |
fn main() { | |
let args: Vec<String> = env::args().collect(); | |
let res_path = if args.len() > 1 { | |
Some(PathBuf::from(&args[1])) | |
} else { | |
None | |
}; | |
let window = glutin::WindowBuilder::new() | |
.with_title("WebRender Sample") | |
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2))) | |
.build() | |
.unwrap(); | |
unsafe { | |
window.make_current().ok(); | |
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _); | |
gl::clear_color(0.3, 0.0, 0.0, 1.0); | |
} | |
let version = unsafe { | |
let data = CStr::from_ptr(gl::GetString(gl::VERSION) as *const _).to_bytes().to_vec(); | |
String::from_utf8(data).unwrap() | |
}; | |
println!("OpenGL version {}", version); | |
println!("Shader resource path: {:?}", res_path); | |
let (width, height) = window.get_inner_size().unwrap(); | |
let opts = webrender::RendererOptions { | |
device_pixel_ratio: 1.0, | |
resource_override_path: res_path, | |
enable_aa: false, | |
enable_msaa: false, | |
enable_profiler: false, | |
enable_recording: false, | |
enable_scrollbars: false, | |
debug: true, | |
precache_shaders: true, | |
renderer_kind: RendererKind::Native, | |
enable_subpixel_aa: false, | |
}; | |
let (mut renderer, sender) = webrender::renderer::Renderer::new(opts); | |
let api = sender.create_api(); | |
// let font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"; | |
// let font_bytes = load_file(font_path); | |
// let font_key = api.add_raw_font(font_bytes); | |
let notifier = Box::new(Notifier::new(window.create_window_proxy())); | |
renderer.set_render_notifier(notifier); | |
let pipeline_id = PipelineId(0, 0); | |
let epoch = Epoch(0); | |
let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0); | |
let mut auxiliary_lists_builder = AuxiliaryListsBuilder::new(); | |
let mut builder = webrender_traits::DisplayListBuilder::new(); | |
let bounds = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(width as f32, height as f32)); | |
builder.push_stacking_context( | |
webrender_traits::StackingContext::new(webrender_traits::ScrollPolicy::Scrollable, | |
bounds, | |
bounds, | |
0, | |
&Matrix4D::identity(), | |
&Matrix4D::identity(), | |
webrender_traits::MixBlendMode::Normal, | |
Vec::new(), | |
&mut auxiliary_lists_builder)); | |
let clip_region = { | |
let mask = webrender_traits::ImageMask { | |
image: api.add_image(2, 2, None, ImageFormat::A8, ImageData::new(vec![0,80, 180, 255])), | |
rect: Rect::new(Point2D::new(75.0, 75.0), Size2D::new(100.0, 100.0)), | |
repeat: false, | |
}; | |
let radius = webrender_traits::BorderRadius::uniform(20.0); | |
let complex = webrender_traits::ComplexClipRegion::new( | |
Rect::new(Point2D::new(50.0, 50.0), Size2D::new(100.0, 100.0)), | |
radius); | |
webrender_traits::ClipRegion::new(&bounds, | |
vec![complex], | |
Some(mask), | |
&mut auxiliary_lists_builder) | |
}; | |
builder.push_rect(Rect::new(Point2D::new(100.0, 100.0), Size2D::new(100.0, 100.0)), | |
clip_region, | |
ColorF::new(0.0, 1.0, 0.0, 1.0)); | |
//builder.push_image( | |
// rect(300.0, 300.0, 500.0, 500.0), | |
// ClipRegion::simple(&rect(200.0, 200.0, 1000.0, 1000.0)), | |
// Size2D::new(500.0, 500.0), | |
// Size2D::zero(), | |
// ImageRendering::Auto, | |
// api.add_image(500, 500, None, ImageFormat::RGBA8, ImageData::new(make_image_rgba(500, 500, 20))), | |
//); | |
builder.push_image( | |
rect(500.0, 100.0, 500.0, 500.0), | |
ClipRegion::simple(&rect(0.0, 0.0, 1000.0, 1000.0)), | |
Size2D::new(500.0, 500.0), | |
Size2D::zero(), | |
ImageRendering::Auto, | |
api.add_image(100, 100, None, ImageFormat::A8, ImageData::new(make_image_a8(100, 100, 20))), | |
); | |
//builder.push_yuv_image( | |
// rect(50.0, 10.0, 100.0, 100.0), | |
// ClipRegion::simple(&rect(0.0, 0.0, 1000.0, 1000.0)), | |
// api.add_image(100, 100, None, ImageFormat::A8, ImageData::new(make_image_a8(100, 100, 40))), | |
// //api.add_image(100, 100, None, ImageFormat::A8, ImageData::new(make_image_a8(100, 100, 40))), | |
// //api.add_image(100, 100, None, ImageFormat::A8, ImageData::new(make_image_a8(100, 100, 40))), | |
// api.add_image(50, 50, None, ImageFormat::A8, ImageData::new(make_image_a8(50, 50, 20))), | |
// api.add_image(50, 50, None, ImageFormat::A8, ImageData::new(make_image_a8(50, 50, 20))), | |
//); | |
let _text_bounds = Rect::new(Point2D::new(100.0, 200.0), Size2D::new(700.0, 300.0)); | |
let _glyphs = vec![ | |
GlyphInstance { | |
index: 48, | |
x: 100.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 68, | |
x: 150.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 80, | |
x: 200.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 82, | |
x: 250.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 81, | |
x: 300.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 3, | |
x: 350.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 86, | |
x: 400.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 79, | |
x: 450.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 72, | |
x: 500.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 83, | |
x: 550.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 87, | |
x: 600.0, | |
y: 100.0, | |
}, | |
GlyphInstance { | |
index: 17, | |
x: 650.0, | |
y: 100.0, | |
}, | |
]; | |
// builder.push_text(text_bounds, | |
// clip_region, | |
// glyphs, | |
// font_key, | |
// ColorF::new(1.0, 1.0, 0.0, 1.0), | |
// Au::from_px(32), | |
// Au::from_px(0), | |
// &mut frame_builder.auxiliary_lists_builder); | |
builder.pop_stacking_context(); | |
api.set_root_display_list( | |
root_background_color, | |
epoch, | |
pipeline_id, | |
Size2D::new(width as f32, height as f32), | |
builder.finalize(), | |
auxiliary_lists_builder.finalize()); | |
api.set_root_pipeline(pipeline_id); | |
for event in window.wait_events() { | |
gl::clear(gl::COLOR_BUFFER_BIT); | |
renderer.update(); | |
renderer.render(Size2D::new(width, height)); | |
window.swap_buffers().ok(); | |
match event { | |
glutin::Event::Closed => break, | |
glutin::Event::KeyboardInput(_element_state, scan_code, _virtual_key_code) => { | |
if scan_code == 9 { | |
break; | |
} | |
} | |
_ => () | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment