前言
flutter 已经成功移植arm32位平台运行,方案是可行的,这里贴一下相关研究文档。移植操作后续再公布
flutter探索研究
opengl相关研究研究:
1. drm:drm是一种图形显示框架,支持vsync(同步信号,适用于fps大于刷新频率的情况),dma-buf(buffer共享,buf和file统一),异步更新,fence机制(cpu,gpu数据同步)。同时DRM可以统一管理GPU和Display驱动,使得软件架构更为统一,方便管理和维护。
2. drm驱动框架可以创建fb驱动框架的设备节点/dev/fb0,但是该节点不可操作(虚拟机中),因为映射的虚拟内存没有和显存物理页进行绑定(虚拟机中,fb框架采用defer io机制,实现上的问题导致异常.fb_deferred_io_page)
3. libdrm了解,只有操作系统支持drm驱动,才能使用libdrm。libdrm本质就是对drm驱动的使用的封装。
4. mesa了解,mesa是管理opengl实现的一个opengl框架,其内部支持opengl的软件实现以及各种gpu型号的硬件调用实现,还包括新型GPU标准vulkan。且必须依赖于libdrm(目前还没有成功去除对libdrm的依赖)
5. opengl相关库的基本了解:libgl是opengl接口的实现的封装(软件libopengl,还是哪款gpu的opengl实现,可能依赖于libdrm),libglu是对libgl接口的封装(集成libglu的接口),libglut是opengl的窗口实现(使用glut创建窗口, 使用gl和glu进行绘图,glut对接桌面
图形系统)
6. flutter-engine内置了swiftshader(opengl软件实现,以及硬件实现,类似mesa)
flutter-elinux-embeddered学习:
1. flutter-elinux是基于wayland,x11,glfw等窗口UI系统实现flutter显示的框架,其内部包含wayland,x11,glfw的flutter embeddered(嵌入器)的实现。flutter embeddered主要需要实现显示对接以及事件对接。
2 flutter-elinux将embedder的对接整理出一套框架,将变化的部分进一步隔离出来,区别实现,简化了flutter embeddered的对接。
2.1 flutter-elinux内置对glfw的支持,example的实现简单,但是内部机制无法深究
2.2 flutter-elinux内置对wayland的支持,需要依赖于libdrm,其支持vsync,可以探究其实现, 且有必要通过了解其机制探索flutter机制
2.3 flutter-elinux内置对x11的支持,需要依赖于libdrm,其支持vsync,可以探究其实现, 且有必要通过了解其机制探索flutter机制
2.4 x11中的xserver调用compositor(合成器,使用gpu)负责将xclient的layer合成到一起去显示,wayland认为xserver存在没有必要,去掉了xserver的存在,直接使用compositor,提高了性能,大概是未来主流的linux桌面图形系统。
flutter_engine源码了解:
1. flutter_engine内置swiftshader(opengl软件实现,以及硬件实现,类似mesa)
2. flutter_engine可以通过编译控制,控制要不要内置dart虚拟机(解释器),如果不内置dart解释器,需要以库的形式提供dart虚拟机支持。(暂未搞清楚dart三方库dart脚本是如何集成进flutter_engine.so的,需要了解)
3. flutter的渲染机制有四种方式可以选择,1. kOpengl 2. kSoftware 3. kMetal 4.kVulkan
3.1 kOpengl就是实现使用opengl渲染,flutter内置opengl软件实现(skia依赖),可以通过编译选项关闭opengl支持,裁剪flutter_engine.so。使用kOpengl模式可以有很多方式支持,目前能看到的参考用例大多数是kOpengl
3.2 kSoftware就是软件渲染,其内部是不是使用的swiftshader进行软件的opengl渲染有待研究,flutter会将绘制好的buffer通过surface_present_callback回调提供。window系统就是此方式进行对接。
3.3 kMetal就是是一种低层次的渲染应用程序编程接口,类似于opengl。百科:专为开发高临场感主机游戏的开发者打造,可让开发者全力发挥 A7 和 A8 芯片的性能。该技术经过优化,使处理器和图形处理器能够协同工作来实现最优性能。
3.4 kVulkan类似opengl,将来可能会淘汰Opengl,成为主流的GPU变成标准,同Opengl,swiftshader和mesa提供软件实现支持
4. flutter内部的playground仅支持kMetal和opengl,这个会不会影响到上层实现,有待研究
5. flutter_engine内部支持window窗口(FlutterWindowWin32),flutter渲染好以后,(kSoftware模式)通过surface_present_callback->FlutterWindowsView::PresentSoftwareBitmap->FlutterWindowWin32::OnBitmapSurfaceUpdated形式通知window进行重绘。
6. 可以通过嵌入器测试用例学习各种嵌入器的接入。engine\shell\platform\embedder\tests\embedder_config_builder.cc
flutter-elinux研究
1. 使用bundle资源路径构造flutter::DartProject对象
1.1 bundle资源路径下需要 /data/flutter_assets,/data/icudtl.dat,/lib/libapp.so
1.1.1 icudtl.dat 由FlutterTool提供,作为资源使用
1.1.2 flutter_assets 由FlutterTool构建
1.1.3 libapp.so 由FlutterTool构建,用于aot构建
1.2 DartProject是官方的类,构造中仅保存三个文件路径
2. 创建flutter::FlutterViewController::ViewProperties对象,填充宽高,旋转角度,是否有光标等参数
3. 使用flutter::FlutterViewController::ViewProperties对象和flutter::DartProject对象构建FlutterWindow对象
3.1 FlutterWindow对象应该就是自定义的
4. 调用FlutterWindow::OnCreate()方法启动引擎
4.1 使用flutter::FlutterViewController::ViewProperties对象
和flutter::DartProject对象构造flutter::FlutterViewController对象
4.1.1 构造中会使用flutter::DartProject对象构造flutter::FlutterEngine对象
4.1.1.1 构造中会从DartProject中取出argc,argv,以及三资源的路径初始化FlutterDesktopEngineProperties
4.1.1.2 构造中会使用FlutterDesktopEngineProperties构造FlutterProjectBundle对象
4.1.1.3 构造中会创建一个TaskRunner对象(用于执行任务), 运行时会检测engine是否为空,
不为空则会调用flutter API接口运行task(engine为FlutterEngine(添加符号是为了以后拓展),此时还未初始化)
task_runner_ = std::make_unique<TaskRunner>(
std::this_thread::get_id(), embedder_api_.GetCurrentTime,
[this](const auto* task) {
if (!engine_) {
ELINUX_LOG(ERROR)
<< "Cannot post an engine task when engine is not running.";
return;
}
if (embedder_api_.RunTask(engine_, task) != kSuccess) {
ELINUX_LOG(ERROR) << "Failed to post an engine task.";
}
});
4.1.1.3 构造中会使用FlutterProjectBundle对象构造FlutterELinuxEngine对象
4.1.1.3.1 构造中初始化FlutterEngineProcTable对象(内含Flutter操作API)
4.1.1.3.2 构造中构造FlutterDesktopMessenger对象,并使用FlutterELinuxEngine初始化engine成员
4.1.1.3.3 构造中创建FlutterDesktopPluginRegistrar对象,并使用FlutterELinuxEngine初始化engine成员
4.1.1.3.4 构造中使用FlutterDesktopMessenger对象构造BinaryMessengerImpl对象
4.1.1.3.5 构造中使用FlutterDesktopMessenger对象构造IncomingMessageDispatcherImpl对象
4.1.1.3.6 构造中使用FlutterELinuxEngine对象构造FlutterELinuxTextureRegistrar对象
4.1.1.3.7 构造中使用FlutterDesktopMessager对象,JsonMessageCodec单例json解码器构建BasicMessageChannel对象
该消息通道的name为:"flutter/settings"
4.1.1.3.8 构造中创建一个VsyncWaiter对象(通过该对象向flutter发送vsync事件)
4.1.1.4 构造中会强制将FlutterELinuxEngine转化为FlutterDesktopEngine对象(实际就是个void*, 无法操作),
并返回,目的是避免别人操作该对象,去掉类属性
4.1.1.5 构造中会使用FlutterELinuxEngine对象中的FlutterDesktopMessenger对象构造BinaryMessengerImpl对象
4.1.2 构造中会使用flutter::FlutterViewController::ViewProperties对象,
构造FlutterDesktopViewProperties(flutter-elinux自定义)对象
4.1.3 构造中会使用FlutterDesktopViewProperties对象
和FlutterELinuxEngine对象调用FlutterDesktopViewControllerCreate
构造flutter::FlutterDesktopViewController对象
4.1.3.1 使用FlutterDesktopViewProperties构造ELinuxWindowX11(父类为WindowBindingHandler)对象
4.1.3.1.1 构造函数中将会创建Display对象(XOpenDisplay()过去Display)
4.1.3.2 构造FlutterDesktopViewControllerState对象
4.1.3.3 使用ELinuxWindowX11(父类为WindowBindingHandler)对象构造
FlutterELinuxView(父类为WindowBindingHandlerDelegate)对象,
并将FlutterELinuxView(父类为WindowBindingHandlerDelegate)对象保存到
FlutterDesktopViewControllerState对象中。
4.1.3.3.1 构造中还将FlutterELinuxView设置到ELinuxWindowX11中,实现双向绑定
4.1.3.4 调用FlutterDesktopViewController对象的CreateRenderSurface方法
4.1.3.4.1 获取ELinuxWindowX11的尺寸
4.1.3.4.2 调用ELinuxWindowX11的CreateRenderSurface方法(以下属于X11窗口机制,需要花事件理解)
4.1.3.4.2.1 使用Display对象构造EnvromentEgl对象
4.1.3.4.2.1.1 构造中使用EGLNativeDisplayType(理论上Dispaly应该是EGLNativeDisplayType的父类)
作为参数,调用eglGetDisplay获取EGLDisplay
4.1.3.4.2.1.2 调用InitializeEgl(初始化egl)
4.1.3.4.2.2 构造NativeWindowX11对象
4.1.3.4.2.2.1 创建EGLNativeWindowType对象(XCreateWindow)
4.1.3.4.2.3 使用EnvironmentElg对象构造SurfaceGL对象
4.1.3.4.2.4 将SurfaceGL对象和NativeWindowX11对象绑定
4.1.3.5 调用FlutterELinuxView::SetEngine将FlutterElinuxEngine设置到FlutterELinuxView对象中(双向绑定)
4.1.3.5.1 获取FlutterELinuxEngine中的FlutterDesktopPluginRegistrar对象
构造flutter::PluginRegistrar对象
4.1.3.5.1.1 使用FlutterDesktopPluginRegistrar中的FlutterDesktopMessenger
构造BinaryMessaengerImpl对象
4.1.3.5.1.2 获取FlutterDesktopPluginRegistrar中的FlutterELinuxTextureRegistrar对象,
并强制转换为FlutterDesktopTextureRegistrar(不可操作)
4.1.3.5.1.3 使用FlutterDesktopTextureRegistrar去构造TextureRegistrarImpl对象
4.1.3.5.2 取出flutter::PluginRegistrar对象中的BinaryMessengerImpl对象
4.1.3.5.3 使用BinaryMessengerImpl对象去构造flutter::KeyeventPlugin对象
4.1.3.5.3.1 构造中会初始化键盘输入上下文(xkb_context)
4.1.3.5.4 使用ELinuxWindowX11(父类为WindowBindingHandler)对象和BinaryMessengerImpl对象
去构造flutter::TextInputPlugin对象
4.1.3.5.4.1 构造中会使用messenger和plugin去
构造flutter::MethodChannel<rapidjson::Document>对象
4.1.3.5.4.2 设置MethodChannel的回调,回调中收到事件后
传给ELinuxWindowX11(::UpdateVirtualKeyboardStatus)
(事件从哪里来)
4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
和BinaryMessengerImpl对象去构造flutter::PlatformPlugin对象
(事件从哪里来)
4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
和BinaryMessengerImpl对象去构造flutter::MouseCursorPlugin对象
(事件从哪里来)
4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
和BinaryMessengerImpl对象去构造flutter::LifecyclePlugin对象
(事件从哪里来)
4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
和BinaryMessengerImpl对象去构造flutter::NavigationPlugin对象
(事件从哪里来)
4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
和BinaryMessengerImpl对象去构造flutter::PlatformViewsPlugin对象
(事件从哪里来)
4.1.3.6 调用FlutterELinuxEngine::RunWithEntrypoint运行引擎
4.1.3.6.1 调用FlutterProjectBundle::HasValidPaths检查路径是否有效
4.1.3.6.2 调用flutter_api的RunsAOTCompilesDartCode,应该是编译dart代码
4.1.3.6.3 调用FlutterProjectBundle::LoadAotData函数获取FlutterEngineAOTData对象
4.1.3.6.3.1 调用flutter_api的CreateAOTData构造FlutterEngineAOTData对象
(其内部将libapp.so映射出来,之后加载过程中解析libapp.so二进制文件的头,段表,以及记录.dynstr和.dynsym段位置,
然后读取段_kDartVmSnapshotData起始地址,保存到vm_data中
然后读取段_kDartVmSnapshotInstructions起始地址,保存到vm_instrs中
然后读取段_kDartIsolateSnapshotData起始地址,保存到isolate_data中
然后读取段_kDartIsolateSnapshotInstructions起始地址,保存到isolate_instrs中)
4.1.3.6.4 调用GetSwitchesFromEnvironment获取环境变量FLUTTER_ENGINE_SWITCH_${N}
然后将环境变量值加上前缀转换为--observatory-port=12345的形势
4.1.3.6.5 新建FlutterTaskRunnerDescription结构体对象
.struct_size = sizeof(FlutterTaskRunnerDescription)
.user_data = TaskRunner对象
// 判断是否是当前线程
.runs_task_on_current_thread_callback = [](void* user_data) -> bool {
return static_cast<TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
};
// 抛出一个消息到主线程消息队列去执行
.post_task_callback = [](FlutterTask task,
uint64_t target_time_nanos,
void* user_data) -> void {
static_cast<TaskRunner*>(user_data)->PostFlutterTask(task, target_time_nanos);
};
4.1.3.6.6 新建FlutterCustomTaskRunners结构体对象
.struct_size = sizeof(FlutterCustomTaskRunners)
.platform_task_runner = FlutterTaskRunnerDescription对象
4.1.3.6.7 新建FlutterProjectArgs结构体对象
.struct_size = sizeof(FlutterCustomTaskRunners)
.assets_path = flutter_assets路径
.icu_data_path = icudtl.dat路径
// 引擎启动参数
.command_line_argc = 前面由环境变量生成的参数的个数
.command_line_argv = 前面由环境变量生成的参数
// dart脚本启动参数
.dart_entrypoint_arg = 前面由环境变量生成的参数的个数
.dart_entrypoint_argv = 前面由环境变量生成的参数
// 监听并处理flutter消息
.platform_message_callback = [](const FlutterPlatformMessage* engine_message,
void* user_data) -> void {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
return host->HandlePlatformMessage(engine_message);
};
.custom_task_runners = FlutterCustomTaskRunners对象
.aot_data = FlutterEngineAOTData对象
// 指定dart脚本入口名, 为空默认main
.custom_dart_entrypoint = nullptr
// 日志消息处理
.log_message_callback = [](const char* tag, const char* message,void* user_data) {
};
4.1.3.6.8 调用GetRendererConfig构造FlutterRenderConfig对象
// opengl引擎
config.type = kOpenGL
config.open_gl.struct_size = sizeof(config.open_gl)
config.open_gl.make_current = [](void* user_data) -> bool {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return false;
}
return host->view()->MakeCurrent();
};
config.open_gl.clear_current = [](void* user_data) -> bool {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return false;
}
return host->view()->ClearCurrent();
};
config.open_gl.present = [](void* user_data) -> bool {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return false;
}
return host->view()->Present();
}
config.open_gl.fbo_callback = [](void* user_data) -> uint32_t {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return false;
}
return host->view()->GetOnscreenFBO();
};
config.open_gl.gl_proc_resolver = [](void *user_data,
const char* name) -> void* {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return nullptr;
}
return host->view()->ProcResolver(name);
};
config.open_gl.make_resource_current = [](void* user_data) -> bool {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->view()) {
return false;
}
return host->view()->MakeResourceCurrent();
};
config.open_gl.gl_external_texture_frame_callback = [](void* user_data,
int64_t texture_id, size_t width, size_t height, FlutterOpenGLTextture *texture) {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
if (!host->texture_registrar()) {
return false;
}
return host->texture_registrar()->PopulateTexture(texture_id, width, height, texture);
};
config.open_gl.surface_transformation = [](void* user_data) {
auto host = static_cast<FlutterELinuxEngine*>(user_data);
return host->view()->GetRootSurfaceTransformation();
};
4.1.3.6.9 调用flutter_api->Run(),将FlutterEngine对象和FlutterRenderConfig对象对象作为参数传入
4.1.3.6.9.1 FlutterEngine对象传入后,flutter引擎会调用FlutterEngine::messenger()接口获取消息传递对象BinaryMessengerImpl
(BinaryMessengerImpl内部持有FlutterDesktopMessenger,而FlutterDesktopMessenger内部持有FlutterELinuxEngine)
4.1.3.6.9.2 flutter获取BinaryMessengerImpl后,会调用SetMeesageHandler接口,传递通道名以及消息传递对象BinaryMessageHandler过来
4.1.3.6.9.3 然后会通过BinaryMessengerImpl深处的FlutterELinuxEngine对象的IncomingMessageDispatcher对象的SetMessageCallback接口
4.1.3.6.9.4 将handler转换成FlutterDesktopMessageCallback对象保存起来,当flutter消息过来时触发回调,并处理消息
4.1.3.6.10 调用SendSystemSettings进行系统设置
4.1.3.6.9.1 获取所有支持的语言,并调用flutter_api的UpdateLocales,设置到引擎中
4.1.3.6.9.2 创建json的配置,调用BasicMessageChannel::Send发送配置
(发到flutter中,通道名为flutter/settings,
路线:BasicMessageChannel->BinaryMessengerImpl->FlutterDesktopMessengerSend->FlutterELinuxEngine::SendPlatformMessage)
4.2 调用FlutterWindow::Run()进入引擎的事件传递,分发,及处理
4.2.1 FlutterViewController对象->FlutterView::DispatchEvent()->FlutterELinuxView::DispatchEvent()->ELinuxWindowX11::DisplayEvent()
4.2.2 ELinuxWindowX11::DispatchEvent中将调用XNextEvent()获取用户输入
4.2.3 根据事件的不同类型调用FlutterELinuxView::OnKey()等等接口
4.2.4.1 首先调用KeyeventPlugin::OnKey()接口
4.2.4.1.1 通过构造KeyeventPlugin时初始化的BasicMessageChannel对象发送消息json格式的event事件
4.2.4.1.2 通过构造KeyeventPlugin时传入的BinaryMessengerImpl对象(flutter::PluginRegistrar构造内创建)去发送消息
4.2.4.1.3 调用FlutterDesktopMessengerSend接口去发送消息(第一个参数时FlutterELinuxEngine对象中的FlutterDeskTopMessenger对象)
4.2.4.1.4 通过FlutterDeskTopMessenger对象中的FlutterELinuxEngine对象的SendPlatformMessageResponse接口去发送
4.2.4.1.5 通过flutter_api->SendPlatformMessage去发送生成的PlatformMessage
(VSync是由窗口wayland发起的,x11没有发起vsync)
flutter-pi研究
flutter-pi基本使用c语言开发,没有desktop这些东西,内存占用更小一些
依赖的库,大多是UI库
1. 调用parse_cmd_args解析参数: ./flutter-pi ...args
1.1 -o参数: portrait_up 竖直向上
landscape_left 水平向左
portrait_down 竖直向下
landscape_right 水平向右
flutterpi.view.orientation = 屏幕方向
flutterpi.view.has_orientation = 是否有屏幕方向
1.2 -r参数: 0,90,180,270 旋转角度
flutterpi.view.rotation屏幕旋转角度
?? 为什么屏幕方向都有了,还需要旋转角度呢?阿拉伯语考虑
1.3 -d参数: width,height 宽高,用逗号隔开
flutterpi.display.width_mm == 屏幕
1.4 -p参数: RGB565,
ARGB8888
XRGB8888,
BGRA8888,
RGBA8888
像素格式
flutterpi.gdm.format
1.5 获取bundle路径:flutterpi.flutter.assert_bundle_path = realpath(argv[optind])
1.6 将解析后的参数去除,将剩余未处理的消息保存,用于作为flutter启动的参数
flutterpi.flutter.engine_argc
flutterpi.flutter.engine_argv
2. 调用setup_path:确定kernel_blob.bin和libapp.so的路径(发布版本不需要 jit模式,但是平时会使用调试模式,有必要搞)
2.1 bundle路径下要有app.so/kernel_blob.bin,icudtl.dat文件(flutter_assert文件不需要吗?)
flutterpi.flutter.kernel_blob_path kernel_blob.bin文件路径
flutterpi.flutter.icu_data_path icudtl.dat文件路径
flutterpi.flutter.app_elf_path app.so文件路径
3. 调用init_main_loop初始化事件循环机制
3.1 保存当前线程id:flutterpi.event_loop_thread
3.2 创建eventfd文件描述符:flutterpi.wakeup_event_loop_fd
3.3 创建sd_event对象:flutterpi.event_loop
3.4 将wakeup_fd添加到sd_event中
4. 调用locales_new初始化flutter支持的语言: flutterpi.locales(struct locales)
4.1 通过环境变量获取系统语言配置(LANG,LC_ALL,LANGUAGE,LC_MESSAGES),语言+区域+编码:en_US.UTF-8
4.2 从配置中,提取至语言,区域,编码到struct FlutterLocale中和struct locale中
struct FlutterLocale.struct_size = sizeof(struct FlutterLocale)
struct FlutterLocale.language_code = en
struct FlutterLocale.country_code = US
struct FlutterLocale.script_code = UTF-8
struct FlutterLocale.variant_code = NULL
struct locale.flutter_locale = struct FlutterLocale对象
struct locale.language = en
struct locale.territory = US
struct locale.codeset = UTF-8
struct locale.modifier = NULL
4.3 struct locales.flutter_locales = struct FlutterLocale多个对象
struct locales.n_locales = 语言数量
struct locales.default_locale = NULL
struct locales.default_flutter_locale = struct FlutterLocale[0]
5. 调用init_user_input初始化用户输入事件管理
5.1 调用 user_input_new 初始化事件管理: flutterpi.view.display_to_view_transform
flutterpi.view.view_to_display_transform
以及struct user_input_interface
5.1.1 创建struct user_input对象
.interface = struct user_input_interface对象
5.1.1.1 struct user_input_interface对象
.on_flutter_pointer_event = on_flutter_pointer_event, //监听处理flutter点击事件
.on_utf8_character = on_utf8_character, //监听处理utf8字符事件
.on_xkb_keysym = on_xkb_keysym, // 监听处理x11的按键事件
.on_gtk_keyevent = on_gtk_keyevent, // 监听处理gtk的按键事件
.on_set_cursor_enabled = on_set_cursor_enabled, // 监听处理鼠标开关事件
.on_move_cursor = on_move_cursor, // 监听处理移动光标的事情
.userdata = flutterpi,
.libinput = struct libinput对象, // input udev的上下文
.kdbcfg = kbdcfg, //键盘配置
.next_unused_flutter_device_id = 0, //
.display_to_view_transform = (当前内部未初始化, 内部都为0)
.view_to_display_transform_nontranslating =(当前内部未初始化, 内部都为0)
.c_cursor_devices = 0,
.cursor_flutter_device_id = -1,
.cursor_x = 0.0,
.cursor_y = 0.0,
.n_collectd_flutter_pointer_events = 0,
5.2 调用sd_event_add_io,监听struct user_input对象的libinput上下文对应的文件描述符
处理事件的回调函数是on_user_input_fd_ready, userdata是struct user_input对象
5.3 flutterpi.user_input = struct user_input对象
5.4 flutterpi.user_input_event_source = event_source,sd_event_add_io事件源
6. 调用init_display初始化显示屏参数和机制
6.1 获取屏幕横竖方向的物理尺寸: flutterpi.display.width_mm, flutter_pi.display.height_mm //用于计算pixel_ratio
6.2 获取屏幕横竖方向的像素值:flutter.display.width, flutter.display.height
6.3 获取屏幕的刷新频率: flutter.display.refresh_rate = 60
6.4 计算屏幕的像素物理尺寸和单位1的比率(类似于dpi):flutterpi.display.pixel_ratio = 1.0
6.5
7. 调用init_application函数初始化flutter引擎并运行
7.1 打开libflutter_engine.so动态库,获取动态库中对外提供的所有函数,主要有以下函数
7.1.1 FlutterEngineRunsAOTCompiledDartCode // 编译按照AOT模式编译dart源码
7.1.2 FlutterEngineCreateAOTData // 获取aot数据
7.1.3 FlutterEngineInitialize // 引擎初始化
7.1.4 FlutterEngineRunInitialized // 引擎运行初始化
7.1.5 FlutterEngineUpdateLocales // 更新语言类型
7.1.6 FlutterEngineRegisterExternalTexture // 注册外部渲染
7.1.7 FlutterEngineUnregisterExternalTexture // 取消外部渲染
7.1.8 FlutterEngineMarkExternalTextureFrameAvailable // 标记外部渲染Frame有效
7.1.9 FlutterEngineNotifyDisplayUpdate
7.1.10 FlutterEngineSendWindowMetricsEvent
7.2 创建FlutterRendererConfig对象
7.3 创建FlutterProjectArgs对象
.assets_path = flutterpi.flutter.asset_bundle_path
.icu_data_path = flutterpi.flutter.icu_data_path
.command_line_argc = flutterpi.flutter.engine_argc
.command_line_argc = flutterpi.flutter.engine_argv
.platform_message_callback = on_platform_message, //接受flutter的消息并处理
.custom_task_runners = (FlutterCustomTaskRunners){
.platform_task_runner = (FlutterTaskRunnerDescription){
.user_data = NULL,
.runs_task_oncurrent_thread_callback = runs_platform_tasks_on_current_thread, // 判断是否是当前事件循环的线程
.post_task_callback = on_post_flutter_task, // 执行一个flutter_task定时任务,最好是在事件循环线程
}
}
.compositor = &flutter_compositer, //合成器
7.4 调用FlutterEngineRunsAOTCompileDartCode() //编译dart源码
7.5 调用FlutterEngineCreateAOTData //获取编译后的AOT数据
7.6 调用FlutterEngineInitialize //引擎初始化
7.7 调用FlutterEngineRunInitialized // 引擎开始运行
7.8 调用FlutterEngineSendWindowMetricsEvent // 设置窗口大小
8. 调用run_main_loop:运行UI引擎
8.1 轮询获取flutter.event_loop中的状态(这么多状态的好处时事件的循环可以在SD_EVENT_INITIAL或者SD_EVENT_FINISH去停止,而不会自动陷入循环)
8.1.1 SD_EVENT_INITIAL: 开始迭代处理事件之前的状态,
此状态需要调用sd_event_prepare()让event_loop转换为SD_EVENT_ARMED或者SD_EVENT_PENDING状态
8.1.2 SD_EVENT_PREPARING: 正在准备事件源,即当前正在执行准备处理程序,这个状态尽在sd_event_prepare()被调用之后可见,
此状态之后紧跟着的是SD_EVENT_ARMED 或者 SD_EVENT_PENDING.
8.1.3 SD_EVENT_ARMED: sd_event_prepare()已经被调用,并且没有事件被分发时处于该状态。调用sd_event_wait等待事件,
之后转换为SD_EVENT_PENDING, 或者返回SD_EVENT_INITIAL状态
8.1.4 SD_EVENT_PENDING: 调用sd_event_prepare()或者sd_event_wait()之后,且有事件待办处于该状态。调用sd_event_dispatch()
去分发(处理)高优先级的事件,并且转换为SD_EVENT_FINISH状态或者回退到SD_EVENT_INITIAL状态.
8.1.5 SD_EVENT_RUNNING: 事件源正在被分发中(处理中),这个状态只会在sd_event_dispatch()被调用之后出现,并且消息处理之后紧随的消息
是SD_EVENT_INITIAL或者SD_EVENT_FINISHED。如果在分发(处理)期间退出事件处理,则之后的状态是SD_EVENT_EXITING。
8.1.6 SD_EVENT_EXITING: 在事件调度退出之后生效的状态,其之后跟随的状态是SD_EVENT_INITIAL活SD_EVENT_FINISHED。
8.1.7 SD_EVENT_FINISHED: 事件循环已推出,所有事件源都已经运行,如果处于该状态,它就不在有任何用途了。