3 @@ -632,6 +632,7 @@ AC_ARG_ENABLE(windowswm, AS_HELP_ST
4 AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
5 AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
6 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
7 +AC_ARG_ENABLE(xmir, AS_HELP_STRING([--enable-xmir], [Build support for nesting in Mir (default: auto)]), [XMIR=$enableval], [XMIR=auto])
8 AC_ARG_ENABLE(linux_acpi, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
9 AC_ARG_ENABLE(linux_apm, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
11 @@ -1334,6 +1335,15 @@ if test "x$XINERAMA" = xyes; then
12 SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $XINERAMAPROTO"
15 +if test "x$XMIR" != xno; then
16 + PKG_CHECK_MODULES([XMIR], [mirclient], [XMIR=yes], [XMIR=no])
17 + AC_SUBST([XMIR_LIBS])
18 + AC_SUBST([XMIR_CFLAGS])
19 + AC_DEFINE(XMIR, 1, [Support Mir nested mode])
20 + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES mirclient"
22 +AM_CONDITIONAL(XMIR, [test "x$XMIR" = xyes])
24 AM_CONDITIONAL(XACE, [test "x$XACE" = xyes])
25 if test "x$XACE" = xyes; then
26 AC_DEFINE(XACE, 1, [Build X-ACE extension])
27 @@ -2510,6 +2520,7 @@ hw/xfree86/utils/Makefile
28 hw/xfree86/utils/man/Makefile
29 hw/xfree86/utils/cvt/Makefile
30 hw/xfree86/utils/gtf/Makefile
31 +hw/xfree86/xmir/Makefile
32 hw/dmx/config/Makefile
33 hw/dmx/config/man/Makefile
35 --- a/hw/xfree86/Makefile.am
36 +++ b/hw/xfree86/Makefile.am
37 @@ -30,15 +30,20 @@ if INT10MODULE
45 SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
46 ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
47 $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
48 - fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
49 + fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \
52 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
53 parser ramdac shadowfb vbe vgahw \
54 loader dixmods dri dri2 exa modes \
59 nodist_Xorg_SOURCES = sdksyms.c
60 --- a/hw/xfree86/common/xf86Config.c
61 +++ b/hw/xfree86/common/xf86Config.c
62 @@ -118,6 +118,7 @@ static ModuleDefault ModuleDefaults[] =
63 {.name = "fb",.toLoad = TRUE,.load_opt = NULL},
64 {.name = "shadow",.toLoad = TRUE,.load_opt = NULL},
66 + {.name = "xmir", .toLoad = FALSE, .load_opt = NULL},
67 {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
70 @@ -260,6 +261,17 @@ xf86ModulelistFromConfig(pointer **optli
75 + * Set the xmir module to autoload if requested.
78 + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
79 + if (strcmp(ModuleDefaults[i].name, "xmir") == 0) {
80 + ModuleDefaults[i].toLoad = TRUE;
85 if (xf86configptr->conf_modules) {
86 /* Walk the disable list and let people know what we've parsed to
88 --- a/hw/xfree86/common/xf86Events.c
89 +++ b/hw/xfree86/common/xf86Events.c
90 @@ -105,8 +105,6 @@ extern fd_set EnabledDevices;
91 extern void (*xf86OSPMClose) (void);
94 -static void xf86VTSwitch(void);
97 * Allow arbitrary drivers or other XFree86 code to register with our main
99 @@ -411,7 +409,7 @@ xf86ReleaseKeys(DeviceIntPtr pDev)
101 * Handle requests for switching the vt.
108 @@ -471,7 +469,7 @@ xf86VTSwitch(void)
110 xf86AccessLeave(); /* We need this here, otherwise */
112 - if (!xf86VTSwitchAway()) {
113 + if (!xorgMir && !xf86VTSwitchAway()) {
117 @@ -530,7 +528,7 @@ xf86VTSwitch(void)
120 DebugF("xf86VTSwitch: Entering\n");
121 - if (!xf86VTSwitchTo())
122 + if (!xorgMir && !xf86VTSwitchTo())
126 --- a/hw/xfree86/common/xf86Globals.c
127 +++ b/hw/xfree86/common/xf86Globals.c
128 @@ -207,3 +207,6 @@ Bool xf86VidModeAllowNonLocal = FALSE;
130 RootWinPropPtr *xf86RegisteredPropertiesTable = NULL;
131 Bool xorgHWAccess = FALSE;
132 +Bool xorgMir = FALSE;
133 +const char *mirID = NULL;
134 +const char *mirSocket = NULL;
135 --- a/hw/xfree86/common/xf86Helper.c
136 +++ b/hw/xfree86/common/xf86Helper.c
137 @@ -100,7 +100,14 @@ xf86DeleteDriver(int drvIndex)
138 if (xf86DriverList[drvIndex]->module)
139 UnloadModule(xf86DriverList[drvIndex]->module);
140 free(xf86DriverList[drvIndex]);
141 - xf86DriverList[drvIndex] = NULL;
143 + /* Compact xf86DriverList array, update xf86NumDrivers */
145 + if(drvIndex != xf86NumDrivers)
146 + memmove(xf86DriverList + drvIndex,
147 + xf86DriverList + drvIndex + 1,
148 + sizeof(DriverPtr) * (xf86NumDrivers - drvIndex));
149 + xf86DriverList = realloc(xf86DriverList, xf86NumDrivers * sizeof(DriverPtr));
153 --- a/hw/xfree86/common/xf86Init.c
154 +++ b/hw/xfree86/common/xf86Init.c
155 @@ -554,7 +554,7 @@ InitOutput(ScreenInfo * pScreenInfo, int
156 * needed at this early stage.
159 - for (i = 0; i < xf86NumDrivers; i++) {
160 + for (i = 0; i < xf86NumDrivers; ) {
161 xorgHWFlags flags = HW_IO;
163 if (xf86DriverList[i]->Identify != NULL)
164 @@ -565,11 +565,20 @@ InitOutput(ScreenInfo * pScreenInfo, int
165 GET_REQUIRED_HW_INTERFACES,
169 + (NEED_IO_ENABLED(flags) || !(flags & HW_SKIP_CONSOLE))) {
170 + ErrorF("Driver needs flags %lu, incompatible with nested, deleting.\n", flags);
171 + xf86DeleteDriver(i);
175 if (NEED_IO_ENABLED(flags))
176 want_hw_access = TRUE;
178 if (!(flags & HW_SKIP_CONSOLE))
179 xorgHWOpenConsole = TRUE;
184 if (xorgHWOpenConsole)
185 @@ -662,9 +671,13 @@ InitOutput(ScreenInfo * pScreenInfo, int
188 /* Remove (unload) drivers that are not required */
189 - for (i = 0; i < xf86NumDrivers; i++)
190 - if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0)
191 + for (i = 0; i < xf86NumDrivers; )
192 + if (xf86DriverList[i] &&
193 + !xf86DriverHasEntities(xf86DriverList[i]) &&
194 + xf86DriverList[i]->refCount <= 0)
200 * At this stage we know how many screens there are.
201 @@ -1490,6 +1503,17 @@ ddxProcessArgument(int argc, char **argv
202 xf86Info.ShareVTs = TRUE;
205 + if (!strcmp(argv[i], "-mir")) {
206 + CHECK_FOR_REQUIRED_ARGUMENT();
211 + if (!strcmp(argv[i], "-mirSocket")) {
212 + CHECK_FOR_REQUIRED_ARGUMENT();
213 + mirSocket = argv[++i];
217 /* OS-specific processing */
218 return xf86ProcessArgument(argc, argv, i);
219 @@ -1563,6 +1587,8 @@ ddxUseMsg(void)
221 ("-novtswitch don't automatically switch VT at reset & exit\n");
222 ErrorF("-sharevts share VTs with another X server\n");
224 + ("-mir MirID run nested in a Mir compositor with app id MirID\n");
225 /* OS-specific usage */
228 --- a/hw/xfree86/common/xf86Priv.h
229 +++ b/hw/xfree86/common/xf86Priv.h
230 @@ -93,6 +93,9 @@ extern _X_EXPORT Bool xf86AttemptedFallb
231 extern _X_EXPORT const char *xf86VisualNames[];
232 extern _X_EXPORT int xf86Verbose; /* verbosity level */
233 extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */
234 +extern _X_EXPORT Bool xorgMir;
235 +extern _X_EXPORT const char *mirID;
236 +extern _X_EXPORT const char *mirSocket;
238 extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
240 @@ -149,6 +152,9 @@ xf86HandlePMEvents(int fd, pointer data)
241 extern _X_EXPORT int (*xf86PMGetEventFromOs) (int fd, pmEvent * events,
243 extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs) (int fd, pmEvent event);
244 +extern _X_EXPORT void
249 extern _X_EXPORT void
250 --- a/hw/xfree86/ramdac/xf86Cursor.c
251 +++ b/hw/xfree86/ramdac/xf86Cursor.c
252 @@ -58,7 +58,12 @@ xf86InitCursor(ScreenPtr pScreen, xf86Cu
253 xf86CursorScreenPtr ScreenPriv;
254 miPointerScreenPtr PointPriv;
256 - if (!xf86InitHardwareCursor(pScreen, infoPtr))
257 + infoPtr->pScrn = xf86ScreenToScrn(pScreen);
259 + /* If we can't create a hardware cursor don't bother initialising HW cursor support */
260 + if (infoPtr->MaxWidth != 0 &&
261 + infoPtr->MaxHeight != 0 &&
262 + !xf86InitHardwareCursor(pScreen, infoPtr))
265 if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0))
266 --- a/hw/xfree86/ramdac/xf86HWCurs.c
267 +++ b/hw/xfree86/ramdac/xf86HWCurs.c
268 @@ -114,8 +114,6 @@ xf86InitHardwareCursor(ScreenPtr pScreen
269 infoPtr->RealizeCursor = RealizeCursorInterleave0;
272 - infoPtr->pScrn = xf86ScreenToScrn(pScreen);
278 +++ b/hw/xfree86/xmir/Makefile.am
282 + -I$(srcdir)/../ddc \
283 + -I$(srcdir)/../ramdac \
284 + -I$(srcdir)/../i2c \
285 + -I$(srcdir)/../parser \
286 + -I$(srcdir)/../modes
288 +libxmir_la_LTLIBRARIES = libxmir.la
289 +libxmir_la_CFLAGS = \
290 + -DHAVE_XORG_CONFIG_H \
292 + $(DIX_CFLAGS) $(XORG_CFLAGS) $(LIBDRM_CFLAGS) \
295 +libxmir_la_LDFLAGS = -module -avoid-version $(LIBDRM_LIBS) $(XMIR_LIBS)
296 +libxmir_ladir = $(moduledir)/extensions
297 +libxmir_la_SOURCES = \
301 + xmir-thread-proxy.c \
305 +sdk_HEADERS = xmir.h
307 +++ b/hw/xfree86/xmir/xmir-output.c
310 + * Copyright © 2012 Canonical, Inc
312 + * Permission is hereby granted, free of charge, to any person obtaining a
313 + * copy of this software and associated documentation files (the "Soft-
314 + * ware"), to deal in the Software without restriction, including without
315 + * limitation the rights to use, copy, modify, merge, publish, distribute,
316 + * and/or sell copies of the Software, and to permit persons to whom the
317 + * Software is furnished to do so, provided that the above copyright
318 + * notice(s) and this permission notice appear in all copies of the Soft-
319 + * ware and that both the above copyright notice(s) and this permission
320 + * notice appear in supporting documentation.
322 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
323 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
324 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
325 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
326 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
327 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
328 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
329 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
330 + * MANCE OF THIS SOFTWARE.
332 + * Except as contained in this notice, the name of a copyright holder shall
333 + * not be used in advertising or otherwise to promote the sale, use or
334 + * other dealings in this Software without prior written authorization of
335 + * the copyright holder.
338 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
345 +#include <xorg-config.h>
347 +#include "xmir-private.h"
348 +#include "xf86Crtc.h"
349 +#include "xf86Priv.h"
353 + xmir_window *root_fragment;
354 + MirDisplayConfiguration *config;
358 +xmir_mir_dpms_mode_description(MirPowerMode mode)
362 + case mir_power_mode_on:
363 + return "mir_power_mode_on";
364 + case mir_power_mode_standby:
365 + return "mir_power_mode_standby";
366 + case mir_power_mode_suspend:
367 + return "mir_power_mode_suspend";
368 + case mir_power_mode_off:
369 + return "mir_power_mode_off";
371 + return "OMGUNKNOWN!";
376 +xmir_crtc_dpms(xf86CrtcPtr crtc, int mode)
378 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
379 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
381 + for (int i = 0; i < crtc_cfg->num_output; i++) {
382 + /* If this output should be driven by our "CRTC", set DPMS mode */
383 + MirDisplayOutput *output = crtc_cfg->output[i]->driver_private;
384 + if (crtc_cfg->output[i]->crtc == crtc) {
385 + xf86Msg(X_INFO, "Setting DPMS mode for output %d to %d\n", i, mode);
388 + output->power_mode = mir_power_mode_on;
389 + xmir_crtc->xmir->dpms_on = TRUE;
391 + case DPMSModeStandby:
392 + output->power_mode = mir_power_mode_standby;
393 + xmir_crtc->xmir->dpms_on = FALSE;
395 + case DPMSModeSuspend:
396 + output->power_mode = mir_power_mode_suspend;
397 + xmir_crtc->xmir->dpms_on = FALSE;
400 + output->power_mode = mir_power_mode_off;
401 + xmir_crtc->xmir->dpms_on = FALSE;
406 + mir_wait_for(mir_connection_apply_display_config(xmir_connection_get(),
407 + xmir_crtc->config));
411 +xmir_get_output_type_str(MirDisplayOutput *mir_output)
413 + const char *str = "Invalid";
415 + switch(mir_output->type)
417 + case mir_display_output_type_vga: str = "VGA"; break;
418 + case mir_display_output_type_dvii: str = "DVI"; break;
419 + case mir_display_output_type_dvid: str = "DVI"; break;
420 + case mir_display_output_type_dvia: str = "DVI"; break;
421 + case mir_display_output_type_composite: str = "Composite"; break;
422 + case mir_display_output_type_svideo: str = "TV"; break;
423 + case mir_display_output_type_lvds: str = "LVDS"; break;
424 + case mir_display_output_type_component: str = "CTV"; break;
425 + case mir_display_output_type_ninepindin: str = "DIN"; break;
426 + case mir_display_output_type_displayport: str = "DP"; break;
427 + case mir_display_output_type_hdmia: str = "HDMI"; break;
428 + case mir_display_output_type_hdmib: str = "HDMI"; break;
429 + case mir_display_output_type_tv: str = "TV"; break;
430 + case mir_display_output_type_edp: str = "eDP"; break;
432 + case mir_display_output_type_unknown: str = "None"; break;
440 +xmir_output_populate(xf86OutputPtr xf86output, MirDisplayOutput *output)
442 + /* We can always arbitrarily clone and output */
443 + xf86output->possible_crtcs = 0xffffffff;
444 + xf86output->possible_clones = 0xffffffff;
446 + xf86output->driver_private = output;
448 + xf86output->interlaceAllowed = FALSE;
449 + xf86output->doubleScanAllowed = FALSE;
450 + xf86output->mm_width = output->physical_width_mm;
451 + xf86output->mm_height = output->physical_height_mm;
452 + /* TODO: Subpixel order from Mir */
453 + xf86output->subpixel_order = SubPixelUnknown;
456 +static DisplayModePtr
457 +xmir_create_xf86mode(const struct MirDisplayMode *mir_mode)
459 + DisplayModePtr mode;
461 + mode = xf86CVTMode(mir_mode->horizontal_resolution,
462 + mir_mode->vertical_resolution,
463 + mir_mode->refresh_rate,
467 + * And now, because the CVT standard doesn't support such common
468 + * resolutions as 1366x768...
470 + mode->VDisplay = mir_mode->vertical_resolution;
471 + mode->HDisplay = mir_mode->horizontal_resolution;
473 + xf86SetModeDefaultName(mode);
479 +xmir_free_xf86mode(DisplayModePtr mode)
486 +xmir_set_mode_for_output(MirDisplayOutput *output,
487 + DisplayModePtr mode)
489 + for (int i = 0; i < output->num_modes; i++) {
490 + Bool modes_equal = FALSE;
491 + DisplayModePtr mir_mode = NULL;
492 + xf86Msg(X_INFO, "Checking against mode (%dx%d)@%.2f\n",
493 + output->modes[i].horizontal_resolution,
494 + output->modes[i].vertical_resolution,
495 + output->modes[i].refresh_rate);
497 + mir_mode = xmir_create_xf86mode(&output->modes[i]);
498 + modes_equal = xf86ModesEqual(mode, mir_mode);
499 + xmir_free_xf86mode(mir_mode);
502 + output->current_mode = i;
504 + xf86Msg(X_INFO, "Matched mode %d\n", i);
512 +xmir_update_outputs_for_crtc(xf86CrtcPtr crtc, DisplayModePtr mode, int x, int y)
514 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
515 + uint32_t representative_output_id = mir_display_output_id_invalid;
517 + for (int i = 0; i < crtc_cfg->num_output; i++) {
518 + /* If this output should be driven by our "CRTC", set its mode */
519 + if (crtc_cfg->output[i]->crtc == crtc) {
520 + MirDisplayOutput *output = crtc_cfg->output[i]->driver_private;
521 + xmir_set_mode_for_output(output, mode);
522 + output->position_x = x;
523 + output->position_y = y;
524 + representative_output_id = output->output_id;
527 + return representative_output_id;
531 +xmir_disable_unused_outputs(xf86CrtcPtr crtc)
533 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
535 + for (int i = 0; i < crtc_cfg->num_output; i++)
536 + /* If any outputs are no longer associated with a CRTC, disable them */
537 + if (crtc_cfg->output[i]->crtc == NULL)
538 + ((MirDisplayOutput*)crtc_cfg->output[i]->driver_private)->used = 0;
542 +xmir_stupid_callback(MirSurface *surf, void *ctx)
547 +xmir_dump_config(MirDisplayConfiguration *config)
549 + for (int i = 0; i < config->num_outputs; i++)
551 + xf86Msg(X_INFO, "Output %d (%s, %s) has mode %d (%d x %d @ %.2f), position (%d,%d), dpms: %s\n",
552 + config->outputs[i].output_id,
553 + config->outputs[i].connected ? "connected" : "disconnected",
554 + config->outputs[i].used ? "enabled" : "disabled",
555 + config->outputs[i].current_mode,
556 + config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].horizontal_resolution : 0,
557 + config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].vertical_resolution : 0,
558 + config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].refresh_rate : 0,
559 + config->outputs[i].position_x,
560 + config->outputs[i].position_y,
561 + xmir_mir_dpms_mode_description(config->outputs[i].power_mode));
562 + for (int m = 0; m < config->outputs[i].num_modes; m++)
564 + xf86Msg(X_INFO, " mode %d: (%d x %d @ %.2f)\n",
566 + config->outputs[i].modes[m].horizontal_resolution,
568 + config->outputs[i].modes[m].vertical_resolution,
569 + config->outputs[i].modes[m].refresh_rate);
575 +xmir_update_config(xf86CrtcConfigPtr crtc_cfg)
577 + MirDisplayConfiguration *new_config;
578 + struct xmir_crtc *xmir_crtc = crtc_cfg->crtc[0]->driver_private;
580 + mir_display_config_destroy(xmir_crtc->config);
582 + new_config = mir_connection_create_display_config(xmir_connection_get());
583 + for (int i = 0; i < crtc_cfg->num_crtc; i++) {
584 + xmir_crtc = crtc_cfg->crtc[i]->driver_private;
585 + xmir_crtc-> config = new_config;
588 + if (crtc_cfg->num_output != new_config->num_outputs)
589 + FatalError("[xmir] New Mir config has different number of outputs?");
591 + for (int i = 0; i < crtc_cfg->num_output ; i++) {
592 + /* TODO: Ensure that the order actually matches up */
593 + xmir_output_populate(crtc_cfg->output[i], new_config->outputs + i);
595 + xf86Msg(X_INFO, "Recieved updated config from Mir:\n");
596 + xmir_dump_config(new_config);
600 +xmir_crtc_surface_created(MirSurface *surface, void *ctx)
602 + xf86CrtcPtr crtc = ctx;
603 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
605 + if (xmir_crtc->root_fragment->surface != NULL)
606 + mir_surface_release(xmir_crtc->root_fragment->surface, xmir_stupid_callback, NULL);
608 + xmir_crtc->root_fragment->surface = surface;
612 +xmir_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
613 + Rotation rotation, int x, int y)
615 + MirSurfaceParameters params = {
617 + .width = mode->HDisplay,
618 + .height = mode->VDisplay,
619 + .pixel_format = mir_pixel_format_xrgb_8888,
620 + .buffer_usage = mir_buffer_usage_hardware,
621 + .output_id = mir_display_output_id_invalid
623 + BoxRec output_bounds = {
626 + .x2 = x + mode->HDisplay,
627 + .y2 = y + mode->VDisplay
629 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
630 + uint32_t output_id = mir_display_output_id_invalid;
631 + const char *error_msg;
633 + if (mode->HDisplay == 0 || mode->VDisplay == 0)
636 + xf86Msg(X_INFO, "Initial configuration for crtc %p:\n", crtc);
637 + xmir_dump_config(xmir_crtc->config);
639 + xf86Msg(X_INFO, "Setting mode to %dx%d (%.2f)\n", mode->HDisplay, mode->VDisplay, mode->VRefresh);
640 + output_id = xmir_update_outputs_for_crtc(crtc, mode, x, y);
641 + xmir_disable_unused_outputs(crtc);
643 + xf86Msg(X_INFO, "Updated configuration:\n");
645 + xmir_dump_config(xmir_crtc->config);
646 + mir_wait_for(mir_connection_apply_display_config(xmir_connection_get(),
647 + xmir_crtc->config));
648 + error_msg = mir_connection_get_error_message(xmir_connection_get());
649 + if (*error_msg != '\0') {
650 + xf86Msg(X_ERROR, "[xmir] Failed to set new display config: %s\n",
653 + /* TODO: Restore correct config cache */
656 + xf86Msg(X_INFO, "Post-modeset config:\n");
657 + xmir_update_config(XF86_CRTC_CONFIG_PTR(crtc->scrn));
659 + if (output_id == mir_display_output_id_invalid) {
660 + if (xmir_crtc->root_fragment->surface != NULL)
661 + mir_wait_for(mir_surface_release(xmir_crtc->root_fragment->surface, xmir_stupid_callback, NULL));
662 + xmir_crtc->root_fragment->surface = NULL;
666 + params.output_id = output_id;
667 + xf86Msg(X_INFO, "Putting surface on output %d\n", output_id);
668 + mir_wait_for(mir_connection_create_surface(xmir_connection_get(),
670 + xmir_crtc_surface_created,
672 + if (!mir_surface_is_valid(xmir_crtc->root_fragment->surface)) {
674 + "[xmir] Failed to create surface for %dx%d mode: %s\n",
675 + mode->HDisplay, mode->VDisplay,
676 + mir_surface_get_error_message(xmir_crtc->root_fragment->surface));
681 + /* During X server init this will be NULL.
682 + This is fixed up in xmir_window_create */
683 + xmir_crtc->root_fragment->win = xf86ScrnToScreen(crtc->scrn)->root;
685 + RegionInit(&xmir_crtc->root_fragment->region, &output_bounds, 0);
686 + xmir_crtc->root_fragment->has_free_buffer = TRUE;
692 +crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
697 +crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
702 +crtc_show_cursor (xf86CrtcPtr crtc)
707 +crtc_hide_cursor (xf86CrtcPtr crtc)
712 +crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
717 +crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
723 +crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
729 +crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
734 +xmir_crtc_destroy(xf86CrtcPtr crtc)
736 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
738 + if (xmir_crtc->root_fragment->surface != NULL)
739 + mir_surface_release(xmir_crtc->root_fragment->surface, NULL, NULL);
744 +static const xf86CrtcFuncsRec crtc_funcs = {
745 + .dpms = xmir_crtc_dpms,
746 + .set_mode_major = xmir_crtc_set_mode_major,
747 + .set_cursor_colors = crtc_set_cursor_colors,
748 + .set_cursor_position = crtc_set_cursor_position,
749 + .show_cursor = crtc_show_cursor,
750 + .hide_cursor = crtc_hide_cursor,
751 + .load_cursor_argb = crtc_load_cursor_argb,
752 + .shadow_create = crtc_shadow_create,
753 + .shadow_allocate = crtc_shadow_allocate,
754 + .shadow_destroy = crtc_shadow_destroy,
755 + .destroy = xmir_crtc_destroy,
759 +xmir_output_dpms(xf86OutputPtr output, int mode)
764 +static xf86OutputStatus
765 +xmir_output_detect(xf86OutputPtr output)
767 + MirDisplayOutput *mir_output = output->driver_private;
768 + return mir_output->connected ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
772 +xmir_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
777 +static DisplayModePtr
778 +xmir_output_get_modes(xf86OutputPtr xf86output)
780 + MirDisplayOutput *mir_output = xf86output->driver_private;
781 + DisplayModePtr modes = NULL;
783 + for (int i = 0; i < mir_output->num_modes; i++) {
784 + DisplayModePtr mode = xmir_create_xf86mode(&mir_output->modes[i]);
786 + mode->type = M_T_DRIVER;
787 + if (i == mir_output->preferred_mode)
788 + mode->type |= M_T_PREFERRED;
790 + modes = xf86ModesAdd(modes, mode);
792 + /* TODO: Get Mir to send us the EDID blob and add that */
798 +xmir_output_destroy(xf86OutputPtr xf86output)
800 + /* The MirDisplayOutput* in driver_private gets cleaned up by
801 + mir_display_config_destroy() */
804 +static const xf86OutputFuncsRec xmir_output_funcs = {
805 + .dpms = xmir_output_dpms,
806 + .detect = xmir_output_detect,
807 + .mode_valid = xmir_output_mode_valid,
808 + .get_modes = xmir_output_get_modes,
809 + .destroy = xmir_output_destroy
813 +struct xmir_visit_set_pixmap_window {
814 + PixmapPtr old, new;
818 +xmir_visit_set_window_pixmap(WindowPtr window, pointer data)
820 + struct xmir_visit_set_pixmap_window *visit = data;
822 + if (window->drawable.pScreen->GetWindowPixmap(window) == visit->old) {
823 + window->drawable.pScreen->SetWindowPixmap(window, visit->new);
824 + return WT_WALKCHILDREN;
827 + return WT_DONTWALKCHILDREN;
831 +xmir_set_screen_pixmap(PixmapPtr old_front, PixmapPtr new_front)
833 + struct xmir_visit_set_pixmap_window visit = {
837 + (old_front->drawable.pScreen->SetScreenPixmap)(new_front);
839 + TraverseTree(old_front->drawable.pScreen->root, &xmir_visit_set_window_pixmap, &visit);
843 +xmir_resize(ScrnInfoPtr scrn, int width, int height)
845 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(scrn);
846 + ScreenPtr screen = xf86ScrnToScreen(scrn);
847 + PixmapPtr old_screen_pixmap, new_screen_pixmap;
849 + if (scrn->virtualX == width && scrn->virtualY == height)
852 + old_screen_pixmap = screen->GetScreenPixmap(screen);
853 + new_screen_pixmap = screen->CreatePixmap(screen, width, height, scrn->depth,
854 + CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
856 + if (!new_screen_pixmap)
859 + scrn->virtualX = width;
860 + scrn->virtualY = height;
861 + scrn->displayWidth = width;
863 + for (int i = 0; i < crtc_cfg->num_crtc; i++) {
864 + xf86CrtcPtr crtc = crtc_cfg->crtc[i];
866 + if (!crtc->enabled)
869 + xmir_crtc_set_mode_major(crtc, &crtc->mode,
870 + crtc->rotation, crtc->x, crtc->y);
873 + xmir_set_screen_pixmap(old_screen_pixmap, new_screen_pixmap);
874 + screen->DestroyPixmap(old_screen_pixmap);
876 + xf86_reload_cursors(screen);
881 +static const xf86CrtcConfigFuncsRec config_funcs = {
886 +xmir_handle_hotplug(void *ctx)
888 + ScrnInfoPtr scrn = *(ScrnInfoPtr *)ctx;
889 + xf86CrtcConfigPtr crtc_config = XF86_CRTC_CONFIG_PTR(scrn);
891 + if (crtc_config->num_crtc == 0)
892 + FatalError("[xmir] Received hotplug event, but have no CRTCs?\n");
894 + xmir_update_config(crtc_config);
896 + /* Trigger RANDR refresh */
897 + RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
901 +xmir_display_config_callback(MirConnection *unused, void *ctx)
903 + xmir_screen *xmir = ctx;
905 + xmir_post_to_eventloop(xmir->hotplug_event_handler, &xmir->scrn);
909 +xmir_mode_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir)
912 + MirDisplayConfiguration *display_config;
913 + xf86CrtcPtr xf86crtc;
914 + int output_type_count[mir_display_output_type_edp + 1];
916 + memset(output_type_count, 0, sizeof output_type_count);
918 + /* Set up CRTC config functions */
919 + xf86CrtcConfigInit(scrn, &config_funcs);
921 + /* We don't scanout of a single surface, so we don't have a scanout limit */
922 + xf86CrtcSetSizeRange(scrn,
924 + INT16_MAX, INT16_MAX);
926 + /* Hook up hotplug notification */
927 + xmir->hotplug_event_handler =
928 + xmir_register_handler(&xmir_handle_hotplug,
929 + sizeof (ScreenPtr));
931 + mir_connection_set_display_config_change_callback(
932 + xmir_connection_get(),
933 + &xmir_display_config_callback, xmir);
936 + mir_connection_create_display_config(xmir_connection_get());
938 + xmir->root_window_fragments = malloc((display_config->cards[0].max_simultaneous_outputs + 1) *
939 + sizeof(xmir_window *));
940 + xmir->root_window_fragments[display_config->cards[0].max_simultaneous_outputs] = NULL;
942 + if (xmir->root_window_fragments == NULL)
945 + for (i = 0; i < display_config->num_outputs; i++) {
946 + xf86OutputPtr xf86output;
948 + MirDisplayOutput *mir_output = &display_config->outputs[i];
949 + const char* output_type_str = xmir_get_output_type_str(mir_output);
950 + int type_count = i;
952 + if (mir_output->type >= 0 && mir_output->type <= mir_display_output_type_edp)
953 + type_count = output_type_count[mir_output->type]++;
955 + snprintf(name, sizeof name, "%s-%d", output_type_str, type_count);
956 + xf86output = xf86OutputCreate(scrn, &xmir_output_funcs, name);
958 + xmir_output_populate(xf86output, mir_output);
961 + for (i = 0; i < display_config->cards[0].max_simultaneous_outputs; i++) {
962 + struct xmir_crtc *xmir_crtc = malloc(sizeof *xmir_crtc);
963 + if (xmir_crtc == NULL)
966 + xmir_crtc->xmir = xmir;
967 + xmir_crtc->root_fragment = calloc(1, sizeof *xmir_crtc->root_fragment);
968 + xmir_crtc->config = display_config;
970 + if (xmir_crtc->root_fragment == NULL)
973 + xmir->root_window_fragments[i] = xmir_crtc->root_fragment;
974 + RegionNull(&xmir_crtc->root_fragment->region);
976 + xf86crtc = xf86CrtcCreate(scrn, &crtc_funcs);
977 + xf86crtc->driver_private = xmir_crtc;
980 + xf86SetScrnInfoModes(scrn);
982 + /* TODO: Use initial Mir state rather than setting up our own */
983 + xf86InitialConfiguration(scrn, TRUE);
988 +++ b/hw/xfree86/xmir/xmir-private.h
991 + * Copyright © 2012 Canonical, Inc
993 + * Permission is hereby granted, free of charge, to any person obtaining a
994 + * copy of this software and associated documentation files (the "Soft-
995 + * ware"), to deal in the Software without restriction, including without
996 + * limitation the rights to use, copy, modify, merge, publish, distribute,
997 + * and/or sell copies of the Software, and to permit persons to whom the
998 + * Software is furnished to do so, provided that the above copyright
999 + * notice(s) and this permission notice appear in all copies of the Soft-
1000 + * ware and that both the above copyright notice(s) and this permission
1001 + * notice appear in supporting documentation.
1003 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1004 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
1005 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
1006 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
1007 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
1008 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1009 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1010 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
1011 + * MANCE OF THIS SOFTWARE.
1013 + * Except as contained in this notice, the name of a copyright holder shall
1014 + * not be used in advertising or otherwise to promote the sale, use or
1015 + * other dealings in this Software without prior written authorization of
1016 + * the copyright holder.
1019 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1022 +#ifndef _XMIR_PRIVATE_H
1023 +#define _XMIR_PRIVATE_H
1025 +#include <mir_toolkit/mir_client_library.h>
1027 +#include "xf86str.h"
1029 +#include "scrnintstr.h"
1030 +#include "regionstr.h"
1032 +#define MIR_MAX_BUFFER_AGE 3
1034 +typedef struct xmir_marshall_handler xmir_marshall_handler;
1036 +struct xmir_screen {
1038 + CreateWindowProcPtr CreateWindow;
1039 + DestroyWindowProcPtr DestroyWindow;
1040 + xmir_driver * driver;
1041 + xmir_marshall_handler *submit_rendering_handler;
1042 + xmir_marshall_handler *hotplug_event_handler;
1043 + xmir_marshall_handler *focus_event_handler;
1044 + struct xorg_list damage_list;
1045 + struct xmir_window **root_window_fragments; /* NULL terminated array of xmir_window * */
1046 + unsigned int dpms_on:1; /* Until Mir is less stupid about DPMS */
1049 +struct xmir_window {
1051 + MirSurface *surface;
1053 + RegionRec past_damage[MIR_MAX_BUFFER_AGE];
1056 + struct xorg_list link_damage;
1057 + unsigned int has_free_buffer:1;
1058 + unsigned int damaged:1;
1062 +xmir_connection_get(void);
1065 +xmir_screen_get(ScreenPtr screen);
1068 +xmir_window_get(WindowPtr win);
1071 +xmir_window_enable_damage_tracking(xmir_window *xmir_win);
1074 +xmir_window_disable_damage_tracking(xmir_window *xmir_win);
1078 +xmir_screen_init_window(ScreenPtr screen, xmir_screen *xmir);
1081 +xmir_mode_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir);
1084 +xmir_init_thread_to_eventloop(void);
1086 +xmir_marshall_handler *
1087 +xmir_register_handler(void (*msg_handler)(void *msg), size_t msg_size);
1090 +xmir_post_to_eventloop(xmir_marshall_handler *handler, void *msg);
1093 +xmir_process_from_eventloop(void);
1095 + #endif /* _MIR_PRIVATE_H */
1097 +++ b/hw/xfree86/xmir/xmir-thread-proxy.c
1100 + * Copyright © 2012 Canonical, Inc
1102 + * Permission is hereby granted, free of charge, to any person obtaining a
1103 + * copy of this software and associated documentation files (the "Soft-
1104 + * ware"), to deal in the Software without restriction, including without
1105 + * limitation the rights to use, copy, modify, merge, publish, distribute,
1106 + * and/or sell copies of the Software, and to permit persons to whom the
1107 + * Software is furnished to do so, provided that the above copyright
1108 + * notice(s) and this permission notice appear in all copies of the Soft-
1109 + * ware and that both the above copyright notice(s) and this permission
1110 + * notice appear in supporting documentation.
1112 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1113 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
1114 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
1115 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
1116 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
1117 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1118 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1119 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
1120 + * MANCE OF THIS SOFTWARE.
1122 + * Except as contained in this notice, the name of a copyright holder shall
1123 + * not be used in advertising or otherwise to promote the sale, use or
1124 + * other dealings in this Software without prior written authorization of
1125 + * the copyright holder.
1128 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1131 +#include <stdint.h>
1132 +#include <string.h>
1133 +#include <unistd.h>
1138 +#include "xmir-private.h"
1140 +struct xmir_marshall_handler {
1141 + void (*msg_handler)(void *msg);
1146 +static int pipefds[2];
1149 +xmir_wakeup_handler(pointer data, int err, pointer read_mask)
1151 + if (err >= 0 && FD_ISSET(pipefds[0], (fd_set *)read_mask))
1152 + xmir_process_from_eventloop();
1156 +xmir_init_thread_to_eventloop(void)
1158 + int err = pipe(pipefds);
1160 + FatalError("[XMIR] Failed to create thread-proxy pipes: %s\n", strerror(errno));
1162 + /* Set the read end to not block; we'll pull from this in the event loop
1163 + * We don't need to care about the write end, as that'll be written to
1164 + * from its own thread
1166 + fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
1168 + AddGeneralSocket(pipefds[0]);
1169 + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1170 + xmir_wakeup_handler,
1174 +xmir_marshall_handler *
1175 +xmir_register_handler(void (*msg_handler)(void *msg), size_t msg_size)
1177 + xmir_marshall_handler *handler;
1179 + if (msg_size + sizeof *handler > PIPE_BUF)
1182 + handler = malloc(sizeof *handler + msg_size);
1186 + handler->msg_handler = msg_handler;
1187 + handler->msg_size = msg_size;
1192 +xmir_post_to_eventloop(xmir_marshall_handler *handler, void *msg)
1195 + const int total_size = sizeof *handler + handler->msg_size;
1196 + /* We require the total size to be less than PIPE_BUF to ensure an atomic write */
1197 + assert(total_size < PIPE_BUF);
1199 + memcpy(handler->msg, msg, handler->msg_size);
1200 + written = write(pipefds[1], handler, total_size);
1201 + if (written != total_size)
1202 + xf86Msg(X_ERROR, "[XMIR] Failed to proxy message to mainloop\n");
1206 +xmir_process_from_eventloop(void)
1208 + xmir_marshall_handler handler;
1212 + if (read(pipefds[0], &handler, sizeof handler) < 0) {
1216 + msg = malloc(handler.msg_size);
1217 + if(read(pipefds[0], msg, handler.msg_size) == handler.msg_size)
1218 + (*handler.msg_handler)(msg);
1224 +++ b/hw/xfree86/xmir/xmir-window.c
1227 + * Copyright © 2012 Canonical, Inc
1229 + * Permission is hereby granted, free of charge, to any person obtaining a
1230 + * copy of this software and associated documentation files (the "Soft-
1231 + * ware"), to deal in the Software without restriction, including without
1232 + * limitation the rights to use, copy, modify, merge, publish, distribute,
1233 + * and/or sell copies of the Software, and to permit persons to whom the
1234 + * Software is furnished to do so, provided that the above copyright
1235 + * notice(s) and this permission notice appear in all copies of the Soft-
1236 + * ware and that both the above copyright notice(s) and this permission
1237 + * notice appear in supporting documentation.
1239 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1240 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
1241 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
1242 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
1243 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
1244 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1245 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1246 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
1247 + * MANCE OF THIS SOFTWARE.
1249 + * Except as contained in this notice, the name of a copyright holder shall
1250 + * not be used in advertising or otherwise to promote the sale, use or
1251 + * other dealings in this Software without prior written authorization of
1252 + * the copyright holder.
1255 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1258 +#ifdef HAVE_XORG_CONFIG_H
1259 +#include "xorg-config.h"
1261 +#include <xorg-server.h>
1262 +#include "windowstr.h"
1263 +#include "regionstr.h"
1264 +#include "damagestr.h"
1267 +#include "xmir-private.h"
1271 +#include <stdlib.h>
1272 +#include <unistd.h>
1274 +static DevPrivateKeyRec xmir_window_private_key;
1275 +static const RegionRec xmir_empty_region = { {0, 0, 0, 0}, &RegionBrokenData };
1278 +xmir_window_get(WindowPtr win)
1280 + /* The root window is handled specially */
1281 + assert(win->parent != NULL);
1283 + return dixGetPrivate(&win->devPrivates, &xmir_window_private_key);
1287 +xmir_window_get_fd(xmir_window *xmir_win)
1289 + MirBufferPackage *package;
1291 + if (mir_platform_type_gbm != mir_surface_get_platform_type(xmir_win->surface))
1292 + FatalError("[xmir] Only supported on DRM Mir platform\n");
1294 + mir_surface_get_current_buffer(xmir_win->surface, &package);
1295 + if (package->fd_items != 1)
1296 + FatalError("[xmir] Unexpected buffer contents from Mir; this is a programming error\n");
1298 + return package->fd[0];
1302 +xmir_handle_buffer_available(void *ctx)
1304 + xmir_screen *xmir;
1305 + xmir_window *mir_win = *(xmir_window **)ctx;
1307 + if (mir_win->surface == NULL)
1310 + xmir = xmir_screen_get(xmir_window_to_windowptr(mir_win)->drawable.pScreen);
1312 + mir_win->has_free_buffer = TRUE;
1313 + mir_win->damage_index = (mir_win->damage_index + 1) % MIR_MAX_BUFFER_AGE;
1315 + if (xmir_window_is_dirty(mir_win))
1316 + (*xmir->driver->BufferAvailableForWindow)(mir_win,
1317 + xmir_window_get_dirty(mir_win));
1321 +index_in_damage_buffer(int current_index, int age)
1323 + int index = (current_index - age) % MIR_MAX_BUFFER_AGE;
1325 + return index < 0 ? MIR_MAX_BUFFER_AGE + index : index;
1329 +handle_buffer_received(MirSurface *surf, void *ctx)
1331 + xmir_window *xmir_win = ctx;
1333 + xmir_screen *xmir =
1334 + xmir_screen_get(xmir_window_to_windowptr(xmir_win)->drawable.pScreen);
1336 + xmir_post_to_eventloop(xmir->submit_rendering_handler, &xmir_win);
1340 +damage_region_for_current_buffer(xmir_window *xmir_win)
1342 + MirBufferPackage *package;
1346 + mir_surface_get_current_buffer(xmir_win->surface, &package);
1347 + age = package->age;
1349 + region = &xmir_win->past_damage[index_in_damage_buffer(xmir_win->damage_index, age)];
1351 + /* As per EGL_EXT_buffer_age, contents are undefined for age == 0 */
1353 + RegionCopy(region, &xmir_win->region);
1358 +/* Submit rendering for @window to Mir
1359 + * @region is an (optional) damage region, to hint the compositor as to what
1360 + * region has changed. It can be NULL to indicate the whole window should be
1361 + * considered dirty.
1364 +xmir_submit_rendering_for_window(xmir_window *xmir_win,
1367 + RegionPtr tracking;
1369 + if (!xmir_screen_get(xmir_win->win->drawable.pScreen)->dpms_on)
1372 + xmir_win->has_free_buffer = FALSE;
1373 + tracking = damage_region_for_current_buffer(xmir_win);
1374 + mir_surface_swap_buffers(xmir_win->surface, &handle_buffer_received, xmir_win);
1376 + if (region == NULL)
1377 + RegionEmpty(tracking);
1379 + RegionSubtract(tracking, tracking, region);
1381 + if (RegionNil(tracking))
1382 + xorg_list_del(&xmir_win->link_damage);
1388 +xmir_window_has_free_buffer(xmir_window *xmir_win)
1390 + return xmir_win->has_free_buffer;
1393 +_X_EXPORT RegionPtr
1394 +xmir_window_get_dirty(xmir_window *xmir_win)
1396 + if (xorg_list_is_empty(&xmir_win->link_damage))
1397 + return (RegionPtr)&xmir_empty_region;
1399 + if (xmir_win->damaged) {
1401 + RegionPtr damage = DamageRegion(xmir_win->damage);
1402 + RegionIntersect(damage, damage, &xmir_win->region);
1404 + for (i = 0; i < MIR_MAX_BUFFER_AGE; i++) {
1405 + RegionUnion(&xmir_win->past_damage[i],
1406 + &xmir_win->past_damage[i],
1410 + DamageEmpty(xmir_win->damage);
1411 + xmir_win->damaged = 0;
1414 + return damage_region_for_current_buffer(xmir_win);
1418 +xmir_window_is_dirty(xmir_window *xmir_win)
1420 + return RegionNotEmpty(xmir_window_get_dirty(xmir_win));
1423 +_X_EXPORT WindowPtr
1424 +xmir_window_to_windowptr(xmir_window *xmir_win)
1426 + return xmir_win->win;
1430 +xmir_window_get_drawable_region(xmir_window *xmir_win)
1432 + return RegionExtents(&xmir_win->region);
1436 +xmir_window_get_stride(xmir_window *xmir_win)
1438 + MirBufferPackage *package;
1440 + mir_surface_get_current_buffer(xmir_win->surface, &package);
1442 + return package->stride;
1446 +damage_report(DamagePtr damage, RegionPtr region, void *ctx)
1448 + xmir_window *xmir_win = ctx;
1450 + xmir_win->damaged = 1;
1451 + xorg_list_move(&xmir_win->link_damage,
1452 + &xmir_screen_get(damage->pScreen)->damage_list);
1456 +damage_destroy(DamagePtr damage, void *ctx)
1458 + xmir_window *xmir_win = ctx;
1459 + xorg_list_del(&xmir_win->link_damage);
1463 +xmir_window_enable_damage_tracking(xmir_window *xmir_win)
1465 + WindowPtr win = xmir_win->win;
1467 + if (xmir_win->damage != NULL)
1470 + xorg_list_init(&xmir_win->link_damage);
1471 + xmir_win->damage = DamageCreate(damage_report, damage_destroy,
1472 + DamageReportNonEmpty, TRUE,
1473 + win->drawable.pScreen, xmir_win);
1474 + DamageRegister(&win->drawable, xmir_win->damage);
1476 + for (int i = 0; i < MIR_MAX_BUFFER_AGE; i++) {
1477 + RegionNull(&xmir_win->past_damage[i]);
1479 + xmir_win->damage_index = 0;
1480 + xmir_win->damaged = 0;
1484 +xmir_window_disable_damage_tracking(xmir_window *xmir_win)
1486 + if (xmir_win->damage != NULL) {
1487 + DamageUnregister(xmir_win->damage);
1488 + DamageDestroy(xmir_win->damage);
1489 + xmir_win->damage = NULL;
1494 +xmir_create_window(WindowPtr win)
1496 + ScreenPtr screen = win->drawable.pScreen;
1497 + xmir_screen *xmir = xmir_screen_get(screen);
1500 + screen->CreateWindow = xmir->CreateWindow;
1501 + ret = (*screen->CreateWindow)(win);
1502 + screen->CreateWindow = xmir_create_window;
1504 + /* Until we support rootless operation, we care only for the root
1505 + * window, which has no parent.
1507 + if (win->parent == NULL) {
1508 + /* The CRTC setup has already created the root_window_fragments
1509 + array. We need to hook the root window into it */
1510 + for (int i = 0; xmir->root_window_fragments[i] != NULL; i++) {
1511 + xmir->root_window_fragments[i]->win = win;
1513 + /* TODO: This creates one Damage tracker per fragment; we only
1514 + really need one, though */
1515 + xmir_window_enable_damage_tracking(xmir->root_window_fragments[i]);
1522 +xmir_destroy_window(WindowPtr win)
1524 + ScreenPtr screen = win->drawable.pScreen;
1525 + xmir_screen *xmir = xmir_screen_get(screen);
1528 + screen->DestroyWindow = xmir->DestroyWindow;
1529 + ret = (*screen->DestroyWindow)(win);
1530 + screen->DestroyWindow = xmir_destroy_window;
1532 + /* Until we support rootless operation, we care only for the root
1533 + * window, which has no parent.
1535 + if (win->parent == NULL) {
1536 + /* Break the link with the root_window_fragments */
1537 + for (int i = 0; xmir->root_window_fragments[i] != NULL; i++) {
1538 + xmir->root_window_fragments[i]->win = NULL;
1540 + /* We cannot use xmir_window_disable_damage_tracking here because
1541 + * the Damage extension will also clean it up on window destruction
1543 + xorg_list_del(&xmir->root_window_fragments[i]->link_damage);
1551 +xmir_screen_init_window(ScreenPtr screen, xmir_screen *xmir)
1553 + if (!dixRegisterPrivateKey(&xmir_window_private_key, PRIVATE_WINDOW, 0))
1556 + xmir->CreateWindow = screen->CreateWindow;
1557 + screen->CreateWindow = xmir_create_window;
1558 + xmir->DestroyWindow = screen->DestroyWindow;
1559 + screen->DestroyWindow = xmir_destroy_window;
1561 + xmir->submit_rendering_handler =
1562 + xmir_register_handler(&xmir_handle_buffer_available,
1563 + sizeof (xmir_window *));
1564 + if (xmir->submit_rendering_handler == NULL)
1570 +++ b/hw/xfree86/xmir/xmir.c
1573 + * Copyright © 2012 Canonical, Inc
1575 + * Permission is hereby granted, free of charge, to any person obtaining a
1576 + * copy of this software and associated documentation files (the "Soft-
1577 + * ware"), to deal in the Software without restriction, including without
1578 + * limitation the rights to use, copy, modify, merge, publish, distribute,
1579 + * and/or sell copies of the Software, and to permit persons to whom the
1580 + * Software is furnished to do so, provided that the above copyright
1581 + * notice(s) and this permission notice appear in all copies of the Soft-
1582 + * ware and that both the above copyright notice(s) and this permission
1583 + * notice appear in supporting documentation.
1585 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1586 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
1587 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
1588 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
1589 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
1590 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1591 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1592 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
1593 + * MANCE OF THIS SOFTWARE.
1595 + * Except as contained in this notice, the name of a copyright holder shall
1596 + * not be used in advertising or otherwise to promote the sale, use or
1597 + * other dealings in this Software without prior written authorization of
1598 + * the copyright holder.
1601 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1604 +#ifdef HAVE_XORG_CONFIG_H
1605 +#include <xorg-config.h>
1609 +#include "xmir-private.h"
1613 +#include "xf86Crtc.h"
1614 +#include "xf86Priv.h"
1616 +#include <xf86drm.h>
1617 +#include <string.h>
1619 +#include <mir_toolkit/mir_client_library.h>
1620 +#include <mir_toolkit/mir_client_library_drm.h>
1622 +static DevPrivateKeyRec xmir_screen_private_key;
1624 + * We have only a single Mir connection, regardless of how many
1627 +static MirConnection *conn;
1630 +xmir_connection_get(void)
1636 +xmir_screen_get(ScreenPtr screen)
1638 + return dixGetPrivate(&screen->devPrivates, &xmir_screen_private_key);
1642 +xmir_get_drm_fd(const char *busid)
1644 + MirPlatformPackage platform;
1647 + mir_connection_get_platform(conn, &platform);
1649 + for (i = 0; i < platform.fd_items; ++i) {
1650 + char *fd_busid = drmGetBusid(platform.fd[i]);
1651 + if (!strcasecmp(busid, fd_busid))
1652 + fd = platform.fd[i];
1653 + drmFreeBusid(fd_busid);
1659 +handle_auth_magic(int status, void *ctx)
1661 + int *retVal = ctx;
1666 +xmir_auth_drm_magic(xmir_screen *xmir, uint32_t magic)
1669 + mir_wait_for(mir_connection_drm_auth_magic(xmir_connection_get(),
1671 + &handle_auth_magic,
1676 +_X_EXPORT xmir_screen *
1677 +xmir_screen_create(ScrnInfoPtr scrn)
1679 + xmir_screen *xmir = calloc (1, sizeof *xmir);
1683 + xmir->scrn = scrn;
1684 + xmir->dpms_on = TRUE;
1690 +xmir_screen_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir, xmir_driver *driver)
1692 + xmir->driver = driver;
1693 + xorg_list_init(&xmir->damage_list);
1695 + if (!xmir_mode_pre_init(scrn, xmir))
1701 +static void xmir_handle_focus_event(void *ctx)
1703 + Bool new_focus = *(Bool *)ctx;
1704 + xf86Msg(X_INFO, "[XMir] Handling focus event, new_focus = %s\n", new_focus ? "TRUE" : "FALSE");
1706 + /* TODO: Split xf86VTSwitch out so that we don't need to check xf86VTOwner*/
1707 + /* TODO: Disable input on startup until we receive a usc ACK */
1708 + if (new_focus && !xf86VTOwner())
1711 + if (!new_focus && xf86VTOwner())
1715 +static void xmir_handle_lifecycle_event(MirConnection *unused, MirLifecycleState state, void *ctx)
1718 + xmir_screen *xmir = ctx;
1722 + case mir_lifecycle_state_will_suspend:
1723 + new_focus = FALSE;
1725 + case mir_lifecycle_state_resumed:
1729 + xf86Msg(X_ERROR, "Received unknown Mir lifetime event\n");
1732 + xmir_post_to_eventloop(xmir->focus_event_handler, &new_focus);
1736 +xmir_screen_init(ScreenPtr screen, xmir_screen *xmir)
1738 + if (!dixRegisterPrivateKey(&xmir_screen_private_key, PRIVATE_SCREEN, 0))
1740 + dixSetPrivate(&screen->devPrivates, &xmir_screen_private_key, xmir);
1742 + if (!xmir_screen_init_window(screen, xmir))
1745 + if (!xf86_cursors_init(screen, 0,0,0))
1746 + xf86Msg(X_WARNING, "xf86Cursor initialisation failed\n");
1748 + /* Hook up focus -> VT switch proxy */
1749 + xmir->focus_event_handler =
1750 + xmir_register_handler(&xmir_handle_focus_event,
1752 + if (xmir->focus_event_handler == NULL)
1755 + mir_connection_set_lifecycle_event_callback(xmir_connection_get(),
1756 + &xmir_handle_lifecycle_event,
1763 +xmir_screen_close(ScreenPtr screen, xmir_screen *xmir)
1769 +xmir_screen_destroy(xmir_screen *xmir)
1775 +xmir_screen_for_each_damaged_window(xmir_screen *xmir, xmir_window_proc callback)
1777 + xmir_window *xmir_win, *tmp_win;
1778 + xorg_list_for_each_entry_safe(xmir_win, tmp_win, &xmir->damage_list, link_damage) {
1779 + if (xmir_window_has_free_buffer(xmir_win) &&
1780 + xmir_window_is_dirty(xmir_win))
1781 + (*callback)(xmir_win, xmir_window_get_dirty(xmir_win));
1785 +static MODULESETUPPROTO(xMirSetup);
1786 +static MODULETEARDOWNPROTO(xMirTeardown);
1788 +static XF86ModuleVersionInfo VersRec = {
1790 + MODULEVENDORSTRING,
1793 + XORG_VERSION_CURRENT,
1795 + ABI_CLASS_EXTENSION,
1796 + ABI_EXTENSION_VERSION,
1801 +_X_EXPORT XF86ModuleData xmirModuleData = { &VersRec, xMirSetup, xMirTeardown };
1804 +xMirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
1806 + static Bool setupDone = FALSE;
1810 + *errmaj = LDR_ONCEONLY;
1814 + conn = mir_connect_sync(mirSocket, mirID);
1816 + if (!mir_connection_is_valid(conn)) {
1818 + *errmaj = LDR_MODSPECIFIC;
1819 + FatalError("Failed to connect to Mir: %s\n",
1820 + mir_connection_get_error_message(conn));
1824 + xmir_init_thread_to_eventloop();
1832 +xMirTeardown(pointer module)
1836 +++ b/hw/xfree86/xmir/xmir.h
1839 + * Copyright © 2012 Canonical, Inc
1841 + * Permission is hereby granted, free of charge, to any person obtaining a
1842 + * copy of this software and associated documentation files (the "Soft-
1843 + * ware"), to deal in the Software without restriction, including without
1844 + * limitation the rights to use, copy, modify, merge, publish, distribute,
1845 + * and/or sell copies of the Software, and to permit persons to whom the
1846 + * Software is furnished to do so, provided that the above copyright
1847 + * notice(s) and this permission notice appear in all copies of the Soft-
1848 + * ware and that both the above copyright notice(s) and this permission
1849 + * notice appear in supporting documentation.
1851 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1852 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
1853 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
1854 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
1855 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
1856 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1857 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1858 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
1859 + * MANCE OF THIS SOFTWARE.
1861 + * Except as contained in this notice, the name of a copyright holder shall
1862 + * not be used in advertising or otherwise to promote the sale, use or
1863 + * other dealings in this Software without prior written authorization of
1864 + * the copyright holder.
1867 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1873 +#include <stdint.h>
1874 +#include <mir_toolkit/mir_client_library.h>
1876 +#include "xf86str.h"
1877 +#include "scrnintstr.h"
1878 +#include "window.h"
1880 +typedef struct xmir_screen xmir_screen;
1881 +typedef struct xmir_window xmir_window;
1883 +typedef void (*xmir_window_proc)(xmir_window *xmir_win, RegionPtr damaged_region);
1885 +#define XMIR_DRIVER_VERSION 1
1888 + xmir_window_proc BufferAvailableForWindow;
1892 +xmir_get_drm_fd(const char *busid);
1895 +xmir_auth_drm_magic(xmir_screen *xmir, uint32_t magic);
1897 +_X_EXPORT xmir_screen *
1898 +xmir_screen_create(ScrnInfoPtr scrn);
1901 +xmir_screen_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir, xmir_driver *driver);
1904 +xmir_screen_init(ScreenPtr screen, xmir_screen *xmir);
1907 +xmir_screen_close(ScreenPtr screen, xmir_screen *xmir);
1910 +xmir_screen_destroy(xmir_screen *xmir);
1912 +_X_EXPORT WindowPtr
1913 +xmir_window_to_windowptr(xmir_window *xmir_win);
1916 +xmir_window_get_fd(xmir_window *xmir_win);
1919 +xmir_submit_rendering_for_window(xmir_window *xmir_win,
1920 + RegionPtr region);
1923 +xmir_window_has_free_buffer(xmir_window *xmir_win);
1925 +_X_EXPORT RegionPtr
1926 +xmir_window_get_dirty(xmir_window *xmir_win);
1929 +xmir_window_is_dirty(xmir_window *xmir_win);
1932 +xmir_window_get_drawable_region(xmir_window *xmir_win);
1935 +xmir_window_get_stride(xmir_window *xmir_win);
1938 +xmir_screen_for_each_damaged_window(xmir_screen *xmir, xmir_window_proc callback);
1940 +#endif /* _XMIR_H */
1941 --- a/include/list.h
1942 +++ b/include/list.h
1943 @@ -184,6 +184,14 @@ __xorg_list_del(struct xorg_list *prev,
1948 +xorg_list_move(struct xorg_list *entry, struct xorg_list *head)
1950 + __xorg_list_del(entry->prev, entry->next);
1951 + __xorg_list_add(entry, head->prev, head);
1956 * Remove the element from the list it is in. Using this function will reset
1957 * the pointers to/from this element so it is removed from the list. It does
1958 --- a/include/xorg-server.h.in
1959 +++ b/include/xorg-server.h.in
1961 /* Use XTrans FD passing support */
1962 #undef XTRANS_SEND_FDS
1964 +/* Build XMIR nested server */
1967 #endif /* _XORG_SERVER_H_ */
1968 --- a/test/Makefile.am
1969 +++ b/test/Makefile.am
1970 @@ -6,6 +6,9 @@ if XORG
1971 # For now, requires xf86 ddx, could be adjusted to use another
1973 noinst_PROGRAMS += xkb input xtest misc fixes xfree86 hashtabletest os signal-logging touch
1975 +noinst_PROGRAMS += xmir-thread-proxy
1978 check_LTLIBRARIES = libxservertest.la
1980 @@ -38,6 +41,8 @@ touch_LDADD=$(TEST_LDADD)
1981 signal_logging_LDADD=$(TEST_LDADD)
1982 hashtabletest_LDADD=$(TEST_LDADD) $(top_srcdir)/Xext/hashtable.c
1983 os_LDADD=$(TEST_LDADD)
1984 +xmir_thread_proxy_LDADD=$(TEST_LDADD) $(top_srcdir)/hw/xfree86/xmir/xmir-thread-proxy.c -lpthread
1985 +xmir_thread_proxy_CFLAGS=$(AM_CFLAGS) $(XMIR_CFLAGS) -I$(top_srcdir)/hw/xfree86/xmir -I$(top_srcdir)/hw/xfree86/common
1987 libxservertest_la_LIBADD = $(XSERVER_LIBS)
1990 +++ b/test/xmir-thread-proxy.c
1993 + * Copyright © 2012 Canonical, Inc
1995 + * Permission is hereby granted, free of charge, to any person obtaining a
1996 + * copy of this software and associated documentation files (the "Soft-
1997 + * ware"), to deal in the Software without restriction, including without
1998 + * limitation the rights to use, copy, modify, merge, publish, distribute,
1999 + * and/or sell copies of the Software, and to permit persons to whom the
2000 + * Software is furnished to do so, provided that the above copyright
2001 + * notice(s) and this permission notice appear in all copies of the Soft-
2002 + * ware and that both the above copyright notice(s) and this permission
2003 + * notice appear in supporting documentation.
2005 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2006 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
2007 + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
2008 + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
2009 + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
2010 + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2011 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2012 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
2013 + * MANCE OF THIS SOFTWARE.
2015 + * Except as contained in this notice, the name of a copyright holder shall
2016 + * not be used in advertising or otherwise to promote the sale, use or
2017 + * other dealings in this Software without prior written authorization of
2018 + * the copyright holder.
2021 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
2024 +#ifdef HAVE_DIX_CONFIG_H
2025 +#include <dix-config.h>
2029 +#include <stdlib.h>
2030 +#include <pthread.h>
2031 +#include <unistd.h>
2033 +#include "xmir-private.h"
2035 +struct test_content {
2041 +_test_callback(void *msg_content)
2043 + struct test_content *content = msg_content;
2044 + *content->variable = content->value;
2048 +xmir_test_marshall_to_eventloop(void)
2050 + xmir_marshall_handler *test_marshaller;
2051 + struct test_content msg;
2054 + xmir_init_thread_to_eventloop();
2056 + test_marshaller = xmir_register_handler(&_test_callback, sizeof msg);
2058 + msg.variable = ✓
2061 + xmir_post_to_eventloop(test_marshaller, &msg);
2062 + xmir_process_from_eventloop();
2064 + assert(check == 1);
2068 +_racy_test_callback(void *msg_content)
2070 + struct test_content *content = msg_content;
2071 + int new_value = *content->variable + 1;
2072 + /* Ensure the other threads get to run and see the old value of content->variable */
2074 + *content->variable = new_value;
2077 +struct thread_context {
2078 + xmir_marshall_handler *marshaller;
2079 + struct test_content *msg;
2083 +_post_racy_msg(void *thread_ctx)
2085 + struct thread_context *ctx = thread_ctx;
2087 + xmir_post_to_eventloop(ctx->marshaller, ctx->msg);
2092 +#define NUM_THREADS 10
2095 +xmir_test_many_threads_to_eventloop(void)
2097 + pthread_t threads[NUM_THREADS];
2098 + pthread_attr_t attr;
2099 + xmir_marshall_handler *test_marshaller;
2100 + struct thread_context ctx;
2101 + struct test_content msg;
2104 + pthread_attr_init(&attr);
2105 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
2107 + xmir_init_thread_to_eventloop();
2109 + test_marshaller = xmir_register_handler(&_racy_test_callback, sizeof msg);
2111 + msg.variable = ✓
2113 + ctx.marshaller = test_marshaller;
2116 + for (i = 0; i < NUM_THREADS; i++) {
2117 + pthread_create(&threads[i], &attr, _post_racy_msg, (void *)&ctx);
2120 + pthread_attr_destroy(&attr);
2122 + for (i = 0; i < NUM_THREADS; i++) {
2123 + pthread_join(threads[i], NULL);
2126 + xmir_process_from_eventloop();
2128 + assert(check == NUM_THREADS);
2132 +xmir_test_refuses_to_marshall_too_large_msg(void)
2134 + xmir_init_thread_to_eventloop();
2136 + assert(xmir_register_handler(&_test_callback, PIPE_BUF) == NULL);
2140 +main(int argc, char **argv)
2142 + xmir_test_marshall_to_eventloop();
2143 + xmir_test_many_threads_to_eventloop();
2144 + xmir_test_refuses_to_marshall_too_large_msg();