1 /*
2 * Copyright © 2011-2014 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of the
9 * copyright holders not be used in advertising or publicity
10 * pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no
12 * representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied
14 * warranty.
15 *
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 * SOFTWARE.
24 */
25
26 #include <xwayland-config.h>
27
28 #if !defined(SYSV) && !defined(WIN32)
29 #include <sys/resource.h>
30 #endif
31
32 #include <stdio.h>
33 #include <errno.h>
34
35 #include <X11/Xatom.h>
36 #include <selection.h>
37 #include <micmap.h>
38 #include <misyncshm.h>
39 #include <compositeext.h>
40 #include <compint.h>
41 #include <glx_extinit.h>
42 #include <opaque.h>
43 #include <os.h>
44 #include <xserver_poll.h>
45 #include <propertyst.h>
46 #include <version-config.h>
47
48 #include "xwayland-screen.h"
49 #include "xwayland-vidmode.h"
50 #include "xwayland-ext.h"
51
52 #ifdef XF86VIDMODE
53 #include <X11/extensions/xf86vmproto.h>
54 extern _X_EXPORT Bool noXFree86VidModeExtension;
55 #endif
56
57 _X_EXPORT Bool noXwaylandExtension;
58
59 void
ddxGiveUp(enum ExitCode error)60 ddxGiveUp(enum ExitCode error)
61 {
62 }
63
64 void
OsVendorInit(void)65 OsVendorInit(void)
66 {
67 if (serverGeneration == 1)
68 ForceClockId(CLOCK_MONOTONIC);
69 }
70
71 void
OsVendorFatalError(const char * f,va_list args)72 OsVendorFatalError(const char *f, va_list args)
73 {
74 }
75
76 #if defined(DDXBEFORERESET)
77 void
ddxBeforeReset(void)78 ddxBeforeReset(void)
79 {
80 return;
81 }
82 #endif
83
84 #if INPUTTHREAD
85 /** This function is called in Xserver/os/inputthread.c when starting
86 the input thread. */
87 void
ddxInputThreadInit(void)88 ddxInputThreadInit(void)
89 {
90 }
91 #endif
92
93 void
ddxUseMsg(void)94 ddxUseMsg(void)
95 {
96 ErrorF("-rootless run rootless, requires wm support\n");
97 ErrorF("-wm fd create X client for wm on given fd\n");
98 ErrorF("-initfd fd add given fd as a listen socket for initialization clients\n");
99 ErrorF("-listenfd fd add given fd as a listen socket\n");
100 ErrorF("-listen fd deprecated, use \"-listenfd\" instead\n");
101 #ifdef XWL_HAS_EGLSTREAM
102 ErrorF("-eglstream use eglstream backend for nvidia GPUs\n");
103 #endif
104 ErrorF("-shm use shared memory for passing buffers\n");
105 ErrorF("-verbose [n] verbose startup messages\n");
106 ErrorF("-version show the server version and exit\n");
107 ErrorF("-noTouchPointerEmulation disable touch pointer emulation\n");
108 }
109
110 static int init_fd = -1;
111 static int wm_fd = -1;
112 static int listen_fds[5] = { -1, -1, -1, -1, -1 };
113 static int listen_fd_count = 0;
114 static int verbosity = 0;
115
116 static void
xwl_show_version(void)117 xwl_show_version(void)
118 {
119 ErrorF("%s Xwayland %s (%d)\n", VENDOR_NAME, VENDOR_MAN_VERSION, VENDOR_RELEASE);
120 ErrorF("X Protocol Version %d, Revision %d\n", X_PROTOCOL, X_PROTOCOL_REVISION);
121 #if defined(BUILDERSTRING)
122 if (strlen(BUILDERSTRING))
123 ErrorF("%s\n", BUILDERSTRING);
124 #endif
125 }
126
127 static void
try_raising_nofile_limit(void)128 try_raising_nofile_limit(void)
129 {
130 #ifdef RLIMIT_NOFILE
131 struct rlimit rlim;
132
133 /* Only fiddle with the limit if not set explicitly from the command line */
134 if (limitNoFile >= 0)
135 return;
136
137 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
138 ErrorF("Failed to get the current nofile limit: %s\n", strerror(errno));
139 return;
140 }
141
142 rlim.rlim_cur = rlim.rlim_max;
143
144 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
145 ErrorF("Failed to set the current nofile limit: %s\n", strerror(errno));
146 return;
147 }
148
149 LogMessageVerb(X_INFO, 3, "Raising the file descriptors limit to %li\n",
150 rlim.rlim_max);
151 #endif
152 }
153
154 static void
xwl_add_listen_fd(int argc,char * argv[],int i)155 xwl_add_listen_fd(int argc, char *argv[], int i)
156 {
157 NoListenAll = TRUE;
158 if (listen_fd_count == ARRAY_SIZE(listen_fds))
159 FatalError("Too many -listen arguments given, max is %zu\n",
160 ARRAY_SIZE(listen_fds));
161
162 listen_fds[listen_fd_count++] = atoi(argv[i + 1]);
163 }
164
165 int
ddxProcessArgument(int argc,char * argv[],int i)166 ddxProcessArgument(int argc, char *argv[], int i)
167 {
168 if (strcmp(argv[i], "-rootless") == 0) {
169 return 1;
170 }
171 else if (strcmp(argv[i], "-listen") == 0) {
172 CHECK_FOR_REQUIRED_ARGUMENTS(1);
173
174 /* Not an FD */
175 if (!isdigit(*argv[i + 1]))
176 return 0;
177
178 LogMessageVerb(X_WARNING, 0, "Option \"-listen\" for file descriptors is deprecated\n"
179 "Please use \"-listenfd\" instead.\n");
180
181 xwl_add_listen_fd (argc, argv, i);
182 return 2;
183 }
184 else if (strcmp(argv[i], "-listenfd") == 0) {
185 CHECK_FOR_REQUIRED_ARGUMENTS(1);
186
187 xwl_add_listen_fd (argc, argv, i);
188 return 2;
189 }
190 else if (strcmp(argv[i], "-wm") == 0) {
191 CHECK_FOR_REQUIRED_ARGUMENTS(1);
192 wm_fd = atoi(argv[i + 1]);
193 return 2;
194 }
195 else if (strcmp(argv[i], "-initfd") == 0) {
196 CHECK_FOR_REQUIRED_ARGUMENTS(1);
197 init_fd = atoi(argv[i + 1]);
198 return 2;
199 }
200 else if (strcmp(argv[i], "-shm") == 0) {
201 return 1;
202 }
203 else if (strcmp(argv[i], "-verbose") == 0) {
204 if (++i < argc && argv[i]) {
205 char *end;
206 long val;
207
208 val = strtol(argv[i], &end, 0);
209 if (*end == '\0') {
210 verbosity = val;
211 LogSetParameter(XLOG_VERBOSITY, verbosity);
212 return 2;
213 }
214 }
215 LogSetParameter(XLOG_VERBOSITY, ++verbosity);
216 return 1;
217 }
218 else if (strcmp(argv[i], "-eglstream") == 0) {
219 return 1;
220 }
221 else if (strcmp(argv[i], "-version") == 0) {
222 xwl_show_version();
223 exit(0);
224 }
225 else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) {
226 touchEmulatePointer = FALSE;
227 return 1;
228 }
229
230 return 0;
231 }
232
233 static CARD32
add_client_fd(OsTimerPtr timer,CARD32 time,void * arg)234 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
235 {
236 if (!AddClientOnOpenFD(wm_fd))
237 FatalError("Failed to add wm client\n");
238
239 TimerFree(timer);
240
241 return 0;
242 }
243
244 static void
listen_on_fds(void)245 listen_on_fds(void)
246 {
247 int i;
248
249 for (i = 0; i < listen_fd_count; i++)
250 ListenOnOpenFD(listen_fds[i], FALSE);
251 }
252
253 static void
wm_selection_callback(CallbackListPtr * p,void * data,void * arg)254 wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
255 {
256 SelectionInfoRec *info = arg;
257 struct xwl_screen *xwl_screen = data;
258 static const char atom_name[] = "WM_S0";
259 static Atom atom_wm_s0;
260
261 if (atom_wm_s0 == None)
262 atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
263 if (info->selection->selection != atom_wm_s0 ||
264 info->kind != SelectionSetOwner)
265 return;
266
267 listen_on_fds();
268
269 DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
270 }
271
272 _X_NORETURN
273 static void _X_ATTRIBUTE_PRINTF(1, 0)
xwl_log_handler(const char * format,va_list args)274 xwl_log_handler(const char *format, va_list args)
275 {
276 char msg[256];
277
278 vsnprintf(msg, sizeof msg, format, args);
279 FatalError("%s", msg);
280 }
281
282 static const ExtensionModule xwayland_extensions[] = {
283 #ifdef XF86VIDMODE
284 { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
285 { xwlExtensionInit, XWAYLANDNAME, &noXwaylandExtension },
286 #endif
287 };
288
289 void
InitOutput(ScreenInfo * screen_info,int argc,char ** argv)290 InitOutput(ScreenInfo * screen_info, int argc, char **argv)
291 {
292 int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
293 int bpp[] = { 1, 8, 8, 16, 16, 32, 32 };
294 int i;
295
296 for (i = 0; i < ARRAY_SIZE(depths); i++) {
297 screen_info->formats[i].depth = depths[i];
298 screen_info->formats[i].bitsPerPixel = bpp[i];
299 screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
300 }
301
302 screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
303 screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
304 screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
305 screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
306 screen_info->numPixmapFormats = ARRAY_SIZE(depths);
307
308 if (serverGeneration == 1) {
309 try_raising_nofile_limit();
310 LoadExtensionList(xwayland_extensions,
311 ARRAY_SIZE(xwayland_extensions), FALSE);
312 }
313
314 wl_log_set_handler_client(xwl_log_handler);
315
316 if (AddScreen(xwl_screen_init, argc, argv) == -1) {
317 FatalError("Couldn't add screen\n");
318 }
319
320 xorgGlxCreateVendor();
321
322 LocalAccessScopeUser();
323
324 if (wm_fd >= 0 || init_fd >= 0) {
325 if (wm_fd >= 0)
326 TimerSet(NULL, 0, 1, add_client_fd, NULL);
327 if (init_fd >= 0)
328 ListenOnOpenFD(init_fd, FALSE);
329 AddCallback(&SelectionCallback, wm_selection_callback, NULL);
330 }
331 else if (listen_fd_count > 0) {
332 listen_on_fds();
333 }
334 }
335