Render into bitmap callback is too slow.
LaineZ opened this issue · 0 comments
LaineZ commented
I'm using a sciter.lite in ggez game framework. And I need draw a UI into the bitmap. There was a problem is low performance when render is goes into reasonable resolution like 2560×1440. The bitmap render callback renders one frame around 169-180 ms on my PC (Ryzen 9 5900X, RTX 3060, Windows 10).
Here is minimal-example, without any render output, just a generating bitmap
//! Windowless mode example (for Sciter.Lite build).
extern crate sciter;
extern crate winit;
extern crate winapi;
extern crate raw_window_handle;
use std::time::Instant;
use winit::event::{Event, WindowEvent};
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
fn main() {
if let Some(arg) = std::env::args().nth(1) {
println!("loading sciter from {:?}", arg);
if let Err(_) = sciter::set_options(sciter::RuntimeOptions::LibraryPath(&arg)) {
panic!("Invalid sciter-lite dll specified.");
}
} else {
panic!("usage: cargo run -p windowless -- sciter-sdk/bin.win/x64lite/sciter.dll")
}
// prepare and create a new window
println!("create window");
let events = EventLoop::new();
use raw_window_handle::HasRawWindowHandle;
let wnd = WindowBuilder::new();
let wnd = wnd.build(&events).expect("Failed to create window");
let window_handle = wnd.raw_window_handle();
// configure Sciter
println!("create sciter instance");
sciter::set_options(sciter::RuntimeOptions::UxTheming(true)).unwrap();
sciter::set_options(sciter::RuntimeOptions::DebugMode(true)).unwrap();
sciter::set_options(sciter::RuntimeOptions::ScriptFeatures(0xFF)).unwrap();
// create an engine instance with an opaque pointer as an identifier
use sciter::windowless::{Message, handle_message};
let scwnd = { &wnd as *const _ as sciter::types::HWINDOW };
handle_message(scwnd, Message::Create { backend: sciter::types::GFX_LAYER::SKIA_OPENGL, transparent: false, });
#[cfg(windows)]
{
// Windows-specific: we need to redraw window in response to a corresponding notification.
// winit 0.20 has an explicit `Window::request_redraw` method,
// here we use `winapi::InvalidateRect` for this.
struct WindowlessHandler {
hwnd: winapi::shared::windef::HWND,
}
impl sciter::HostHandler for WindowlessHandler {
fn on_invalidate(&mut self, pnm: &sciter::host::SCN_INVALIDATE_RECT) {
unsafe {
let rc = &pnm.invalid_rect;
let dst = winapi::shared::windef::RECT {
left: rc.left,
top: rc.top,
right: rc.right,
bottom: rc.bottom,
};
winapi::um::winuser::InvalidateRect(self.hwnd, &dst as *const _, 0);
// println!("- {} {}", rc.width(), rc.height());
}
}
}
let handler = WindowlessHandler {
hwnd: match window_handle {
raw_window_handle::RawWindowHandle::Windows(data) => data.hwnd as winapi::shared::windef::HWND,
_ => unreachable!(),
},
};
let instance = sciter::Host::attach_with(scwnd, handler);
let html = include_bytes!("../../minimal.htm");
instance.load_html(html, Some("example://minimal.htm"));
}
// events processing
use sciter::windowless::RenderEvent;
println!("running...");
let startup = std::time::Instant::now();
// release CPU a bit, hackish
std::thread::sleep(std::time::Duration::from_millis(0));
handle_message(scwnd, Message::Heartbit {
milliseconds: std::time::Instant::now().duration_since(startup).as_millis() as u32,
});
handle_message(scwnd, Message::Size { width: 2560, height: 1440 });
// the actual event loop polling
events.run(move |event, _, control_flow| {
match event {
Event::RedrawRequested(_) => {
let on_render = move |bitmap_area: &sciter::types::RECT, bitmap_data: &[u8]|
{
};
let render_time = Instant::now();
let cb = RenderEvent {
layer: None,
callback: Box::new(on_render),
};
handle_message(scwnd, Message::RenderTo(cb));
println!("Render took {} ms", render_time.elapsed().as_millis());
},
_ => (),
}
});
}
output:
loading sciter from "F:\\rust-sciter\\sciter-js-sdk-main\\sciter-js-sdk-main\\bin.lite\\windows\\x64\\sciter.dll"
create window
create sciter instance
running...
Render took 169 ms