图形系统wayland和weston基础

简单地说,Wayland是一套display server(Wayland compositor)与client间的通信协议,而Weston是Wayland compositor的参考实现。其
官网为http://wayland.freedesktop.org/。它们定位于在Linux上替换X图形系统。X图形系统经历了30年左右的发展,其设计在今天看来已略显陈旧。在X系统中,XServer作为中心服务,连接dien和硬件以刀及compositor。但时至今日,原本在XServer中做的事很多已被移到kemel口或者单独的库中,因此XServer就显得比较累赘了。Wayland在架构上去掉了了这个中间层,将compositor作为display server,使client与compositor直接通信,从而在灵活性和性能等方面上能够比前前辈更加出色。

Wayland既可以用于传统的桌面又适用于移动设备,已经被用于Tizer,SailfishOS等商业操作系统,同时越来越多的窗口和图形系统开
始兼容Wayland协议。Wayland基于domain socket实现了一套displayserver与clien间通信的库,并且以XML形式定义了一套可扩展通信协议。这个协议分为Wayland核心协议和扩展协议(位于Weston中)。Weston作为Wayland compositor的参考实现,一设和Wayland同步发布,其它Wayland compositor实现还有如mutter, Kwin, Lipstick, Enlightenment, Clayland等。

1,架构

Wayland的系统体系架构如上文所示,官方给出了一个源码实现Weston。Weston从内部体系结构来看,主要分为窗口管理(shell),合成器(compositor)和输入管理几个部分。可见,如果拿Android作类比,从功能上看它约等同于InputManagerService,WindowManagerService和SurfaceFlinger。从大体的流程上来看,输入管理模块接受用户输入,然后一方面shell作出相应的窗口管理操作(如窗口堆栈的改变,focus的变化等),另一方面将该input event传给之前注册了相应输入事件的client。client收到后会在handler中做相应动作,如调整视图然后重绘。如有重绘发生,新buffer渲染完成后client将其handle传给server,接着server端生成z-order序的窗口列表,之后compositor用renderer进行合成,最后输出(比如到framebuffer)。
在这里插入图片描述 Weston是主要服务进程,它的事件处理模型采用的是典型的Reactor模式。根据Linux中万物皆文件的原则,主循环通过epoll机制等待在一系列的文件fd上。这种模型与基于线程的binder不同,是一种串行的事件处理模型。在此模型上的过程调用在不加额外同步机制的情况下是异步的。好处是不会有竞争问题,数据同步开销较小。缺点是当有一个事件处理比较耗时或者在等待IO,则有可能使整个系统性能下降或响应不及时。
在这里插入图片描述
主循环上等待的几个核心fd包括:
• Server/Client通信:listener fd在Weston启动时建立,并一直监听新的client连接。一个client连接后会与Weston建立一对domain socket,Wayland就是基于它来通信的。

• 输入处理:一方面通过udev monitor监听设备的添加删除事件。另一方面如有新设备添加时会将该设备打开并监听该fd来得到输入事件。

• 其它:监听如timer(用于如睡眠锁屏等场景)和signal(如收到SIGINT, SIGTERM, SIGQUIT时退出主循环)等事件。timer和signal可以分别用timerfd和signalfd来用fd来表示。另外还有logind的dbus连接等。
除这些外,在event loop中还会维护一个idle list。Weston中需要异步处理的操作可以放在其中。每轮循环都会检查其中是否有任务,有的话拿出来执行。

下面看下Weston的运行时进程模型。Weston设计时是可以以一般用户运行的,但就需要用weston-launch来启动。当需要进行一些需要root权限的工作,比如关于DRM, TTY, input device的相关操作,就交由weston-launch去做。

Weston会在启动时或按需起一些子进程,它们本质上是Weston的client,它们会通过专用的协议做一些系统应用的工作。如系统应用weston-desktop-shell负责一些系统全局的界面,比如panel, background, cursor, app launcher, lock screen等。它不作为Weston服务本身的一部分,而是作为一个client。其作用有点类似于Android中的SystemUI。这样便可方便地替换成定制的界面。weston-keyboard是软键盘面板。weston-screenshooter和weston-screensaver分别用于截屏和屏保,它们都是按需才由Weston启动的。前者在截屏快捷键按下时启动,后者在需要锁屏时启动。
在这里插入图片描述
另外,Weston启动时会读取weston.ini这个配置文件,其中可以配置桌面,动画和后端等等信息。

Wayland主要依赖于两个库,一个expat用于protocol解析xml文件,另一个libffi用于在跨进程过程调用中根据函数描述生成相应calling convention的跳板代码。

Weston的主要实现在src目录下。与Wayland类似,protocol目录下放着Wayland协议定义。在clients目录下是一些client的例子,也包括了desktop-shell和keyboard等核心client的例子,也包含了如simple-egl, simple-shm, simple-touch等针对性的简单用例。Weston启动过程中会分别加载几个backend:shell backend, render backend和compositor backend。它们分别用于窗口管理,合成渲染和合成内容输出。
在这里插入图片描述
由于这些后端都可有不同的实现,为了逻辑上的独立性和结构上的灵活性,他们都编译成动态链接库从而可以在Weston初始化时被加载进来。这种方式在Weston中被广泛采用,一些功能比如屏幕共享等都是以这种形式加载的。

举例来说,compositor backend主要决定了compositor合成完后的结果怎么处置。从数据结构上,weston_output是output设备的抽象,而下面的backend会实现具体的output设备。

• fbdev:直接输出至linux的framebuffer设备。接口通用。

