Weston结构说明

Weston源码结构

clients:wayland显示客户端应用
compositor:合成器进程(服务端),窗体风 格样式处理
libweston:合成器以及客户端渲染处理以及驱动实现方式,以及wayland服务与客户端逻辑处理(焦点处理,鼠标事件,窗口创建绘制处理等)
backend-drm:默认渲染后端,支持Pixman和OpenGL/ES
backend-headless:不带任何ui及面,主要用于测试
backend-rdp:为远程桌面实现的渲染
backend-vnc:支持传统的fbdev,只支持Pixman
backend-wayland:weston作为一个wayland的客户端形式类似与X11在wayland上
backend-x11:weston作为一个X的客户端,使wayland跑在X服务上
color-lcms:显示器彩色管理相关处理
desktop:支持desktopshell的wayland协议调用处理
renderer-gl:gl渲染接口给display_create使用
shell-utils:shell里面共有的逻辑处理(部分焦点屏幕位置输出等函数)
desktopshell(ivishell、kioskshell、fullscreenshell):不同桌面显示形式
pipewire:
remoting:
shared: weston具体绘制窗口(外窗、模糊)处理函数。
tests: weston测试单元
tools:
wcap:
xwayland: 使X应用可以运行在wayland服务商
weston结构流程

Weston注册事件
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启动流程

1、主函数: main
2、创建weston日志流:
设置文件路径
static bool weston_log_file_open(const char *filename);
创建日志文件
struct weston_log_subscriber* weston_log_subscriber_create_log(FILE *dump_to);
3、创建wl_display对象
创建全局唯一显示对象
struct wl_display *wl_display_create(void);
4、获取服务事件循环
获取事件循环,以便添加信号量
struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display)
5、读取配置文件
可以动态的改变运行配置(需要重启Server端进程),比如使用哪种界面、动画的类型、渲染驱动的类型等
static intload_configuration(struct weston_config **config, int32_t noconfig,
const char *config_file)
6、创建compositor
创建合成器,主要把相关server端服务注册到事件循环当中,当客户端有请求时相应客户端请求
struct weston_compositor *weston_compositor_create(struct wl_display *display, struct weston_log_context *log_ctx, void *user_data, const struct weston_testsuite_data *test_data)
7、初始化后端渲染驱动
根据传入的参数/配置初始化后端渲染驱动等
static int load_backend(struct weston_compositor *compositor, const char *name, int *argc, char **argv, struct weston_config *config, const char *renderer_name)
8、创建socket
创建监听socket(默认/run/user/1000/wayland-0),监听客户与服务端连接
static int weston_create_listening_socket(struct wl_display *display, const char *socket_name)
9、加载shell
加载不同的shell,不同的显示的桌面和桌面上的应用。
static int wet_load_shell(struct weston_compositor *compositor, const char *_name, int *argc, char *argv[])
10、加载其他模块
主要加载输入输出设备等
static int load_modules(struct weston_compositor *ec, const char *modules, int *argc, char *argv[])
11、唤醒合成器
如果合成器处于休眠模式,则所有输出都通过 DPMS 重新启动。如果合成器处于非活动状态(idle/locked, offscreen, or sleeping) 合成器的唤醒信号会被触发。
void weston_compositor_wake(struct weston_compositor *compositor)
12、启动事件循环
监听客户端活动,处理客户端渲染,输入事件等。
void wl_display_run(struct wl_display *display)
窗口创建流程

1、客户端获取display对象
通过这个wayland协议获取全局唯一display对象
struct wl_display *wl_display_connect(const char *name);
2、获取全局注册表对象(服务端wl_global_create注册的服务)
static inline struct wl_registry *wl_display_get_registry(struct wl_display *wl_display)
3、client监听代理对象,当有服务端新的全局服务注册时,客户端可以接收到事件通知。
static inline int wl_registry_add_listener(struct wl_registry *wl_registry, const struct wl_registry_listener *listener, void *data)
4、同步客户与服务之间的调用
int wl_display_roundtrip(struct wl_display *display);
5、向服务请求创建窗口surface
创建抽象窗口
static inline struct wl_surface *wl_compositor_create_surface( struct wl_compositor *wl_compositor)
创建实体窗口
static inline struct xdg_surface *xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface)
6、添加窗口绘图事件
static inline int xdg_surface_add_listener(struct xdg_surface *xdg_surface,
const struct xdg_surface_listener *listener, void *data)
7、从服务端获取渲染缓冲
static inline struct wl_buffer *wl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format)
8、监听缓冲区状态(是否被服务端释放)
static inline int wl_buffer_add_listener(struct wl_buffer *wl_buffer,
const struct wl_buffer_listener *listener, void *data)
9、设置缓冲区为surface渲染内容
static inline void wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
10、向服务端发送需要重绘区域
static inline void wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
11、使用双缓冲机制绘制渲染数据
static inline int wl_callback_add_listener(struct wl_callback *wl_callback,
const struct wl_callback_listener *listener, void *data)
12、提交窗口状态
因为表面状态使用双缓冲机制,一次性提交替换当前状态,
static inline void wl_surface_commit(struct wl_surface *wl_surface)
13、开启事件将事件添加到队列开启事件循环
int wl_display_dispatch(struct wl_display *display);
数据结构

