Changed loop to our own using poll_events and rendering everything every loop iteration.

This commit is contained in:
Samuel Guerra 2019-08-03 01:37:33 -03:00
parent 8038d4cb77
commit e1350f503d
2 changed files with 233 additions and 153 deletions

View File

@ -1,5 +1,5 @@
mod window;
fn main() {
window::show_window();
window::Window::show().run();
}

View File

@ -1,183 +1,263 @@
use euclid::rect;
use gleam::gl;
use glutin::dpi::LogicalSize;
use glutin::ControlFlow;
use webrender::api::*;
pub fn show_window() {
let mut events_loop = glutin::EventsLoop::new();
pub struct Window {
events_loop: glutin::EventsLoop,
w_context: glutin::ContextWrapper<glutin::PossiblyCurrent, glutin::Window>,
renderer: webrender::Renderer,
renderer_sender: RenderApiSender,
background: ColorF,
render: Option<RenderData>,
content: Option<Button>,
}
let w_context = glutin::ContextBuilder::new()
.with_gl(glutin::GlRequest::GlThenGles {
opengl_version: (3, 2),
opengles_version: (3, 0),
})
.build_windowed(
glutin::WindowBuilder::new()
.with_title("Test")
.with_dimensions(LogicalSize::new(800.0, 600.0))
.with_multitouch(),
&events_loop,
)
.expect("Error building windowed GL context");
struct RenderData {
api: RenderApi,
doc: DocumentId,
epoch: Epoch,
pipe: PipelineId,
}
let w_context = unsafe {
w_context
.make_current()
.expect("Error making context current")
};
let gl = match w_context.get_api() {
glutin::Api::OpenGl => unsafe {
gl::GlFns::load_with(|addr| w_context.get_proc_address(addr) as *const _)
},
glutin::Api::OpenGlEs => unsafe {
gl::GlesFns::load_with(|addr| w_context.get_proc_address(addr) as *const _)
},
_ => unreachable!(),
};
println!("OpenGL version {}", gl.get_string(gl::VERSION));
let dpi = w_context.window().get_hidpi_factor();
println!("Device pixel ratio: {}", dpi);
let background = ColorF::new(0., 0., 0., 1.);
let opts = webrender::RendererOptions {
device_pixel_ratio: dpi as f32,
clear_color: Some(background),
..Default::default()
};
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
let (mut render, sender) =
webrender::Renderer::new(gl, notifier, opts, None).expect("Error creating web renderer");
let framebuffer_size = {
let size = w_context
.window()
.get_inner_size()
.unwrap()
.to_physical(dpi);
DeviceIntSize::new(size.width as i32, size.height as i32)
};
let api = sender.create_api();
let document_id = api.add_document(framebuffer_size, 0);
let mut epoch = Epoch(0);
let pipeline_id = PipelineId(0, 0);
let mut tsn = Transaction::new();
tsn.set_root_pipeline(pipeline_id);
tsn.generate_frame();
api.send_transaction(document_id, tsn);
let mut is_hovered = false;
let mut awaiting_frame = false;
let rect_tag = (1, 0);
events_loop.run_forever(|global_event| {
let mut tsn = Transaction::new();
let framebuffer_size = {
let size = w_context
.window()
.get_inner_size()
.unwrap()
.to_physical(dpi);
DeviceIntSize::new(size.width as i32, size.height as i32)
impl RenderData {
pub fn increase_epoch(&mut self) {
use std::u32;
const MAX_ID: u32 = u32::MAX - 1;
self.epoch = match self.epoch.0 {
MAX_ID => Epoch(0),
other => Epoch(other + 1),
};
}
}
let win_event = match global_event {
glutin::Event::WindowEvent { event, .. } => event,
glutin::Event::Awakened => {
if awaiting_frame {
api.send_transaction(document_id, tsn);
render.update();
render.render(framebuffer_size).unwrap();
awaiting_frame = false;
}
return ControlFlow::Continue;
}
_ => return ControlFlow::Continue,
};
struct Button {
tag: (u64, u16),
is_hovered: bool,
}
match win_event {
glutin::WindowEvent::CloseRequested => return ControlFlow::Break,
// skip high-frequency events
glutin::WindowEvent::AxisMotion { .. } => return ControlFlow::Continue,
impl Button {
pub fn on_event(&mut self, event: &glutin::WindowEvent, render: &RenderData) -> bool {
match event {
glutin::WindowEvent::CursorMoved { position, .. } => {
let position = position.to_physical(dpi);
let ht_result = api.hit_test(
document_id,
Some(pipeline_id),
let r = render.api.hit_test(
render.doc,
Some(render.pipe),
WorldPoint::new(position.x as f32, position.y as f32),
HitTestFlags::FIND_ALL,
);
let new_is_hovered = ht_result.items.into_iter().any(|i| i.tag == rect_tag);
if new_is_hovered == is_hovered {
return ControlFlow::Continue;
} else {
is_hovered = dbg!(new_is_hovered);
let new_is_hovered = r.items.into_iter().any(|r| r.tag == self.tag);
if self.is_hovered != new_is_hovered {
self.is_hovered = new_is_hovered;
return true;
}
}
_ => {}
};
epoch = increase_epoch(epoch);
let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(dpi as f32);
let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
}
false
}
pub fn render(&self, render: &RenderData, builder: &mut DisplayListBuilder) {
let mut layour_primitive_info = LayoutPrimitiveInfo::new(rect(80.0, 2.0, 554., 50.));
layour_primitive_info.tag = Some(rect_tag);
layour_primitive_info.tag = Some(self.tag);
builder.push_rect(
&layour_primitive_info,
&SpaceAndClipInfo::root_scroll(pipeline_id),
if dbg!(is_hovered) {
&SpaceAndClipInfo::root_scroll(render.pipe),
if self.is_hovered {
ColorF::new(0., 1., 0.4, 1.)
} else {
ColorF::new(1., 0., 0.4, 1.)
},
);
api.set_window_parameters(
document_id,
framebuffer_size,
DeviceIntRect::new(DeviceIntPoint::zero(), framebuffer_size),
dpi as f32,
);
tsn.set_display_list(
epoch,
Some(background),
layout_size,
builder.finalize(),
true,
);
//tsn.set_root_pipeline(pipeline_id);
tsn.generate_frame();
awaiting_frame = true;
api.send_transaction(document_id, tsn);
render.update();
render.render(framebuffer_size).unwrap();
let _ = render.flush_pipeline_info();
w_context.swap_buffers().unwrap();
ControlFlow::Continue
});
render.deinit();
}
}
fn increase_epoch(old: Epoch) -> Epoch {
use std::u32;
const MAX_ID: u32 = u32::MAX - 1;
match old.0 {
MAX_ID => Epoch(0),
other => Epoch(other + 1),
impl Window {
pub fn show() -> Window {
let events_loop = glutin::EventsLoop::new();
let w_context = glutin::ContextBuilder::new()
.with_gl(glutin::GlRequest::GlThenGles {
opengl_version: (3, 2),
opengles_version: (3, 0),
})
.build_windowed(
glutin::WindowBuilder::new()
.with_title("Test")
.with_dimensions(LogicalSize::new(800.0, 600.0))
.with_multitouch(),
&events_loop,
)
.expect("Error building windowed GL context");
let w_context = unsafe {
w_context
.make_current()
.expect("Error making context current")
};
let gl = match w_context.get_api() {
glutin::Api::OpenGl => unsafe {
gl::GlFns::load_with(|addr| w_context.get_proc_address(addr) as *const _)
},
glutin::Api::OpenGlEs => unsafe {
gl::GlesFns::load_with(|addr| w_context.get_proc_address(addr) as *const _)
},
_ => unreachable!(),
};
let dpi = w_context.window().get_hidpi_factor();
let background = ColorF::new(0., 0., 0., 1.);
let opts = webrender::RendererOptions {
device_pixel_ratio: dpi as f32,
clear_color: Some(background),
..Default::default()
};
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
let (renderer, renderer_sender) = webrender::Renderer::new(gl, notifier, opts, None)
.expect("Error creating web renderer");
Window {
events_loop,
w_context,
renderer,
renderer_sender,
background,
render: None,
content: None,
}
}
fn init_render(&mut self) {
let api = self.renderer_sender.create_api();
let doc = api.add_document(self.framebuffer_size(), 0);
let epoch = Epoch(0);
let pipe = PipelineId(0, 0);
let mut tsn = Transaction::new();
tsn.set_root_pipeline(pipe);
tsn.generate_frame();
api.send_transaction(doc, tsn);
self.render = Some(RenderData {
api,
doc,
epoch,
pipe,
});
}
fn init_content(&mut self) {
self.content = Some(Button {
tag: (0, 0),
is_hovered: false,
});
}
pub fn run(mut self) {
self.init_render();
self.init_content();
let mut events_loop = self.events_loop;
let mut content = self.content.unwrap();
let mut render = self.render.unwrap();
let w_context = self.w_context;
let mut run = true;
let mut first_render = true;
loop {
let mut render_content = first_render;
first_render = false;
events_loop.poll_events(|event| {
let w_event = match event {
glutin::Event::WindowEvent { event, .. } => event,
_ => return,
};
match w_event {
glutin::WindowEvent::CloseRequested => {
run = false;
return;
}
glutin::WindowEvent::Resized { .. } => render_content = true,
e => {
if content.on_event(&e, &render) {
render_content = true
}
}
}
});
if !run {
break;
}
let dpi = w_context.window().get_hidpi_factor();
let fsz = w_context
.window()
.get_inner_size()
.unwrap()
.to_physical(dpi);
let fsz = DeviceIntSize::new(fsz.width as i32, fsz.height as i32);
if true {
let dpi = dpi as f32;
render.increase_epoch();
let layout_size = fsz.to_f32() / euclid::TypedScale::new(dpi);
let mut tsn = Transaction::new();
let mut builder = DisplayListBuilder::new(render.pipe, layout_size);
content.render(&render, &mut builder);
render.api.set_window_parameters(
render.doc,
fsz,
DeviceIntRect::new(DeviceIntPoint::zero(), fsz),
dpi,
);
tsn.set_display_list(
render.epoch,
Some(self.background),
layout_size,
builder.finalize(),
true,
);
tsn.generate_frame();
render.api.send_transaction(render.doc, tsn);
self.renderer.update();
}
self.renderer.render(fsz).unwrap();
self.renderer.flush_pipeline_info();
w_context.swap_buffers().unwrap();
}
self.renderer.deinit();
}
fn dpi(&self) -> f64 {
self.w_context.window().get_hidpi_factor()
}
fn framebuffer_size(&self) -> DeviceIntSize {
let size = self
.w_context
.window()
.get_inner_size()
.unwrap()
.to_physical(self.dpi());
DeviceIntSize::new(size.width as i32, size.height as i32)
}
}