Changed loop to our own using poll_events and rendering everything every loop iteration.
This commit is contained in:
parent
8038d4cb77
commit
e1350f503d
|
@ -1,5 +1,5 @@
|
|||
mod window;
|
||||
|
||||
fn main() {
|
||||
window::show_window();
|
||||
window::Window::show().run();
|
||||
}
|
||||
|
|
384
src/window.rs
384
src/window.rs
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue