• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2010-2011 Intel Corporation
3  * Copyright © 2008-2011 Kristian Høgsberg
4  * Copyright © 2012-2018 Collabora, Ltd.
5  * Copyright © 2010-2011 Benjamin Franzke
6  * Copyright © 2013 Jason Ekstrand
7  * Copyright © 2017, 2018 General Electric Company
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice (including the
18  * next paragraph) shall be included in all copies or substantial
19  * portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  */
30 
31 #include "config.h"
32 
33 #include <unistd.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <dlfcn.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <sys/utsname.h>
40 #include <sys/stat.h>
41 #include <sys/wait.h>
42 #include <sys/socket.h>
43 #include <libinput.h>
44 #include <libevdev/libevdev.h>
45 #include <linux/input.h>
46 #include <sys/time.h>
47 #include <linux/limits.h>
48 #include <pthread.h>
49 
50 #include "weston.h"
51 #include <libweston/libweston.h>
52 #include "shared/os-compatibility.h"
53 #include "shared/helpers.h"
54 #include "shared/string-helpers.h"
55 #include "git-version.h"
56 #include <libweston/version.h>
57 #include "weston.h"
58 
59 #include <vsync_module_c.h> // OHOS vsync module
60 
61 #include <libweston/backend-drm.h>
62 #include <libweston/backend-headless.h>
63 #include <libweston/backend-hdi.h>
64 #include <libweston/backend-rdp.h>
65 #include <libweston/backend-fbdev.h>
66 #include <libweston/backend-x11.h>
67 #include <libweston/backend-wayland.h>
68 #include <libweston/windowed-output-api.h>
69 #include <libweston/weston-log.h>
70 #include "../remoting/remoting-plugin.h"
71 #include "../pipewire/pipewire-plugin.h"
72 
73 #include "libweston/trace.h"
74 DEFINE_LOG_LABEL("Weston");
75 
76 #define WINDOW_TITLE "Weston Compositor"
77 /* flight recorder size (in bytes) */
78 #define DEFAULT_FLIGHT_REC_SIZE (5 * 1024 * 1024)
79 
80 struct wet_output_config {
81 	int width;
82 	int height;
83 	int32_t scale;
84 	uint32_t transform;
85 };
86 
87 struct wet_compositor;
88 struct wet_layoutput;
89 
90 struct wet_head_tracker {
91 	struct wl_listener head_destroy_listener;
92 };
93 
94 /** User data for each weston_output */
95 struct wet_output {
96 	struct weston_output *output;
97 	struct wl_listener output_destroy_listener;
98 	struct wet_layoutput *layoutput;
99 	struct wl_list link;	/**< in wet_layoutput::output_list */
100 };
101 
102 #define MAX_CLONE_HEADS 16
103 
104 struct wet_head_array {
105 	struct weston_head *heads[MAX_CLONE_HEADS];	/**< heads to add */
106 	unsigned n;				/**< the number of heads */
107 };
108 
109 /** A layout output
110  *
111  * Contains wet_outputs that are all clones (independent CRTCs).
112  * Stores output layout information in the future.
113  */
114 struct wet_layoutput {
115 	struct wet_compositor *compositor;
116 	struct wl_list compositor_link;	/**< in wet_compositor::layoutput_list */
117 	struct wl_list output_list;	/**< wet_output::link */
118 	char *name;
119 	struct weston_config_section *section;
120 	struct wet_head_array add;	/**< tmp: heads to add as clones */
121 };
122 
123 struct wet_compositor {
124 	struct weston_compositor *compositor;
125 	struct weston_config *config;
126 	struct wet_output_config *parsed_options;
127 	bool drm_use_current_mode;
128 	struct wl_listener heads_changed_listener;
129 	int (*simple_output_configure)(struct weston_output *output);
130 	bool init_failed;
131 	struct wl_list layoutput_list;	/**< wet_layoutput::compositor_link */
132 };
133 
134 static FILE *weston_logfile = NULL;
135 // OHOS remove logger
136 //static struct weston_log_scope *log_scope;
137 //static struct weston_log_scope *protocol_scope;
138 static int cached_tm_mday = -1;
139 
140 // OHOS remove logger
141 //static char *
142 //weston_log_timestamp(char *buf, size_t len)
143 //{
144 //	struct timeval tv;
145 //	struct tm *brokendown_time;
146 //	char datestr[128];
147 //	char timestr[128];
148 //
149 //	gettimeofday(&tv, NULL);
150 //
151 //	brokendown_time = localtime(&tv.tv_sec);
152 //	if (brokendown_time == NULL) {
153 //		snprintf(buf, len, "%{public}s", "[(NULL)localtime] ");
154 //		return buf;
155 //	}
156 //
157 //	memset(datestr, 0, sizeof(datestr));
158 //	if (brokendown_time->tm_mday != cached_tm_mday) {
159 //		strftime(datestr, sizeof(datestr), "Date: %Y-%m-%d %Z\n",
160 //			 brokendown_time);
161 //		cached_tm_mday = brokendown_time->tm_mday;
162 //	}
163 //
164 //	strftime(timestr, sizeof(timestr), "%H:%M:%S", brokendown_time);
165 //	/* if datestr is empty it prints only timestr*/
166 //	snprintf(buf, len, "%{public}s[%{public}s.%03li]", datestr,
167 //		 timestr, (tv.tv_usec / 1000));
168 //
169 //	return buf;
170 //}
171 //
172 //static void
173 //custom_handler(const char *fmt, va_list arg)
174 //{
175 //	char timestr[512];
176 //
177 //	weston_log_scope_printf(log_scope, "%{public}s libwayland: ",
178 //				weston_log_timestamp(timestr,
179 //				sizeof(timestr)));
180 //	weston_log_scope_vprintf(log_scope, fmt, arg);
181 //}
182 //
183 //static bool
184 //weston_log_file_open(const char *filename)
185 //{
186 //	wl_log_set_handler_server(custom_handler);
187 //
188 //	if (filename != NULL) {
189 //		weston_logfile = fopen(filename, "a");
190 //		if (weston_logfile) {
191 //			os_fd_set_cloexec(fileno(weston_logfile));
192 //		} else {
193 //			fprintf(stderr, "Failed to open %{public}s: %{public}s\n", filename, strerror(errno));
194 //			return false;
195 //		}
196 //	}
197 //
198 //	if (weston_logfile == NULL)
199 //		weston_logfile = stderr;
200 //	else
201 //		setvbuf(weston_logfile, NULL, _IOLBF, 256);
202 //
203 //	return true;
204 //}
205 //
206 //static void
207 //weston_log_file_close(void)
208 //{
209 //	if ((weston_logfile != stderr) && (weston_logfile != NULL))
210 //		fclose(weston_logfile);
211 //	weston_logfile = stderr;
212 //}
213 //
214 //static int
215 //vlog(const char *fmt, va_list ap)
216 //{
217 //	const char *oom = "Out of memory";
218 //	char timestr[128];
219 //	int len = 0;
220 //	char *str;
221 //
222 //	if (weston_log_scope_is_enabled(log_scope)) {
223 //		int len_va;
224 //		char *log_timestamp = weston_log_timestamp(timestr,
225 //							   sizeof(timestr));
226 //		len_va = vasprintf(&str, fmt, ap);
227 //		if (len_va >= 0) {
228 //			len = weston_log_scope_printf(log_scope, "%{public}s %{public}s",
229 //						      log_timestamp, str);
230 //			free(str);
231 //		} else {
232 //			len = weston_log_scope_printf(log_scope, "%{public}s %{public}s",
233 //						      log_timestamp, oom);
234 //		}
235 //	}
236 //
237 //	return len;
238 //}
239 //
240 //static int
241 //vlog_continue(const char *fmt, va_list argp)
242 //{
243 //	return weston_log_scope_vprintf(log_scope, fmt, argp);
244 //}
245 //
246 //static const char *
247 //get_next_argument(const char *signature, char* type)
248 //{
249 //	for(; *signature; ++signature) {
250 //		switch(*signature) {
251 //		case 'i':
252 //		case 'u':
253 //		case 'f':
254 //		case 's':
255 //		case 'o':
256 //		case 'n':
257 //		case 'a':
258 //		case 'h':
259 //			*type = *signature;
260 //			return signature + 1;
261 //		}
262 //	}
263 //	*type = '\0';
264 //	return signature;
265 //}
266 //
267 //static void
268 //protocol_log_fn(void *user_data,
269 //		enum wl_protocol_logger_type direction,
270 //		const struct wl_protocol_logger_message *message)
271 //{
272 //	FILE *fp;
273 //	char *logstr;
274 //	size_t logsize;
275 //	char timestr[128];
276 //	struct wl_resource *res = message->resource;
277 //	const char *signature = message->message->signature;
278 //	int i;
279 //	char type;
280 //
281 //	if (!weston_log_scope_is_enabled(protocol_scope))
282 //		return;
283 //
284 //	fp = open_memstream(&logstr, &logsize);
285 //	if (!fp)
286 //		return;
287 //
288 //	weston_log_scope_timestamp(protocol_scope,
289 //			timestr, sizeof timestr);
290 //	fprintf(fp, "%{public}s ", timestr);
291 //	fprintf(fp, "client %p %{public}s ", wl_resource_get_client(res),
292 //		direction == WL_PROTOCOL_LOGGER_REQUEST ? "rq" : "ev");
293 //	fprintf(fp, "%{public}s@%u.%{public}s(",
294 //		wl_resource_get_class(res),
295 //		wl_resource_get_id(res),
296 //		message->message->name);
297 //
298 //	for (i = 0; i < message->arguments_count; i++) {
299 //		signature = get_next_argument(signature, &type);
300 //
301 //		if (i > 0)
302 //			fprintf(fp, ", ");
303 //
304 //		switch (type) {
305 //		case 'u':
306 //			fprintf(fp, "%u", message->arguments[i].u);
307 //			break;
308 //		case 'i':
309 //			fprintf(fp, "%d", message->arguments[i].i);
310 //			break;
311 //		case 'f':
312 //			fprintf(fp, "%f",
313 //				wl_fixed_to_double(message->arguments[i].f));
314 //			break;
315 //		case 's':
316 //			fprintf(fp, "\"%{public}s\"", message->arguments[i].s);
317 //			break;
318 //		case 'o':
319 //			if (message->arguments[i].o) {
320 //				struct wl_resource* resource;
321 //				resource = (struct wl_resource*) message->arguments[i].o;
322 //				fprintf(fp, "%{public}s@%u",
323 //					wl_resource_get_class(resource),
324 //					wl_resource_get_id(resource));
325 //			}
326 //			else
327 //				fprintf(fp, "nil");
328 //			break;
329 //		case 'n':
330 //			fprintf(fp, "new id %{public}s@",
331 //				(message->message->types[i]) ?
332 //				message->message->types[i]->name :
333 //				"[unknown]");
334 //			if (message->arguments[i].n != 0)
335 //				fprintf(fp, "%u", message->arguments[i].n);
336 //			else
337 //				fprintf(fp, "nil");
338 //			break;
339 //		case 'a':
340 //			fprintf(fp, "array");
341 //			break;
342 //		case 'h':
343 //			fprintf(fp, "fd %d", message->arguments[i].h);
344 //			break;
345 //		}
346 //	}
347 //
348 //	fprintf(fp, ")\n");
349 //
350 //	if (fclose(fp) == 0)
351 //		weston_log_scope_write(protocol_scope, logstr, logsize);
352 //
353 //	free(logstr);
354 //}
355 
356 static struct wl_list child_process_list;
357 static struct weston_compositor *segv_compositor;
358 
359 static int
sigchld_handler(int signal_number,void * data)360 sigchld_handler(int signal_number, void *data)
361 {
362 	struct weston_process *p;
363 	int status;
364 	pid_t pid;
365 
366 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
367 		wl_list_for_each(p, &child_process_list, link) {
368 			if (p->pid == pid)
369 				break;
370 		}
371 
372 		if (&p->link == &child_process_list) {
373 			weston_log("unknown child process exited\n");
374 			continue;
375 		}
376 
377 		wl_list_remove(&p->link);
378 		p->cleanup(p, status);
379 	}
380 
381 	if (pid < 0 && errno != ECHILD)
382 		weston_log("waitpid error %{public}s\n", strerror(errno));
383 
384 	return 1;
385 }
386 
387 static void
child_client_exec(int sockfd,const char * path)388 child_client_exec(int sockfd, const char *path)
389 {
390 	int clientfd;
391 	char s[32];
392 	sigset_t allsigs;
393 
394 	/* do not give our signal mask to the new process */
395 	sigfillset(&allsigs);
396 	sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
397 
398 	/* Launch clients as the user. Do not launch clients with wrong euid. */
399 	if (seteuid(getuid()) == -1) {
400 		weston_log("compositor: failed seteuid\n");
401 		return;
402 	}
403 
404 	/* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
405 	 * non-CLOEXEC fd to pass through exec. */
406 	clientfd = dup(sockfd);
407 	if (clientfd == -1) {
408 		weston_log("compositor: dup failed: %{public}s\n", strerror(errno));
409 		return;
410 	}
411 
412 	snprintf(s, sizeof s, "%d", clientfd);
413 	setenv("WAYLAND_SOCKET", s, 1);
414 
415 	if (execl(path, path, NULL) < 0)
416 		weston_log("compositor: executing '%{public}s' failed: %{public}s\n",
417 			   path, strerror(errno));
418 }
419 
420 WL_EXPORT struct wl_client *
weston_client_launch(struct weston_compositor * compositor,struct weston_process * proc,const char * path,weston_process_cleanup_func_t cleanup)421 weston_client_launch(struct weston_compositor *compositor,
422 		     struct weston_process *proc,
423 		     const char *path,
424 		     weston_process_cleanup_func_t cleanup)
425 {
426 	int sv[2];
427 	pid_t pid;
428 	struct wl_client *client;
429 
430 	weston_log("launching '%{public}s'\n", path);
431 
432 	if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
433 		weston_log("weston_client_launch: "
434 			   "socketpair failed while launching '%{public}s': %{public}s\n",
435 			   path, strerror(errno));
436 		return NULL;
437 	}
438 
439 	pid = fork();
440 	if (pid == -1) {
441 		close(sv[0]);
442 		close(sv[1]);
443 		weston_log("weston_client_launch: "
444 			   "fork failed while launching '%{public}s': %{public}s\n", path,
445 			   strerror(errno));
446 		return NULL;
447 	}
448 
449 	if (pid == 0) {
450 		child_client_exec(sv[1], path);
451 		_exit(-1);
452 	}
453 
454 	close(sv[1]);
455 
456 	client = wl_client_create(compositor->wl_display, sv[0]);
457 	if (!client) {
458 		close(sv[0]);
459 		weston_log("weston_client_launch: "
460 			"wl_client_create failed while launching '%{public}s'.\n",
461 			path);
462 		return NULL;
463 	}
464 
465 	proc->pid = pid;
466 	proc->cleanup = cleanup;
467 	weston_watch_process(proc);
468 
469 	return client;
470 }
471 
472 WL_EXPORT void
weston_watch_process(struct weston_process * process)473 weston_watch_process(struct weston_process *process)
474 {
475 	wl_list_insert(&child_process_list, &process->link);
476 }
477 
478 struct process_info {
479 	struct weston_process proc;
480 	char *path;
481 };
482 
483 static void
process_handle_sigchld(struct weston_process * process,int status)484 process_handle_sigchld(struct weston_process *process, int status)
485 {
486 	struct process_info *pinfo =
487 		container_of(process, struct process_info, proc);
488 
489 	/*
490 	 * There are no guarantees whether this runs before or after
491 	 * the wl_client destructor.
492 	 */
493 
494 	if (WIFEXITED(status)) {
495 		weston_log("%{public}s exited with status %d\n", pinfo->path,
496 			   WEXITSTATUS(status));
497 	} else if (WIFSIGNALED(status)) {
498 		weston_log("%{public}s died on signal %d\n", pinfo->path,
499 			   WTERMSIG(status));
500 	} else {
501 		weston_log("%{public}s disappeared\n", pinfo->path);
502 	}
503 
504 	free(pinfo->path);
505 	free(pinfo);
506 }
507 
508 WL_EXPORT struct wl_client *
weston_client_start(struct weston_compositor * compositor,const char * path)509 weston_client_start(struct weston_compositor *compositor, const char *path)
510 {
511 	struct process_info *pinfo;
512 	struct wl_client *client;
513 
514 	pinfo = zalloc(sizeof *pinfo);
515 	if (!pinfo)
516 		return NULL;
517 
518 	pinfo->path = strdup(path);
519 	if (!pinfo->path)
520 		goto out_free;
521 
522 	client = weston_client_launch(compositor, &pinfo->proc, path,
523 				      process_handle_sigchld);
524 	if (!client)
525 		goto out_str;
526 
527 	return client;
528 
529 out_str:
530 	free(pinfo->path);
531 
532 out_free:
533 	free(pinfo);
534 
535 	return NULL;
536 }
537 
538 static void
log_uname(void)539 log_uname(void)
540 {
541 	struct utsname usys;
542 
543 	uname(&usys);
544 
545 	weston_log("OS: %{public}s, %{public}s, %{public}s, %{public}s\n", usys.sysname, usys.release,
546 						usys.version, usys.machine);
547 }
548 
549 static struct wet_compositor *
to_wet_compositor(struct weston_compositor * compositor)550 to_wet_compositor(struct weston_compositor *compositor)
551 {
552 	return weston_compositor_get_user_data(compositor);
553 }
554 
555 static struct wet_output_config *
wet_init_parsed_options(struct weston_compositor * ec)556 wet_init_parsed_options(struct weston_compositor *ec)
557 {
558 	struct wet_compositor *compositor = to_wet_compositor(ec);
559 	struct wet_output_config *config;
560 
561 	config = zalloc(sizeof *config);
562 
563 	if (!config) {
564 		perror("out of memory");
565 		return NULL;
566 	}
567 
568 	config->width = 0;
569 	config->height = 0;
570 	config->scale = 0;
571 	config->transform = UINT32_MAX;
572 
573 	compositor->parsed_options = config;
574 
575 	return config;
576 }
577 
578 WL_EXPORT struct weston_config *
wet_get_config(struct weston_compositor * ec)579 wet_get_config(struct weston_compositor *ec)
580 {
581 	struct wet_compositor *compositor = to_wet_compositor(ec);
582 
583 	return compositor->config;
584 }
585 
586 static const char xdg_error_message[] =
587 	"fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
588 
589 static const char xdg_wrong_message[] =
590 	"fatal: environment variable XDG_RUNTIME_DIR\n"
591 	"is set to \"%{public}s\", which is not a directory.\n";
592 
593 static const char xdg_wrong_mode_message[] =
594 	"warning: XDG_RUNTIME_DIR \"%{public}s\" is not configured\n"
595 	"correctly.  Unix access mode must be 0700 (current mode is %o),\n"
596 	"and must be owned by the user (current owner is UID %d).\n";
597 
598 static const char xdg_detail_message[] =
599 	"Refer to your distribution on how to get it, or\n"
600 	"http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
601 	"on how to implement it.\n";
602 
603 static void
verify_xdg_runtime_dir(void)604 verify_xdg_runtime_dir(void)
605 {
606 	char *dir = getenv("XDG_RUNTIME_DIR");
607 	struct stat s;
608 
609 	if (!dir) {
610 		weston_log(xdg_error_message);
611 		weston_log_continue(xdg_detail_message);
612 		exit(EXIT_FAILURE);
613 	}
614 
615 	if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
616 		weston_log(xdg_wrong_message, dir);
617 		weston_log_continue(xdg_detail_message);
618 		exit(EXIT_FAILURE);
619 	}
620 
621 	if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
622 		weston_log(xdg_wrong_mode_message,
623 			   dir, s.st_mode & 0777, s.st_uid);
624 		weston_log_continue(xdg_detail_message);
625 	}
626 }
627 
628 static int
usage(int error_code)629 usage(int error_code)
630 {
631 	FILE *out = error_code == EXIT_SUCCESS ? stdout : stderr;
632 
633 	fprintf(out,
634 		"Usage: weston [OPTIONS]\n\n"
635 		"This is weston version " VERSION ", the Wayland reference compositor.\n"
636 		"Weston supports multiple backends, and depending on which backend is in use\n"
637 		"different options will be accepted.\n\n"
638 
639 
640 		"Core options:\n\n"
641 		"  --version\t\tPrint weston version\n"
642 		"  -B, --backend=MODULE\tBackend module, one of\n"
643 #if defined(BUILD_DRM_COMPOSITOR)
644 			"\t\t\t\tdrm-backend.so\n"
645 #endif
646 #if defined(BUILD_FBDEV_COMPOSITOR)
647 			"\t\t\t\tfbdev-backend.so\n"
648 #endif
649 #if defined(BUILD_HEADLESS_COMPOSITOR)
650 			"\t\t\t\theadless-backend.so\n"
651 #endif
652 #if defined(BUILD_RDP_COMPOSITOR)
653 			"\t\t\t\trdp-backend.so\n"
654 #endif
655 #if defined(BUILD_WAYLAND_COMPOSITOR)
656 			"\t\t\t\twayland-backend.so\n"
657 #endif
658 #if defined(BUILD_X11_COMPOSITOR)
659 			"\t\t\t\tx11-backend.so\n"
660 #endif
661 		"  --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
662 		"  -S, --socket=NAME\tName of socket to listen on\n"
663 		"  -i, --idle-time=SECS\tIdle time in seconds\n"
664 #if defined(BUILD_XWAYLAND)
665 		"  --xwayland\t\tLoad the xwayland module\n"
666 #endif
667 		"  --modules\t\tLoad the comma-separated list of modules\n"
668 		"  --log=FILE\t\tLog to the given file\n"
669 		"  -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
670 		"  --no-config\t\tDo not read weston.ini\n"
671 		"  --wait-for-debugger\tRaise SIGSTOP on start-up\n"
672 		"  --debug\t\tEnable debug extension\n"
673 		"  -l, --logger-scopes=SCOPE\n\t\t\tSpecify log scopes to "
674 			"subscribe to.\n\t\t\tCan specify multiple scopes, "
675 			"each followed by comma\n"
676 		"  -f, --flight-rec-scopes=SCOPE\n\t\t\tSpecify log scopes to "
677 			"subscribe to.\n\t\t\tCan specify multiple scopes, "
678 			"each followed by comma\n"
679 		"  -h, --help\t\tThis help message\n\n");
680 
681 #if defined(BUILD_DRM_COMPOSITOR)
682 	fprintf(out,
683 		"Options for drm-backend.so:\n\n"
684 		"  --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
685 		"  --tty=TTY\t\tThe tty to use\n"
686 		"  --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
687 		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
688 		"  --current-mode\tPrefer current KMS mode over EDID preferred mode\n"
689 		"  --continue-without-input\tAllow the compositor to start without input devices\n\n");
690 #endif
691 
692 #if defined(BUILD_FBDEV_COMPOSITOR)
693 	fprintf(out,
694 		"Options for fbdev-backend.so:\n\n"
695 		"  --tty=TTY\t\tThe tty to use\n"
696 		"  --device=DEVICE\tThe framebuffer device to use\n"
697 		"  --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
698 		"\n");
699 #endif
700 
701 #if defined(BUILD_HEADLESS_COMPOSITOR)
702 	fprintf(out,
703 		"Options for headless-backend.so:\n\n"
704 		"  --width=WIDTH\t\tWidth of memory surface\n"
705 		"  --height=HEIGHT\tHeight of memory surface\n"
706 		"  --scale=SCALE\t\tScale factor of output\n"
707 		"  --transform=TR\tThe output transformation, TR is one of:\n"
708 		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
709 		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n"
710 		"  --use-gl\t\tUse the GL renderer (default: no rendering)\n"
711 		"  --no-outputs\t\tDo not create any virtual outputs\n"
712 		"\n");
713 #endif
714 
715 #if defined(BUILD_RDP_COMPOSITOR)
716 	fprintf(out,
717 		"Options for rdp-backend.so:\n\n"
718 		"  --width=WIDTH\t\tWidth of desktop\n"
719 		"  --height=HEIGHT\tHeight of desktop\n"
720 		"  --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
721 		"  --address=ADDR\tThe address to bind\n"
722 		"  --port=PORT\t\tThe port to listen on\n"
723 		"  --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
724 		"  --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
725 		"  --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
726 		"  --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
727 		"\n");
728 #endif
729 
730 #if defined(BUILD_WAYLAND_COMPOSITOR)
731 	fprintf(out,
732 		"Options for wayland-backend.so:\n\n"
733 		"  --width=WIDTH\t\tWidth of Wayland surface\n"
734 		"  --height=HEIGHT\tHeight of Wayland surface\n"
735 		"  --scale=SCALE\t\tScale factor of output\n"
736 		"  --fullscreen\t\tRun in fullscreen mode\n"
737 		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
738 		"  --output-count=COUNT\tCreate multiple outputs\n"
739 		"  --sprawl\t\tCreate one fullscreen output for every parent output\n"
740 		"  --display=DISPLAY\tWayland display to connect to\n\n");
741 #endif
742 
743 #if defined(BUILD_X11_COMPOSITOR)
744 	fprintf(out,
745 		"Options for x11-backend.so:\n\n"
746 		"  --width=WIDTH\t\tWidth of X window\n"
747 		"  --height=HEIGHT\tHeight of X window\n"
748 		"  --scale=SCALE\t\tScale factor of output\n"
749 		"  --fullscreen\t\tRun in fullscreen mode\n"
750 		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
751 		"  --output-count=COUNT\tCreate multiple outputs\n"
752 		"  --no-input\t\tDont create input devices\n\n");
753 #endif
754 
755 	exit(error_code);
756 }
757 
on_term_signal(int signal_number,void * data)758 static int on_term_signal(int signal_number, void *data)
759 {
760 	struct wl_display *display = data;
761 
762 	weston_log("caught signal %d\n", signal_number);
763 	wl_display_terminate(display);
764 
765 	return 1;
766 }
767 
768 static const char *
clock_name(clockid_t clk_id)769 clock_name(clockid_t clk_id)
770 {
771 	static const char *names[] = {
772 		[CLOCK_REALTIME] =		"CLOCK_REALTIME",
773 		[CLOCK_MONOTONIC] =		"CLOCK_MONOTONIC",
774 		[CLOCK_MONOTONIC_RAW] =		"CLOCK_MONOTONIC_RAW",
775 		[CLOCK_REALTIME_COARSE] =	"CLOCK_REALTIME_COARSE",
776 		[CLOCK_MONOTONIC_COARSE] =	"CLOCK_MONOTONIC_COARSE",
777 #ifdef CLOCK_BOOTTIME
778 		[CLOCK_BOOTTIME] =		"CLOCK_BOOTTIME",
779 #endif
780 	};
781 
782 	if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
783 		return "unknown";
784 
785 	return names[clk_id];
786 }
787 
788 static const struct {
789 	uint32_t bit; /* enum weston_capability */
790 	const char *desc;
791 } capability_strings[] = {
792 	{ WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
793 	{ WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
794 };
795 
796 static void
weston_compositor_log_capabilities(struct weston_compositor * compositor)797 weston_compositor_log_capabilities(struct weston_compositor *compositor)
798 {
799 	unsigned i;
800 	int yes;
801 	struct timespec res;
802 
803 	weston_log("Compositor capabilities:\n");
804 	for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
805 		yes = compositor->capabilities & capability_strings[i].bit;
806 		weston_log_continue(STAMP_SPACE "%{public}s %{public}s\n",
807 				    capability_strings[i].desc,
808 				    yes ? "yes" : "no");
809 	}
810 
811 	weston_log_continue(STAMP_SPACE "presentation clock: %{public}s, id %d\n",
812 			    clock_name(compositor->presentation_clock),
813 			    compositor->presentation_clock);
814 
815 	if (clock_getres(compositor->presentation_clock, &res) == 0)
816 		weston_log_continue(STAMP_SPACE
817 				"presentation clock resolution: %d.%09ld s\n",
818 				(int)res.tv_sec, res.tv_nsec);
819 	else
820 		weston_log_continue(STAMP_SPACE
821 				"presentation clock resolution: N/A\n");
822 }
823 
824 static void
handle_primary_client_destroyed(struct wl_listener * listener,void * data)825 handle_primary_client_destroyed(struct wl_listener *listener, void *data)
826 {
827 	struct wl_client *client = data;
828 
829 	weston_log("Primary client died.  Closing...\n");
830 
831 	wl_display_terminate(wl_client_get_display(client));
832 }
833 
834 static int
weston_create_listening_socket(struct wl_display * display,const char * socket_name)835 weston_create_listening_socket(struct wl_display *display, const char *socket_name)
836 {
837 	if (socket_name) {
838 		if (wl_display_add_socket(display, socket_name)) {
839 			weston_log("fatal: failed to add socket: %{public}s\n",
840 				   strerror(errno));
841 			return -1;
842 		}
843 	} else {
844 		socket_name = wl_display_add_socket_auto(display);
845 		if (!socket_name) {
846 			weston_log("fatal: failed to add socket: %{public}s\n",
847 				   strerror(errno));
848 			return -1;
849 		}
850 	}
851 
852 	setenv("WAYLAND_DISPLAY", socket_name, 1);
853 
854 	return 0;
855 }
856 
857 WL_EXPORT void *
wet_load_module_entrypoint(const char * name,const char * entrypoint)858 wet_load_module_entrypoint(const char *name, const char *entrypoint)
859 {
860 	char path[PATH_MAX];
861 	void *module, *init;
862 	size_t len;
863 
864 	if (name == NULL)
865 		return NULL;
866 
867 	if (name[0] != '/') {
868 		len = weston_module_path_from_env(name, path, sizeof path);
869 		if (len == 0)
870 			len = snprintf(path, sizeof path, "%s/%s", MODULEDIR,
871 				       name);
872 	} else {
873 		len = snprintf(path, sizeof path, "%s", name);
874 	}
875 
876 	/* snprintf returns the length of the string it would've written,
877 	 * _excluding_ the NUL byte. So even being equal to the size of
878 	 * our buffer is an error here. */
879 	if (len >= sizeof path)
880 		return NULL;
881 
882 	module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
883 	if (module) {
884 		weston_log("Module '%{public}s' already loaded\n", path);
885 	} else {
886 		weston_log("Loading module '%{public}s'\n", path);
887 		module = dlopen(path, RTLD_NOW);
888 		if (!module) {
889 			weston_log("Failed to load module: %{public}s\n", dlerror());
890 			return NULL;
891 		}
892 	}
893 
894 	init = dlsym(module, entrypoint);
895 	if (!init) {
896 		weston_log("Failed to lookup init function: %{public}s\n", dlerror());
897 		dlclose(module);
898 		return NULL;
899 	}
900 
901 	return init;
902 }
903 
904 WL_EXPORT int
wet_load_module(struct weston_compositor * compositor,const char * name,int * argc,char * argv[])905 wet_load_module(struct weston_compositor *compositor,
906 	        const char *name, int *argc, char *argv[])
907 {
908 	int (*module_init)(struct weston_compositor *ec,
909 			   int *argc, char *argv[]);
910 
911 	module_init = wet_load_module_entrypoint(name, "wet_module_init");
912 	if (!module_init)
913 		return -1;
914 	if (module_init(compositor, argc, argv) < 0)
915 		return -1;
916 	return 0;
917 }
918 
919 static int
wet_load_shell(struct weston_compositor * compositor,const char * name,int * argc,char * argv[])920 wet_load_shell(struct weston_compositor *compositor,
921 	       const char *name, int *argc, char *argv[])
922 {
923 	int (*shell_init)(struct weston_compositor *ec,
924 			  int *argc, char *argv[]);
925 
926 	shell_init = wet_load_module_entrypoint(name, "wet_shell_init");
927 	if (!shell_init)
928 		return -1;
929 	if (shell_init(compositor, argc, argv) < 0)
930 		return -1;
931 	return 0;
932 }
933 
934 static char *
wet_get_binary_path(const char * name,const char * dir)935 wet_get_binary_path(const char *name, const char *dir)
936 {
937 	char path[PATH_MAX];
938 	size_t len;
939 
940 	len = weston_module_path_from_env(name, path, sizeof path);
941 	if (len > 0)
942 		return strdup(path);
943 
944 	len = snprintf(path, sizeof path, "%s/%s", dir, name);
945 	if (len >= sizeof path)
946 		return NULL;
947 
948 	return strdup(path);
949 }
950 
951 WL_EXPORT char *
wet_get_libexec_path(const char * name)952 wet_get_libexec_path(const char *name)
953 {
954 	return wet_get_binary_path(name, LIBEXECDIR);
955 }
956 
957 WL_EXPORT char *
wet_get_bindir_path(const char * name)958 wet_get_bindir_path(const char *name)
959 {
960 	return wet_get_binary_path(name, BINDIR);
961 }
962 
963 static int
load_modules(struct weston_compositor * ec,const char * modules,int * argc,char * argv[],bool * xwayland)964 load_modules(struct weston_compositor *ec, const char *modules,
965 	     int *argc, char *argv[], bool *xwayland)
966 {
967 	const char *p, *end;
968 	char buffer[256];
969 
970 	if (modules == NULL)
971 		return 0;
972 
973 	p = modules;
974 	while (*p) {
975 		end = strchrnul(p, ',');
976 		snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
977 
978 		if (strstr(buffer, "xwayland.so")) {
979 			weston_log("Old Xwayland module loading detected: "
980 				   "Please use --xwayland command line option "
981 				   "or set xwayland=true in the [core] section "
982 				   "in weston.ini\n");
983 			*xwayland = true;
984 		} else {
985 			if (wet_load_module(ec, buffer, argc, argv) < 0)
986 				return -1;
987 		}
988 
989 		p = end;
990 		while (*p == ',')
991 			p++;
992 	}
993 
994 	return 0;
995 }
996 
997 static int
save_touch_device_calibration(struct weston_compositor * compositor,struct weston_touch_device * device,const struct weston_touch_device_matrix * calibration)998 save_touch_device_calibration(struct weston_compositor *compositor,
999 			      struct weston_touch_device *device,
1000 			      const struct weston_touch_device_matrix *calibration)
1001 {
1002 	struct weston_config_section *s;
1003 	struct weston_config *config = wet_get_config(compositor);
1004 	char *helper = NULL;
1005 	char *helper_cmd = NULL;
1006 	int ret = -1;
1007 	int status;
1008 	const float *m = calibration->m;
1009 
1010 	s = weston_config_get_section(config,
1011 				      "libinput", NULL, NULL);
1012 
1013 	weston_config_section_get_string(s, "calibration_helper",
1014 					 &helper, NULL);
1015 
1016 	if (!helper || strlen(helper) == 0) {
1017 		ret = 0;
1018 		goto out;
1019 	}
1020 
1021 	if (asprintf(&helper_cmd, "\"%s\" '%s' %f %f %f %f %f %f",
1022 		     helper, device->syspath,
1023 		     m[0], m[1], m[2],
1024 		     m[3], m[4], m[5]) < 0)
1025 		goto out;
1026 
1027 	status = system(helper_cmd);
1028 	free(helper_cmd);
1029 
1030 	if (status < 0) {
1031 		weston_log("Error: failed to run calibration helper '%{public}s'.\n",
1032 			   helper);
1033 		goto out;
1034 	}
1035 
1036 	if (!WIFEXITED(status)) {
1037 		weston_log("Error: calibration helper '%{public}s' possibly killed.\n",
1038 			   helper);
1039 		goto out;
1040 	}
1041 
1042 	if (WEXITSTATUS(status) == 0) {
1043 		ret = 0;
1044 	} else {
1045 		weston_log("Calibration helper '%{public}s' exited with status %d.\n",
1046 			   helper, WEXITSTATUS(status));
1047 	}
1048 
1049 out:
1050 	free(helper);
1051 
1052 	return ret;
1053 }
1054 
1055 static int
weston_compositor_init_config(struct weston_compositor * ec,struct weston_config * config)1056 weston_compositor_init_config(struct weston_compositor *ec,
1057 			      struct weston_config *config)
1058 {
1059 	struct xkb_rule_names xkb_names;
1060 	struct weston_config_section *s;
1061 	int repaint_msec;
1062 	bool cal;
1063 
1064 	/* weston.ini [keyboard] */
1065 	s = weston_config_get_section(config, "keyboard", NULL, NULL);
1066 	weston_config_section_get_string(s, "keymap_rules",
1067 					 (char **) &xkb_names.rules, NULL);
1068 	weston_config_section_get_string(s, "keymap_model",
1069 					 (char **) &xkb_names.model, NULL);
1070 	weston_config_section_get_string(s, "keymap_layout",
1071 					 (char **) &xkb_names.layout, NULL);
1072 	weston_config_section_get_string(s, "keymap_variant",
1073 					 (char **) &xkb_names.variant, NULL);
1074 	weston_config_section_get_string(s, "keymap_options",
1075 					 (char **) &xkb_names.options, NULL);
1076 
1077 	if (weston_compositor_set_xkb_rule_names(ec, &xkb_names) < 0)
1078 		return -1;
1079 
1080 	weston_config_section_get_int(s, "repeat-rate",
1081 				      &ec->kb_repeat_rate, 40);
1082 	weston_config_section_get_int(s, "repeat-delay",
1083 				      &ec->kb_repeat_delay, 400);
1084 
1085 	weston_config_section_get_bool(s, "vt-switching",
1086 				       &ec->vt_switching, true);
1087 
1088 	/* weston.ini [core] */
1089 	s = weston_config_get_section(config, "core", NULL, NULL);
1090 	weston_config_section_get_int(s, "repaint-window", &repaint_msec,
1091 				      ec->repaint_msec);
1092 	if (repaint_msec < -10 || repaint_msec > 1000) {
1093 		weston_log("Invalid repaint_window value in config: %d\n",
1094 			   repaint_msec);
1095 	} else {
1096 		ec->repaint_msec = repaint_msec;
1097 	}
1098 	weston_log("Output repaint window is %d ms maximum.\n",
1099 		   ec->repaint_msec);
1100 
1101 	/* weston.ini [libinput] */
1102 	s = weston_config_get_section(config, "libinput", NULL, NULL);
1103 	weston_config_section_get_bool(s, "touchscreen_calibrator", &cal, 0);
1104 	if (cal)
1105 		weston_compositor_enable_touch_calibrator(ec,
1106 						save_touch_device_calibration);
1107 
1108 	return 0;
1109 }
1110 
1111 static char *
weston_choose_default_backend(void)1112 weston_choose_default_backend(void)
1113 {
1114 	char *backend = NULL;
1115 
1116 	if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
1117 		backend = strdup("wayland-backend.so");
1118 	else if (getenv("DISPLAY"))
1119 		backend = strdup("x11-backend.so");
1120 	else
1121 		backend = strdup(WESTON_NATIVE_BACKEND);
1122 
1123 	return backend;
1124 }
1125 
1126 static const struct { const char *name; uint32_t token; } transforms[] = {
1127 	{ "normal",             WL_OUTPUT_TRANSFORM_NORMAL },
1128 	{ "rotate-90",          WL_OUTPUT_TRANSFORM_90 },
1129 	{ "rotate-180",         WL_OUTPUT_TRANSFORM_180 },
1130 	{ "rotate-270",         WL_OUTPUT_TRANSFORM_270 },
1131 	{ "flipped",            WL_OUTPUT_TRANSFORM_FLIPPED },
1132 	{ "flipped-rotate-90",  WL_OUTPUT_TRANSFORM_FLIPPED_90 },
1133 	{ "flipped-rotate-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
1134 	{ "flipped-rotate-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
1135 };
1136 
1137 WL_EXPORT int
weston_parse_transform(const char * transform,uint32_t * out)1138 weston_parse_transform(const char *transform, uint32_t *out)
1139 {
1140 	unsigned int i;
1141 
1142 	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
1143 		if (strcmp(transforms[i].name, transform) == 0) {
1144 			*out = transforms[i].token;
1145 			return 0;
1146 		}
1147 
1148 	*out = WL_OUTPUT_TRANSFORM_NORMAL;
1149 	return -1;
1150 }
1151 
1152 WL_EXPORT const char *
weston_transform_to_string(uint32_t output_transform)1153 weston_transform_to_string(uint32_t output_transform)
1154 {
1155 	unsigned int i;
1156 
1157 	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
1158 		if (transforms[i].token == output_transform)
1159 			return transforms[i].name;
1160 
1161 	return "<illegal value>";
1162 }
1163 
1164 static int
load_configuration(struct weston_config ** config,int32_t noconfig,const char * config_file)1165 load_configuration(struct weston_config **config, int32_t noconfig,
1166 		   const char *config_file)
1167 {
1168 	const char *file = "weston.ini";
1169 	const char *full_path;
1170 
1171 	*config = NULL;
1172 
1173 	if (config_file)
1174 		file = config_file;
1175 
1176 	if (noconfig == 0)
1177 		*config = weston_config_parse(file);
1178 
1179 	if (*config) {
1180 		full_path = weston_config_get_full_path(*config);
1181 
1182 		weston_log("Using config file '%{public}s'\n", full_path);
1183 		setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
1184 
1185 		return 0;
1186 	}
1187 
1188 	if (config_file && noconfig == 0) {
1189 		weston_log("fatal: error opening or reading config file"
1190 			   " '%{public}s'.\n", config_file);
1191 
1192 		return -1;
1193 	}
1194 
1195 	weston_log("Starting with no config file.\n");
1196 	setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
1197 
1198 	return 0;
1199 }
1200 
1201 static void
handle_exit(struct weston_compositor * c)1202 handle_exit(struct weston_compositor *c)
1203 {
1204 	wl_display_terminate(c->wl_display);
1205 }
1206 
1207 static void
wet_output_set_scale(struct weston_output * output,struct weston_config_section * section,int32_t default_scale,int32_t parsed_scale)1208 wet_output_set_scale(struct weston_output *output,
1209 		     struct weston_config_section *section,
1210 		     int32_t default_scale,
1211 		     int32_t parsed_scale)
1212 {
1213 	int32_t scale = default_scale;
1214 
1215 	if (section)
1216 		weston_config_section_get_int(section, "scale", &scale, default_scale);
1217 
1218 	if (parsed_scale)
1219 		scale = parsed_scale;
1220 
1221 	weston_output_set_scale(output, scale);
1222 }
1223 
1224 /* UINT32_MAX is treated as invalid because 0 is a valid
1225  * enumeration value and the parameter is unsigned
1226  */
1227 static int
wet_output_set_transform(struct weston_output * output,struct weston_config_section * section,uint32_t default_transform,uint32_t parsed_transform)1228 wet_output_set_transform(struct weston_output *output,
1229 			 struct weston_config_section *section,
1230 			 uint32_t default_transform,
1231 			 uint32_t parsed_transform)
1232 {
1233 	char *t = NULL;
1234 	uint32_t transform = default_transform;
1235 
1236 	if (section) {
1237 		weston_config_section_get_string(section,
1238 						 "transform", &t, NULL);
1239 	}
1240 
1241 	if (t) {
1242 		if (weston_parse_transform(t, &transform) < 0) {
1243 			weston_log("Invalid transform \"%{public}s\" for output %{public}s\n",
1244 				   t, output->name);
1245 			return -1;
1246 		}
1247 		free(t);
1248 	}
1249 
1250 	if (parsed_transform != UINT32_MAX)
1251 		transform = parsed_transform;
1252 
1253 	weston_output_set_transform(output, transform);
1254 
1255 	return 0;
1256 }
1257 
1258 static void
allow_content_protection(struct weston_output * output,struct weston_config_section * section)1259 allow_content_protection(struct weston_output *output,
1260 			struct weston_config_section *section)
1261 {
1262 	bool allow_hdcp = true;
1263 
1264 	if (section)
1265 		weston_config_section_get_bool(section, "allow_hdcp",
1266 					       &allow_hdcp, true);
1267 
1268 	weston_output_allow_protection(output, allow_hdcp);
1269 }
1270 
1271 static int
wet_configure_windowed_output_from_config(struct weston_output * output,struct wet_output_config * defaults)1272 wet_configure_windowed_output_from_config(struct weston_output *output,
1273 					  struct wet_output_config *defaults)
1274 {
1275     LOG_ENTER();
1276 	const struct weston_windowed_output_api *api =
1277 		weston_windowed_output_get_api(output->compositor);
1278 
1279 	struct weston_config *wc = wet_get_config(output->compositor);
1280 	struct weston_config_section *section = NULL;
1281 	struct wet_compositor *compositor = to_wet_compositor(output->compositor);
1282 	struct wet_output_config *parsed_options = compositor->parsed_options;
1283 	int width = defaults->width;
1284 	int height = defaults->height;
1285 
1286 	assert(parsed_options);
1287 
1288 	if (!api) {
1289 		weston_log("Cannot use weston_windowed_output_api.\n");
1290         LOG_EXIT();
1291 		return -1;
1292 	}
1293 
1294 	section = weston_config_get_section(wc, "output", "name", output->name);
1295 
1296 	if (section) {
1297 		char *mode;
1298 
1299 		weston_config_section_get_string(section, "mode", &mode, NULL);
1300 		if (!mode || sscanf(mode, "%dx%d", &width,
1301 				    &height) != 2) {
1302 			weston_log("Invalid mode for output %{public}s. Using defaults.\n",
1303 				   output->name);
1304 			width = defaults->width;
1305 			height = defaults->height;
1306 		}
1307 		free(mode);
1308 	}
1309 
1310 	allow_content_protection(output, section);
1311 
1312 	if (parsed_options->width)
1313 		width = parsed_options->width;
1314 
1315 	if (parsed_options->height)
1316 		height = parsed_options->height;
1317 
1318 	wet_output_set_scale(output, section, defaults->scale, parsed_options->scale);
1319 	if (wet_output_set_transform(output, section, defaults->transform,
1320 				     parsed_options->transform) < 0) {
1321         LOG_EXIT();
1322 		return -1;
1323 	}
1324 
1325 	if (api->output_set_size(output, width, height) < 0) {
1326 		weston_log("Cannot configure output \"%{public}s\" using weston_windowed_output_api.\n",
1327 			   output->name);
1328 		return -1;
1329 	}
1330 
1331     LOG_EXIT();
1332 	return 0;
1333 }
1334 
1335 static int
count_remaining_heads(struct weston_output * output,struct weston_head * to_go)1336 count_remaining_heads(struct weston_output *output, struct weston_head *to_go)
1337 {
1338 	struct weston_head *iter = NULL;
1339 	int n = 0;
1340 
1341 	while ((iter = weston_output_iterate_heads(output, iter))) {
1342 		if (iter != to_go)
1343 			n++;
1344 	}
1345 
1346 	return n;
1347 }
1348 
1349 static void
wet_head_tracker_destroy(struct wet_head_tracker * track)1350 wet_head_tracker_destroy(struct wet_head_tracker *track)
1351 {
1352 	wl_list_remove(&track->head_destroy_listener.link);
1353 	free(track);
1354 }
1355 
1356 static void
handle_head_destroy(struct wl_listener * listener,void * data)1357 handle_head_destroy(struct wl_listener *listener, void *data)
1358 {
1359 	struct weston_head *head = data;
1360 	struct weston_output *output;
1361 	struct wet_head_tracker *track =
1362 		container_of(listener, struct wet_head_tracker,
1363 			     head_destroy_listener);
1364 
1365 	wet_head_tracker_destroy(track);
1366 
1367 	output = weston_head_get_output(head);
1368 
1369 	/* On shutdown path, the output might be already gone. */
1370 	if (!output)
1371 		return;
1372 
1373 	if (count_remaining_heads(output, head) > 0)
1374 		return;
1375 
1376 	weston_output_destroy(output);
1377 }
1378 
1379 static struct wet_head_tracker *
wet_head_tracker_from_head(struct weston_head * head)1380 wet_head_tracker_from_head(struct weston_head *head)
1381 {
1382 	struct wl_listener *lis;
1383 
1384 	lis = weston_head_get_destroy_listener(head, handle_head_destroy);
1385 	if (!lis)
1386 		return NULL;
1387 
1388 	return container_of(lis, struct wet_head_tracker,
1389 			    head_destroy_listener);
1390 }
1391 
1392 /* Listen for head destroy signal.
1393  *
1394  * If a head is destroyed and it was the last head on the output, we
1395  * destroy the associated output.
1396  *
1397  * Do not bother destroying the head trackers on shutdown, the backend will
1398  * destroy the heads which calls our handler to destroy the trackers.
1399  */
1400 static void
wet_head_tracker_create(struct wet_compositor * compositor,struct weston_head * head)1401 wet_head_tracker_create(struct wet_compositor *compositor,
1402 			struct weston_head *head)
1403 {
1404 	struct wet_head_tracker *track;
1405 
1406 	track = zalloc(sizeof *track);
1407 	if (!track)
1408 		return;
1409 
1410 	track->head_destroy_listener.notify = handle_head_destroy;
1411 	weston_head_add_destroy_listener(head, &track->head_destroy_listener);
1412 }
1413 
1414 static void
simple_head_enable(struct wet_compositor * wet,struct weston_head * head)1415 simple_head_enable(struct wet_compositor *wet, struct weston_head *head)
1416 {
1417 	struct weston_output *output;
1418 	int ret = 0;
1419 
1420 	output = weston_compositor_create_output_with_head(wet->compositor,
1421 							   head);
1422 	if (!output) {
1423 		weston_log("Could not create an output for head \"%{public}s\".\n",
1424 			   weston_head_get_name(head));
1425 		wet->init_failed = true;
1426 
1427 		return;
1428 	}
1429 
1430 	if (wet->simple_output_configure)
1431 		ret = wet->simple_output_configure(output);
1432 	if (ret < 0) {
1433 		weston_log("Cannot configure output \"%{public}s\".\n",
1434 			   weston_head_get_name(head));
1435 		weston_output_destroy(output);
1436 		wet->init_failed = true;
1437 
1438 		return;
1439 	}
1440 
1441 	if (weston_output_enable(output) < 0) {
1442 		weston_log("Enabling output \"%{public}s\" failed.\n",
1443 			   weston_head_get_name(head));
1444 		weston_output_destroy(output);
1445 		wet->init_failed = true;
1446 
1447 		return;
1448 	}
1449 
1450 	wet_head_tracker_create(wet, head);
1451 
1452 	/* The weston_compositor will track and destroy the output on exit. */
1453 }
1454 
1455 static void
simple_head_disable(struct weston_head * head)1456 simple_head_disable(struct weston_head *head)
1457 {
1458 	struct weston_output *output;
1459 	struct wet_head_tracker *track;
1460 
1461 	track = wet_head_tracker_from_head(head);
1462 	if (track)
1463 		wet_head_tracker_destroy(track);
1464 
1465 	output = weston_head_get_output(head);
1466 	assert(output);
1467 	weston_output_destroy(output);
1468 }
1469 
1470 static void
simple_heads_changed(struct wl_listener * listener,void * arg)1471 simple_heads_changed(struct wl_listener *listener, void *arg)
1472 {
1473     LOG_ENTER();
1474 	struct weston_compositor *compositor = arg;
1475 	struct wet_compositor *wet = to_wet_compositor(compositor);
1476 	struct weston_head *head = NULL;
1477 	bool connected;
1478 	bool enabled;
1479 	bool changed;
1480 	bool non_desktop;
1481 
1482 	while ((head = weston_compositor_iterate_heads(wet->compositor, head))) {
1483 		connected = weston_head_is_connected(head);
1484 		enabled = weston_head_is_enabled(head);
1485 		changed = weston_head_is_device_changed(head);
1486 		non_desktop = weston_head_is_non_desktop(head);
1487 
1488 		if (connected && !enabled && !non_desktop) {
1489 			simple_head_enable(wet, head);
1490 		} else if (!connected && enabled) {
1491 			simple_head_disable(head);
1492 		} else if (enabled && changed) {
1493 			weston_log("Detected a monitor change on head '%{public}s', "
1494 				   "not bothering to do anything about it.\n",
1495 				   weston_head_get_name(head));
1496 		}
1497 		weston_head_reset_device_changed(head);
1498 	}
1499     LOG_EXIT();
1500 }
1501 
1502 static void
wet_set_simple_head_configurator(struct weston_compositor * compositor,int (* fn)(struct weston_output *))1503 wet_set_simple_head_configurator(struct weston_compositor *compositor,
1504 				 int (*fn)(struct weston_output *))
1505 {
1506 	struct wet_compositor *wet = to_wet_compositor(compositor);
1507 
1508 	wet->simple_output_configure = fn;
1509 
1510 	wet->heads_changed_listener.notify = simple_heads_changed;
1511 	weston_compositor_add_heads_changed_listener(compositor,
1512 						&wet->heads_changed_listener);
1513 }
1514 
1515 static void
configure_input_device_accel(struct weston_config_section * s,struct libinput_device * device)1516 configure_input_device_accel(struct weston_config_section *s,
1517 		struct libinput_device *device)
1518 {
1519 	char *profile_string = NULL;
1520 	int is_a_profile = 1;
1521 	uint32_t profiles;
1522 	enum libinput_config_accel_profile profile;
1523 	double speed;
1524 
1525 	if (weston_config_section_get_string(s, "accel-profile",
1526 					     &profile_string, NULL) == 0) {
1527 		if (strcmp(profile_string, "flat") == 0)
1528 			profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
1529 		else if (strcmp(profile_string, "adaptive") == 0)
1530 			profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
1531 		else {
1532 			weston_log("warning: no such accel-profile: %{public}s\n",
1533 				   profile_string);
1534 			is_a_profile = 0;
1535 		}
1536 
1537 		profiles = libinput_device_config_accel_get_profiles(device);
1538 		if (is_a_profile && (profile & profiles) != 0) {
1539 			weston_log("          accel-profile=%{public}s\n",
1540 				   profile_string);
1541 			libinput_device_config_accel_set_profile(device,
1542 					profile);
1543 		}
1544 	}
1545 
1546 	if (weston_config_section_get_double(s, "accel-speed",
1547 					     &speed, 0) == 0 &&
1548 	    speed >= -1. && speed <= 1.) {
1549 		weston_log("          accel-speed=%.3f\n", speed);
1550 		libinput_device_config_accel_set_speed(device, speed);
1551 	}
1552 
1553 	free(profile_string);
1554 }
1555 
1556 static void
configure_input_device_scroll(struct weston_config_section * s,struct libinput_device * device)1557 configure_input_device_scroll(struct weston_config_section *s,
1558 		struct libinput_device *device)
1559 {
1560 	bool natural;
1561 	char *method_string = NULL;
1562 	uint32_t methods;
1563 	enum libinput_config_scroll_method method;
1564 	char *button_string = NULL;
1565 	int button;
1566 
1567 	if (libinput_device_config_scroll_has_natural_scroll(device) &&
1568 	    weston_config_section_get_bool(s, "natural-scroll",
1569 					   &natural, false) == 0) {
1570 		weston_log("          natural-scroll=%{public}s\n",
1571 			   natural ? "true" : "false");
1572 		libinput_device_config_scroll_set_natural_scroll_enabled(
1573 				device, natural);
1574 	}
1575 
1576 	if (weston_config_section_get_string(s, "scroll-method",
1577 					     &method_string, NULL) != 0)
1578 		goto done;
1579 	if (strcmp(method_string, "two-finger") == 0)
1580 		method = LIBINPUT_CONFIG_SCROLL_2FG;
1581 	else if (strcmp(method_string, "edge") == 0)
1582 		method = LIBINPUT_CONFIG_SCROLL_EDGE;
1583 	else if (strcmp(method_string, "button") == 0)
1584 		method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
1585 	else if (strcmp(method_string, "none") == 0)
1586 		method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
1587 	else {
1588 		weston_log("warning: no such scroll-method: %{public}s\n",
1589 			   method_string);
1590 		goto done;
1591 	}
1592 
1593 	methods = libinput_device_config_scroll_get_methods(device);
1594 	if (method != LIBINPUT_CONFIG_SCROLL_NO_SCROLL &&
1595 	    (method & methods) == 0)
1596 		goto done;
1597 
1598 	weston_log("          scroll-method=%{public}s\n", method_string);
1599 	libinput_device_config_scroll_set_method(device, method);
1600 
1601 	if (method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) {
1602 		if (weston_config_section_get_string(s, "scroll-button",
1603 						     &button_string,
1604 						     NULL) != 0)
1605 			goto done;
1606 
1607 		button = libevdev_event_code_from_name(EV_KEY, button_string);
1608 		if (button == -1) {
1609 			weston_log("          Bad scroll-button: %{public}s\n",
1610 				   button_string);
1611 			goto done;
1612 		}
1613 
1614 		weston_log("          scroll-button=%{public}s\n", button_string);
1615 		libinput_device_config_scroll_set_button(device, button);
1616 	}
1617 
1618 done:
1619 	free(method_string);
1620 	free(button_string);
1621 }
1622 
1623 static void
configure_input_device(struct weston_compositor * compositor,struct libinput_device * device)1624 configure_input_device(struct weston_compositor *compositor,
1625 		       struct libinput_device *device)
1626 {
1627 	struct weston_config_section *s;
1628 	struct weston_config *config = wet_get_config(compositor);
1629 	bool has_enable_tap = false;
1630 	bool enable_tap;
1631 	bool disable_while_typing;
1632 	bool middle_emulation;
1633 	bool tap_and_drag;
1634 	bool tap_and_drag_lock;
1635 	bool left_handed;
1636 	unsigned int rotation;
1637 
1638 	weston_log("libinput: configuring device \"%{public}s\".\n",
1639 		   libinput_device_get_name(device));
1640 
1641 	s = weston_config_get_section(config,
1642 				      "libinput", NULL, NULL);
1643 
1644 	if (libinput_device_config_tap_get_finger_count(device) > 0) {
1645 		if (weston_config_section_get_bool(s, "enable_tap",
1646 						   &enable_tap, false) == 0) {
1647 			weston_log("!!DEPRECATION WARNING!!: In weston.ini, "
1648 				   "enable_tap is deprecated in favour of "
1649 				   "enable-tap. Support for it may be removed "
1650 				   "at any time!");
1651 			has_enable_tap = true;
1652 		}
1653 		if (weston_config_section_get_bool(s, "enable-tap",
1654 						   &enable_tap, false) == 0)
1655 			has_enable_tap = true;
1656 		if (has_enable_tap) {
1657 			weston_log("          enable-tap=%{public}s.\n",
1658 				   enable_tap ? "true" : "false");
1659 			libinput_device_config_tap_set_enabled(device,
1660 							       enable_tap);
1661 		}
1662 		if (weston_config_section_get_bool(s, "tap-and-drag",
1663 						   &tap_and_drag, false) == 0) {
1664 			weston_log("          tap-and-drag=%{public}s.\n",
1665 				   tap_and_drag ? "true" : "false");
1666 			libinput_device_config_tap_set_drag_enabled(device,
1667 					tap_and_drag);
1668 		}
1669 		if (weston_config_section_get_bool(s, "tap-and-drag-lock",
1670 					       &tap_and_drag_lock, false) == 0) {
1671 			weston_log("          tap-and-drag-lock=%{public}s.\n",
1672 				   tap_and_drag_lock ? "true" : "false");
1673 			libinput_device_config_tap_set_drag_lock_enabled(
1674 					device, tap_and_drag_lock);
1675 		}
1676 	}
1677 
1678 	if (libinput_device_config_dwt_is_available(device) &&
1679 	    weston_config_section_get_bool(s, "disable-while-typing",
1680 					   &disable_while_typing, false) == 0) {
1681 		weston_log("          disable-while-typing=%{public}s.\n",
1682 			   disable_while_typing ? "true" : "false");
1683 		libinput_device_config_dwt_set_enabled(device,
1684 						       disable_while_typing);
1685 	}
1686 
1687 	if (libinput_device_config_middle_emulation_is_available(device) &&
1688 	    weston_config_section_get_bool(s, "middle-button-emulation",
1689 					   &middle_emulation, false) == 0) {
1690 		weston_log("          middle-button-emulation=%{public}s\n",
1691 			   middle_emulation ? "true" : "false");
1692 		libinput_device_config_middle_emulation_set_enabled(
1693 				device, middle_emulation);
1694 	}
1695 
1696 	if (libinput_device_config_left_handed_is_available(device) &&
1697 	    weston_config_section_get_bool(s, "left-handed",
1698 				           &left_handed, false) == 0) {
1699 		weston_log("          left-handed=%{public}s\n",
1700 			   left_handed ? "true" : "false");
1701 		libinput_device_config_left_handed_set(device, left_handed);
1702 	}
1703 
1704 	if (libinput_device_config_rotation_is_available(device) &&
1705 	    weston_config_section_get_uint(s, "rotation",
1706 				           &rotation, false) == 0) {
1707 		weston_log("          rotation=%u\n", rotation);
1708 		libinput_device_config_rotation_set_angle(device, rotation);
1709 	}
1710 
1711 	if (libinput_device_config_accel_is_available(device))
1712 		configure_input_device_accel(s, device);
1713 
1714 	configure_input_device_scroll(s, device);
1715 }
1716 
1717 static int
drm_backend_output_configure(struct weston_output * output,struct weston_config_section * section)1718 drm_backend_output_configure(struct weston_output *output,
1719 			     struct weston_config_section *section)
1720 {
1721 	struct wet_compositor *wet = to_wet_compositor(output->compositor);
1722 	const struct weston_drm_output_api *api;
1723 	enum weston_drm_backend_output_mode mode =
1724 		WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
1725 	uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL;
1726 	char *s;
1727 	char *modeline = NULL;
1728 	char *gbm_format = NULL;
1729 	char *seat = NULL;
1730 
1731 	api = weston_drm_output_get_api(output->compositor);
1732 	if (!api) {
1733 		weston_log("Cannot use weston_drm_output_api.\n");
1734 		return -1;
1735 	}
1736 
1737 	weston_config_section_get_string(section, "mode", &s, "preferred");
1738 
1739 	if (strcmp(s, "off") == 0) {
1740 		assert(0 && "off was supposed to be pruned");
1741 		return -1;
1742 	} else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) {
1743 		mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
1744 	} else if (strcmp(s, "preferred") != 0) {
1745 		modeline = s;
1746 		s = NULL;
1747 	}
1748 	free(s);
1749 
1750 	if (api->set_mode(output, mode, modeline) < 0) {
1751 		weston_log("Cannot configure an output using weston_drm_output_api.\n");
1752 		free(modeline);
1753 		return -1;
1754 	}
1755 	free(modeline);
1756 
1757 	if (count_remaining_heads(output, NULL) == 1) {
1758 		struct weston_head *head = weston_output_get_first_head(output);
1759 		transform = weston_head_get_transform(head);
1760 	}
1761 
1762 	wet_output_set_scale(output, section, 1, 0);
1763 	if (wet_output_set_transform(output, section, transform,
1764 				     UINT32_MAX) < 0) {
1765 		return -1;
1766 	}
1767 
1768 	weston_config_section_get_string(section,
1769 					 "gbm-format", &gbm_format, NULL);
1770 
1771 	api->set_gbm_format(output, gbm_format);
1772 	free(gbm_format);
1773 
1774 	weston_config_section_get_string(section, "seat", &seat, "");
1775 
1776 	api->set_seat(output, seat);
1777 	free(seat);
1778 
1779 	allow_content_protection(output, section);
1780 
1781 	return 0;
1782 }
1783 
1784 /* Find the output section to use for configuring the output with the
1785  * named head. If an output section with the given name contains
1786  * a "same-as" key, ignore all other settings in the output section and
1787  * instead find an output section named by the "same-as". Do this
1788  * recursively.
1789  */
1790 static struct weston_config_section *
drm_config_find_controlling_output_section(struct weston_config * config,const char * head_name)1791 drm_config_find_controlling_output_section(struct weston_config *config,
1792 					   const char *head_name)
1793 {
1794 	struct weston_config_section *section;
1795 	char *same_as;
1796 	int depth = 0;
1797 
1798 	same_as = strdup(head_name);
1799 	do {
1800 		section = weston_config_get_section(config, "output",
1801 						    "name", same_as);
1802 		if (!section && depth > 0)
1803 			weston_log("Configuration error: "
1804 				   "output section referred to with "
1805 				   "'same-as=%{public}s' not found.\n", same_as);
1806 
1807 		free(same_as);
1808 
1809 		if (!section)
1810 			return NULL;
1811 
1812 		if (++depth > 10) {
1813 			weston_log("Configuration error: "
1814 				   "'same-as' nested too deep for output '%{public}s'.\n",
1815 				   head_name);
1816 			return NULL;
1817 		}
1818 
1819 		weston_config_section_get_string(section, "same-as",
1820 						 &same_as, NULL);
1821 	} while (same_as);
1822 
1823 	return section;
1824 }
1825 
1826 static struct wet_layoutput *
wet_compositor_create_layoutput(struct wet_compositor * compositor,const char * name,struct weston_config_section * section)1827 wet_compositor_create_layoutput(struct wet_compositor *compositor,
1828 				const char *name,
1829 				struct weston_config_section *section)
1830 {
1831 	struct wet_layoutput *lo;
1832 
1833 	lo = zalloc(sizeof *lo);
1834 	if (!lo)
1835 		return NULL;
1836 
1837 	lo->compositor = compositor;
1838 	wl_list_insert(compositor->layoutput_list.prev, &lo->compositor_link);
1839 	wl_list_init(&lo->output_list);
1840 	lo->name = strdup(name);
1841 	lo->section = section;
1842 
1843 	return lo;
1844 }
1845 
1846 static void
wet_layoutput_destroy(struct wet_layoutput * lo)1847 wet_layoutput_destroy(struct wet_layoutput *lo)
1848 {
1849 	wl_list_remove(&lo->compositor_link);
1850 	assert(wl_list_empty(&lo->output_list));
1851 	free(lo->name);
1852 	free(lo);
1853 }
1854 
1855 static void
wet_output_handle_destroy(struct wl_listener * listener,void * data)1856 wet_output_handle_destroy(struct wl_listener *listener, void *data)
1857 {
1858 	struct wet_output *output;
1859 
1860 	output = wl_container_of(listener, output, output_destroy_listener);
1861 	assert(output->output == data);
1862 
1863 	output->output = NULL;
1864 	wl_list_remove(&output->output_destroy_listener.link);
1865 }
1866 
1867 static struct wet_output *
wet_layoutput_create_output(struct wet_layoutput * lo,const char * name)1868 wet_layoutput_create_output(struct wet_layoutput *lo, const char *name)
1869 {
1870 	struct wet_output *output;
1871 
1872 	output = zalloc(sizeof *output);
1873 	if (!output)
1874 		return NULL;
1875 
1876 	output->output =
1877 		weston_compositor_create_output(lo->compositor->compositor,
1878 						name);
1879 	if (!output->output) {
1880 		free(output);
1881 		return NULL;
1882 	}
1883 
1884 	output->layoutput = lo;
1885 	wl_list_insert(lo->output_list.prev, &output->link);
1886 	output->output_destroy_listener.notify = wet_output_handle_destroy;
1887 	weston_output_add_destroy_listener(output->output,
1888 					   &output->output_destroy_listener);
1889 
1890 	return output;
1891 }
1892 
1893 static struct wet_output *
wet_output_from_weston_output(struct weston_output * base)1894 wet_output_from_weston_output(struct weston_output *base)
1895 {
1896 	struct wl_listener *lis;
1897 
1898 	lis = weston_output_get_destroy_listener(base,
1899 						 wet_output_handle_destroy);
1900 	if (!lis)
1901 		return NULL;
1902 
1903 	return container_of(lis, struct wet_output, output_destroy_listener);
1904 }
1905 
1906 static void
wet_output_destroy(struct wet_output * output)1907 wet_output_destroy(struct wet_output *output)
1908 {
1909 	if (output->output) {
1910 		/* output->output destruction may be deferred in some cases (see
1911 		 * drm_output_destroy()), so we need to forcibly trigger the
1912 		 * destruction callback now, or otherwise would later access
1913 		 * data that we are about to free
1914 		 */
1915 		struct weston_output *save = output->output;
1916 		wet_output_handle_destroy(&output->output_destroy_listener, save);
1917 		weston_output_destroy(save);
1918 	}
1919 
1920 	wl_list_remove(&output->link);
1921 	free(output);
1922 }
1923 
1924 static struct wet_layoutput *
wet_compositor_find_layoutput(struct wet_compositor * wet,const char * name)1925 wet_compositor_find_layoutput(struct wet_compositor *wet, const char *name)
1926 {
1927 	struct wet_layoutput *lo;
1928 
1929 	wl_list_for_each(lo, &wet->layoutput_list, compositor_link)
1930 		if (strcmp(lo->name, name) == 0)
1931 			return lo;
1932 
1933 	return NULL;
1934 }
1935 
1936 static void
wet_compositor_layoutput_add_head(struct wet_compositor * wet,const char * output_name,struct weston_config_section * section,struct weston_head * head)1937 wet_compositor_layoutput_add_head(struct wet_compositor *wet,
1938 				  const char *output_name,
1939 				  struct weston_config_section *section,
1940 				  struct weston_head *head)
1941 {
1942 	struct wet_layoutput *lo;
1943 
1944 	lo = wet_compositor_find_layoutput(wet, output_name);
1945 	if (!lo) {
1946 		lo = wet_compositor_create_layoutput(wet, output_name, section);
1947 		if (!lo)
1948 			return;
1949 	}
1950 
1951 	if (lo->add.n + 1 >= ARRAY_LENGTH(lo->add.heads))
1952 		return;
1953 
1954 	lo->add.heads[lo->add.n++] = head;
1955 }
1956 
1957 static void
wet_compositor_destroy_layout(struct wet_compositor * wet)1958 wet_compositor_destroy_layout(struct wet_compositor *wet)
1959 {
1960 	struct wet_layoutput *lo, *lo_tmp;
1961 	struct wet_output *output, *output_tmp;
1962 
1963 	wl_list_for_each_safe(lo, lo_tmp,
1964 			      &wet->layoutput_list, compositor_link) {
1965 		wl_list_for_each_safe(output, output_tmp,
1966 				      &lo->output_list, link) {
1967 			wet_output_destroy(output);
1968 		}
1969 		wet_layoutput_destroy(lo);
1970 	}
1971 }
1972 
1973 static void
drm_head_prepare_enable(struct wet_compositor * wet,struct weston_head * head)1974 drm_head_prepare_enable(struct wet_compositor *wet,
1975 			struct weston_head *head)
1976 {
1977 	const char *name = weston_head_get_name(head);
1978 	struct weston_config_section *section;
1979 	char *output_name = NULL;
1980 	char *mode = NULL;
1981 
1982 	section = drm_config_find_controlling_output_section(wet->config, name);
1983 	if (section) {
1984 		/* skip outputs that are explicitly off, or non-desktop and not
1985 		 * explicitly enabled. The backend turns them off automatically.
1986 		 */
1987 		weston_config_section_get_string(section, "mode", &mode, NULL);
1988 		if (mode && strcmp(mode, "off") == 0) {
1989 			free(mode);
1990 			return;
1991 		}
1992 		if (!mode && weston_head_is_non_desktop(head))
1993 			return;
1994 		free(mode);
1995 
1996 		weston_config_section_get_string(section, "name",
1997 						 &output_name, NULL);
1998 		assert(output_name);
1999 
2000 		wet_compositor_layoutput_add_head(wet, output_name,
2001 						  section, head);
2002 		free(output_name);
2003 	} else {
2004 		wet_compositor_layoutput_add_head(wet, name, NULL, head);
2005 	}
2006 }
2007 
2008 static bool
drm_head_should_force_enable(struct wet_compositor * wet,struct weston_head * head)2009 drm_head_should_force_enable(struct wet_compositor *wet,
2010 			     struct weston_head *head)
2011 {
2012 	const char *name = weston_head_get_name(head);
2013 	struct weston_config_section *section;
2014 	bool force;
2015 
2016 	section = drm_config_find_controlling_output_section(wet->config, name);
2017 	if (!section)
2018 		return false;
2019 
2020 	weston_config_section_get_bool(section, "force-on", &force, false);
2021 	return force;
2022 }
2023 
2024 static void
drm_try_attach(struct weston_output * output,struct wet_head_array * add,struct wet_head_array * failed)2025 drm_try_attach(struct weston_output *output,
2026 	       struct wet_head_array *add,
2027 	       struct wet_head_array *failed)
2028 {
2029 	unsigned i;
2030 
2031 	/* try to attach all heads, this probably succeeds */
2032 	for (i = 0; i < add->n; i++) {
2033 		if (!add->heads[i])
2034 			continue;
2035 
2036 		if (weston_output_attach_head(output, add->heads[i]) < 0) {
2037 			assert(failed->n < ARRAY_LENGTH(failed->heads));
2038 
2039 			failed->heads[failed->n++] = add->heads[i];
2040 			add->heads[i] = NULL;
2041 		}
2042 	}
2043 }
2044 
2045 static int
drm_try_enable(struct weston_output * output,struct wet_head_array * undo,struct wet_head_array * failed)2046 drm_try_enable(struct weston_output *output,
2047 	       struct wet_head_array *undo,
2048 	       struct wet_head_array *failed)
2049 {
2050 	/* Try to enable, and detach heads one by one until it succeeds. */
2051 	while (!output->enabled) {
2052 		if (weston_output_enable(output) == 0)
2053 			return 0;
2054 
2055 		/* the next head to drop */
2056 		while (undo->n > 0 && undo->heads[--undo->n] == NULL)
2057 			;
2058 
2059 		/* No heads left to undo and failed to enable. */
2060 		if (undo->heads[undo->n] == NULL)
2061 			return -1;
2062 
2063 		assert(failed->n < ARRAY_LENGTH(failed->heads));
2064 
2065 		/* undo one head */
2066 		weston_head_detach(undo->heads[undo->n]);
2067 		failed->heads[failed->n++] = undo->heads[undo->n];
2068 		undo->heads[undo->n] = NULL;
2069 	}
2070 
2071 	return 0;
2072 }
2073 
2074 static int
drm_try_attach_enable(struct weston_output * output,struct wet_layoutput * lo)2075 drm_try_attach_enable(struct weston_output *output, struct wet_layoutput *lo)
2076 {
2077 	struct wet_head_array failed = {};
2078 	unsigned i;
2079 
2080 	assert(!output->enabled);
2081 
2082 	drm_try_attach(output, &lo->add, &failed);
2083 	if (drm_backend_output_configure(output, lo->section) < 0)
2084 		return -1;
2085 
2086 	if (drm_try_enable(output, &lo->add, &failed) < 0)
2087 		return -1;
2088 
2089 	/* For all successfully attached/enabled heads */
2090 	for (i = 0; i < lo->add.n; i++)
2091 		if (lo->add.heads[i])
2092 			wet_head_tracker_create(lo->compositor,
2093 						lo->add.heads[i]);
2094 
2095 	/* Push failed heads to the next round. */
2096 	lo->add = failed;
2097 
2098 	return 0;
2099 }
2100 
2101 static int
drm_process_layoutput(struct wet_compositor * wet,struct wet_layoutput * lo)2102 drm_process_layoutput(struct wet_compositor *wet, struct wet_layoutput *lo)
2103 {
2104 	struct wet_output *output, *tmp;
2105 	char *name = NULL;
2106 	int ret;
2107 
2108 	/*
2109 	 *   For each existing wet_output:
2110 	 *     try attach
2111 	 *   While heads left to enable:
2112 	 *     Create output
2113 	 *     try attach, try enable
2114 	 */
2115 
2116 	wl_list_for_each_safe(output, tmp, &lo->output_list, link) {
2117 		struct wet_head_array failed = {};
2118 
2119 		if (!output->output) {
2120 			/* Clean up left-overs from destroyed heads. */
2121 			wet_output_destroy(output);
2122 			continue;
2123 		}
2124 
2125 		assert(output->output->enabled);
2126 
2127 		drm_try_attach(output->output, &lo->add, &failed);
2128 		lo->add = failed;
2129 		if (lo->add.n == 0)
2130 			return 0;
2131 	}
2132 
2133 	if (!weston_compositor_find_output_by_name(wet->compositor, lo->name))
2134 		name = strdup(lo->name);
2135 
2136 	while (lo->add.n > 0) {
2137 		if (!wl_list_empty(&lo->output_list)) {
2138 			weston_log("Error: independent-CRTC clone mode is not implemented.\n");
2139 			return -1;
2140 		}
2141 
2142 		if (!name) {
2143 			ret = asprintf(&name, "%s:%s", lo->name,
2144 				       weston_head_get_name(lo->add.heads[0]));
2145 			if (ret < 0)
2146 				return -1;
2147 		}
2148 		output = wet_layoutput_create_output(lo, name);
2149 		free(name);
2150 		name = NULL;
2151 
2152 		if (!output)
2153 			return -1;
2154 
2155 		if (drm_try_attach_enable(output->output, lo) < 0) {
2156 			wet_output_destroy(output);
2157 			return -1;
2158 		}
2159 	}
2160 
2161 	return 0;
2162 }
2163 
2164 static int
drm_process_layoutputs(struct wet_compositor * wet)2165 drm_process_layoutputs(struct wet_compositor *wet)
2166 {
2167 	struct wet_layoutput *lo;
2168 	int ret = 0;
2169 
2170 	wl_list_for_each(lo, &wet->layoutput_list, compositor_link) {
2171 		if (lo->add.n == 0)
2172 			continue;
2173 
2174 		if (drm_process_layoutput(wet, lo) < 0) {
2175 			lo->add = (struct wet_head_array){};
2176 			ret = -1;
2177 		}
2178 	}
2179 
2180 	return ret;
2181 }
2182 
2183 static void
drm_head_disable(struct weston_head * head)2184 drm_head_disable(struct weston_head *head)
2185 {
2186 	struct weston_output *output_base;
2187 	struct wet_output *output;
2188 	struct wet_head_tracker *track;
2189 
2190 	track = wet_head_tracker_from_head(head);
2191 	if (track)
2192 		wet_head_tracker_destroy(track);
2193 
2194 	output_base = weston_head_get_output(head);
2195 	assert(output_base);
2196 	output = wet_output_from_weston_output(output_base);
2197 	assert(output && output->output == output_base);
2198 
2199 	weston_head_detach(head);
2200 	if (count_remaining_heads(output->output, NULL) == 0)
2201 		wet_output_destroy(output);
2202 }
2203 
2204 static void
drm_heads_changed(struct wl_listener * listener,void * arg)2205 drm_heads_changed(struct wl_listener *listener, void *arg)
2206 {
2207 	struct weston_compositor *compositor = arg;
2208 	struct wet_compositor *wet = to_wet_compositor(compositor);
2209 	struct weston_head *head = NULL;
2210 	bool connected;
2211 	bool enabled;
2212 	bool changed;
2213 	bool forced;
2214 
2215 	/* We need to collect all cloned heads into outputs before enabling the
2216 	 * output.
2217 	 */
2218 	while ((head = weston_compositor_iterate_heads(compositor, head))) {
2219 		connected = weston_head_is_connected(head);
2220 		enabled = weston_head_is_enabled(head);
2221 		changed = weston_head_is_device_changed(head);
2222 		forced = drm_head_should_force_enable(wet, head);
2223 
2224 		if ((connected || forced) && !enabled) {
2225 			drm_head_prepare_enable(wet, head);
2226 		} else if (!(connected || forced) && enabled) {
2227 			drm_head_disable(head);
2228 		} else if (enabled && changed) {
2229 			weston_log("Detected a monitor change on head '%{public}s', "
2230 				   "not bothering to do anything about it.\n",
2231 				   weston_head_get_name(head));
2232 		}
2233 		weston_head_reset_device_changed(head);
2234 	}
2235 
2236 	if (drm_process_layoutputs(wet) < 0)
2237 		wet->init_failed = true;
2238 }
2239 
2240 static int
drm_backend_remoted_output_configure(struct weston_output * output,struct weston_config_section * section,char * modeline,const struct weston_remoting_api * api)2241 drm_backend_remoted_output_configure(struct weston_output *output,
2242 				     struct weston_config_section *section,
2243 				     char *modeline,
2244 				     const struct weston_remoting_api *api)
2245 {
2246 	char *gbm_format = NULL;
2247 	char *seat = NULL;
2248 	char *host = NULL;
2249 	char *pipeline = NULL;
2250 	int port, ret;
2251 
2252 	ret = api->set_mode(output, modeline);
2253 	if (ret < 0) {
2254 		weston_log("Cannot configure an output \"%{public}s\" using "
2255 			   "weston_remoting_api. Invalid mode\n",
2256 			   output->name);
2257 		return -1;
2258 	}
2259 
2260 	wet_output_set_scale(output, section, 1, 0);
2261 	if (wet_output_set_transform(output, section,
2262 				     WL_OUTPUT_TRANSFORM_NORMAL,
2263 				     UINT32_MAX) < 0) {
2264 		return -1;
2265 	};
2266 
2267 	weston_config_section_get_string(section, "gbm-format", &gbm_format,
2268 					 NULL);
2269 	api->set_gbm_format(output, gbm_format);
2270 	free(gbm_format);
2271 
2272 	weston_config_section_get_string(section, "seat", &seat, "");
2273 
2274 	api->set_seat(output, seat);
2275 	free(seat);
2276 
2277 	weston_config_section_get_string(section, "gst-pipeline", &pipeline,
2278 					 NULL);
2279 	if (pipeline) {
2280 		api->set_gst_pipeline(output, pipeline);
2281 		free(pipeline);
2282 		return 0;
2283 	}
2284 
2285 	weston_config_section_get_string(section, "host", &host, NULL);
2286 	weston_config_section_get_int(section, "port", &port, 0);
2287 	if (!host || port <= 0 || 65533 < port) {
2288 		weston_log("Cannot configure an output \"%{public}s\". "
2289 			   "Need to specify gst-pipeline or "
2290 			   "host and port (1-65533).\n", output->name);
2291 	}
2292 	api->set_host(output, host);
2293 	free(host);
2294 	api->set_port(output, port);
2295 
2296 	return 0;
2297 }
2298 
2299 static void
remoted_output_init(struct weston_compositor * c,struct weston_config_section * section,const struct weston_remoting_api * api)2300 remoted_output_init(struct weston_compositor *c,
2301 		    struct weston_config_section *section,
2302 		    const struct weston_remoting_api *api)
2303 {
2304 	struct weston_output *output = NULL;
2305 	char *output_name, *modeline = NULL;
2306 	int ret;
2307 
2308 	weston_config_section_get_string(section, "name", &output_name,
2309 					 NULL);
2310 	if (!output_name)
2311 		return;
2312 
2313 	weston_config_section_get_string(section, "mode", &modeline, "off");
2314 	if (strcmp(modeline, "off") == 0)
2315 		goto err;
2316 
2317 	output = api->create_output(c, output_name);
2318 	if (!output) {
2319 		weston_log("Cannot create remoted output \"%{public}s\".\n",
2320 			   output_name);
2321 		goto err;
2322 	}
2323 
2324 	ret = drm_backend_remoted_output_configure(output, section, modeline,
2325 						   api);
2326 	if (ret < 0) {
2327 		weston_log("Cannot configure remoted output \"%{public}s\".\n",
2328 			   output_name);
2329 		goto err;
2330 	}
2331 
2332 	if (weston_output_enable(output) < 0) {
2333 		weston_log("Enabling remoted output \"%{public}s\" failed.\n",
2334 			   output_name);
2335 		goto err;
2336 	}
2337 
2338 	free(modeline);
2339 	free(output_name);
2340 	weston_log("remoted output '%{public}s' enabled\n", output->name);
2341 	return;
2342 
2343 err:
2344 	free(modeline);
2345 	free(output_name);
2346 	if (output)
2347 		weston_output_destroy(output);
2348 }
2349 
2350 static void
load_remoting(struct weston_compositor * c,struct weston_config * wc)2351 load_remoting(struct weston_compositor *c, struct weston_config *wc)
2352 {
2353 	const struct weston_remoting_api *api = NULL;
2354 	int (*module_init)(struct weston_compositor *ec);
2355 	struct weston_config_section *section = NULL;
2356 	const char *section_name;
2357 
2358 	/* read remote-output section in weston.ini */
2359 	while (weston_config_next_section(wc, &section, &section_name)) {
2360 		if (strcmp(section_name, "remote-output"))
2361 			continue;
2362 
2363 		if (!api) {
2364 			char *module_name;
2365 			struct weston_config_section *core_section =
2366 				weston_config_get_section(wc, "core", NULL,
2367 							  NULL);
2368 
2369 			weston_config_section_get_string(core_section,
2370 							 "remoting",
2371 							 &module_name,
2372 							 "remoting-plugin.so");
2373 			module_init = weston_load_module(module_name,
2374 							 "weston_module_init");
2375 			free(module_name);
2376 			if (!module_init) {
2377 				weston_log("Can't load remoting-plugin\n");
2378 				return;
2379 			}
2380 			if (module_init(c) < 0) {
2381 				weston_log("Remoting-plugin init failed\n");
2382 				return;
2383 			}
2384 
2385 			api = weston_remoting_get_api(c);
2386 			if (!api)
2387 				return;
2388 		}
2389 
2390 		remoted_output_init(c, section, api);
2391 	}
2392 }
2393 
2394 static int
drm_backend_pipewire_output_configure(struct weston_output * output,struct weston_config_section * section,char * modeline,const struct weston_pipewire_api * api)2395 drm_backend_pipewire_output_configure(struct weston_output *output,
2396 				     struct weston_config_section *section,
2397 				     char *modeline,
2398 				     const struct weston_pipewire_api *api)
2399 {
2400 	char *seat = NULL;
2401 	int ret;
2402 
2403 	ret = api->set_mode(output, modeline);
2404 	if (ret < 0) {
2405 		weston_log("Cannot configure an output \"%{public}s\" using "
2406 			   "weston_pipewire_api. Invalid mode\n",
2407 			   output->name);
2408 		return -1;
2409 	}
2410 
2411 	wet_output_set_scale(output, section, 1, 0);
2412 	if (wet_output_set_transform(output, section,
2413 				     WL_OUTPUT_TRANSFORM_NORMAL,
2414 				     UINT32_MAX) < 0) {
2415 		return -1;
2416 	}
2417 
2418 	weston_config_section_get_string(section, "seat", &seat, "");
2419 
2420 	api->set_seat(output, seat);
2421 	free(seat);
2422 
2423 	return 0;
2424 }
2425 
2426 static void
pipewire_output_init(struct weston_compositor * c,struct weston_config_section * section,const struct weston_pipewire_api * api)2427 pipewire_output_init(struct weston_compositor *c,
2428 		    struct weston_config_section *section,
2429 		    const struct weston_pipewire_api *api)
2430 {
2431 	struct weston_output *output = NULL;
2432 	char *output_name, *modeline = NULL;
2433 	int ret;
2434 
2435 	weston_config_section_get_string(section, "name", &output_name,
2436 					 NULL);
2437 	if (!output_name)
2438 		return;
2439 
2440 	weston_config_section_get_string(section, "mode", &modeline, "off");
2441 	if (strcmp(modeline, "off") == 0)
2442 		goto err;
2443 
2444 	output = api->create_output(c, output_name);
2445 	if (!output) {
2446 		weston_log("Cannot create pipewire output \"%{public}s\".\n",
2447 			   output_name);
2448 		goto err;
2449 	}
2450 
2451 	ret = drm_backend_pipewire_output_configure(output, section, modeline,
2452 						   api);
2453 	if (ret < 0) {
2454 		weston_log("Cannot configure pipewire output \"%{public}s\".\n",
2455 			   output_name);
2456 		goto err;
2457 	}
2458 
2459 	if (weston_output_enable(output) < 0) {
2460 		weston_log("Enabling pipewire output \"%{public}s\" failed.\n",
2461 			   output_name);
2462 		goto err;
2463 	}
2464 
2465 	free(modeline);
2466 	free(output_name);
2467 	weston_log("pipewire output '%{public}s' enabled\n", output->name);
2468 	return;
2469 
2470 err:
2471 	free(modeline);
2472 	free(output_name);
2473 	if (output)
2474 		weston_output_destroy(output);
2475 }
2476 
2477 static void
load_pipewire(struct weston_compositor * c,struct weston_config * wc)2478 load_pipewire(struct weston_compositor *c, struct weston_config *wc)
2479 {
2480 	const struct weston_pipewire_api *api = NULL;
2481 	int (*module_init)(struct weston_compositor *ec);
2482 	struct weston_config_section *section = NULL;
2483 	const char *section_name;
2484 
2485 	/* read pipewire-output section in weston.ini */
2486 	while (weston_config_next_section(wc, &section, &section_name)) {
2487 		if (strcmp(section_name, "pipewire-output"))
2488 			continue;
2489 
2490 		if (!api) {
2491 			char *module_name;
2492 			struct weston_config_section *core_section =
2493 				weston_config_get_section(wc, "core", NULL,
2494 							  NULL);
2495 
2496 			weston_config_section_get_string(core_section,
2497 							 "pipewire",
2498 							 &module_name,
2499 							 "pipewire-plugin.so");
2500 			module_init = weston_load_module(module_name,
2501 							 "weston_module_init");
2502 			free(module_name);
2503 			if (!module_init) {
2504 				weston_log("Can't load pipewire-plugin\n");
2505 				return;
2506 			}
2507 			if (module_init(c) < 0) {
2508 				weston_log("Pipewire-plugin init failed\n");
2509 				return;
2510 			}
2511 
2512 			api = weston_pipewire_get_api(c);
2513 			if (!api)
2514 				return;
2515 		}
2516 
2517 		pipewire_output_init(c, section, api);
2518 	}
2519 }
2520 
2521 static int
load_drm_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2522 load_drm_backend(struct weston_compositor *c,
2523 		 int *argc, char **argv, struct weston_config *wc)
2524 {
2525 	struct weston_drm_backend_config config = {{ 0, }};
2526 	struct weston_config_section *section;
2527 	struct wet_compositor *wet = to_wet_compositor(c);
2528 	int ret = 0;
2529 
2530 	wet->drm_use_current_mode = false;
2531 
2532 	section = weston_config_get_section(wc, "core", NULL, NULL);
2533 	weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2534 				       false);
2535 
2536 	const struct weston_option options[] = {
2537 		{ WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
2538 		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
2539 		{ WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
2540 		{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
2541 		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2542 		{ WESTON_OPTION_BOOLEAN, "continue-without-input", 0, &config.continue_without_input },
2543 	};
2544 
2545 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
2546 
2547 	section = weston_config_get_section(wc, "core", NULL, NULL);
2548 	weston_config_section_get_string(section,
2549 					 "gbm-format", &config.gbm_format,
2550 					 NULL);
2551 	weston_config_section_get_uint(section, "pageflip-timeout",
2552 	                               &config.pageflip_timeout, 0);
2553 	weston_config_section_get_bool(section, "pixman-shadow",
2554 				       &config.use_pixman_shadow, true);
2555 
2556 	config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
2557 	config.base.struct_size = sizeof(struct weston_drm_backend_config);
2558 	config.configure_device = configure_input_device;
2559 
2560 	wet->heads_changed_listener.notify = drm_heads_changed;
2561 	weston_compositor_add_heads_changed_listener(c,
2562 						&wet->heads_changed_listener);
2563 
2564 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
2565 					     &config.base);
2566 
2567 	/* remoting */
2568 	load_remoting(c, wc);
2569 
2570 	/* pipewire */
2571 	load_pipewire(c, wc);
2572 
2573 	free(config.gbm_format);
2574 	free(config.seat_id);
2575 
2576 	return ret;
2577 }
2578 
2579 static int
hdi_backend_output_configure(struct weston_output * output)2580 hdi_backend_output_configure(struct weston_output *output)
2581 {
2582     const struct weston_hdi_output_api *api = NULL;
2583     api = weston_hdi_output_get_api(output->compositor);
2584     if (api == NULL) {
2585         weston_log("Cannot use weston_hdi_output_api.\n");
2586         return -1;
2587     }
2588 
2589     wet_output_set_scale(output, NULL, 1, 0);
2590     if (wet_output_set_transform(output, NULL,
2591                                  WL_OUTPUT_TRANSFORM_NORMAL, UINT32_MAX) < 0) {
2592         return -1;
2593     }
2594 
2595     if (api->set_mode(output) < 0) {
2596         weston_log("Cannot configure an output using weston_hdi_output_api.\n");
2597         return -1;
2598     }
2599     return 0;
2600 }
2601 
2602 static int
load_hdi_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2603 load_hdi_backend(struct weston_compositor *c,
2604 		      int *argc, char **argv, struct weston_config *wc)
2605 {
2606 	const struct weston_windowed_output_api *api;
2607 	struct weston_hdi_backend_config config = {};
2608 	struct weston_config_section *section;
2609 	bool no_outputs = false;
2610 	int ret = 0;
2611 	char *transform = NULL;
2612 
2613 	struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2614 	if (!parsed_options)
2615 		return -1;
2616 
2617 	section = weston_config_get_section(wc, "core", NULL, NULL);
2618 	weston_config_section_get_bool(section, "use-hdi", &config.use_hdi,
2619 				       false);
2620 
2621 	const struct weston_option options[] = {
2622 		{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2623 		{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2624 		{ WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2625 		{ WESTON_OPTION_BOOLEAN, "use-hdi", 0, &config.use_hdi },
2626 		{ WESTON_OPTION_STRING, "transform", 0, &transform },
2627 		{ WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
2628 	};
2629 
2630 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
2631 
2632 	if (transform) {
2633 		if (weston_parse_transform(transform, &parsed_options->transform) < 0) {
2634 			weston_log("Invalid transform \"%{public}s\"\n", transform);
2635 			return -1;
2636 		}
2637 		free(transform);
2638 	}
2639 
2640 	config.base.struct_version = WESTON_HDI_BACKEND_CONFIG_VERSION;
2641 	config.base.struct_size = sizeof(struct weston_hdi_backend_config);
2642 	config.configure_device = configure_input_device;
2643 
2644 	wet_set_simple_head_configurator(c, hdi_backend_output_configure);
2645 
2646 	/* load the actual wayland backend and configure it */
2647 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_HDI,
2648 					     &config.base);
2649 
2650 	if (ret < 0)
2651 		return ret;
2652 
2653 	return 0;
2654 }
2655 
2656 static int
headless_backend_output_configure(struct weston_output * output)2657 headless_backend_output_configure(struct weston_output *output)
2658 {
2659 	struct wet_output_config defaults = {
2660 		.width = 1024,
2661 		.height = 640,
2662 		.scale = 1,
2663 		.transform = WL_OUTPUT_TRANSFORM_NORMAL
2664 	};
2665 
2666 	return wet_configure_windowed_output_from_config(output, &defaults);
2667 }
2668 
2669 static int
load_headless_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2670 load_headless_backend(struct weston_compositor *c,
2671 		      int *argc, char **argv, struct weston_config *wc)
2672 {
2673 	const struct weston_windowed_output_api *api;
2674 	struct weston_headless_backend_config config = {{ 0, }};
2675 	struct weston_config_section *section;
2676 	bool no_outputs = false;
2677 	int ret = 0;
2678 	char *transform = NULL;
2679 
2680 	struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2681 	if (!parsed_options)
2682 		return -1;
2683 
2684 	section = weston_config_get_section(wc, "core", NULL, NULL);
2685 	weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2686 				       false);
2687 	weston_config_section_get_bool(section, "use-gl", &config.use_gl,
2688 				       false);
2689 
2690 	const struct weston_option options[] = {
2691 		{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2692 		{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2693 		{ WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2694 		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2695 		{ WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
2696 		{ WESTON_OPTION_STRING, "transform", 0, &transform },
2697 		{ WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
2698 	};
2699 
2700 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
2701 
2702 	if (transform) {
2703 		if (weston_parse_transform(transform, &parsed_options->transform) < 0) {
2704 			weston_log("Invalid transform \"%{public}s\"\n", transform);
2705 			return -1;
2706 		}
2707 		free(transform);
2708 	}
2709 
2710 	config.base.struct_version = WESTON_HEADLESS_BACKEND_CONFIG_VERSION;
2711 	config.base.struct_size = sizeof(struct weston_headless_backend_config);
2712 
2713 	wet_set_simple_head_configurator(c, headless_backend_output_configure);
2714 
2715 	/* load the actual wayland backend and configure it */
2716 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_HEADLESS,
2717 					     &config.base);
2718 
2719 	if (ret < 0)
2720 		return ret;
2721 
2722 	if (!no_outputs) {
2723 		api = weston_windowed_output_get_api(c);
2724 
2725 		if (!api) {
2726 			weston_log("Cannot use weston_windowed_output_api.\n");
2727 			return -1;
2728 		}
2729 
2730 		if (api->create_head(c, "headless") < 0)
2731 			return -1;
2732 	}
2733 
2734 	return 0;
2735 }
2736 
2737 static int
rdp_backend_output_configure(struct weston_output * output)2738 rdp_backend_output_configure(struct weston_output *output)
2739 {
2740 	struct wet_compositor *compositor = to_wet_compositor(output->compositor);
2741 	struct wet_output_config *parsed_options = compositor->parsed_options;
2742 	const struct weston_rdp_output_api *api = weston_rdp_output_get_api(output->compositor);
2743 	int width = 640;
2744 	int height = 480;
2745 
2746 	assert(parsed_options);
2747 
2748 	if (!api) {
2749 		weston_log("Cannot use weston_rdp_output_api.\n");
2750 		return -1;
2751 	}
2752 
2753 	if (parsed_options->width)
2754 		width = parsed_options->width;
2755 
2756 	if (parsed_options->height)
2757 		height = parsed_options->height;
2758 
2759 	weston_output_set_scale(output, 1);
2760 	weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
2761 
2762 	if (api->output_set_size(output, width, height) < 0) {
2763 		weston_log("Cannot configure output \"%{public}s\" using weston_rdp_output_api.\n",
2764 			   output->name);
2765 		return -1;
2766 	}
2767 
2768 	return 0;
2769 }
2770 
2771 static void
weston_rdp_backend_config_init(struct weston_rdp_backend_config * config)2772 weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
2773 {
2774 	config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
2775 	config->base.struct_size = sizeof(struct weston_rdp_backend_config);
2776 
2777 	config->bind_address = NULL;
2778 	config->port = 3389;
2779 	config->rdp_key = NULL;
2780 	config->server_cert = NULL;
2781 	config->server_key = NULL;
2782 	config->env_socket = 0;
2783 	config->no_clients_resize = 0;
2784 	config->force_no_compression = 0;
2785 }
2786 
2787 static int
load_rdp_backend(struct weston_compositor * c,int * argc,char * argv[],struct weston_config * wc)2788 load_rdp_backend(struct weston_compositor *c,
2789 		int *argc, char *argv[], struct weston_config *wc)
2790 {
2791 	struct weston_rdp_backend_config config  = {{ 0, }};
2792 	int ret = 0;
2793 
2794 	struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2795 	if (!parsed_options)
2796 		return -1;
2797 
2798 	weston_rdp_backend_config_init(&config);
2799 
2800 	const struct weston_option rdp_options[] = {
2801 		{ WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
2802 		{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2803 		{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2804 		{ WESTON_OPTION_STRING,  "address", 0, &config.bind_address },
2805 		{ WESTON_OPTION_INTEGER, "port", 0, &config.port },
2806 		{ WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
2807 		{ WESTON_OPTION_STRING,  "rdp4-key", 0, &config.rdp_key },
2808 		{ WESTON_OPTION_STRING,  "rdp-tls-cert", 0, &config.server_cert },
2809 		{ WESTON_OPTION_STRING,  "rdp-tls-key", 0, &config.server_key },
2810 		{ WESTON_OPTION_BOOLEAN, "force-no-compression", 0, &config.force_no_compression },
2811 	};
2812 
2813 	parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
2814 
2815 	wet_set_simple_head_configurator(c, rdp_backend_output_configure);
2816 
2817 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_RDP,
2818 					     &config.base);
2819 
2820 	free(config.bind_address);
2821 	free(config.rdp_key);
2822 	free(config.server_cert);
2823 	free(config.server_key);
2824 
2825 	return ret;
2826 }
2827 
2828 static int
fbdev_backend_output_configure(struct weston_output * output)2829 fbdev_backend_output_configure(struct weston_output *output)
2830 {
2831 	struct weston_config *wc = wet_get_config(output->compositor);
2832 	struct weston_config_section *section;
2833 
2834 	section = weston_config_get_section(wc, "output", "name", "fbdev");
2835 
2836 	if (wet_output_set_transform(output, section,
2837 				     WL_OUTPUT_TRANSFORM_NORMAL,
2838 				     UINT32_MAX) < 0) {
2839 		return -1;
2840 	}
2841 
2842 	weston_output_set_scale(output, 1);
2843 
2844 	return 0;
2845 }
2846 
2847 static int
load_fbdev_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2848 load_fbdev_backend(struct weston_compositor *c,
2849 		      int *argc, char **argv, struct weston_config *wc)
2850 {
2851 	struct weston_fbdev_backend_config config = {{ 0, }};
2852 	int ret = 0;
2853 
2854 	const struct weston_option fbdev_options[] = {
2855 		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
2856 		{ WESTON_OPTION_STRING, "device", 0, &config.device },
2857 		{ WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
2858 	};
2859 
2860 	parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
2861 
2862 	config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
2863 	config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
2864 	config.configure_device = configure_input_device;
2865 
2866 	wet_set_simple_head_configurator(c, fbdev_backend_output_configure);
2867 
2868 	/* load the actual wayland backend and configure it */
2869 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_FBDEV,
2870 					     &config.base);
2871 
2872 	free(config.device);
2873 	return ret;
2874 }
2875 
2876 static int
x11_backend_output_configure(struct weston_output * output)2877 x11_backend_output_configure(struct weston_output *output)
2878 {
2879 	struct wet_output_config defaults = {
2880 		.width = 1024,
2881 		.height = 600,
2882 		.scale = 1,
2883 		.transform = WL_OUTPUT_TRANSFORM_NORMAL
2884 	};
2885 
2886 	return wet_configure_windowed_output_from_config(output, &defaults);
2887 }
2888 
2889 static int
load_x11_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2890 load_x11_backend(struct weston_compositor *c,
2891 		 int *argc, char **argv, struct weston_config *wc)
2892 {
2893 	char *default_output;
2894 	const struct weston_windowed_output_api *api;
2895 	struct weston_x11_backend_config config = {{ 0, }};
2896 	struct weston_config_section *section;
2897 	int ret = 0;
2898 	int option_count = 1;
2899 	int output_count = 0;
2900 	char const *section_name;
2901 	int i;
2902 
2903 	struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2904 	if (!parsed_options)
2905 		return -1;
2906 
2907 	section = weston_config_get_section(wc, "core", NULL, NULL);
2908 	weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2909 				       false);
2910 
2911 	const struct weston_option options[] = {
2912 	       { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2913 	       { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2914 	       { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2915 	       { WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
2916 	       { WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
2917 	       { WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
2918 	       { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2919 	};
2920 
2921 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
2922 
2923 	config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
2924 	config.base.struct_size = sizeof(struct weston_x11_backend_config);
2925 
2926 	wet_set_simple_head_configurator(c, x11_backend_output_configure);
2927 
2928 	/* load the actual backend and configure it */
2929 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
2930 					     &config.base);
2931 
2932 	if (ret < 0)
2933 		return ret;
2934 
2935 	api = weston_windowed_output_get_api(c);
2936 
2937 	if (!api) {
2938 		weston_log("Cannot use weston_windowed_output_api.\n");
2939 		return -1;
2940 	}
2941 
2942 	section = NULL;
2943 	while (weston_config_next_section(wc, &section, &section_name)) {
2944 		char *output_name;
2945 
2946 		if (output_count >= option_count)
2947 			break;
2948 
2949 		if (strcmp(section_name, "output") != 0) {
2950 			continue;
2951 		}
2952 
2953 		weston_config_section_get_string(section, "name", &output_name, NULL);
2954 		if (output_name == NULL || output_name[0] != 'X') {
2955 			free(output_name);
2956 			continue;
2957 		}
2958 
2959 		if (api->create_head(c, output_name) < 0) {
2960 			free(output_name);
2961 			return -1;
2962 		}
2963 		free(output_name);
2964 
2965 		output_count++;
2966 	}
2967 
2968 	default_output = NULL;
2969 
2970 	for (i = output_count; i < option_count; i++) {
2971 		if (asprintf(&default_output, "screen%d", i) < 0) {
2972 			return -1;
2973 		}
2974 
2975 		if (api->create_head(c, default_output) < 0) {
2976 			free(default_output);
2977 			return -1;
2978 		}
2979 		free(default_output);
2980 	}
2981 
2982 	return 0;
2983 }
2984 
2985 static int
wayland_backend_output_configure(struct weston_output * output)2986 wayland_backend_output_configure(struct weston_output *output)
2987 {
2988 	struct wet_output_config defaults = {
2989 		.width = 1024,
2990 		.height = 640,
2991 		.scale = 1,
2992 		.transform = WL_OUTPUT_TRANSFORM_NORMAL
2993 	};
2994 
2995 	return wet_configure_windowed_output_from_config(output, &defaults);
2996 }
2997 
2998 static int
load_wayland_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2999 load_wayland_backend(struct weston_compositor *c,
3000 		     int *argc, char **argv, struct weston_config *wc)
3001 {
3002 	struct weston_wayland_backend_config config = {{ 0, }};
3003 	struct weston_config_section *section;
3004 	const struct weston_windowed_output_api *api;
3005 	const char *section_name;
3006 	char *output_name = NULL;
3007 	int count = 1;
3008 	int ret = 0;
3009 	int i;
3010 
3011 	struct wet_output_config *parsed_options = wet_init_parsed_options(c);
3012 	if (!parsed_options)
3013 		return -1;
3014 
3015 	config.cursor_size = 32;
3016 	config.cursor_theme = NULL;
3017 	config.display_name = NULL;
3018 
3019 	section = weston_config_get_section(wc, "core", NULL, NULL);
3020 	weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
3021 				       false);
3022 
3023 	const struct weston_option wayland_options[] = {
3024 		{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
3025 		{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
3026 		{ WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
3027 		{ WESTON_OPTION_STRING, "display", 0, &config.display_name },
3028 		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
3029 		{ WESTON_OPTION_BOOLEAN, "use-tde", 0, &config.use_tde }, // OHOS tde
3030 		{ WESTON_OPTION_INTEGER, "output-count", 0, &count },
3031 		{ WESTON_OPTION_BOOLEAN, "fullscreen", 0, &config.fullscreen },
3032 		{ WESTON_OPTION_BOOLEAN, "sprawl", 0, &config.sprawl },
3033 	};
3034 
3035 	parse_options(wayland_options, ARRAY_LENGTH(wayland_options), argc, argv);
3036 
3037 	section = weston_config_get_section(wc, "shell", NULL, NULL);
3038 	weston_config_section_get_string(section, "cursor-theme",
3039 					 &config.cursor_theme, NULL);
3040 	weston_config_section_get_int(section, "cursor-size",
3041 				      &config.cursor_size, 32);
3042 
3043 	config.base.struct_size = sizeof(struct weston_wayland_backend_config);
3044 	config.base.struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION;
3045 
3046 	/* load the actual wayland backend and configure it */
3047 	ret = weston_compositor_load_backend(c, WESTON_BACKEND_WAYLAND,
3048 					     &config.base);
3049 
3050 	free(config.cursor_theme);
3051 	free(config.display_name);
3052 
3053 	if (ret < 0)
3054 		return ret;
3055 
3056 	api = weston_windowed_output_get_api(c);
3057 
3058 	if (api == NULL) {
3059 		/* We will just assume if load_backend() finished cleanly and
3060 		 * windowed_output_api is not present that wayland backend is
3061 		 * started with --sprawl or runs on fullscreen-shell.
3062 		 * In this case, all values are hardcoded, so nothing can be
3063 		 * configured; simply create and enable an output. */
3064 		wet_set_simple_head_configurator(c, NULL);
3065 
3066 		return 0;
3067 	}
3068 
3069 	wet_set_simple_head_configurator(c, wayland_backend_output_configure);
3070 
3071 	section = NULL;
3072 	while (weston_config_next_section(wc, &section, &section_name)) {
3073 		if (count == 0)
3074 			break;
3075 
3076 		if (strcmp(section_name, "output") != 0) {
3077 			continue;
3078 		}
3079 
3080 		weston_config_section_get_string(section, "name", &output_name, NULL);
3081 
3082 		if (output_name == NULL)
3083 			continue;
3084 
3085 		if (output_name[0] != 'W' || output_name[1] != 'L') {
3086 			free(output_name);
3087 			continue;
3088 		}
3089 
3090 		if (api->create_head(c, output_name) < 0) {
3091 			free(output_name);
3092 			return -1;
3093 		}
3094 		free(output_name);
3095 
3096 		--count;
3097 	}
3098 
3099 	for (i = 0; i < count; i++) {
3100 		if (asprintf(&output_name, "wayland%d", i) < 0)
3101 			return -1;
3102 
3103 		if (api->create_head(c, output_name) < 0) {
3104 			free(output_name);
3105 			return -1;
3106 		}
3107 		free(output_name);
3108 	}
3109 
3110 	return 0;
3111 }
3112 
3113 
3114 static int
load_backend(struct weston_compositor * compositor,const char * backend,int * argc,char ** argv,struct weston_config * config)3115 load_backend(struct weston_compositor *compositor, const char *backend,
3116 	     int *argc, char **argv, struct weston_config *config)
3117 {
3118 	if (strstr(backend, "headless-backend.so"))
3119 		return load_headless_backend(compositor, argc, argv, config);
3120 	if (strstr(backend, "hdi-backend.so"))
3121 		return load_hdi_backend(compositor, argc, argv, config);
3122 	else if (strstr(backend, "rdp-backend.so"))
3123 		return load_rdp_backend(compositor, argc, argv, config);
3124 	else if (strstr(backend, "fbdev-backend.so"))
3125 		return load_fbdev_backend(compositor, argc, argv, config);
3126 	else if (strstr(backend, "drm-backend.so"))
3127 		return load_drm_backend(compositor, argc, argv, config);
3128 	else if (strstr(backend, "x11-backend.so"))
3129 		return load_x11_backend(compositor, argc, argv, config);
3130 	else if (strstr(backend, "wayland-backend.so"))
3131 		return load_wayland_backend(compositor, argc, argv, config);
3132 
3133 	weston_log("Error: unknown backend \"%{public}s\"\n", backend);
3134 	return -1;
3135 }
3136 
3137 static char *
copy_command_line(int argc,char * const argv[])3138 copy_command_line(int argc, char * const argv[])
3139 {
3140 	FILE *fp;
3141 	char *str = NULL;
3142 	size_t size = 0;
3143 	int i;
3144 
3145 	fp = open_memstream(&str, &size);
3146 	if (!fp)
3147 		return NULL;
3148 
3149 	fprintf(fp, "%s", argv[0]);
3150 	for (i = 1; i < argc; i++)
3151 		fprintf(fp, " %s", argv[i]);
3152 	fclose(fp);
3153 
3154 	return str;
3155 }
3156 
3157 #if !defined(BUILD_XWAYLAND)
3158 int
wet_load_xwayland(struct weston_compositor * comp)3159 wet_load_xwayland(struct weston_compositor *comp)
3160 {
3161 	return -1;
3162 }
3163 #endif
3164 
3165 // OHOS remove logger
3166 //static void
3167 //weston_log_setup_scopes(struct weston_log_context *log_ctx,
3168 //			struct weston_log_subscriber *subscriber,
3169 //			const char *names)
3170 //{
3171 //	assert(log_ctx);
3172 //	assert(subscriber);
3173 //
3174 //	char *tokenize = strdup(names);
3175 //	char *token = strtok(tokenize, ",");
3176 //	while (token) {
3177 //		weston_log_subscribe(log_ctx, subscriber, token);
3178 //		token = strtok(NULL, ",");
3179 //	}
3180 //	free(tokenize);
3181 //}
3182 //
3183 //static void
3184 //flight_rec_key_binding_handler(struct weston_keyboard *keyboard,
3185 //			       const struct timespec *time, uint32_t key,
3186 //			       void *data)
3187 //{
3188 //	struct weston_log_subscriber *flight_rec = data;
3189 //	weston_log_subscriber_display_flight_rec(flight_rec);
3190 //}
3191 //
3192 //static void
3193 //weston_log_subscribe_to_scopes(struct weston_log_context *log_ctx,
3194 //			       struct weston_log_subscriber *logger,
3195 //			       struct weston_log_subscriber *flight_rec,
3196 //			       const char *log_scopes,
3197 //			       const char *flight_rec_scopes)
3198 //{
3199 //	if (log_scopes)
3200 //		weston_log_setup_scopes(log_ctx, logger, log_scopes);
3201 //	else
3202 //		weston_log_subscribe(log_ctx, logger, "log");
3203 //
3204 //	if (flight_rec_scopes) {
3205 //		weston_log_setup_scopes(log_ctx, flight_rec, flight_rec_scopes);
3206 //	} else {
3207 //		/* by default subscribe to 'log', and 'drm-backend' */
3208 //		weston_log_subscribe(log_ctx, flight_rec, "log");
3209 //		weston_log_subscribe(log_ctx, flight_rec, "drm-backend");
3210 //	}
3211 //}
3212 
3213 // OHOS vsync module
3214 static void
ohos_soft_vsync_thread_main(void * data)3215 ohos_soft_vsync_thread_main(void *data)
3216 {
3217 	bool *pvsync_thread_running = data;
3218 	while (*pvsync_thread_running == true) {
3219 		VsyncModuleTrigger();
3220 		usleep(1e6 / 60);
3221 	}
3222 }
3223 
3224 WL_EXPORT int
wet_main(int argc,char * argv[])3225 wet_main(int argc, char *argv[])
3226 {
3227     log_init();
3228     LOG_ENTERS("main");
3229 	int ret = EXIT_FAILURE;
3230 	char *cmdline;
3231 	struct wl_display *display;
3232 	struct wl_event_source *signals[4];
3233 	struct wl_event_loop *loop;
3234 	int i, fd;
3235 	char *backend = NULL;
3236 	char *shell = NULL;
3237 	bool xwayland = false;
3238 	char *modules = NULL;
3239 	char *option_modules = NULL;
3240 	char *log = NULL;
3241 	char *log_scopes = NULL;
3242 	char *flight_rec_scopes = NULL;
3243 	char *server_socket = NULL;
3244 	int32_t idle_time = -1;
3245 	int32_t help = 0;
3246 	char *socket_name = NULL;
3247 	int32_t version = 0;
3248 	int32_t noconfig = 0;
3249 	int32_t debug_protocol = 0;
3250 	bool numlock_on;
3251 	char *config_file = NULL;
3252 	struct weston_config *config = NULL;
3253 	struct weston_config_section *section;
3254 	struct wl_client *primary_client;
3255 	struct wl_listener primary_client_destroyed;
3256 	struct weston_seat *seat;
3257 	struct wet_compositor wet = { 0 };
3258 // OHOS remove logger
3259 //	struct weston_log_context *log_ctx = NULL;
3260 //	struct weston_log_subscriber *logger = NULL;
3261 //	struct weston_log_subscriber *flight_rec = NULL;
3262 	sigset_t mask;
3263 
3264 	bool wait_for_debugger = false;
3265 	struct wl_protocol_logger *protologger = NULL;
3266 
3267 	// OHOS vsync module
3268 	pthread_t soft_vsync_thread;
3269 	bool vsync_thread_running = false;
3270 
3271 	const struct weston_option core_options[] = {
3272 		{ WESTON_OPTION_STRING, "backend", 'B', &backend },
3273 		{ WESTON_OPTION_STRING, "shell", 0, &shell },
3274 		{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
3275 		{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
3276 #if defined(BUILD_XWAYLAND)
3277 		{ WESTON_OPTION_BOOLEAN, "xwayland", 0, &xwayland },
3278 #endif
3279 		{ WESTON_OPTION_STRING, "modules", 0, &option_modules },
3280 		{ WESTON_OPTION_STRING, "log", 0, &log },
3281 		{ WESTON_OPTION_BOOLEAN, "help", 'h', &help },
3282 		{ WESTON_OPTION_BOOLEAN, "version", 0, &version },
3283 		{ WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
3284 		{ WESTON_OPTION_STRING, "config", 'c', &config_file },
3285 		{ WESTON_OPTION_BOOLEAN, "wait-for-debugger", 0, &wait_for_debugger },
3286 		{ WESTON_OPTION_BOOLEAN, "debug", 0, &debug_protocol },
3287 		{ WESTON_OPTION_STRING, "logger-scopes", 'l', &log_scopes },
3288 		{ WESTON_OPTION_STRING, "flight-rec-scopes", 'f', &flight_rec_scopes },
3289 	};
3290 
3291 	wl_list_init(&wet.layoutput_list);
3292 
3293 	os_fd_set_cloexec(fileno(stdin));
3294 
3295 	cmdline = copy_command_line(argc, argv);
3296 	parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
3297 
3298 	if (help) {
3299 		free(cmdline);
3300 		usage(EXIT_SUCCESS);
3301 	}
3302 
3303 	if (version) {
3304 		printf(PACKAGE_STRING "\n");
3305 		free(cmdline);
3306 
3307         LOG_EXITS("main");
3308 		return EXIT_SUCCESS;
3309 	}
3310 
3311 // OHOS remove logger
3312 //	log_ctx = weston_log_ctx_create();
3313 //	if (!log_ctx) {
3314 //		fprintf(stderr, "Failed to initialize weston debug framework.\n");
3315 //		return EXIT_FAILURE;
3316 //	}
3317 //
3318 //	log_scope = weston_log_ctx_add_log_scope(log_ctx, "log",
3319 //			"Weston and Wayland log\n", NULL, NULL, NULL);
3320 //
3321 //	if (!weston_log_file_open(log))
3322 //		return EXIT_FAILURE;
3323 //
3324 //	weston_log_set_handler(vlog, vlog_continue);
3325 //
3326 //	logger = weston_log_subscriber_create_log(weston_logfile);
3327 //	flight_rec = weston_log_subscriber_create_flight_rec(DEFAULT_FLIGHT_REC_SIZE);
3328 //
3329 //	weston_log_subscribe_to_scopes(log_ctx, logger, flight_rec,
3330 //				       log_scopes, flight_rec_scopes);
3331 
3332 	weston_log("%{public}s\n"
3333 		   STAMP_SPACE "%{public}s\n"
3334 		   STAMP_SPACE "Bug reports to: %{public}s\n"
3335 		   STAMP_SPACE "Build: %{public}s\n",
3336 		   PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
3337 		   BUILD_ID);
3338 	weston_log("Command line: %{public}s\n", cmdline);
3339 	free(cmdline);
3340 	log_uname();
3341 
3342 	verify_xdg_runtime_dir();
3343 
3344 	display = wl_display_create();
3345 	if (display == NULL) {
3346 		weston_log("fatal: failed to create display\n");
3347 		goto out_display;
3348 	}
3349 
3350 	loop = wl_display_get_event_loop(display);
3351 	signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
3352 					      display);
3353 	signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
3354 					      display);
3355 	signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
3356 					      display);
3357 
3358 	wl_list_init(&child_process_list);
3359 	signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
3360 					      NULL);
3361 
3362 	if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
3363 		goto out_signals;
3364 
3365 	/* Xwayland uses SIGUSR1 for communicating with weston. Since some
3366 	   weston plugins may create additional threads, set up any necessary
3367 	   signal blocking early so that these threads can inherit the settings
3368 	   when created. */
3369 	sigemptyset(&mask);
3370 	sigaddset(&mask, SIGUSR1);
3371 	pthread_sigmask(SIG_BLOCK, &mask, NULL);
3372 
3373 	if (load_configuration(&config, noconfig, config_file) < 0)
3374 		goto out_signals;
3375 	wet.config = config;
3376 	wet.parsed_options = NULL;
3377 
3378 	section = weston_config_get_section(config, "core", NULL, NULL);
3379 
3380 // OHOS remove debugger
3381 //	if (!wait_for_debugger) {
3382 //		weston_config_section_get_bool(section, "wait-for-debugger",
3383 //					       &wait_for_debugger, false);
3384 //	}
3385 //	if (wait_for_debugger) {
3386 //		weston_log("Weston PID is %ld - "
3387 //			   "waiting for debugger, send SIGCONT to continue...\n",
3388 //			   (long)getpid());
3389 //		raise(SIGSTOP);
3390 //	}
3391 
3392 	if (!backend) {
3393 		weston_config_section_get_string(section, "backend", &backend,
3394 						 NULL);
3395 		if (!backend)
3396 			backend = weston_choose_default_backend();
3397 	}
3398 
3399 // OHOS remove logger
3400 //	wet.compositor = weston_compositor_create(display, log_ctx, &wet);
3401 	wet.compositor = weston_compositor_create(display, &wet);
3402 	if (wet.compositor == NULL) {
3403 		weston_log("fatal: failed to create compositor\n");
3404 		goto out;
3405 	}
3406 	segv_compositor = wet.compositor;
3407 
3408 // OHOS remove log, debugger
3409 //	protocol_scope =
3410 //		weston_log_ctx_add_log_scope(log_ctx, "proto",
3411 //					     "Wayland protocol dump for all clients.\n",
3412 //					     NULL, NULL, NULL);
3413 //
3414 //	protologger = wl_display_add_protocol_logger(display,
3415 //						     protocol_log_fn,
3416 //						     NULL);
3417 //	if (debug_protocol)
3418 //		weston_compositor_enable_debug_protocol(wet.compositor);
3419 //
3420 //	weston_compositor_add_debug_binding(wet.compositor, KEY_D,
3421 //					    flight_rec_key_binding_handler,
3422 //					    flight_rec);
3423 
3424 	if (weston_compositor_init_config(wet.compositor, config) < 0)
3425 		goto out;
3426 
3427 	weston_config_section_get_bool(section, "require-input",
3428 				       &wet.compositor->require_input, true);
3429 
3430     LOG_ENTERS("load_backend");
3431 	if (load_backend(wet.compositor, backend, &argc, argv, config) < 0) {
3432 		weston_log("fatal: failed to create compositor backend\n");
3433 		goto out;
3434 	}
3435     LOG_EXITS("load_backend");
3436 
3437 	// OHOS vsync module
3438 	if (VsyncModuleIsRunning() == 0) { // other vsync init failed
3439 		weston_log("soft vsync");
3440 		vsync_thread_running = true;
3441 		if (VsyncModuleStart() == 0) {
3442 			pthread_create(&soft_vsync_thread,
3443 				       NULL, ohos_soft_vsync_thread_main, &vsync_thread_running);
3444 		} else {
3445 			weston_log("soft vsync failed");
3446 		}
3447 	}
3448 
3449     LOG_ENTERS("weston_compositor_flush_heads_changed");
3450 	weston_compositor_flush_heads_changed(wet.compositor);
3451     LOG_EXITS("weston_compositor_flush_heads_changed");
3452 	// OHOS
3453 	// if (wet.init_failed)
3454 	// 	goto out;
3455 	if (wet.init_failed && wl_list_empty(&wet.compositor->output_list))
3456 		goto out;
3457 
3458 	if (idle_time < 0)
3459 		weston_config_section_get_int(section, "idle-time", &idle_time, -1);
3460 	if (idle_time < 0)
3461 		idle_time = 300; /* default idle timeout, in seconds */
3462 
3463 	wet.compositor->idle_time = idle_time;
3464 	wet.compositor->default_pointer_grab = NULL;
3465 	wet.compositor->exit = handle_exit;
3466 
3467 	weston_compositor_log_capabilities(wet.compositor);
3468 
3469 	server_socket = getenv("WAYLAND_SERVER_SOCKET");
3470 	if (server_socket) {
3471 		weston_log("Running with single client\n");
3472 		if (!safe_strtoint(server_socket, &fd))
3473 			fd = -1;
3474 	} else {
3475 		fd = -1;
3476 	}
3477 
3478 	if (fd != -1) {
3479 		primary_client = wl_client_create(display, fd);
3480 		if (!primary_client) {
3481 			weston_log("fatal: failed to add client: %{public}s\n",
3482 				   strerror(errno));
3483 			goto out;
3484 		}
3485 		primary_client_destroyed.notify =
3486 			handle_primary_client_destroyed;
3487 		wl_client_add_destroy_listener(primary_client,
3488 					       &primary_client_destroyed);
3489 	} else if (weston_create_listening_socket(display, socket_name)) {
3490 		goto out;
3491 	}
3492 
3493 	if (!shell)
3494 		weston_config_section_get_string(section, "shell", &shell,
3495 						 "desktop-shell.so");
3496 
3497 	if (wet_load_shell(wet.compositor, shell, &argc, argv) < 0)
3498 		goto out;
3499 
3500 	weston_config_section_get_string(section, "modules", &modules, "");
3501 	if (load_modules(wet.compositor, modules, &argc, argv, &xwayland) < 0)
3502 		goto out;
3503 
3504 	if (load_modules(wet.compositor, option_modules, &argc, argv, &xwayland) < 0)
3505 		goto out;
3506 
3507 	if (!xwayland) {
3508 		weston_config_section_get_bool(section, "xwayland", &xwayland,
3509 					       false);
3510 	}
3511 	if (xwayland) {
3512 		if (wet_load_xwayland(wet.compositor) < 0)
3513 			goto out;
3514 	}
3515 
3516 	section = weston_config_get_section(config, "keyboard", NULL, NULL);
3517 	weston_config_section_get_bool(section, "numlock-on", &numlock_on, false);
3518 	if (numlock_on) {
3519 		wl_list_for_each(seat, &wet.compositor->seat_list, link) {
3520 			struct weston_keyboard *keyboard =
3521 				weston_seat_get_keyboard(seat);
3522 
3523 			if (keyboard)
3524 				weston_keyboard_set_locks(keyboard,
3525 							  WESTON_NUM_LOCK,
3526 							  WESTON_NUM_LOCK);
3527 		}
3528 	}
3529 
3530 	for (i = 1; i < argc; i++)
3531 		weston_log("fatal: unhandled option: %{public}s\n", argv[i]);
3532 	if (argc > 1)
3533 		goto out;
3534 
3535 	weston_compositor_wake(wet.compositor);
3536 
3537     LOG_EXITS("main");
3538     LOG_ENTERS("wl_display_run");
3539 	wl_display_run(display);
3540     LOG_EXITS("wl_display_run");
3541 
3542 	/* Allow for setting return exit code after
3543 	* wl_display_run returns normally. This is
3544 	* useful for devs/testers and automated tests
3545 	* that want to indicate failure status to
3546 	* testing infrastructure above
3547 	*/
3548 	ret = wet.compositor->exit_code;
3549 
3550 out:
3551 	// OHOS vsync module
3552 	if (vsync_thread_running == true) {
3553 		VsyncModuleStop();
3554 		vsync_thread_running = false;
3555 		pthread_join(soft_vsync_thread, NULL);
3556 	}
3557 
3558 	wet_compositor_destroy_layout(&wet);
3559 
3560 	/* free(NULL) is valid, and it won't be NULL if it's used */
3561 	free(wet.parsed_options);
3562 
3563 // OHOS remove logger
3564 //	if (protologger)
3565 //		wl_protocol_logger_destroy(protologger);
3566 
3567 	weston_compositor_destroy(wet.compositor);
3568 // OHOS remove logger
3569 //	weston_log_scope_destroy(protocol_scope);
3570 //	protocol_scope = NULL;
3571 //	weston_log_scope_destroy(log_scope);
3572 //	log_scope = NULL;
3573 //	weston_log_subscriber_destroy(logger);
3574 //	weston_log_subscriber_destroy(flight_rec);
3575 //	weston_log_ctx_destroy(log_ctx);
3576 
3577 out_signals:
3578 	for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
3579 		if (signals[i])
3580 			wl_event_source_remove(signals[i]);
3581 
3582 	wl_display_destroy(display);
3583 
3584 out_display:
3585 // OHOS remove logger
3586 //	weston_log_file_close();
3587 
3588 	if (config)
3589 		weston_config_destroy(config);
3590 	free(config_file);
3591 	free(backend);
3592 	free(shell);
3593 	free(socket_name);
3594 	free(option_modules);
3595 	free(log);
3596 	free(modules);
3597 
3598     LOG_EXITS("main");
3599 	return ret;
3600 }
3601