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.h"
27
28 #include <stdio.h>
29
30 #include <X11/Xatom.h>
31 #include <selection.h>
32 #include <micmap.h>
33 #include <misyncshm.h>
34 #include <compositeext.h>
35 #include <compint.h>
36 #include <glx_extinit.h>
37 #include <os.h>
38 #include <xserver_poll.h>
39 #include <propertyst.h>
40
41 #ifdef XF86VIDMODE
42 #include <X11/extensions/xf86vmproto.h>
43 extern _X_EXPORT Bool noXFree86VidModeExtension;
44 #endif
45
46 #ifdef XWL_HAS_GLAMOR
47 #include <glamor.h>
48 #endif
49
50 void
ddxGiveUp(enum ExitCode error)51 ddxGiveUp(enum ExitCode error)
52 {
53 }
54
55 void
AbortDDX(enum ExitCode error)56 AbortDDX(enum ExitCode error)
57 {
58 ddxGiveUp(error);
59 }
60
61 void
OsVendorInit(void)62 OsVendorInit(void)
63 {
64 if (serverGeneration == 1)
65 ForceClockId(CLOCK_MONOTONIC);
66 }
67
68 void
OsVendorFatalError(const char * f,va_list args)69 OsVendorFatalError(const char *f, va_list args)
70 {
71 }
72
73 #if defined(DDXBEFORERESET)
74 void
ddxBeforeReset(void)75 ddxBeforeReset(void)
76 {
77 return;
78 }
79 #endif
80
81 #if INPUTTHREAD
82 /** This function is called in Xserver/os/inputthread.c when starting
83 the input thread. */
84 void
ddxInputThreadInit(void)85 ddxInputThreadInit(void)
86 {
87 }
88 #endif
89
90 #define DEFAULT_DPI 96
91
92 _X_NORETURN
93 static void _X_ATTRIBUTE_PRINTF(1, 2)
xwl_give_up(const char * f,...)94 xwl_give_up(const char *f, ...)
95 {
96 va_list args;
97
98 va_start(args, f);
99 VErrorFSigSafe(f, args);
100 va_end(args);
101
102 CloseWellKnownConnections();
103 OsCleanup(TRUE);
104 fflush(stderr);
105 exit(1);
106 }
107
108 void
ddxUseMsg(void)109 ddxUseMsg(void)
110 {
111 ErrorF("-rootless run rootless, requires wm support\n");
112 ErrorF("-wm fd create X client for wm on given fd\n");
113 ErrorF("-listen fd add give fd as a listen socket\n");
114 ErrorF("-eglstream use eglstream backend for nvidia GPUs\n");
115 }
116
117 int
ddxProcessArgument(int argc,char * argv[],int i)118 ddxProcessArgument(int argc, char *argv[], int i)
119 {
120 if (strcmp(argv[i], "-rootless") == 0) {
121 return 1;
122 }
123 else if (strcmp(argv[i], "-listen") == 0) {
124 NoListenAll = TRUE;
125 return 2;
126 }
127 else if (strcmp(argv[i], "-wm") == 0) {
128 return 2;
129 }
130 else if (strcmp(argv[i], "-shm") == 0) {
131 return 1;
132 }
133 else if (strcmp(argv[i], "-eglstream") == 0) {
134 return 1;
135 }
136
137 return 0;
138 }
139
140 static DevPrivateKeyRec xwl_window_private_key;
141 static DevPrivateKeyRec xwl_screen_private_key;
142 static DevPrivateKeyRec xwl_pixmap_private_key;
143 static DevPrivateKeyRec xwl_damage_private_key;
144
145 static struct xwl_window *
xwl_window_get(WindowPtr window)146 xwl_window_get(WindowPtr window)
147 {
148 return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
149 }
150
151 struct xwl_screen *
xwl_screen_get(ScreenPtr screen)152 xwl_screen_get(ScreenPtr screen)
153 {
154 return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
155 }
156
157 static void
xwl_window_set_allow_commits(struct xwl_window * xwl_window,Bool allow,const char * debug_msg)158 xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
159 const char *debug_msg)
160 {
161 xwl_window->allow_commits = allow;
162 DebugF("xwayland: win %d allow_commits = %d (%s)\n",
163 xwl_window->window->drawable.id, allow, debug_msg);
164 }
165
166 static void
xwl_window_set_allow_commits_from_property(struct xwl_window * xwl_window,PropertyPtr prop)167 xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window,
168 PropertyPtr prop)
169 {
170 static Bool warned = FALSE;
171 CARD32 *propdata;
172
173 if (prop->propertyName != xwl_window->xwl_screen->allow_commits_prop)
174 FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__);
175
176 if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
177 /* Not properly set, so fall back to safe and glitchy */
178 xwl_window_set_allow_commits(xwl_window, TRUE, "WM fault");
179
180 if (!warned) {
181 LogMessageVerb(X_WARNING, 0, "Window manager is misusing property %s.\n",
182 NameForAtom(prop->propertyName));
183 warned = TRUE;
184 }
185 return;
186 }
187
188 propdata = prop->data;
189 xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property");
190 }
191
192 static void
xwl_window_property_allow_commits(struct xwl_window * xwl_window,PropertyStateRec * propstate)193 xwl_window_property_allow_commits(struct xwl_window *xwl_window,
194 PropertyStateRec *propstate)
195 {
196 switch (propstate->state) {
197 case PropertyNewValue:
198 xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
199 break;
200
201 case PropertyDelete:
202 xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
203 break;
204
205 default:
206 break;
207 }
208 }
209
210 static void
xwl_property_callback(CallbackListPtr * pcbl,void * closure,void * calldata)211 xwl_property_callback(CallbackListPtr *pcbl, void *closure,
212 void *calldata)
213 {
214 ScreenPtr screen = closure;
215 PropertyStateRec *rec = calldata;
216 struct xwl_screen *xwl_screen;
217 struct xwl_window *xwl_window;
218
219 if (rec->win->drawable.pScreen != screen)
220 return;
221
222 xwl_window = xwl_window_get(rec->win);
223 if (!xwl_window)
224 return;
225
226 xwl_screen = xwl_screen_get(screen);
227
228 if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
229 xwl_window_property_allow_commits(xwl_window, rec);
230 }
231
232 static Bool
xwl_close_screen(ScreenPtr screen)233 xwl_close_screen(ScreenPtr screen)
234 {
235 struct xwl_screen *xwl_screen = xwl_screen_get(screen);
236 struct xwl_output *xwl_output, *next_xwl_output;
237 struct xwl_seat *xwl_seat, *next_xwl_seat;
238
239 DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
240
241 xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
242 &xwl_screen->output_list, link)
243 xwl_output_destroy(xwl_output);
244
245 xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
246 &xwl_screen->seat_list, link)
247 xwl_seat_destroy(xwl_seat);
248
249 xwl_screen_release_tablet_manager(xwl_screen);
250
251 RemoveNotifyFd(xwl_screen->wayland_fd);
252
253 wl_display_disconnect(xwl_screen->display);
254
255 screen->CloseScreen = xwl_screen->CloseScreen;
256 free(xwl_screen);
257
258 return screen->CloseScreen(screen);
259 }
260
261 struct xwl_window *
xwl_window_from_window(WindowPtr window)262 xwl_window_from_window(WindowPtr window)
263 {
264 struct xwl_window *xwl_window;
265
266 while (window) {
267 xwl_window = xwl_window_get(window);
268 if (xwl_window)
269 return xwl_window;
270
271 window = window->parent;
272 }
273
274 return NULL;
275 }
276
277 static struct xwl_seat *
xwl_screen_get_default_seat(struct xwl_screen * xwl_screen)278 xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
279 {
280 if (xorg_list_is_empty(&xwl_screen->seat_list))
281 return NULL;
282
283 return container_of(xwl_screen->seat_list.prev,
284 struct xwl_seat,
285 link);
286 }
287
288 static void
xwl_cursor_warped_to(DeviceIntPtr device,ScreenPtr screen,ClientPtr client,WindowPtr window,SpritePtr sprite,int x,int y)289 xwl_cursor_warped_to(DeviceIntPtr device,
290 ScreenPtr screen,
291 ClientPtr client,
292 WindowPtr window,
293 SpritePtr sprite,
294 int x, int y)
295 {
296 struct xwl_screen *xwl_screen = xwl_screen_get(screen);
297 struct xwl_seat *xwl_seat = device->public.devicePrivate;
298 struct xwl_window *xwl_window;
299 WindowPtr focus;
300
301 if (!xwl_seat)
302 xwl_seat = xwl_screen_get_default_seat(xwl_screen);
303
304 if (!window)
305 window = XYToWindow(sprite, x, y);
306
307 xwl_window = xwl_window_from_window(window);
308 if (!xwl_window && xwl_seat->focus_window) {
309 focus = xwl_seat->focus_window->window;
310
311 /* Warps on non wl_surface backed Windows are only allowed
312 * as long as the pointer stays within the focus window.
313 */
314 if (x >= focus->drawable.x &&
315 y >= focus->drawable.y &&
316 x < focus->drawable.x + focus->drawable.width &&
317 y < focus->drawable.y + focus->drawable.height) {
318 if (!window) {
319 DebugF("Warp relative to pointer, assuming pointer focus\n");
320 xwl_window = xwl_seat->focus_window;
321 } else if (window == screen->root) {
322 DebugF("Warp on root window, assuming pointer focus\n");
323 xwl_window = xwl_seat->focus_window;
324 }
325 }
326 }
327 if (!xwl_window)
328 return;
329
330 xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
331 }
332
333 static void
xwl_cursor_confined_to(DeviceIntPtr device,ScreenPtr screen,WindowPtr window)334 xwl_cursor_confined_to(DeviceIntPtr device,
335 ScreenPtr screen,
336 WindowPtr window)
337 {
338 struct xwl_screen *xwl_screen = xwl_screen_get(screen);
339 struct xwl_seat *xwl_seat = device->public.devicePrivate;
340 struct xwl_window *xwl_window;
341
342 if (!xwl_seat)
343 xwl_seat = xwl_screen_get_default_seat(xwl_screen);
344
345 /* xwl_seat hasn't been setup yet, don't do anything just yet */
346 if (!xwl_seat)
347 return;
348
349 if (window == screen->root) {
350 xwl_seat_unconfine_pointer(xwl_seat);
351 return;
352 }
353
354 xwl_window = xwl_window_from_window(window);
355 if (!xwl_window && xwl_seat->focus_window) {
356 /* Allow confining on InputOnly windows, but only if the geometry
357 * is the same than the focus window.
358 */
359 if (window->drawable.class == InputOnly) {
360 DebugF("Confine on InputOnly window, assuming pointer focus\n");
361 xwl_window = xwl_seat->focus_window;
362 }
363 }
364 if (!xwl_window)
365 return;
366
367 xwl_seat_confine_pointer(xwl_seat, xwl_window);
368 }
369
370 static void
damage_report(DamagePtr pDamage,RegionPtr pRegion,void * data)371 damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
372 {
373 WindowPtr window = data;
374 struct xwl_window *xwl_window = xwl_window_get(window);
375 struct xwl_screen *xwl_screen;
376
377 if (!xwl_window)
378 return;
379
380 xwl_screen = xwl_window->xwl_screen;
381
382 #ifdef GLAMOR_HAS_GBM
383 if (xwl_window->present_flipped) {
384 /* This damage is from a Present flip, which already committed a new
385 * buffer for the surface, so we don't need to do anything in response
386 */
387 RegionEmpty(DamageRegion(pDamage));
388 xorg_list_del(&xwl_window->link_damage);
389 xwl_window->present_flipped = FALSE;
390 return;
391 }
392 #endif
393
394 xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
395 }
396
397 static void
damage_destroy(DamagePtr pDamage,void * data)398 damage_destroy(DamagePtr pDamage, void *data)
399 {
400 }
401
402 static Bool
register_damage(WindowPtr window)403 register_damage(WindowPtr window)
404 {
405 DamagePtr damage;
406
407 damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
408 FALSE, window->drawable.pScreen, window);
409 if (damage == NULL) {
410 ErrorF("Failed creating damage\n");
411 return FALSE;
412 }
413
414 DamageRegister(&window->drawable, damage);
415 DamageSetReportAfterOp(damage, TRUE);
416
417 dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
418
419 return TRUE;
420 }
421
422 static void
unregister_damage(WindowPtr window)423 unregister_damage(WindowPtr window)
424 {
425 DamagePtr damage;
426
427 damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
428 if (!damage)
429 return;
430
431 DamageUnregister(damage);
432 DamageDestroy(damage);
433
434 dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
435 }
436
437 static DamagePtr
window_get_damage(WindowPtr window)438 window_get_damage(WindowPtr window)
439 {
440 return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
441 }
442
443 static void
shell_surface_ping(void * data,struct wl_shell_surface * shell_surface,uint32_t serial)444 shell_surface_ping(void *data,
445 struct wl_shell_surface *shell_surface, uint32_t serial)
446 {
447 wl_shell_surface_pong(shell_surface, serial);
448 }
449
450 static void
shell_surface_configure(void * data,struct wl_shell_surface * wl_shell_surface,uint32_t edges,int32_t width,int32_t height)451 shell_surface_configure(void *data,
452 struct wl_shell_surface *wl_shell_surface,
453 uint32_t edges, int32_t width, int32_t height)
454 {
455 }
456
457 static void
shell_surface_popup_done(void * data,struct wl_shell_surface * wl_shell_surface)458 shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
459 {
460 }
461
462 static const struct wl_shell_surface_listener shell_surface_listener = {
463 shell_surface_ping,
464 shell_surface_configure,
465 shell_surface_popup_done
466 };
467
468 void
xwl_pixmap_set_private(PixmapPtr pixmap,struct xwl_pixmap * xwl_pixmap)469 xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap)
470 {
471 dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap);
472 }
473
474 struct xwl_pixmap *
xwl_pixmap_get(PixmapPtr pixmap)475 xwl_pixmap_get(PixmapPtr pixmap)
476 {
477 return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
478 }
479
480 static void
xwl_window_init_allow_commits(struct xwl_window * xwl_window)481 xwl_window_init_allow_commits(struct xwl_window *xwl_window)
482 {
483 PropertyPtr prop = NULL;
484 int ret;
485
486 ret = dixLookupProperty(&prop, xwl_window->window,
487 xwl_window->xwl_screen->allow_commits_prop,
488 serverClient, DixReadAccess);
489 if (ret == Success && prop)
490 xwl_window_set_allow_commits_from_property(xwl_window, prop);
491 else
492 xwl_window_set_allow_commits(xwl_window, TRUE, "no property");
493 }
494
495 static void
send_surface_id_event(struct xwl_window * xwl_window)496 send_surface_id_event(struct xwl_window *xwl_window)
497 {
498 static const char atom_name[] = "WL_SURFACE_ID";
499 static Atom type_atom;
500 DeviceIntPtr dev;
501 xEvent e;
502
503 if (type_atom == None)
504 type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
505
506 e.u.u.type = ClientMessage;
507 e.u.u.detail = 32;
508 e.u.clientMessage.window = xwl_window->window->drawable.id;
509 e.u.clientMessage.u.l.type = type_atom;
510 e.u.clientMessage.u.l.longs0 =
511 wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
512 e.u.clientMessage.u.l.longs1 = 0;
513 e.u.clientMessage.u.l.longs2 = 0;
514 e.u.clientMessage.u.l.longs3 = 0;
515 e.u.clientMessage.u.l.longs4 = 0;
516
517 dev = PickPointer(serverClient);
518 DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
519 &e, 1, SubstructureRedirectMask, NullGrab);
520 }
521
522 static Bool
ensure_surface_for_window(WindowPtr window)523 ensure_surface_for_window(WindowPtr window)
524 {
525 ScreenPtr screen = window->drawable.pScreen;
526 struct xwl_screen *xwl_screen;
527 struct xwl_window *xwl_window;
528 struct wl_region *region;
529
530 if (xwl_window_from_window(window))
531 return TRUE;
532
533 xwl_screen = xwl_screen_get(screen);
534
535 if (xwl_screen->rootless) {
536 if (window->redirectDraw != RedirectDrawManual)
537 return TRUE;
538 }
539 else {
540 if (window->parent)
541 return TRUE;
542 }
543
544 xwl_window = calloc(1, sizeof *xwl_window);
545 if (xwl_window == NULL)
546 return FALSE;
547
548 xwl_window->xwl_screen = xwl_screen;
549 xwl_window->window = window;
550 xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
551 if (xwl_window->surface == NULL) {
552 ErrorF("wl_display_create_surface failed\n");
553 goto err;
554 }
555
556 if (!xwl_screen->rootless) {
557 xwl_window->shell_surface =
558 wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
559 if (xwl_window->shell_surface == NULL) {
560 ErrorF("Failed creating shell surface\n");
561 goto err_surf;
562 }
563
564 wl_shell_surface_add_listener(xwl_window->shell_surface,
565 &shell_surface_listener, xwl_window);
566
567 wl_shell_surface_set_toplevel(xwl_window->shell_surface);
568
569 region = wl_compositor_create_region(xwl_screen->compositor);
570 if (region == NULL) {
571 ErrorF("Failed creating region\n");
572 goto err_surf;
573 }
574
575 wl_region_add(region, 0, 0,
576 window->drawable.width, window->drawable.height);
577 wl_surface_set_opaque_region(xwl_window->surface, region);
578 wl_region_destroy(region);
579 }
580
581 wl_display_flush(xwl_screen->display);
582
583 send_surface_id_event(xwl_window);
584
585 wl_surface_set_user_data(xwl_window->surface, xwl_window);
586
587 compRedirectWindow(serverClient, window, CompositeRedirectManual);
588
589 dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
590 xorg_list_init(&xwl_window->link_damage);
591
592 #ifdef GLAMOR_HAS_GBM
593 xorg_list_init(&xwl_window->frame_callback_list);
594 #endif
595
596 xwl_window_init_allow_commits(xwl_window);
597
598 return TRUE;
599
600 err_surf:
601 if (xwl_window->shell_surface)
602 wl_shell_surface_destroy(xwl_window->shell_surface);
603 wl_surface_destroy(xwl_window->surface);
604 err:
605 free(xwl_window);
606 return FALSE;
607 }
608
609 static Bool
xwl_realize_window(WindowPtr window)610 xwl_realize_window(WindowPtr window)
611 {
612 ScreenPtr screen = window->drawable.pScreen;
613 struct xwl_screen *xwl_screen;
614 Bool ret;
615
616 xwl_screen = xwl_screen_get(screen);
617
618 screen->RealizeWindow = xwl_screen->RealizeWindow;
619 ret = (*screen->RealizeWindow) (window);
620 xwl_screen->RealizeWindow = screen->RealizeWindow;
621 screen->RealizeWindow = xwl_realize_window;
622
623 if (!ret)
624 return FALSE;
625
626 if (xwl_screen->rootless && !window->parent) {
627 BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
628
629 RegionReset(&window->winSize, &box);
630 RegionNull(&window->clipList);
631 RegionNull(&window->borderClip);
632 }
633
634 if (xwl_screen->rootless ?
635 (window->drawable.class == InputOutput &&
636 window->parent == window->drawable.pScreen->root) :
637 !window->parent) {
638 if (!register_damage(window))
639 return FALSE;
640 }
641
642 return ensure_surface_for_window(window);
643 }
644
645 static Bool
xwl_unrealize_window(WindowPtr window)646 xwl_unrealize_window(WindowPtr window)
647 {
648 ScreenPtr screen = window->drawable.pScreen;
649 struct xwl_screen *xwl_screen;
650 struct xwl_window *xwl_window;
651 struct xwl_seat *xwl_seat;
652 Bool ret;
653
654 xwl_screen = xwl_screen_get(screen);
655
656 xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
657 if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
658 xwl_seat->focus_window = NULL;
659 if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
660 xwl_seat->tablet_focus_window = NULL;
661 if (xwl_seat->last_xwindow == window)
662 xwl_seat->last_xwindow = NullWindow;
663 if (xwl_seat->cursor_confinement_window &&
664 xwl_seat->cursor_confinement_window->window == window)
665 xwl_seat_unconfine_pointer(xwl_seat);
666 if (xwl_seat->pointer_warp_emulator &&
667 xwl_seat->pointer_warp_emulator->locked_window &&
668 xwl_seat->pointer_warp_emulator->locked_window->window == window)
669 xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
670 xwl_seat_clear_touch(xwl_seat, window);
671 }
672
673 compUnredirectWindow(serverClient, window, CompositeRedirectManual);
674
675 screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
676 ret = (*screen->UnrealizeWindow) (window);
677 xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
678 screen->UnrealizeWindow = xwl_unrealize_window;
679
680 xwl_window = xwl_window_get(window);
681 if (!xwl_window)
682 return ret;
683
684 wl_surface_destroy(xwl_window->surface);
685 xorg_list_del(&xwl_window->link_damage);
686 unregister_damage(window);
687
688 if (xwl_window->frame_callback)
689 wl_callback_destroy(xwl_window->frame_callback);
690
691 #ifdef GLAMOR_HAS_GBM
692 if (xwl_screen->present) {
693 struct xwl_present_window *xwl_present_window, *tmp;
694
695 xorg_list_for_each_entry_safe(xwl_present_window, tmp,
696 &xwl_window->frame_callback_list,
697 frame_callback_list) {
698 xwl_present_unrealize_window(xwl_present_window);
699 }
700 }
701 #endif
702
703 free(xwl_window);
704 dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
705
706 return ret;
707 }
708
709 static Bool
xwl_save_screen(ScreenPtr pScreen,int on)710 xwl_save_screen(ScreenPtr pScreen, int on)
711 {
712 return TRUE;
713 }
714
715 static void
xwl_set_window_pixmap(WindowPtr window,PixmapPtr pixmap)716 xwl_set_window_pixmap(WindowPtr window,
717 PixmapPtr pixmap)
718 {
719 ScreenPtr screen = window->drawable.pScreen;
720 struct xwl_screen *xwl_screen;
721
722 xwl_screen = xwl_screen_get(screen);
723
724 screen->SetWindowPixmap = xwl_screen->SetWindowPixmap;
725 (*screen->SetWindowPixmap) (window, pixmap);
726 xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
727 screen->SetWindowPixmap = xwl_set_window_pixmap;
728
729 if (!RegionNotEmpty(&window->winSize))
730 return;
731
732 ensure_surface_for_window(window);
733 }
734
735 static void
frame_callback(void * data,struct wl_callback * callback,uint32_t time)736 frame_callback(void *data,
737 struct wl_callback *callback,
738 uint32_t time)
739 {
740 struct xwl_window *xwl_window = data;
741
742 wl_callback_destroy (xwl_window->frame_callback);
743 xwl_window->frame_callback = NULL;
744
745 #ifdef GLAMOR_HAS_GBM
746 if (xwl_window->xwl_screen->present) {
747 struct xwl_present_window *xwl_present_window, *tmp;
748
749 xorg_list_for_each_entry_safe(xwl_present_window, tmp,
750 &xwl_window->frame_callback_list,
751 frame_callback_list) {
752 xwl_present_frame_callback(xwl_present_window);
753 }
754 }
755 #endif
756 }
757
758 static const struct wl_callback_listener frame_listener = {
759 frame_callback
760 };
761
762 void
xwl_window_create_frame_callback(struct xwl_window * xwl_window)763 xwl_window_create_frame_callback(struct xwl_window *xwl_window)
764 {
765 xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
766 wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
767 xwl_window);
768 }
769
770 static Bool
xwl_destroy_window(WindowPtr window)771 xwl_destroy_window(WindowPtr window)
772 {
773 ScreenPtr screen = window->drawable.pScreen;
774 struct xwl_screen *xwl_screen = xwl_screen_get(screen);
775 Bool ret;
776
777 #ifdef GLAMOR_HAS_GBM
778 if (xwl_screen->present)
779 xwl_present_cleanup(window);
780 #endif
781
782 screen->DestroyWindow = xwl_screen->DestroyWindow;
783
784 if (screen->DestroyWindow)
785 ret = screen->DestroyWindow (window);
786 else
787 ret = TRUE;
788
789 xwl_screen->DestroyWindow = screen->DestroyWindow;
790 screen->DestroyWindow = xwl_destroy_window;
791
792 return ret;
793 }
794
795 static void
xwl_window_post_damage(struct xwl_window * xwl_window)796 xwl_window_post_damage(struct xwl_window *xwl_window)
797 {
798 struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
799 RegionPtr region;
800 BoxPtr box;
801 struct wl_buffer *buffer;
802 PixmapPtr pixmap;
803 int i;
804
805 assert(!xwl_window->frame_callback);
806
807 region = DamageRegion(window_get_damage(xwl_window->window));
808 pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
809
810 #ifdef XWL_HAS_GLAMOR
811 if (xwl_screen->glamor)
812 buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap,
813 NULL);
814 else
815 #endif
816 buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
817
818 #ifdef XWL_HAS_GLAMOR
819 if (xwl_screen->glamor)
820 xwl_glamor_post_damage(xwl_window, pixmap, region);
821 #endif
822
823 wl_surface_attach(xwl_window->surface, buffer, 0, 0);
824
825 /* Arbitrary limit to try to avoid flooding the Wayland
826 * connection. If we flood it too much anyway, this could
827 * abort in libwayland-client.
828 */
829 if (RegionNumRects(region) > 256) {
830 box = RegionExtents(region);
831 wl_surface_damage(xwl_window->surface, box->x1, box->y1,
832 box->x2 - box->x1, box->y2 - box->y1);
833 } else {
834 box = RegionRects(region);
835 for (i = 0; i < RegionNumRects(region); i++, box++)
836 wl_surface_damage(xwl_window->surface, box->x1, box->y1,
837 box->x2 - box->x1, box->y2 - box->y1);
838 }
839
840 xwl_window_create_frame_callback(xwl_window);
841 DamageEmpty(window_get_damage(xwl_window->window));
842 }
843
844 static void
xwl_screen_post_damage(struct xwl_screen * xwl_screen)845 xwl_screen_post_damage(struct xwl_screen *xwl_screen)
846 {
847 struct xwl_window *xwl_window, *next_xwl_window;
848 struct xorg_list commit_window_list;
849
850 xorg_list_init(&commit_window_list);
851
852 xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
853 &xwl_screen->damage_window_list, link_damage) {
854 /* If we're waiting on a frame callback from the server,
855 * don't attach a new buffer. */
856 if (xwl_window->frame_callback)
857 continue;
858
859 if (!xwl_window->allow_commits)
860 continue;
861
862 #ifdef XWL_HAS_GLAMOR
863 if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
864 continue;
865 #endif
866
867 xwl_window_post_damage(xwl_window);
868 xorg_list_del(&xwl_window->link_damage);
869 xorg_list_append(&xwl_window->link_damage, &commit_window_list);
870 }
871
872 if (xorg_list_is_empty(&commit_window_list))
873 return;
874
875 #ifdef XWL_HAS_GLAMOR
876 if (xwl_screen->glamor &&
877 xwl_screen->egl_backend == &xwl_screen->gbm_backend) {
878 glamor_block_handler(xwl_screen->screen);
879 }
880 #endif
881
882 xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
883 &commit_window_list, link_damage) {
884 wl_surface_commit(xwl_window->surface);
885 xorg_list_del(&xwl_window->link_damage);
886 }
887 }
888
889 static void
registry_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)890 registry_global(void *data, struct wl_registry *registry, uint32_t id,
891 const char *interface, uint32_t version)
892 {
893 struct xwl_screen *xwl_screen = data;
894
895 if (strcmp(interface, "wl_compositor") == 0) {
896 xwl_screen->compositor =
897 wl_registry_bind(registry, id, &wl_compositor_interface, 1);
898 }
899 else if (strcmp(interface, "wl_shm") == 0) {
900 xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
901 }
902 else if (strcmp(interface, "wl_shell") == 0) {
903 xwl_screen->shell =
904 wl_registry_bind(registry, id, &wl_shell_interface, 1);
905 }
906 else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
907 if (xwl_output_create(xwl_screen, id))
908 xwl_screen->expecting_event++;
909 }
910 else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
911 xwl_screen->xdg_output_manager =
912 wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1);
913 xwl_screen_init_xdg_output(xwl_screen);
914 }
915 #ifdef XWL_HAS_GLAMOR
916 else if (xwl_screen->glamor) {
917 xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
918 version);
919 }
920 #endif
921 }
922
923 static void
global_remove(void * data,struct wl_registry * registry,uint32_t name)924 global_remove(void *data, struct wl_registry *registry, uint32_t name)
925 {
926 struct xwl_screen *xwl_screen = data;
927 struct xwl_output *xwl_output, *tmp_xwl_output;
928
929 xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
930 &xwl_screen->output_list, link) {
931 if (xwl_output->server_output_id == name) {
932 xwl_output_remove(xwl_output);
933 break;
934 }
935 }
936 }
937
938 static const struct wl_registry_listener registry_listener = {
939 registry_global,
940 global_remove
941 };
942
943 static void
xwl_read_events(struct xwl_screen * xwl_screen)944 xwl_read_events (struct xwl_screen *xwl_screen)
945 {
946 int ret;
947
948 if (xwl_screen->wait_flush)
949 return;
950
951 ret = wl_display_read_events(xwl_screen->display);
952 if (ret == -1)
953 xwl_give_up("failed to read Wayland events: %s\n", strerror(errno));
954
955 xwl_screen->prepare_read = 0;
956
957 ret = wl_display_dispatch_pending(xwl_screen->display);
958 if (ret == -1)
959 xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
960 }
961
962 static int
xwl_display_pollout(struct xwl_screen * xwl_screen,int timeout)963 xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
964 {
965 struct pollfd poll_fd;
966
967 poll_fd.fd = wl_display_get_fd(xwl_screen->display);
968 poll_fd.events = POLLOUT;
969
970 return xserver_poll(&poll_fd, 1, timeout);
971 }
972
973 static void
xwl_dispatch_events(struct xwl_screen * xwl_screen)974 xwl_dispatch_events (struct xwl_screen *xwl_screen)
975 {
976 int ret = 0;
977 int ready;
978
979 if (xwl_screen->wait_flush)
980 goto pollout;
981
982 while (xwl_screen->prepare_read == 0 &&
983 wl_display_prepare_read(xwl_screen->display) == -1) {
984 ret = wl_display_dispatch_pending(xwl_screen->display);
985 if (ret == -1)
986 xwl_give_up("failed to dispatch Wayland events: %s\n",
987 strerror(errno));
988 }
989
990 xwl_screen->prepare_read = 1;
991
992 pollout:
993 ready = xwl_display_pollout(xwl_screen, 5);
994 if (ready == -1 && errno != EINTR)
995 xwl_give_up("error polling on XWayland fd: %s\n", strerror(errno));
996
997 if (ready > 0)
998 ret = wl_display_flush(xwl_screen->display);
999
1000 if (ret == -1 && errno != EAGAIN)
1001 xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
1002
1003 xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
1004 }
1005
1006 static void
socket_handler(int fd,int ready,void * data)1007 socket_handler(int fd, int ready, void *data)
1008 {
1009 struct xwl_screen *xwl_screen = data;
1010
1011 xwl_read_events (xwl_screen);
1012 }
1013
1014 static void
wakeup_handler(void * data,int err)1015 wakeup_handler(void *data, int err)
1016 {
1017 }
1018
1019 static void
block_handler(void * data,void * timeout)1020 block_handler(void *data, void *timeout)
1021 {
1022 struct xwl_screen *xwl_screen = data;
1023
1024 xwl_screen_post_damage(xwl_screen);
1025 xwl_dispatch_events (xwl_screen);
1026 }
1027
1028 void
xwl_sync_events(struct xwl_screen * xwl_screen)1029 xwl_sync_events (struct xwl_screen *xwl_screen)
1030 {
1031 xwl_dispatch_events (xwl_screen);
1032 xwl_read_events (xwl_screen);
1033 }
1034
1035 void
xwl_screen_roundtrip(struct xwl_screen * xwl_screen)1036 xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
1037 {
1038 int ret;
1039
1040 ret = wl_display_roundtrip(xwl_screen->display);
1041 while (ret >= 0 && xwl_screen->expecting_event)
1042 ret = wl_display_roundtrip(xwl_screen->display);
1043
1044 if (ret < 0)
1045 xwl_give_up("could not connect to wayland server\n");
1046 }
1047
1048 static CARD32
add_client_fd(OsTimerPtr timer,CARD32 time,void * arg)1049 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
1050 {
1051 struct xwl_screen *xwl_screen = arg;
1052
1053 if (!AddClientOnOpenFD(xwl_screen->wm_fd))
1054 FatalError("Failed to add wm client\n");
1055
1056 TimerFree(timer);
1057
1058 return 0;
1059 }
1060
1061 static void
listen_on_fds(struct xwl_screen * xwl_screen)1062 listen_on_fds(struct xwl_screen *xwl_screen)
1063 {
1064 int i;
1065
1066 for (i = 0; i < xwl_screen->listen_fd_count; i++)
1067 ListenOnOpenFD(xwl_screen->listen_fds[i], FALSE);
1068 }
1069
1070 static void
wm_selection_callback(CallbackListPtr * p,void * data,void * arg)1071 wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
1072 {
1073 SelectionInfoRec *info = arg;
1074 struct xwl_screen *xwl_screen = data;
1075 static const char atom_name[] = "WM_S0";
1076 static Atom atom_wm_s0;
1077
1078 if (atom_wm_s0 == None)
1079 atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
1080 if (info->selection->selection != atom_wm_s0 ||
1081 info->kind != SelectionSetOwner)
1082 return;
1083
1084 listen_on_fds(xwl_screen);
1085
1086 DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
1087 }
1088
1089 static Bool
xwl_screen_init(ScreenPtr pScreen,int argc,char ** argv)1090 xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
1091 {
1092 static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
1093 struct xwl_screen *xwl_screen;
1094 Pixel red_mask, blue_mask, green_mask;
1095 int ret, bpc, green_bpc, i;
1096 Bool use_eglstreams = FALSE;
1097
1098 xwl_screen = calloc(1, sizeof *xwl_screen);
1099 if (xwl_screen == NULL)
1100 return FALSE;
1101 xwl_screen->wm_fd = -1;
1102
1103 if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
1104 return FALSE;
1105 if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
1106 return FALSE;
1107 if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
1108 return FALSE;
1109 if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
1110 return FALSE;
1111
1112 dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
1113 xwl_screen->screen = pScreen;
1114
1115 #ifdef XWL_HAS_GLAMOR
1116 xwl_screen->glamor = 1;
1117 #endif
1118
1119 for (i = 1; i < argc; i++) {
1120 if (strcmp(argv[i], "-rootless") == 0) {
1121 xwl_screen->rootless = 1;
1122
1123 /* Disable the XSS extension on Xwayland rootless.
1124 *
1125 * Xwayland is just a Wayland client, no X11 screensaver
1126 * should be expected to work reliably on Xwayland rootless.
1127 */
1128 #ifdef SCREENSAVER
1129 noScreenSaverExtension = TRUE;
1130 #endif
1131 ScreenSaverTime = 0;
1132 ScreenSaverInterval = 0;
1133 defaultScreenSaverTime = 0;
1134 defaultScreenSaverInterval = 0;
1135 }
1136 else if (strcmp(argv[i], "-wm") == 0) {
1137 xwl_screen->wm_fd = atoi(argv[i + 1]);
1138 i++;
1139 TimerSet(NULL, 0, 1, add_client_fd, xwl_screen);
1140 }
1141 else if (strcmp(argv[i], "-listen") == 0) {
1142 if (xwl_screen->listen_fd_count ==
1143 ARRAY_SIZE(xwl_screen->listen_fds))
1144 FatalError("Too many -listen arguments given, max is %zu\n",
1145 ARRAY_SIZE(xwl_screen->listen_fds));
1146
1147 xwl_screen->listen_fds[xwl_screen->listen_fd_count++] =
1148 atoi(argv[i + 1]);
1149 i++;
1150 }
1151 else if (strcmp(argv[i], "-shm") == 0) {
1152 xwl_screen->glamor = 0;
1153 }
1154 else if (strcmp(argv[i], "-eglstream") == 0) {
1155 #ifdef XWL_HAS_EGLSTREAM
1156 use_eglstreams = TRUE;
1157 #else
1158 ErrorF("xwayland glamor: this build does not have EGLStream support\n");
1159 #endif
1160 }
1161 }
1162
1163 #ifdef XWL_HAS_GLAMOR
1164 if (xwl_screen->glamor)
1165 xwl_glamor_init_backends(xwl_screen, use_eglstreams);
1166 #endif
1167
1168 /* In rootless mode, we don't have any screen storage, and the only
1169 * rendering should be to redirected mode. */
1170 if (xwl_screen->rootless)
1171 xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY;
1172 else
1173 xwl_screen->root_clip_mode = ROOT_CLIP_FULL;
1174
1175 if (xwl_screen->listen_fd_count > 0) {
1176 if (xwl_screen->wm_fd >= 0)
1177 AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
1178 else
1179 listen_on_fds(xwl_screen);
1180 }
1181
1182 xorg_list_init(&xwl_screen->output_list);
1183 xorg_list_init(&xwl_screen->seat_list);
1184 xorg_list_init(&xwl_screen->damage_window_list);
1185 xwl_screen->depth = 24;
1186
1187 if (!monitorResolution)
1188 monitorResolution = DEFAULT_DPI;
1189
1190 xwl_screen->display = wl_display_connect(NULL);
1191 if (xwl_screen->display == NULL) {
1192 ErrorF("could not connect to wayland server\n");
1193 return FALSE;
1194 }
1195
1196 if (!xwl_screen_init_output(xwl_screen))
1197 return FALSE;
1198
1199 xwl_screen->expecting_event = 0;
1200 xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
1201 wl_registry_add_listener(xwl_screen->registry,
1202 ®istry_listener, xwl_screen);
1203 xwl_screen_roundtrip(xwl_screen);
1204
1205 if (!xwl_screen->rootless && !xwl_screen->shell) {
1206 ErrorF("missing wl_shell protocol\n");
1207 return FALSE;
1208 }
1209
1210 bpc = xwl_screen->depth / 3;
1211 green_bpc = xwl_screen->depth - 2 * bpc;
1212 blue_mask = (1 << bpc) - 1;
1213 green_mask = ((1 << green_bpc) - 1) << bpc;
1214 red_mask = blue_mask << (green_bpc + bpc);
1215
1216 miSetVisualTypesAndMasks(xwl_screen->depth,
1217 ((1 << TrueColor) | (1 << DirectColor)),
1218 green_bpc, TrueColor,
1219 red_mask, green_mask, blue_mask);
1220
1221 miSetPixmapDepths();
1222
1223 ret = fbScreenInit(pScreen, NULL,
1224 xwl_screen->width, xwl_screen->height,
1225 monitorResolution, monitorResolution, 0,
1226 BitsPerPixel(xwl_screen->depth));
1227 if (!ret)
1228 return FALSE;
1229
1230 fbPictureInit(pScreen, 0, 0);
1231
1232 #ifdef HAVE_XSHMFENCE
1233 if (!miSyncShmScreenInit(pScreen))
1234 return FALSE;
1235 #endif
1236
1237 xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
1238 SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen);
1239 RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
1240
1241 pScreen->SaveScreen = xwl_save_screen;
1242
1243 pScreen->blackPixel = 0;
1244 pScreen->whitePixel = 1;
1245
1246 ret = fbCreateDefColormap(pScreen);
1247
1248 if (!xwl_screen_init_cursor(xwl_screen))
1249 return FALSE;
1250
1251 #ifdef XWL_HAS_GLAMOR
1252 if (xwl_screen->glamor) {
1253 xwl_glamor_select_backend(xwl_screen, use_eglstreams);
1254
1255 if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
1256 ErrorF("Failed to initialize glamor, falling back to sw\n");
1257 xwl_screen->glamor = 0;
1258 }
1259 }
1260
1261 if (xwl_screen->glamor && xwl_screen->rootless)
1262 xwl_screen->present = xwl_present_init(pScreen);
1263 #endif
1264
1265 if (!xwl_screen->glamor) {
1266 xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
1267 pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
1268 pScreen->CreatePixmap = xwl_shm_create_pixmap;
1269 pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
1270 }
1271
1272 xwl_screen->RealizeWindow = pScreen->RealizeWindow;
1273 pScreen->RealizeWindow = xwl_realize_window;
1274
1275 xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
1276 pScreen->UnrealizeWindow = xwl_unrealize_window;
1277
1278 xwl_screen->DestroyWindow = pScreen->DestroyWindow;
1279 pScreen->DestroyWindow = xwl_destroy_window;
1280
1281 xwl_screen->CloseScreen = pScreen->CloseScreen;
1282 pScreen->CloseScreen = xwl_close_screen;
1283
1284 if (xwl_screen->rootless) {
1285 xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
1286 pScreen->SetWindowPixmap = xwl_set_window_pixmap;
1287 }
1288
1289 pScreen->CursorWarpedTo = xwl_cursor_warped_to;
1290 pScreen->CursorConfinedTo = xwl_cursor_confined_to;
1291
1292 xwl_screen->allow_commits_prop = MakeAtom(allow_commits,
1293 strlen(allow_commits),
1294 TRUE);
1295 if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
1296 return FALSE;
1297
1298 AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
1299
1300 xwl_screen_roundtrip(xwl_screen);
1301
1302 return ret;
1303 }
1304
1305 _X_NORETURN
1306 static void _X_ATTRIBUTE_PRINTF(1, 0)
xwl_log_handler(const char * format,va_list args)1307 xwl_log_handler(const char *format, va_list args)
1308 {
1309 char msg[256];
1310
1311 vsnprintf(msg, sizeof msg, format, args);
1312 FatalError("%s", msg);
1313 }
1314
1315 static const ExtensionModule xwayland_extensions[] = {
1316 #ifdef XF86VIDMODE
1317 { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
1318 #endif
1319 };
1320
1321 void
InitOutput(ScreenInfo * screen_info,int argc,char ** argv)1322 InitOutput(ScreenInfo * screen_info, int argc, char **argv)
1323 {
1324 int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
1325 int bpp[] = { 1, 8, 8, 16, 16, 32, 32 };
1326 int i;
1327
1328 for (i = 0; i < ARRAY_SIZE(depths); i++) {
1329 screen_info->formats[i].depth = depths[i];
1330 screen_info->formats[i].bitsPerPixel = bpp[i];
1331 screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
1332 }
1333
1334 screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
1335 screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1336 screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1337 screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
1338 screen_info->numPixmapFormats = ARRAY_SIZE(depths);
1339
1340 if (serverGeneration == 1)
1341 LoadExtensionList(xwayland_extensions,
1342 ARRAY_SIZE(xwayland_extensions), FALSE);
1343
1344 /* Cast away warning from missing printf annotation for
1345 * wl_log_func_t. Wayland 1.5 will have the annotation, so we can
1346 * remove the cast and require that when it's released. */
1347 wl_log_set_handler_client((void *) xwl_log_handler);
1348
1349 if (AddScreen(xwl_screen_init, argc, argv) == -1) {
1350 FatalError("Couldn't add screen\n");
1351 }
1352
1353 xorgGlxCreateVendor();
1354
1355 LocalAccessScopeUser();
1356 }
1357