当前位置:网站首页>[Wayland] Weston startup process analysis
[Wayland] Weston startup process analysis
2022-06-12 10:09:00 【Lindo】
Weston Start process analysis
- Weston yes Wayland Compositor The implementation of the . Its Server The client runs in the system as an independent process .MakeFile The intermediate compilation result is ,“weston” Executable program of
- MakeFile.am(weston 2.0.0)
bin_PROGRAMS += weston
weston_LDFLAGS = -export-dynamic
weston_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON \
-DMODULEDIR='"$(moduledir)"' \
-DXSERVER_PATH='"@[email protected]"'
weston_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBUNWIND_CFLAGS)
weston_LDADD = libshared.la [email protected][email protected] \
$(COMPOSITOR_LIBS) $(LIBUNWIND_LIBS) \
$(DLOPEN_LIBS) $(LIBINPUT_BACKEND_LIBS) \
$(CLOCK_GETRES_LIBS) \
-lm
weston_SOURCES = \
compositor/main.c \
compositor/weston-screenshooter.c \
compositor/text-backend.c \
compositor/xwayland.c
Start process analysis
flow chart :

main function : Entry function . In fact, now weston-2.0.0/compositor/main.c
Main content analysis
int main(int argc, char *argv[])
{
// Log Log initialization
weston_log_set_handler(vlog, vlog_continue);
weston_log_file_open(log);
// start-up Log
weston_log("%s\n"
STAMP_SPACE "%s\n"
STAMP_SPACE "Bug reports to: %s\n"
STAMP_SPACE "Build: %s\n",
PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
BUILD_ID);
// Create a globally unique Display
display = wl_display_create();
// Read weston.ini Configuration in file
if (load_configuration(&config, noconfig, config_file) < 0)
goto out_signals;
// establish Compositor
ec = weston_compositor_create(display, &user_data);
if (ec == NULL) {
weston_log("fatal: failed to create compositor\n");
goto out;
}
// load backend( The default is drm-backend)
if (load_backend(ec, backend, &argc, argv, config) < 0) {
weston_log("fatal: failed to create compositor backend\n");
goto out;
}
// Capture exception Signal
catch_signals();
if (fd != -1) {
// ...
// Default walk else if, establish socket
} else if (weston_create_listening_socket(display, socket_name)) {
goto out;
}
// load shell
if (wet_load_shell(ec, shell, &argc, argv) < 0)
goto out;
// Wake up the compositor
weston_compositor_wake(ec);
// run: Loop monitoring client End request
wl_display_run(display);
}
- It can be seen that the general process is :
- initialization Log System
- establish Display( Globally unique )
- Load profile (ini file )
- establish Compositor
- load backend
- establish socket
- load shell
- Turn on the cycle
initialization Log System
- weston-2.0.0/libweston/log.c
// take vlog As log_handler
WL_EXPORT void
weston_log_set_handler(log_func_t log, log_func_t cont)
{
log_handler = log;
log_continue_handler = cont;
}
// Use log_handler For the output , It's actually used main.c It's from
// vlog
WL_EXPORT int
weston_vlog(const char *fmt, va_list ap)
{
return log_handler(fmt, ap);
}
// Used in the code log Output interface
WL_EXPORT int
weston_log(const char *fmt, ...)
{
int l;
va_list argp;
va_start(argp, fmt);
l = weston_vlog(fmt, argp);
va_end(argp);
return l;
}
- actually ,log System Use vlog and vlog_continue These two functions . The definition of both , stay main.c in .
static FILE *weston_logfile = NULL;
static void
weston_log_file_open(const char *filename)
{
wl_log_set_handler_server(custom_handler);
if (filename != NULL) {
weston_logfile = fopen(filename, "a");
if (weston_logfile)
os_fd_set_cloexec(fileno(weston_logfile));
}
if (weston_logfile == NULL)
weston_logfile = stderr;
else
setvbuf(weston_logfile, NULL, _IOLBF, 256);
}
static int
vlog(const char *fmt, va_list ap)
{
int l;
l = weston_log_timestamp();
l += vfprintf(weston_logfile, fmt, ap);
return l;
}
static int
vlog_continue(const char *fmt, va_list argp)
{
return vfprintf(weston_logfile, fmt, argp);
}
- By default weston_log_file_open function , Parameter is NULL. therefore log The information will be output to stderr in .
establish Global Display
- wl_display_create:wayland1.13.0/src/wayland-server.c
WL_EXPORT struct wl_display *
wl_display_create(void)
{
struct wl_display *display;
const char *debug;
debug = getenv("WAYLAND_DEBUG");
if (debug && (strstr(debug, "server") || strstr(debug, "1")))
debug_server = 1;
display = malloc(sizeof *display);
if (display == NULL)
return NULL;
// establish Loop
display->loop = wl_event_loop_create();
if (display->loop == NULL) {
free(display);
return NULL;
}
// list initialization
wl_list_init(&display->global_list);
wl_list_init(&display->socket_list);
wl_list_init(&display->client_list);
wl_list_init(&display->registry_resource_list);
wl_list_init(&display->protocol_loggers);
// signal initialization
wl_priv_signal_init(&display->destroy_signal);
wl_priv_signal_init(&display->create_client_signal);
display->id = 1;
display->serial = 0;
display->global_filter = NULL;
display->global_filter_data = NULL;
wl_array_init(&display->additional_shm_formats);
return display;
}
- wl_event_loop_create:wayland-1.13.0/src/event-loop.c
WL_EXPORT struct wl_event_loop *
wl_event_loop_create(void)
{
struct wl_event_loop *loop;
loop = malloc(sizeof *loop);
if (loop == NULL)
return NULL;
// The final call epoll_create
loop->epoll_fd = wl_os_epoll_create_cloexec();
if (loop->epoll_fd < 0) {
free(loop);
return NULL;
}
wl_list_init(&loop->check_list);
wl_list_init(&loop->idle_list);
wl_list_init(&loop->destroy_list);
wl_signal_init(&loop->destroy_signal);
return loop;
}
- This part is mainly about initialization Display Structure , Use epoll_create Created loop.
Load profile
- The configuration file :weston Configuration files are provided , The running configuration can be changed dynamically ( Need to restart Server End processes ), For example, what kind of shell、 The type of animation 、backend Type of... Etc .
- compostior/main.c
static int
load_configuration(struct weston_config **config, int32_t noconfig,
const char *config_file)
{
// The default configuration file is weston.ini
const char *file = "weston.ini";
const char *full_path;
*config = NULL;
if (config_file)
file = config_file;
// Parse configuration file
if (noconfig == 0)
*config = weston_config_parse(file);
if (*config) {
full_path = weston_config_get_full_path(*config);
weston_log("Using config file '%s'\n", full_path);
setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
return 0;
}
if (config_file && noconfig == 0) {
weston_log("fatal: error opening or reading config file"
" '%s'.\n", config_file);
return -1;
}
weston_log("Starting with no config file.\n");
setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
return 0;
}
- weston_config_parse The function is responsible for parsing the configuration file . Finally, it will be parsed into a linked list data structure . This function has a large number of lines of code , I won't introduce .
- Official weston.ini
[core]
#modules=cms-colord.so
#xwayland=true
#shell=desktop-shell.so
#gbm-format=xrgb2101010
#require-input=true
[shell]
background-image=/usr/share/backgrounds/gnome/Aqua.jpg
background-color=0xff002244
background-type=tile
clock-format=minutes
panel-color=0x90ff0000
locking=true
animation=zoom
startup-animation=fade
#binding-modifier=ctrl
#num-workspaces=6
#cursor-theme=whiteglass
#cursor-size=24
#lockscreen-icon=/usr/share/icons/gnome/256x256/actions/lock.png
#lockscreen=/usr/share/backgrounds/gnome/Garden.jpg
#homescreen=/usr/share/backgrounds/gnome/Blinds.jpg
#animation=fade
[launcher]
icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
path=/usr/bin/gnome-terminal
[launcher]
icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
[email protected]@/weston-terminal
[launcher]
icon=/usr/share/icons/hicolor/24x24/apps/google-chrome.png
path=/usr/bin/google-chrome
[launcher]
icon=/usr/share/icons/gnome/24x24/apps/arts.png
[email protected][email protected]/weston-flower
[input-method]
[email protected]@/weston-keyboard
#[output]
#name=LVDS1
#mode=1680x1050
#transform=90
#icc_profile=/usr/share/color/icc/colord/Bluish.icc
#[output]
#name=VGA1
#mode=173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
#transform=flipped
#[output]
#name=X1
#[email protected]
#transform=flipped-90
#[libinput]
#enable_tap=true
#[touchpad]
#constant_accel_factor = 50
#min_accel_factor = 0.16
#max_accel_factor = 1.0
[screen-share]
[email protected]@/weston --backend=rdp-backend.so --shell=fullscreen-shell.so --no-clients-resize
#[xwayland]
#[email protected]@/Xwayland
establish Compositor
- weston_compositor_create:libweston/compostior.c
WL_EXPORT struct weston_compositor *
weston_compositor_create(struct wl_display *display, void *user_data)
{
struct weston_compositor *ec;
struct wl_event_loop *loop;
ec = zalloc(sizeof *ec);
if (!ec)
return NULL;
// display For the previously created global display
ec->wl_display = display;
ec->user_data = user_data;
// Initialize a series of signal
wl_signal_init(&ec->destroy_signal);
wl_signal_init(&ec->create_surface_signal);
wl_signal_init(&ec->activate_signal);
wl_signal_init(&ec->transform_signal);
wl_signal_init(&ec->kill_signal);
wl_signal_init(&ec->idle_signal);
wl_signal_init(&ec->wake_signal);
wl_signal_init(&ec->show_input_panel_signal);
wl_signal_init(&ec->hide_input_panel_signal);
wl_signal_init(&ec->update_input_panel_signal);
wl_signal_init(&ec->seat_created_signal);
wl_signal_init(&ec->output_pending_signal);
wl_signal_init(&ec->output_created_signal);
wl_signal_init(&ec->output_destroyed_signal);
wl_signal_init(&ec->output_moved_signal);
wl_signal_init(&ec->output_resized_signal);
wl_signal_init(&ec->session_signal);
ec->session_active = 1;
ec->output_id_pool = 0;
ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
ec->activate_serial = 1;
// These steps are key . Again weston There are many such calls in the code .
// wl_global_create There are four parameters
// display、interface、version、bind_func
// It can be understood as :Display There is a global object List, Here is the global object List in , Add a new global object . Implementation of the specific interface of the object , Namely wl_compositor_interface.
if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 4,
ec, compositor_bind))
goto fail;
// ditto wl_subcompositor_interface Interface implementation .
if (!wl_global_create(ec->wl_display, &wl_subcompositor_interface, 1,
ec, bind_subcompositor))
goto fail;
// ditto
if (!wl_global_create(ec->wl_display, &wp_viewporter_interface, 1,
ec, bind_viewporter))
goto fail;
// Same as On
if (!wl_global_create(ec->wl_display, &wp_presentation_interface, 1,
ec, bind_presentation))
goto fail;
// I created two golbal object , Corresponding interface by
// 1. zwp_relative_pointer_manager_v1_interface
// 2. zwp_pointer_constraints_v1_interface
if (weston_input_init(ec) != 0)
goto fail;
// initialization , Several key list: view\plane\layer
wl_list_init(&ec->view_list);
wl_list_init(&ec->plane_list);
wl_list_init(&ec->layer_list);
wl_list_init(&ec->seat_list);
wl_list_init(&ec->pending_output_list);
wl_list_init(&ec->output_list);
wl_list_init(&ec->key_binding_list);
wl_list_init(&ec->modifier_binding_list);
wl_list_init(&ec->button_binding_list);
wl_list_init(&ec->touch_binding_list);
wl_list_init(&ec->axis_binding_list);
wl_list_init(&ec->debug_binding_list);
wl_list_init(&ec->plugin_api_list);
// initialization First of all plane
weston_plane_init(&ec->primary_plane, ec, 0, 0);
weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
wl_data_device_manager_init(ec->wl_display);
wl_display_init_shm(ec->wl_display);
loop = wl_display_get_event_loop(ec->wl_display);
ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
// initialization layer
weston_layer_init(&ec->fade_layer, ec);
weston_layer_init(&ec->cursor_layer, ec);
weston_layer_set_position(&ec->fade_layer, WESTON_LAYER_POSITION_FADE);
weston_layer_set_position(&ec->cursor_layer,
WESTON_LAYER_POSITION_CURSOR);
weston_compositor_add_debug_binding(ec, KEY_T,
timeline_key_binding_handler, ec);
return ec;
fail:
free(ec);
return NULL;
}
- Here, several global objects are created , Set the... Corresponding to these global objects interface Realization . And initialized view、layer、plane And so on .
load backend
- load_backend:compositor/main.c
static int
load_backend(struct weston_compositor *compositor, const char *backend,
int *argc, char **argv, struct weston_config *config)
{
if (strstr(backend, "headless-backend.so"))
return load_headless_backend(compositor, argc, argv, config);
else if (strstr(backend, "rdp-backend.so"))
return load_rdp_backend(compositor, argc, argv, config);
else if (strstr(backend, "fbdev-backend.so"))
return load_fbdev_backend(compositor, argc, argv, config);
// Default walk drm-backend
else if (strstr(backend, "drm-backend.so"))
return load_drm_backend(compositor, argc, argv, config);
else if (strstr(backend, "x11-backend.so"))
return load_x11_backend(compositor, argc, argv, config);
else if (strstr(backend, "wayland-backend.so"))
return load_wayland_backend(compositor, argc, argv, config);
weston_log("Error: unknown backend \"%s\"\n", backend);
return -1;
}
- load_drm_backend
static int
load_drm_backend(struct weston_compositor *c,
int *argc, char **argv, struct weston_config *wc)
{
struct weston_drm_backend_config config = {
{
0, }};
struct weston_config_section *section;
struct wet_compositor *wet = to_wet_compositor(c);
// Go here to create backend
ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
&config.base);
wet_set_pending_output_handler(c, drm_backend_output_configure);
free(config.gbm_format);
free(config.seat_id);
return ret;
}
- weston_compositor_load_backend:libweston/compositor.c
WL_EXPORT int
weston_compositor_load_backend(struct weston_compositor *compositor,
enum weston_compositor_backend backend,
struct weston_backend_config *config_base)
{
int (*backend_init)(struct weston_compositor *c,
struct weston_backend_config *config_base);
if (backend >= ARRAY_LENGTH(backend_map))
return -1;
// adopt dlopen, open drm-backend.so, lookup weston_backend_init function
backend_init = weston_load_module(backend_map[backend], "weston_backend_init");
if (!backend_init)
return -1;
// perform weston_backend_init function
return backend_init(compositor, config_base);
}
- weston_backend_init:libweston/compositor-drm.c
WL_EXPORT int
weston_backend_init(struct weston_compositor *compositor,
struct weston_backend_config *config_base)
{
struct drm_backend *b;
struct weston_drm_backend_config config = {
{
0, }};
if (config_base == NULL ||
config_base->struct_version != WESTON_DRM_BACKEND_CONFIG_VERSION ||
config_base->struct_size > sizeof(struct weston_drm_backend_config)) {
weston_log("drm backend config structure is invalid\n");
return -1;
}
config_init_to_defaults(&config);
memcpy(&config, config_base, config_base->struct_size);
// establish drm backend
b = drm_backend_create(compositor, &config);
if (b == NULL)
return -1;
return 0;
}
- drm_backend_create:libweston/compositor-drm.c
static struct drm_backend *
drm_backend_create(struct weston_compositor *compositor,
struct weston_drm_backend_config *config)
{
// Use libdrm Interface , Do some initialization
// establish output object drmModeGetConnector
}
establish Socket
- Server Process creation listener socket
- weston_create_listening_socket:compositor/main.c
static int
weston_create_listening_socket(struct wl_display *display, const char *socket_name)
{
if (socket_name) {
if (wl_display_add_socket(display, socket_name)) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
} else {
// Default socketname It's empty .
// Create a file called wayland-0 Of socket
socket_name = wl_display_add_socket_auto(display);
if (!socket_name) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
}
setenv("WAYLAND_DISPLAY", socket_name, 1);
return 0;
}
load shell
- wet_load_shell:compositor/main.c
static int
wet_load_shell(struct weston_compositor *compositor,
const char *name, int *argc, char *argv[])
{
int (*shell_init)(struct weston_compositor *ec,
int *argc, char *argv[]);
// Default :
// Use dlopen, open desktop-shell.so, lookup wet_shell_init function
shell_init = wet_load_module_entrypoint(name, "wet_shell_init");
if (!shell_init)
return -1;
// call wet_shell_init
if (shell_init(compositor, argc, argv) < 0)
return -1;
return 0;
}
- wet_shell_init:deskstop-shell/shell.c
WL_EXPORT int
wet_shell_init(struct weston_compositor *ec,
int *argc, char *argv[])
{
// establish desktop
shell->desktop = weston_desktop_create(ec, &shell_desktop_api, shell);
if (!shell->desktop)
return -1;
// Create global objects
if (wl_global_create(ec->wl_display,
&weston_desktop_shell_interface, 1,
shell, bind_desktop_shell) == NULL)
return -1;
}
Turn on the cycle
- The cycle here , Refers to the use epoll Mechanism , Interception pair socket( above Server End created socket) Generated read / write events .
WL_EXPORT void
wl_display_run(struct wl_display *display)
{
display->run = 1;
while (display->run) {
wl_display_flush_clients(display);
wl_event_loop_dispatch(display->loop, -1);
}
}
- wl_event_loop_dispatch:event-loop.c
WL_EXPORT int
wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
{
struct epoll_event ep[32];
struct wl_event_source *source;
int i, count, n;
wl_event_loop_dispatch_idle(loop);
count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
if (count < 0)
return -1;
for (i = 0; i < count; i++) {
source = ep[i].data.ptr;
if (source->fd != -1)
source->interface->dispatch(source, &ep[i]);
}
wl_event_loop_process_destroy_list(loop);
wl_event_loop_dispatch_idle(loop);
do {
n = post_dispatch_check(loop);
} while (n > 0);
return 0;
}
边栏推荐
- 2022 pole technology communication - the dispute over anmou technology is settled, and the cornerstone of the local semiconductor industry is more stable
- High performance computing framework for image processing
- Auto. JS learning note 9: basic methods such as using the script engine, starting the script file with the specified path, and closing
- Auto. JS learning note 4: after autojs is packaged, most Huawei and other big brand mobile phones cannot be installed? This problem can be solved by using the simulator to remotely sign and package in
- Code implementation of hash table based on linear detection
- JVM (V) Virtual machine class loading (parental delegation mechanism)
- There is always a negative line (upper shadow line) that will stop the advance of many armies, and there is always a positive line (lower shadow line) that will stop the rampant bombing of the air for
- Pandorabox uses firewall rules to define non internet time
- Combat tactics based on CEPH object storage
- C#入门系列(十二) -- 字符串
猜你喜欢

