Skip to content

Commit

Permalink
rebaseme
Browse files Browse the repository at this point in the history
  • Loading branch information
not-fl3 committed May 22, 2024
1 parent e02a8a5 commit 107a7b2
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 20 deletions.
17 changes: 15 additions & 2 deletions js/gl.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ var clipboard = null;

var plugins = [];
var wasm_memory;
var animation_frame_timeout;

var high_dpi = false;
// if true, requestAnimationFrame will only be called from "schedule_update"
// if false, requestAnimationFrame will be called at the end of each frame
var blocking_event_loop = false;

canvas.focus();

Expand Down Expand Up @@ -424,7 +428,12 @@ function resize(canvas, on_resize) {

function animation() {
wasm_exports.frame();
window.requestAnimationFrame(animation);
if (!window.blocking_event_loop) {
if (animation_frame_timeout) {
window.cancelAnimationFrame(animation_frame_timeout);
}
animation_frame_timeout = window.requestAnimationFrame(animation);
}
}

const SAPP_EVENTTYPE_TOUCHES_BEGAN = 10;
Expand Down Expand Up @@ -1114,7 +1123,7 @@ var importObject = {
window.high_dpi = high_dpi;
resize(canvas);
},
run_animation_loop: function (ptr) {
run_animation_loop: function (blocking) {
canvas.onmousemove = function (event) {
var relative_position = mouse_relative_position(event.clientX, event.clientY);
var x = relative_position.x;
Expand Down Expand Up @@ -1314,6 +1323,7 @@ var importObject = {
window.addEventListener("focus", checkFocus);
window.addEventListener("blur", checkFocus);

window.blocking_event_loop = blocking;
window.requestAnimationFrame(animation);
},

Expand Down Expand Up @@ -1387,6 +1397,9 @@ var importObject = {
canvas.width = new_width;
canvas.height = new_height;
resize(canvas, wasm_exports.resize);
},
sapp_schedule_update: function () {
window.requestAnimationFrame(animation);
}
}
};
Expand Down
6 changes: 5 additions & 1 deletion src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ pub struct Platform {
/// the way to limit FPS in the game!
pub swap_interval: Option<i32>,

/// update()/draw() will only be called after `window::request_update()`.
pub blocking_event_loop: bool,

/// Whether the framebuffer should have an alpha channel.
/// Currently supported only on Android
/// TODO: Make it works on web, on web it should make a transparent HTML5 canvas
Expand All @@ -113,9 +116,10 @@ impl Default for Platform {
fn default() -> Platform {
Platform {
linux_x11_gl: LinuxX11Gl::GLXWithEGLFallback,
swap_interval: None,
linux_backend: LinuxBackend::X11Only,
apple_gfx_api: AppleGfxApi::OpenGl,
blocking_event_loop: false,
swap_interval: None,
framebuffer_alpha: false,
wayland_use_fallback_decorations: true,
}
Expand Down
4 changes: 2 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ pub trait EventHandler {
/// When the app is in background, Android destroys the rendering surface,
/// while app is still alive and can do some usefull calculations.
/// Note that in this case drawing from update may lead to crashes.
fn update(&mut self);
fn draw(&mut self);
fn update(&mut self) {}
fn draw(&mut self) {}
fn resize_event(&mut self, _width: f32, _height: f32) {}
fn mouse_motion_event(&mut self, _x: f32, _y: f32) {}
fn mouse_wheel_event(&mut self, _x: f32, _y: f32) {}
Expand Down
23 changes: 22 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ pub mod window {
d.high_dpi
}

pub fn blocking_event_loop() -> bool {
let d = native_display().lock().unwrap();
d.blocking_event_loop
}

/// This function simply quits the application without
/// giving the user a chance to intervene. Usually this might
/// be called when the user clicks the 'Ok' button in a 'Really Quit?'
Expand Down Expand Up @@ -190,6 +195,21 @@ pub mod window {
d.native_requests.send(native::Request::SetCursorGrab(grab));
}

/// With `conf.platform.blocking_event_loop`, `schedule_update` called from an
/// event handler makes draw()/update() functions to be called without waiting
/// for a next event.
///
/// Does nothing without `conf.platform.blocking_event_loop`.
pub fn schedule_update() {
let mut d = native_display().lock().unwrap();
d.native_requests.send(native::Request::Wat {});

#[cfg(target_arch = "wasm32")]
unsafe {
native::wasm::sapp_schedule_update();
}
}

/// Show or hide the mouse cursor
pub fn show_mouse(shown: bool) {
let mut d = native_display().lock().unwrap();
Expand All @@ -214,7 +234,8 @@ pub mod window {

pub fn set_window_position(new_x: u32, new_y: u32) {
let mut d = native_display().lock().unwrap();
d.native_requests.send(native::Request::SetWindowPosition { new_x, new_y });
d.native_requests
.send(native::Request::SetWindowPosition { new_x, new_y });
}

/// Get the position of the window.
Expand Down
3 changes: 3 additions & 0 deletions src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub(crate) struct NativeDisplayData {
pub native_requests: mpsc::Sender<Request>,
pub clipboard: Box<dyn Clipboard>,
pub dropped_files: DroppedFiles,
pub blocking_event_loop: bool,

#[cfg(target_vendor = "apple")]
pub view: crate::native::apple::frameworks::ObjcId,
Expand Down Expand Up @@ -47,6 +48,7 @@ impl NativeDisplayData {
native_requests,
clipboard,
dropped_files: Default::default(),
blocking_event_loop: false,
#[cfg(target_vendor = "apple")]
gfx_api: crate::conf::AppleGfxApi::OpenGl,
#[cfg(target_vendor = "apple")]
Expand All @@ -59,6 +61,7 @@ impl NativeDisplayData {

#[derive(Debug)]
pub(crate) enum Request {
Wat {},
SetCursorGrab(bool),
ShowMouse(bool),
SetMouseCursor(crate::CursorIcon),
Expand Down
38 changes: 31 additions & 7 deletions src/native/linux_x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct X11Display {
repeated_keycodes: [bool; 256],
empty_cursor: libx11::Cursor,
cursor_cache: HashMap<CursorIcon, libx11::Cursor>,
update_requested: bool,
}

impl X11Display {
Expand Down Expand Up @@ -317,6 +318,9 @@ impl X11Display {
use Request::*;
unsafe {
match request {
Wat {} => {
self.update_requested = true;
}
SetCursorGrab(grab) => self.set_cursor_grab(self.window, grab),
ShowMouse(show) => self.show_mouse(show),
SetMouseCursor(icon) => self.set_cursor(self.window, Some(icon)),
Expand Down Expand Up @@ -382,6 +386,7 @@ where
crate::set_display(NativeDisplayData {
high_dpi: conf.high_dpi,
dpi_scale: display.libx11.update_system_dpi(display.display),
blocking_event_loop: conf.platform.blocking_event_loop,
..NativeDisplayData::new(w, h, tx, clipboard)
});
if conf.fullscreen {
Expand All @@ -395,19 +400,31 @@ where
display.process_request(request);
}
glx.make_current(display.display, glx_window, glx_context);
let count = (display.libx11.XPending)(display.display);

let mut count = (display.libx11.XPending)(display.display);
let block_on_wait = conf.platform.blocking_event_loop && !display.update_requested;
if block_on_wait {
// if there are multiple events pending, it is still desired to process
// them all in one frame.
// However, when there are no events in the queue, +1 hack
// will block main thread and release the cpu until the new event.
count = count + 1;
}

for _ in 0..count {
let mut xevent = _XEvent { type_0: 0 };
(display.libx11.XNextEvent)(display.display, &mut xevent);
display.process_event(&mut xevent, &mut *event_handler);
}

event_handler.update();
event_handler.draw();
if !conf.platform.blocking_event_loop || display.update_requested {
event_handler.update();
event_handler.draw();

glx.swap_buffers(display.display, glx_window);
(display.libx11.XFlush)(display.display);
glx.swap_buffers(display.display, glx_window);
(display.libx11.XFlush)(display.display);
display.update_requested = false;
}
}

glx.destroy_context(display.display, glx_window, glx_context);
Expand Down Expand Up @@ -479,6 +496,7 @@ where
crate::set_display(NativeDisplayData {
high_dpi: conf.high_dpi,
dpi_scale: display.libx11.update_system_dpi(display.display),
blocking_event_loop: conf.platform.blocking_event_loop,
..NativeDisplayData::new(w, h, tx, clipboard)
});
if conf.fullscreen {
Expand All @@ -494,8 +512,13 @@ where
display.process_request(request);
}

let count = (display.libx11.XPending)(display.display);

let mut count = (display.libx11.XPending)(display.display);
let block_on_wait = conf.platform.blocking_event_loop && !display.update_requested;
display.update_requested = false;
if block_on_wait {
// same thing as in glx loop, explained there
count = count + 1;
}
for _ in 0..count {
let mut xevent = _XEvent { type_0: 0 };
(display.libx11.XNextEvent)(display.display, &mut xevent);
Expand Down Expand Up @@ -559,6 +582,7 @@ where
libxi,
repeated_keycodes: [false; 256],
cursor_cache: HashMap::new(),
update_requested: true,
};

display
Expand Down
7 changes: 4 additions & 3 deletions src/native/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ where
let h = unsafe { canvas_height() as _ };
let clipboard = Box::new(Clipboard);
crate::set_display(NativeDisplayData {
blocking_event_queue: conf.platform.blocking_event_queue,

Check failure on line 81 in src/native/wasm.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, wasm32-unknown-unknown)

struct `NativeDisplayData` has no field named `blocking_event_queue`

Check failure on line 81 in src/native/wasm.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, wasm32-unknown-unknown)

no field `blocking_event_queue` on type `Platform`
..NativeDisplayData::new(w, h, tx, clipboard)
});
EVENT_HANDLER.with(|g| {
Expand All @@ -86,7 +87,7 @@ where

// start requestAnimationFrame loop
unsafe {
run_animation_loop();
run_animation_loop(conf.platform.blocking_event_loop);
}
}

Expand All @@ -100,7 +101,7 @@ pub unsafe fn sapp_height() -> ::std::os::raw::c_int {

extern "C" {
pub fn setup_canvas_size(high_dpi: bool);
pub fn run_animation_loop();
pub fn run_animation_loop(blocking: bool);
pub fn canvas_width() -> i32;
pub fn canvas_height() -> i32;
pub fn dpi_scale() -> f32;
Expand All @@ -126,7 +127,7 @@ extern "C" {
pub fn sapp_set_fullscreen(fullscreen: bool);
pub fn sapp_is_fullscreen() -> bool;
pub fn sapp_set_window_size(new_width: u32, new_height: u32);

pub fn sapp_schedule_update();
pub fn now() -> f64;
}

Expand Down
26 changes: 22 additions & 4 deletions src/native/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,17 @@ impl WindowsDisplay {
let mut new_rect = rect;
new_rect.right = new_rect.right - new_rect.left + new_x as i32;
new_rect.bottom = new_rect.bottom - new_rect.top + new_y as i32;
unsafe { SetWindowPos(self.wnd, HWND_TOP, new_x as i32, new_y as i32, 0, 0, SWP_NOSIZE) };
unsafe {
SetWindowPos(
self.wnd,
HWND_TOP,
new_x as i32,
new_y as i32,
0,
0,
SWP_NOSIZE,
)
};
}
}

Expand Down Expand Up @@ -752,8 +762,10 @@ impl WindowsDisplay {
let mut client_rect: RECT = std::mem::zeroed();
if GetClientRect(hwnd, &mut client_rect as *mut _ as _) != 0 {
// Calculate window width and height based on the client area
let window_width = ((client_rect.right - client_rect.left) as f32 / self.window_scale) as i32;
let window_height = ((client_rect.bottom - client_rect.top) as f32 / self.window_scale) as i32;
let window_width =
((client_rect.right - client_rect.left) as f32 / self.window_scale) as i32;
let window_height =
((client_rect.bottom - client_rect.top) as f32 / self.window_scale) as i32;

// Prevent a framebuffer size of 0 when the window is minimized
let fb_width = ((window_width as f32 * self.content_scale) as i32).max(1);
Expand Down Expand Up @@ -883,7 +895,13 @@ where
crate::set_display(NativeDisplayData {
high_dpi: conf.high_dpi,
dpi_scale: display.window_scale,
..NativeDisplayData::new(conf.window_width, conf.window_height, tx, clipboard)
..NativeDisplayData::new(

Check failure on line 898 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

this function takes 4 arguments but 5 arguments were supplied

Check failure on line 898 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

this function takes 4 arguments but 5 arguments were supplied
conf.window_width,
conf.window_height,
tx,
clipboard,
conf.blocking_event_queue,

Check failure on line 903 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

no field `blocking_event_queue` on type `&Conf`

Check failure on line 903 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

no field `blocking_event_queue` on type `&Conf`
)
});

display.update_dimensions(wnd);
Expand Down

0 comments on commit 107a7b2

Please sign in to comment.