• headless:和noop-renderer配合使用,可以在没有窗口系统的机子(比如server上)测试逻辑。

• RPI:用于Raspberry Pi平台。

• RDP:合成后通过RDP传输到RDP peer显示,用于远程桌面。

• DRM:Direct redering manager,桌面上一般用这个。

• x11:Wayland compositor作为X server的client。它可以让Wayland client运行在X11上。

• wayland:Wayland composiotr作为server同时,也作为另一个Wayland compositor的client。用于nested compositor。

Renderer backend主要用于compositor的合成之用,除去noop-renderer外,有gl-renderer和pixman-renderer两种。前者为GPU硬件渲染,后者为软件渲染。shell backend用于实现具体的窗口管理。相应的实现分别在desktop-shell,fullscreen-shell和ivi-shell目录中。

Wayland/Weston运行时依赖的库主要有下面几个,其相互关系大体如下。

在这里插入图片描述• libEGL, libGLES:本地窗口系统与图形driver的glue layer,mesa提供了开源版本的实现。

• libdrm:封装KMS,GEM等图形相关接口。平台相关。

• libffi:用于在运行时根据调用接口描述生成函数跳板并调用。

• pixman:用于像素操作的库,包括region, box等计算。用了许多平台相关的优化。

• cairo:软件渲染库,类似于skia。也有OpenGL后端。

• libinput:输入处理,依赖于mtdev, libudev, libevdev等库。

• libxkbcommon:主要用于键盘处理。

• libjpeg, libpng, libwebp:用于加载各种图片文件,像壁纸,面板和鼠标等都需要。

2、初始化模块源码

启动代码

Service启动脚本
"/system/bin/weston", "-c", "/system/etc/weston.ini", "-B", "drm-backend.so", "--tty=1"
 
//weston.ini
 
[core]
shell=libivi-shell.z.so
modules=libivi-controller.z.so,libwmserver.z.so,libmmi-server.z.so
 
[ivi-shell]
ivi-input-module=libivi-input-controller.z.so
ivi-id-agent-module=libivi-id-agent.z.so
screen-info-module=libscreen-info-module.z.so
transition-duration=30
cursor-theme=default
 
[keyboard]
keymap_layout=de
 
[input-method]
path=

下面开始分析主要的主流程wet_main

2.1 参数初始化

	wl_list_init(&wet.layoutput_list);
 
	os_fd_set_cloexec(fileno(stdin));
 
	cmdline = copy_command_line(argc, argv);
	parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
 
	if (help) {
   
		free(cmdline);
		usage(EXIT_SUCCESS);
	}
 
	if (version) {
   
		printf(PACKAGE_STRING "\n");
		free(cmdline);
 
        LOG_EXITS("main");
		return EXIT_SUCCESS;
	}
 
// OHOS remove logger
//	log_ctx = weston_log_ctx_create();
//	if (!log_ctx) {
   
//		fprintf(stderr, "Failed to initialize weston debug framework.\n");
//		return EXIT_FAILURE;
//	}
//
//	log_scope = weston_log_ctx_add_log_scope(log_ctx, "log",
//			"Weston and Wayland log\n", NULL, NULL, NULL);
//
//	if (!weston_log_file_open(log))
//		return EXIT_FAILURE;
//
//	weston_log_set_handler(vlog, vlog_continue);
//
//	logger = weston_log_subscriber_create_log(weston_logfile);
//	flight_rec = weston_log_subscriber_create_flight_rec(DEFAULT_FLIGHT_REC_SIZE);
//
//	weston_log_subscribe_to_scopes(log_ctx, logger, flight_rec,
//				       log_scopes, flight_rec_scopes);
 
	weston_log("%{public}s\n"
		   STAMP_SPACE "%{public}s\n"
		   STAMP_SPACE "Bug reports to: %{public}s\n"
		   STAMP_SPACE "Build: %{public}s\n",
		   PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
		   BUILD_ID);
	weston_log("Command line: %{public}s\n", cmdline);
	free(cmdline);
	log_uname();
 
	verify_xdg_runtime_dir();

backend drm-backend.so

config_file /system/etc/weston.ini

进行一些数据结构的初始化

确保XDG_RUNTIME_DIR相关权限和存在

2.2 创建display

	display = wl_display_create();
	if (display == NULL) {
   
		weston_log("fatal: failed to create display\n");
		goto out_display;
	}
 
	loop = wl_display_get_event_loop(display);
	signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
					      display);
	signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
					      display);
	signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
					      display);
 
	wl_list_init(&child_process_list);
	signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
					      NULL);
 
	if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
		goto out_signals;
 
	/* Xwayland uses SIGUSR1 for communicating with weston. Since some
	   weston plugins may create additional threads, set up any necessary
	   signal blocking early so that these threads can inherit the settings
	   when created. */
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	pthread_sigmask(SIG_BLOCK, &mask, NULL);

创建display对象,将一些信号监测和处理函数增加进event loop

2.3 加载配置

	if (load_configuration(&config, noconfig, config_file) < 0)
		goto out_signals;
	wet.config = config;
	wet.parsed_options = NULL;
 
	section = weston_config_get_section(config, "core", NULL, NULL);
 
// OHOS remove debugger
//	if (!wait_for_debugger) {
   
//		weston_config_section_get_bool(section, "wait-for-debugger",
//					       &wait_for_debugger, false);
//	}
//	if (wait_for_debugger) {
   
//		weston_log("Weston PID is %ld - "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值