sciter-sdk/rust-sciter

Render into bitmap callback is too slow.

LaineZ opened this issue · 0 comments

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