As a follow up to #88, I propose refactoring the library into:
flutter-engine-sys: the ffi code
flutter-engine: codec, channels, pointer events, tasks etc (i.e. wrapper around sys crate)
flutter-engine-plugins: text-input etc, each plugin could be a feature flag
flutter-engine-glfw: current logic around glfw rendering
This means that the flutter-engine crate is no longer dependent on opengl etc, or glfw, and can be used as an independent library in the following manor:
struct MyHandler {
}
impl FlutterEngineHandler for MyHandler {
fn swap_buffers(&self) -> bool {
unimplemented!()
}
fn make_current(&self) -> bool {
unimplemented!()
}
fn clear_current(&self) -> bool {
unimplemented!()
}
fn fbo_callback(&self) -> u32 {
unimplemented!()
}
fn make_resource_current(&self) -> bool {
unimplemented!()
}
fn gl_proc_resolver(&self, proc: *const i8) -> *mut c_void {
unimplemented!()
}
fn wake_platform_thread(&self) {
unimplemented!()
}
fn run_in_background(&self, func: Box<dyn Future<Output = ()> + Send + 'static>) {
unimplemented!()
}
fn get_texture_frame(
&self,
texture_id: i64,
size: (usize, usize),
) -> Option<ExternalTextureFrame> {
unimplemented!()
}
}
// Handler is called by the engine on different threads to handle embedder specific tasks
let handler = Arc::new(MyHandler);
let engine = FlutterEngine::new(Arc::downgrade(&handler) as _);
// Add plugins (plugins can registered before the engine starts)
engine.add_plugin(KeyEventPlugin::default());
// Start engine
engine.run(assets_path, icu_data_path, arguments).expect("Failed to create engine");
// In some sort of loop, you can call execute_platform_tasks, which will give the time you should sleep to for the next task
let next_task_time = engine.execute_platform_tasks();
If in the future flutter gets alternative renderers, such as Vulkan, we can break down the FlutterEngineHandler into multiple traits, or use a feature flag.
TaskRunner
are now an independent concept, meaning if flutter adds extra task runners in the future, the logic should be reusable.