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