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 #include <stdio.h>
29 #include <unistd.h>
30 #include <errno.h>
31 
32 #ifdef XWL_HAS_GLAMOR
33 #include <glamor.h>
34 #endif
35 
36 #include <X11/Xatom.h>
37 #include <micmap.h>
38 #include <misyncshm.h>
39 #include <os.h>
40 #include <fb.h>
41 #include <dixstruct.h>
42 #include <propertyst.h>
43 #include <inputstr.h>
44 #include <xserver_poll.h>
45 
46 #include "xwayland-cursor.h"
47 #include "xwayland-screen.h"
48 #include "xwayland-window.h"
49 #include "xwayland-input.h"
50 #include "xwayland-output.h"
51 #include "xwayland-pixmap.h"
52 #include "xwayland-present.h"
53 #include "xwayland-shm.h"
54 
55 #ifdef MITSHM
56 #include "shmint.h"
57 #endif
58 
59 #include "xdg-output-unstable-v1-client-protocol.h"
60 #include "viewporter-client-protocol.h"
61 #include "xdg-shell-client-protocol.h"
62 
63 static DevPrivateKeyRec xwl_screen_private_key;
64 static DevPrivateKeyRec xwl_client_private_key;
65 
66 #define DEFAULT_DPI 96
67 
68 _X_NORETURN
69 static void _X_ATTRIBUTE_PRINTF(1, 2)
xwl_give_up(const char * f,...)70 xwl_give_up(const char *f, ...)
71 {
72     va_list args;
73 
74     va_start(args, f);
75     VErrorFSigSafe(f, args);
76     va_end(args);
77 
78     CloseWellKnownConnections();
79     OsCleanup(TRUE);
80     fflush(stderr);
81     exit(1);
82 }
83 
84 struct xwl_client *
xwl_client_get(ClientPtr client)85 xwl_client_get(ClientPtr client)
86 {
87     return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key);
88 }
89 
90 struct xwl_screen *
xwl_screen_get(ScreenPtr screen)91 xwl_screen_get(ScreenPtr screen)
92 {
93     return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
94 }
95 
96 Bool
xwl_screen_has_viewport_support(struct xwl_screen * xwl_screen)97 xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen)
98 {
99     return wl_compositor_get_version(xwl_screen->compositor) >=
100                             WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION &&
101            xwl_screen->viewporter != NULL;
102 }
103 
104 Bool
xwl_screen_has_resolution_change_emulation(struct xwl_screen * xwl_screen)105 xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
106 {
107     /* Resolution change emulation is only supported in rootless mode and
108      * it requires viewport support.
109      */
110     return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
111 }
112 
113 int
xwl_scale_to(struct xwl_screen * xwl_screen,int value)114 xwl_scale_to(struct xwl_screen *xwl_screen, int value)
115 {
116     return value / (double)xwl_screen->global_output_scale + 0.5;
117 }
118 
119 /* Return the output @ 0x0, falling back to the first output in the list */
120 struct xwl_output *
xwl_screen_get_first_output(struct xwl_screen * xwl_screen)121 xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
122 {
123     struct xwl_output *xwl_output;
124 
125     xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
126         if (xwl_output->x == 0 && xwl_output->y == 0)
127             return xwl_output;
128     }
129 
130     if (xorg_list_is_empty(&xwl_screen->output_list))
131         return NULL;
132 
133     return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
134 }
135 
136 static void
xwl_property_callback(CallbackListPtr * pcbl,void * closure,void * calldata)137 xwl_property_callback(CallbackListPtr *pcbl, void *closure,
138                       void *calldata)
139 {
140     ScreenPtr screen = closure;
141     PropertyStateRec *rec = calldata;
142     struct xwl_screen *xwl_screen;
143     struct xwl_window *xwl_window;
144 
145     if (rec->win->drawable.pScreen != screen)
146         return;
147 
148     xwl_window = xwl_window_get(rec->win);
149     if (!xwl_window)
150         return;
151 
152     xwl_screen = xwl_screen_get(screen);
153 
154     if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
155         xwl_window_update_property(xwl_window, rec);
156 }
157 
158 static void
xwl_root_window_finalized_callback(CallbackListPtr * pcbl,void * closure,void * calldata)159 xwl_root_window_finalized_callback(CallbackListPtr *pcbl,
160                                    void *closure,
161                                    void *calldata)
162 {
163     ScreenPtr screen = closure;
164     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
165     struct xwl_queued_drm_lease_device *queued_device, *next;
166 
167     xorg_list_for_each_entry_safe(queued_device, next,
168                                   &xwl_screen->queued_drm_lease_devices, link) {
169         xwl_screen_add_drm_lease_device(xwl_screen, queued_device->id);
170         xorg_list_del(&queued_device->link);
171         free(queued_device);
172     }
173     DeleteCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, screen);
174 }
175 
176 Bool
xwl_close_screen(ScreenPtr screen)177 xwl_close_screen(ScreenPtr screen)
178 {
179     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
180     struct xwl_output *xwl_output, *next_xwl_output;
181     struct xwl_seat *xwl_seat, *next_xwl_seat;
182 
183     DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
184 
185     xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
186                                   &xwl_screen->output_list, link)
187         xwl_output_destroy(xwl_output);
188 
189     xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
190                                   &xwl_screen->seat_list, link)
191         xwl_seat_destroy(xwl_seat);
192 
193     xwl_screen_release_tablet_manager(xwl_screen);
194 
195     struct xwl_drm_lease_device *device_data, *next;
196     xorg_list_for_each_entry_safe(device_data, next,
197                                   &xwl_screen->drm_lease_devices, link)
198         xwl_screen_destroy_drm_lease_device(xwl_screen,
199                                             device_data->drm_lease_device);
200 
201     RemoveNotifyFd(xwl_screen->wayland_fd);
202 
203     wl_display_disconnect(xwl_screen->display);
204 
205     screen->CloseScreen = xwl_screen->CloseScreen;
206     free(xwl_screen);
207 
208     return screen->CloseScreen(screen);
209 }
210 
211 static struct xwl_seat *
xwl_screen_get_default_seat(struct xwl_screen * xwl_screen)212 xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
213 {
214     if (xorg_list_is_empty(&xwl_screen->seat_list))
215         return NULL;
216 
217     return container_of(xwl_screen->seat_list.prev,
218                         struct xwl_seat,
219                         link);
220 }
221 
222 static void
xwl_cursor_warped_to(DeviceIntPtr device,ScreenPtr screen,ClientPtr client,WindowPtr window,SpritePtr sprite,int x,int y)223 xwl_cursor_warped_to(DeviceIntPtr device,
224                      ScreenPtr screen,
225                      ClientPtr client,
226                      WindowPtr window,
227                      SpritePtr sprite,
228                      int x, int y)
229 {
230     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
231     struct xwl_seat *xwl_seat = device->public.devicePrivate;
232     struct xwl_window *xwl_window;
233     WindowPtr focus;
234 
235     if (!xwl_seat)
236         xwl_seat = xwl_screen_get_default_seat(xwl_screen);
237 
238     if (!window)
239         window = XYToWindow(sprite, x, y);
240 
241     xwl_window = xwl_window_from_window(window);
242     if (!xwl_window && xwl_seat->focus_window) {
243         focus = xwl_seat->focus_window->window;
244 
245         /* Warps on non wl_surface backed Windows are only allowed
246          * as long as the pointer stays within the focus window.
247          */
248         if (x >= focus->drawable.x &&
249             y >= focus->drawable.y &&
250             x < focus->drawable.x + focus->drawable.width &&
251             y < focus->drawable.y + focus->drawable.height) {
252             if (!window) {
253                 DebugF("Warp relative to pointer, assuming pointer focus\n");
254                 xwl_window = xwl_seat->focus_window;
255             } else if (window == screen->root) {
256                 DebugF("Warp on root window, assuming pointer focus\n");
257                 xwl_window = xwl_seat->focus_window;
258             }
259         }
260     }
261     if (!xwl_window)
262         return;
263 
264     xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
265 }
266 
267 static struct xwl_window *
find_matching_input_output_window(struct xwl_screen * xwl_screen,WindowPtr window)268 find_matching_input_output_window(struct xwl_screen *xwl_screen,
269                                   WindowPtr window)
270 {
271     struct xwl_window *xwl_window;
272 
273     xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) {
274         /* When confining happens on InputOnly windows, work out the InputOutput
275          * window that would be covered by its geometry.
276          */
277         if (window->drawable.x < xwl_window->window->drawable.x ||
278             window->drawable.x + window->drawable.width >
279             xwl_window->window->drawable.x + xwl_window->window->drawable.width ||
280             window->drawable.y < xwl_window->window->drawable.y ||
281             window->drawable.y + window->drawable.height >
282             xwl_window->window->drawable.y + xwl_window->window->drawable.height)
283             continue;
284 
285         if (xwl_window->window->drawable.class == InputOnly)
286             continue;
287 
288         return xwl_window;
289     }
290 
291     return NULL;
292 }
293 
294 static void
xwl_cursor_confined_to(DeviceIntPtr device,ScreenPtr screen,WindowPtr window)295 xwl_cursor_confined_to(DeviceIntPtr device,
296                        ScreenPtr screen,
297                        WindowPtr window)
298 {
299     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
300     struct xwl_seat *xwl_seat = device->public.devicePrivate;
301     struct xwl_window *xwl_window;
302 
303     if (!xwl_seat)
304         xwl_seat = xwl_screen_get_default_seat(xwl_screen);
305 
306     /* xwl_seat hasn't been setup yet, don't do anything just yet */
307     if (!xwl_seat)
308         return;
309 
310     if (window == screen->root) {
311         xwl_seat_unconfine_pointer(xwl_seat);
312         return;
313     }
314 
315     xwl_window = xwl_window_from_window(window);
316     if (!xwl_window && window->drawable.class == InputOnly) {
317         DebugF("Confine on InputOnly window, finding matching toplevel\n");
318         xwl_window = find_matching_input_output_window(xwl_screen, window);
319     }
320     if (!xwl_window)
321         return;
322 
323     xwl_seat_confine_pointer(xwl_seat, xwl_window);
324 }
325 
326 void
xwl_screen_check_resolution_change_emulation(struct xwl_screen * xwl_screen)327 xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
328 {
329     struct xwl_window *xwl_window;
330 
331     xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window)
332         xwl_window_check_resolution_change_emulation(xwl_window);
333 }
334 
335 static void
xwl_screen_post_damage(struct xwl_screen * xwl_screen)336 xwl_screen_post_damage(struct xwl_screen *xwl_screen)
337 {
338     struct xwl_window *xwl_window, *next_xwl_window;
339     struct xorg_list commit_window_list;
340 
341     xorg_list_init(&commit_window_list);
342 
343     xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
344                                   &xwl_screen->damage_window_list, link_damage) {
345         /* If we're waiting on a frame callback from the server,
346          * don't attach a new buffer. */
347         if (xwl_window->frame_callback)
348             continue;
349 
350         if (!xwl_window->allow_commits)
351             continue;
352 
353 #ifdef XWL_HAS_GLAMOR
354         if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
355             continue;
356 #endif
357 
358         xwl_window_post_damage(xwl_window);
359         xorg_list_del(&xwl_window->link_damage);
360         xorg_list_append(&xwl_window->link_damage, &commit_window_list);
361     }
362 
363     if (xorg_list_is_empty(&commit_window_list))
364         return;
365 
366 #ifdef XWL_HAS_GLAMOR
367     if (xwl_glamor_needs_buffer_flush(xwl_screen))
368         glamor_block_handler(xwl_screen->screen);
369 #endif
370 
371     xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
372                                   &commit_window_list, link_damage) {
373         wl_surface_commit(xwl_window->surface);
374         xorg_list_del(&xwl_window->link_damage);
375     }
376 }
377 
378 static void
xdg_wm_base_ping(void * data,struct xdg_wm_base * xdg_wm_base,uint32_t serial)379 xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base,
380                  uint32_t serial)
381 {
382     xdg_wm_base_pong(xdg_wm_base, serial);
383 }
384 
385 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
386     xdg_wm_base_ping,
387 };
388 
389 static void
registry_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)390 registry_global(void *data, struct wl_registry *registry, uint32_t id,
391                 const char *interface, uint32_t version)
392 {
393     struct xwl_screen *xwl_screen = data;
394 
395     if (strcmp(interface, "wl_compositor") == 0) {
396         uint32_t request_version = 1;
397 
398         if (version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
399             request_version = WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION;
400 
401         xwl_screen->compositor =
402             wl_registry_bind(registry, id, &wl_compositor_interface, request_version);
403     }
404     else if (strcmp(interface, "wl_shm") == 0) {
405         xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
406     }
407     else if (strcmp(interface, "xdg_wm_base") == 0) {
408         xwl_screen->xdg_wm_base =
409             wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
410         xdg_wm_base_add_listener(xwl_screen->xdg_wm_base,
411                                  &xdg_wm_base_listener,
412                                  NULL);
413     }
414     else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
415         if (xwl_output_create(xwl_screen, id))
416             xwl_screen->expecting_event++;
417     }
418     else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
419         /* We support xdg-output from version 1 to version 3 */
420         version = min(version, 3);
421         xwl_screen->xdg_output_manager =
422             wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version);
423         xwl_screen_init_xdg_output(xwl_screen);
424     }
425     else if (strcmp(interface, "wp_drm_lease_device_v1") == 0) {
426         if (xwl_screen->screen->root == NULL) {
427             struct xwl_queued_drm_lease_device *queued = malloc(sizeof(struct xwl_queued_drm_lease_device));
428             queued->id = id;
429             xorg_list_append(&queued->link, &xwl_screen->queued_drm_lease_devices);
430         } else {
431             xwl_screen_add_drm_lease_device(xwl_screen, id);
432         }
433     }
434     else if (strcmp(interface, "wp_viewporter") == 0) {
435         xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
436     }
437 #ifdef XWL_HAS_GLAMOR
438     else if (xwl_screen->glamor) {
439         xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
440                                     version);
441     }
442 #endif
443 }
444 
445 static void
global_remove(void * data,struct wl_registry * registry,uint32_t name)446 global_remove(void *data, struct wl_registry *registry, uint32_t name)
447 {
448     struct xwl_screen *xwl_screen = data;
449     struct xwl_output *xwl_output, *tmp_xwl_output;
450     struct xwl_drm_lease_device *lease_device, *tmp_lease_device;
451 
452     xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
453                                   &xwl_screen->output_list, link) {
454         if (xwl_output->server_output_id == name) {
455             xwl_output_remove(xwl_output);
456             break;
457         }
458     }
459 
460     xorg_list_for_each_entry_safe(lease_device, tmp_lease_device,
461                                   &xwl_screen->drm_lease_devices, link) {
462         if (lease_device->id == name) {
463             wp_drm_lease_device_v1_release(lease_device->drm_lease_device);
464             break;
465         }
466     }
467 }
468 
469 static const struct wl_registry_listener registry_listener = {
470     registry_global,
471     global_remove
472 };
473 
474 static void
xwl_read_events(struct xwl_screen * xwl_screen)475 xwl_read_events (struct xwl_screen *xwl_screen)
476 {
477     int ret;
478 
479     if (xwl_screen->wait_flush)
480         return;
481 
482     ret = wl_display_read_events(xwl_screen->display);
483     if (ret == -1)
484         xwl_give_up("failed to read Wayland events: %s\n", strerror(errno));
485 
486     xwl_screen->prepare_read = 0;
487 
488     ret = wl_display_dispatch_pending(xwl_screen->display);
489     if (ret == -1)
490         xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
491 }
492 
493 static int
xwl_display_pollout(struct xwl_screen * xwl_screen,int timeout)494 xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
495 {
496     struct pollfd poll_fd;
497 
498     poll_fd.fd = wl_display_get_fd(xwl_screen->display);
499     poll_fd.events = POLLOUT;
500 
501     return xserver_poll(&poll_fd, 1, timeout);
502 }
503 
504 static void
xwl_dispatch_events(struct xwl_screen * xwl_screen)505 xwl_dispatch_events (struct xwl_screen *xwl_screen)
506 {
507     int ret = 0;
508     int ready;
509 
510     if (xwl_screen->wait_flush)
511         goto pollout;
512 
513     while (xwl_screen->prepare_read == 0 &&
514            wl_display_prepare_read(xwl_screen->display) == -1) {
515         ret = wl_display_dispatch_pending(xwl_screen->display);
516         if (ret == -1)
517             xwl_give_up("failed to dispatch Wayland events: %s\n",
518                        strerror(errno));
519     }
520 
521     xwl_screen->prepare_read = 1;
522 
523 pollout:
524     ready = xwl_display_pollout(xwl_screen, 5);
525     if (ready == -1 && errno != EINTR)
526         xwl_give_up("error polling on Xwayland fd: %s\n", strerror(errno));
527 
528     if (ready > 0)
529         ret = wl_display_flush(xwl_screen->display);
530 
531     if (ret == -1 && errno != EAGAIN)
532         xwl_give_up("failed to write to Xwayland fd: %s\n", strerror(errno));
533 
534     xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
535 }
536 
537 static void
socket_handler(int fd,int ready,void * data)538 socket_handler(int fd, int ready, void *data)
539 {
540     struct xwl_screen *xwl_screen = data;
541 
542     xwl_read_events (xwl_screen);
543 }
544 
545 static void
wakeup_handler(void * data,int err)546 wakeup_handler(void *data, int err)
547 {
548 }
549 
550 static void
block_handler(void * data,void * timeout)551 block_handler(void *data, void *timeout)
552 {
553     struct xwl_screen *xwl_screen = data;
554 
555     xwl_screen_post_damage(xwl_screen);
556     xwl_dispatch_events (xwl_screen);
557 }
558 
559 void
xwl_sync_events(struct xwl_screen * xwl_screen)560 xwl_sync_events (struct xwl_screen *xwl_screen)
561 {
562     xwl_dispatch_events (xwl_screen);
563     xwl_read_events (xwl_screen);
564 }
565 
xwl_surface_damage(struct xwl_screen * xwl_screen,struct wl_surface * surface,int32_t x,int32_t y,int32_t width,int32_t height)566 void xwl_surface_damage(struct xwl_screen *xwl_screen,
567                         struct wl_surface *surface,
568                         int32_t x, int32_t y, int32_t width, int32_t height)
569 {
570     if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
571         wl_surface_damage_buffer(surface, x, y, width, height);
572     else {
573         x = xwl_scale_to(xwl_screen, x);
574         y = xwl_scale_to(xwl_screen, y);
575         width = xwl_scale_to(xwl_screen, width);
576         height = xwl_scale_to(xwl_screen, height);
577 
578         wl_surface_damage(surface, x, y, width, height);
579     }
580 }
581 
582 void
xwl_screen_roundtrip(struct xwl_screen * xwl_screen)583 xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
584 {
585     int ret;
586 
587     ret = wl_display_roundtrip(xwl_screen->display);
588     while (ret >= 0 && xwl_screen->expecting_event)
589         ret = wl_display_roundtrip(xwl_screen->display);
590 
591     if (ret < 0)
592         xwl_give_up("could not connect to wayland server\n");
593 }
594 
595 void
xwl_screen_set_global_scale(struct xwl_screen * xwl_screen,int32_t scale)596 xwl_screen_set_global_scale( struct xwl_screen *xwl_screen, int32_t scale)
597 {
598     struct xwl_output *it;
599     xwl_screen->global_output_scale = scale;
600 
601     /* change randr resolutions and positions */
602     xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
603         xwl_output_apply_changes(it);
604     }
605 }
606 
607 Bool
xwl_screen_init(ScreenPtr pScreen,int argc,char ** argv)608 xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
609 {
610     static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
611     struct xwl_screen *xwl_screen;
612     Pixel red_mask, blue_mask, green_mask;
613     int ret, bpc, green_bpc, i;
614 #ifdef XWL_HAS_GLAMOR
615     Bool use_eglstreams = FALSE;
616 #endif
617 
618     if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
619         return FALSE;
620     if (!xwl_pixmap_init())
621         return FALSE;
622     if (!xwl_window_init())
623         return FALSE;
624     /* There are no easy to use new / delete client hooks, we could use a
625      * ClientStateCallback, but it is easier to let the dix code manage the
626      * memory for us. This will zero fill the initial xwl_client data.
627      */
628     if (!dixRegisterPrivateKey(&xwl_client_private_key, PRIVATE_CLIENT,
629                                sizeof(struct xwl_client)))
630         return FALSE;
631 
632     xwl_screen = calloc(1, sizeof *xwl_screen);
633     if (xwl_screen == NULL)
634         return FALSE;
635 
636     dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
637     xwl_screen->screen = pScreen;
638 
639 #ifdef XWL_HAS_GLAMOR
640     xwl_screen->glamor = 1;
641 #endif
642     xwl_screen->global_output_scale = 1;
643 
644     for (i = 1; i < argc; i++) {
645         if (strcmp(argv[i], "-rootless") == 0) {
646             xwl_screen->rootless = 1;
647 
648             /* Disable the XSS extension on Xwayland rootless.
649              *
650              * Xwayland is just a Wayland client, no X11 screensaver
651              * should be expected to work reliably on Xwayland rootless.
652              */
653 #ifdef SCREENSAVER
654             noScreenSaverExtension = TRUE;
655 #endif
656             ScreenSaverTime = 0;
657             ScreenSaverInterval = 0;
658             defaultScreenSaverTime = 0;
659             defaultScreenSaverInterval = 0;
660         }
661         else if (strcmp(argv[i], "-shm") == 0) {
662             xwl_screen->glamor = 0;
663         }
664         else if (strcmp(argv[i], "-eglstream") == 0) {
665 #ifdef XWL_HAS_EGLSTREAM
666             use_eglstreams = TRUE;
667 #else
668             ErrorF("xwayland glamor: this build does not have EGLStream support\n");
669 #endif
670         }
671     }
672 
673 #ifdef XWL_HAS_GLAMOR
674     if (xwl_screen->glamor)
675         xwl_glamor_init_backends(xwl_screen, use_eglstreams);
676 #endif
677 
678     /* In rootless mode, we don't have any screen storage, and the only
679      * rendering should be to redirected mode. */
680     if (xwl_screen->rootless)
681         xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY;
682     else
683         xwl_screen->root_clip_mode = ROOT_CLIP_FULL;
684 
685     xorg_list_init(&xwl_screen->output_list);
686     xorg_list_init(&xwl_screen->seat_list);
687     xorg_list_init(&xwl_screen->damage_window_list);
688     xorg_list_init(&xwl_screen->window_list);
689     xorg_list_init(&xwl_screen->drm_lease_devices);
690     xorg_list_init(&xwl_screen->queued_drm_lease_devices);
691     xorg_list_init(&xwl_screen->drm_leases);
692     xwl_screen->depth = 24;
693 
694     if (!monitorResolution)
695         monitorResolution = DEFAULT_DPI;
696 
697     xwl_screen->display = wl_display_connect(NULL);
698     if (xwl_screen->display == NULL) {
699         ErrorF("could not connect to wayland server\n");
700         return FALSE;
701     }
702 
703     if (!xwl_screen_init_output(xwl_screen))
704         return FALSE;
705 
706     xwl_screen->expecting_event = 0;
707     xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
708     wl_registry_add_listener(xwl_screen->registry,
709                              &registry_listener, xwl_screen);
710     xwl_screen_roundtrip(xwl_screen);
711 
712     if (!xwl_screen->rootless && !xwl_screen->xdg_wm_base) {
713         ErrorF("missing XDG-WM-Base protocol\n");
714         return FALSE;
715     }
716 
717     bpc = xwl_screen->depth / 3;
718     green_bpc = xwl_screen->depth - 2 * bpc;
719     blue_mask = (1 << bpc) - 1;
720     green_mask = ((1 << green_bpc) - 1) << bpc;
721     red_mask = blue_mask << (green_bpc + bpc);
722 
723     miSetVisualTypesAndMasks(xwl_screen->depth,
724                              ((1 << TrueColor) | (1 << DirectColor)),
725                              green_bpc, TrueColor,
726                              red_mask, green_mask, blue_mask);
727 
728     miSetPixmapDepths();
729 
730     ret = fbScreenInit(pScreen, NULL,
731                        xwl_screen->width, xwl_screen->height,
732                        monitorResolution, monitorResolution, 0,
733                        BitsPerPixel(xwl_screen->depth));
734     if (!ret)
735         return FALSE;
736 
737     fbPictureInit(pScreen, 0, 0);
738 
739 #ifdef MITSHM
740     ShmRegisterFbFuncs(pScreen);
741 #endif
742 
743 #ifdef HAVE_XSHMFENCE
744     if (!miSyncShmScreenInit(pScreen))
745         return FALSE;
746 #endif
747 
748     xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
749     SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen);
750     RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
751 
752     pScreen->blackPixel = 0;
753     pScreen->whitePixel = 1;
754 
755     ret = fbCreateDefColormap(pScreen);
756 
757     if (!xwl_screen_init_cursor(xwl_screen))
758         return FALSE;
759 
760 #ifdef XWL_HAS_GLAMOR
761     if (xwl_screen->glamor) {
762         xwl_glamor_select_backend(xwl_screen, use_eglstreams);
763 
764         if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
765            ErrorF("Failed to initialize glamor, falling back to sw\n");
766            xwl_screen->glamor = 0;
767         }
768     }
769 
770     if (xwl_screen->glamor && xwl_screen->rootless)
771         xwl_screen->present = xwl_present_init(pScreen);
772 #endif
773 
774     if (!xwl_screen->glamor) {
775         xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
776         pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
777         pScreen->CreatePixmap = xwl_shm_create_pixmap;
778         pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
779     }
780 
781     xwl_screen->RealizeWindow = pScreen->RealizeWindow;
782     pScreen->RealizeWindow = xwl_realize_window;
783 
784     xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
785     pScreen->UnrealizeWindow = xwl_unrealize_window;
786 
787     xwl_screen->DestroyWindow = pScreen->DestroyWindow;
788     pScreen->DestroyWindow = xwl_destroy_window;
789 
790     xwl_screen->CloseScreen = pScreen->CloseScreen;
791     pScreen->CloseScreen = xwl_close_screen;
792 
793     xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
794     pScreen->ChangeWindowAttributes = xwl_change_window_attributes;
795 
796     xwl_screen->ResizeWindow = pScreen->ResizeWindow;
797     pScreen->ResizeWindow = xwl_resize_window;
798 
799     xwl_screen->MoveWindow = pScreen->MoveWindow;
800     pScreen->MoveWindow = xwl_move_window;
801 
802     if (xwl_screen->rootless) {
803         xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
804         pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
805     }
806 
807     pScreen->CursorWarpedTo = xwl_cursor_warped_to;
808     pScreen->CursorConfinedTo = xwl_cursor_confined_to;
809 
810     xwl_screen->allow_commits_prop = MakeAtom(allow_commits,
811                                               strlen(allow_commits),
812                                               TRUE);
813     if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
814         return FALSE;
815 
816     AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
817     AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen);
818 
819     xwl_screen_roundtrip(xwl_screen);
820 
821     return ret;
822 }
823