Weston介绍

  1. Weston结构说明

  1. 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服务商

  1. weston结构流程

  1. 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中需要异步处理的操作可以放在其中。每轮循环都会检查其中是否有任务,如果有则执行。

  1. 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. 窗口创建流程

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);

  1. 数据结构

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;

};

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值