1268_ Implementation of FreeRTOS task context switching
![[DDS] ddsi-rtps specification](/img/fe/16b835e3e4a8ff71ab3dbc4b9c4d2a.jpg)
[DDS] ddsi-rtps specification

传输层协议 ——— TCP协议

JVM (VI) Virtual machine bytecode execution engine (with stack execution process and bytecode instruction table)

Theoretical explanation of hash table

How to implement Web3.0 and digital fashion?

Introduction to IOT

Implementation of fruit mall wholesale platform based on SSM

行业分析怎么做

C 语言仅凭自学能到什么高度?
随机推荐
JVM (III) Virtual machine performance monitoring & fault handling tool
Crazy temporary products: super low price, big scuffle and new hope
Jetpack architecture component learning (3) -- activity results API usage
Canal ha mode configuration
How to do industry analysis
GNU EFI development environment settings
【ParquetEncodingException: empty fields are illegal, the field should be ommited completely instead
优质好书助成长 猿辅导携四大出版社推荐“暑期好书”
Japanese economic foam and house price foam
2021-01-13
Introduction to applet
np.meshgrid()函数 以及 三维空间中的坐标位置生成 以及 numpy.repeat()函数介绍
C # getting started series (12) -- string
Auto. JS learning note 4: after autojs is packaged, most Huawei and other big brand mobile phones cannot be installed? This problem can be solved by using the simulator to remotely sign and package in
Code implementation of hash table based on linear detection
价值投资.
2021-02-12
Explanation of the principle of MySQL's leftmost matching principle
2021-02-22
JVM (V) Virtual machine class loading (parental delegation mechanism)