wayland协议客户端和服务端接口数据类型(wayland-util.h)
union wl_argument {
/**< int */
int32_t i;
/**< uint */
uint32_t u;
/**< fixed double和int兼容类型*/
wl_fixed_t f;
/**< string */
const char *s;
/**< object interface基类指针,可以接收保存所有interface的指针*/
struct wl_object *o;
/**< new_id 客户端被解释时的返回值,但是在服务端,这个参数被转化成uint32_t类型传递过来一个id */
uint32_t n;
/**< array */
struct wl_array *a;
/**< fd linux进程文件描述符*/
int32_t h;
};
wayland协议接口参数传递数据(wayland-private.h)
struct wl_object {
const struct wl_interface *interface;
const void *implementation;
uint32_t id;
};
服务端注册的服务(wayland-util.h)
struct wl_interface {
/** Interface name 注册服务的名称*/
const char *name;
/** Interface version 注册服务版本 */
int version;
/** Number of methods (requests) */
int method_count;
/** Method (request) signatures */
const struct wl_message *methods;
/** Number of events */
int event_count;
/** Event signatures */
const struct wl_message *events;
};
wayland 通信时确定object或者new_id参数类型(wayland-util.h)
struct wl_message {
/** Message name */
const char *name;
/** Message signature */
const char *signature;
/** Object argument interfaces */
const struct wl_interface **types;
};
客户端资源对象(wayland-client.h)
struct wl_proxy {
struct wl_object object;
struct wl_display *display;
struct wl_event_queue *queue;
uint32_t flags;
int refcount;
void *user_data;
wl_dispatcher_func_t dispatcher;
uint32_t version;
const char * const *tag;
}
客户端socket连接用来接收发送事件(wayland-client.c)
struct wl_display {
struct wl_proxy proxy;
struct wl_connection *connection;
/* errno of the last wl_display error */
int last_error;
/* When display gets an error event from some object, it stores
* information about it here, so that client can get this
* information afterwards */
struct {
/* Code of the error. It can be compared to
* the interface's errors enumeration. */
uint32_t code;
/* interface (protocol) in which the error occurred */
const struct wl_interface *interface;
/* id of the proxy that caused the error. There's no warranty
* that the proxy is still valid. It's up to client how it will
* use it */
uint32_t id;
} protocol_error;
int fd;
struct wl_map objects;
struct wl_event_queue display_queue;
struct wl_event_queue default_queue;
pthread_mutex_t mutex;
int reader_count;
uint32_t read_serial;
pthread_cond_t reader_cond;
};
服务端所有interface全都是wl_resource结构对象,客户端资源存储对象(wayland-server.c)
struct wl_resource {
struct wl_object object;
wl_resource_destroy_func_t destroy;
struct wl_list link;
struct wl_signal destroy_signal;
struct wl_client *client;
void *data;
};
服务端存储客户端信息结构(wayland-server.c)
struct wl_client {
struct wl_connection *connection;
struct wl_event_source *source;
struct wl_display *display;
struct wl_resource *display_resource;
struct wl_list link;
struct wl_map objects;
struct wl_priv_signal destroy_signal;
struct wl_priv_signal destroy_late_signal;
pid_t pid;
uid_t uid;
gid_t gid;
int error;
struct wl_priv_signal resource_created_signal;
};
服务端与客户端socket连接,用来接收发送事件(wayland-server.c)
struct wl_display {
struct wl_event_loop *loop;
int run;
uint32_t id;
uint32_t serial;
struct wl_list registry_resource_list;
struct wl_list global_list;
struct wl_list socket_list;
struct wl_list client_list;
struct wl_list protocol_loggers;
struct wl_priv_signal destroy_signal;
struct wl_priv_signal create_client_signal;
struct wl_array additional_shm_formats;
wl_display_global_filter_func_t global_filter;
void *global_filter_data;
int terminate_efd;
struct wl_event_source *term_source;
};
enum wl_map_entry_flags {
WL_MAP_ENTRY_LEGACY = (1 << 0), /* Server side only */
WL_MAP_ENTRY_ZOMBIE = (1 << 0) /* Client side only */
};
wayland核心,用于保存进程之间通信的实际对象指针,并得到对于指针的ID,用于进程之间传递(wayland-private.h)
struct wl_map {
/* 保存客户端对象数组*/
struct wl_array client_entries;
/* 保存服务端对象数组*/
struct wl_array server_entries;
uint32_t side;
uint32_t free_list;
};
可以翻倍增长的数组,alloc>size,当相等时alloc扩大为原来两倍(wayland-util.h)
struct wl_array {
/** Array size */
size_t size;
/** Allocated space */
size_t alloc;
/** Array data */
void *data;
};
union map_entry {
uintptr_t next;
void *data;
};
链表指针结构(wayland-util.h)
struct wl_list {
/** Previous list element */
struct wl_list *prev;
/** Next list element */
struct wl_list *next;
};