flutter 移植arm32嵌入式应用的相关研究文档

前言

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: 事件循环已推出,所有事件源都已经运行,如果处于该状态,它就不在有任何用途了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值