ODROID-U3 xorg-server debian package fork :
[deb_xorg-server.git] / debian / patches / xmir.patch
1 --- a/configure.ac
2 +++ b/configure.ac
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])
10
11 @@ -1334,6 +1335,15 @@ if test "x$XINERAMA" = xyes; then
12 SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $XINERAMAPROTO"
13 fi
14
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"
21 +fi
22 +AM_CONDITIONAL(XMIR, [test "x$XMIR" = xyes])
23 +
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
34 hw/dmx/doc/Makefile
35 --- a/hw/xfree86/Makefile.am
36 +++ b/hw/xfree86/Makefile.am
37 @@ -30,15 +30,20 @@ if INT10MODULE
38 INT10_SUBDIR = int10
39 endif
40
41 +if XMIR
42 +XMIR_SUBDIR = xmir
43 +endif
44 +
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 \
50 + $(XMIR_SUBDIR)
51
52 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
53 parser ramdac shadowfb vbe vgahw \
54 loader dixmods dri dri2 exa modes \
55 - utils doc man
56 + utils doc man xmir
57
58 bin_PROGRAMS = Xorg
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},
65 #endif
66 + {.name = "xmir", .toLoad = FALSE, .load_opt = NULL},
67 {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
68 };
69
70 @@ -260,6 +261,17 @@ xf86ModulelistFromConfig(pointer **optli
71 return NULL;
72 }
73
74 + /*
75 + * Set the xmir module to autoload if requested.
76 + */
77 + if (xorgMir) {
78 + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
79 + if (strcmp(ModuleDefaults[i].name, "xmir") == 0) {
80 + ModuleDefaults[i].toLoad = TRUE;
81 + }
82 + }
83 + }
84 +
85 if (xf86configptr->conf_modules) {
86 /* Walk the disable list and let people know what we've parsed to
87 * not be loaded
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);
92 #endif
93
94 -static void xf86VTSwitch(void);
95 -
96 /*
97 * Allow arbitrary drivers or other XFree86 code to register with our main
98 * Wakeup handler.
99 @@ -411,7 +409,7 @@ xf86ReleaseKeys(DeviceIntPtr pDev)
100 * xf86VTSwitch --
101 * Handle requests for switching the vt.
102 */
103 -static void
104 +_X_EXPORT void
105 xf86VTSwitch(void)
106 {
107 int i;
108 @@ -471,7 +469,7 @@ xf86VTSwitch(void)
109
110 xf86AccessLeave(); /* We need this here, otherwise */
111
112 - if (!xf86VTSwitchAway()) {
113 + if (!xorgMir && !xf86VTSwitchAway()) {
114 /*
115 * switch failed
116 */
117 @@ -530,7 +528,7 @@ xf86VTSwitch(void)
118 }
119 else {
120 DebugF("xf86VTSwitch: Entering\n");
121 - if (!xf86VTSwitchTo())
122 + if (!xorgMir && !xf86VTSwitchTo())
123 return;
124
125 #ifdef XF86PM
126 --- a/hw/xfree86/common/xf86Globals.c
127 +++ b/hw/xfree86/common/xf86Globals.c
128 @@ -207,3 +207,6 @@ Bool xf86VidModeAllowNonLocal = FALSE;
129 #endif
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;
142 +
143 + /* Compact xf86DriverList array, update xf86NumDrivers */
144 + 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));
150 }
151 }
152
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.
157 */
158
159 - for (i = 0; i < xf86NumDrivers; i++) {
160 + for (i = 0; i < xf86NumDrivers; ) {
161 xorgHWFlags flags = HW_IO;
162
163 if (xf86DriverList[i]->Identify != NULL)
164 @@ -565,11 +565,20 @@ InitOutput(ScreenInfo * pScreenInfo, int
165 GET_REQUIRED_HW_INTERFACES,
166 &flags);
167
168 + if (xorgMir &&
169 + (NEED_IO_ENABLED(flags) || !(flags & HW_SKIP_CONSOLE))) {
170 + ErrorF("Driver needs flags %lu, incompatible with nested, deleting.\n", flags);
171 + xf86DeleteDriver(i);
172 + continue;
173 + }
174 +
175 if (NEED_IO_ENABLED(flags))
176 want_hw_access = TRUE;
177
178 if (!(flags & HW_SKIP_CONSOLE))
179 xorgHWOpenConsole = TRUE;
180 +
181 + i++;
182 }
183
184 if (xorgHWOpenConsole)
185 @@ -662,9 +671,13 @@ InitOutput(ScreenInfo * pScreenInfo, int
186 }
187
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)
195 xf86DeleteDriver(i);
196 + else
197 + i++;
198
199 /*
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;
203 return 1;
204 }
205 + if (!strcmp(argv[i], "-mir")) {
206 + CHECK_FOR_REQUIRED_ARGUMENT();
207 + mirID = argv[++i];
208 + xorgMir = TRUE;
209 + return 2;
210 + }
211 + if (!strcmp(argv[i], "-mirSocket")) {
212 + CHECK_FOR_REQUIRED_ARGUMENT();
213 + mirSocket = argv[++i];
214 + return 2;
215 + }
216
217 /* OS-specific processing */
218 return xf86ProcessArgument(argc, argv, i);
219 @@ -1563,6 +1587,8 @@ ddxUseMsg(void)
220 ErrorF
221 ("-novtswitch don't automatically switch VT at reset & exit\n");
222 ErrorF("-sharevts share VTs with another X server\n");
223 + ErrorF
224 + ("-mir MirID run nested in a Mir compositor with app id MirID\n");
225 /* OS-specific usage */
226 xf86UseMsg();
227 ErrorF("\n");
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;
237
238 extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
239
240 @@ -149,6 +152,9 @@ xf86HandlePMEvents(int fd, pointer data)
241 extern _X_EXPORT int (*xf86PMGetEventFromOs) (int fd, pmEvent * events,
242 int num);
243 extern _X_EXPORT pmWait (*xf86PMConfirmEventToOs) (int fd, pmEvent event);
244 +extern _X_EXPORT void
245 +xf86VTSwitch(void);
246 +
247
248 /* xf86Helper.c */
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;
255
256 - if (!xf86InitHardwareCursor(pScreen, infoPtr))
257 + infoPtr->pScrn = xf86ScreenToScrn(pScreen);
258 +
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))
263 return FALSE;
264
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;
270 }
271
272 - infoPtr->pScrn = xf86ScreenToScrn(pScreen);
273 -
274 return TRUE;
275 }
276
277 --- /dev/null
278 +++ b/hw/xfree86/xmir/Makefile.am
279 @@ -0,0 +1,26 @@
280 +INCLUDES = \
281 + $(XORG_INCS) \
282 + -I$(srcdir)/../ddc \
283 + -I$(srcdir)/../ramdac \
284 + -I$(srcdir)/../i2c \
285 + -I$(srcdir)/../parser \
286 + -I$(srcdir)/../modes
287 +
288 +libxmir_la_LTLIBRARIES = libxmir.la
289 +libxmir_la_CFLAGS = \
290 + -DHAVE_XORG_CONFIG_H \
291 + $(DRI_CFLAGS) \
292 + $(DIX_CFLAGS) $(XORG_CFLAGS) $(LIBDRM_CFLAGS) \
293 + $(XMIR_CFLAGS)
294 +
295 +libxmir_la_LDFLAGS = -module -avoid-version $(LIBDRM_LIBS) $(XMIR_LIBS)
296 +libxmir_ladir = $(moduledir)/extensions
297 +libxmir_la_SOURCES = \
298 + xmir.c \
299 + xmir-window.c \
300 + xmir-output.c \
301 + xmir-thread-proxy.c \
302 + xmir.h \
303 + xmir-private.h
304 +
305 +sdk_HEADERS = xmir.h
306 --- /dev/null
307 +++ b/hw/xfree86/xmir/xmir-output.c
308 @@ -0,0 +1,678 @@
309 +/*
310 + * Copyright © 2012 Canonical, Inc
311 + *
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.
321 + *
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.
331 + *
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.
336 + *
337 + * Authors:
338 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
339 + */
340 +
341 +#include <stdlib.h>
342 +#include <stdio.h>
343 +#include <math.h>
344 +
345 +#include <xorg-config.h>
346 +#include "xmir.h"
347 +#include "xmir-private.h"
348 +#include "xf86Crtc.h"
349 +#include "xf86Priv.h"
350 +
351 +struct xmir_crtc {
352 + xmir_screen *xmir;
353 + xmir_window *root_fragment;
354 + MirDisplayConfiguration *config;
355 +};
356 +
357 +static const char *
358 +xmir_mir_dpms_mode_description(MirPowerMode mode)
359 +{
360 + switch (mode)
361 + {
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";
370 + default:
371 + return "OMGUNKNOWN!";
372 + }
373 +}
374 +
375 +static void
376 +xmir_crtc_dpms(xf86CrtcPtr crtc, int mode)
377 +{
378 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
379 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
380 +
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);
386 + switch (mode) {
387 + case DPMSModeOn:
388 + output->power_mode = mir_power_mode_on;
389 + xmir_crtc->xmir->dpms_on = TRUE;
390 + break;
391 + case DPMSModeStandby:
392 + output->power_mode = mir_power_mode_standby;
393 + xmir_crtc->xmir->dpms_on = FALSE;
394 + break;
395 + case DPMSModeSuspend:
396 + output->power_mode = mir_power_mode_suspend;
397 + xmir_crtc->xmir->dpms_on = FALSE;
398 + break;
399 + case DPMSModeOff:
400 + output->power_mode = mir_power_mode_off;
401 + xmir_crtc->xmir->dpms_on = FALSE;
402 + break;
403 + }
404 + }
405 + }
406 + mir_wait_for(mir_connection_apply_display_config(xmir_connection_get(),
407 + xmir_crtc->config));
408 +}
409 +
410 +static const char*
411 +xmir_get_output_type_str(MirDisplayOutput *mir_output)
412 +{
413 + const char *str = "Invalid";
414 +
415 + switch(mir_output->type)
416 + {
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;
431 +
432 + case mir_display_output_type_unknown: str = "None"; break;
433 + default: break;
434 + }
435 +
436 + return str;
437 +}
438 +
439 +static void
440 +xmir_output_populate(xf86OutputPtr xf86output, MirDisplayOutput *output)
441 +{
442 + /* We can always arbitrarily clone and output */
443 + xf86output->possible_crtcs = 0xffffffff;
444 + xf86output->possible_clones = 0xffffffff;
445 +
446 + xf86output->driver_private = output;
447 +
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;
454 +}
455 +
456 +static DisplayModePtr
457 +xmir_create_xf86mode(const struct MirDisplayMode *mir_mode)
458 +{
459 + DisplayModePtr mode;
460 +
461 + mode = xf86CVTMode(mir_mode->horizontal_resolution,
462 + mir_mode->vertical_resolution,
463 + mir_mode->refresh_rate,
464 + FALSE, FALSE);
465 +
466 + /*
467 + * And now, because the CVT standard doesn't support such common
468 + * resolutions as 1366x768...
469 + */
470 + mode->VDisplay = mir_mode->vertical_resolution;
471 + mode->HDisplay = mir_mode->horizontal_resolution;
472 +
473 + xf86SetModeDefaultName(mode);
474 +
475 + return mode;
476 +}
477 +
478 +static void
479 +xmir_free_xf86mode(DisplayModePtr mode)
480 +{
481 + free(mode->name);
482 + free(mode);
483 +}
484 +
485 +static Bool
486 +xmir_set_mode_for_output(MirDisplayOutput *output,
487 + DisplayModePtr mode)
488 +{
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);
496 +
497 + mir_mode = xmir_create_xf86mode(&output->modes[i]);
498 + modes_equal = xf86ModesEqual(mode, mir_mode);
499 + xmir_free_xf86mode(mir_mode);
500 +
501 + if (modes_equal) {
502 + output->current_mode = i;
503 + output->used = 1;
504 + xf86Msg(X_INFO, "Matched mode %d\n", i);
505 + return TRUE;
506 + }
507 + }
508 + return FALSE;
509 +}
510 +
511 +static uint32_t
512 +xmir_update_outputs_for_crtc(xf86CrtcPtr crtc, DisplayModePtr mode, int x, int y)
513 +{
514 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
515 + uint32_t representative_output_id = mir_display_output_id_invalid;
516 +
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;
525 + }
526 + }
527 + return representative_output_id;
528 +}
529 +
530 +static void
531 +xmir_disable_unused_outputs(xf86CrtcPtr crtc)
532 +{
533 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
534 +
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;
539 +}
540 +
541 +static void
542 +xmir_stupid_callback(MirSurface *surf, void *ctx)
543 +{
544 +}
545 +
546 +static void
547 +xmir_dump_config(MirDisplayConfiguration *config)
548 +{
549 + for (int i = 0; i < config->num_outputs; i++)
550 + {
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++)
563 + {
564 + xf86Msg(X_INFO, " mode %d: (%d x %d @ %.2f)\n",
565 + m,
566 + config->outputs[i].modes[m].horizontal_resolution,
567 +
568 + config->outputs[i].modes[m].vertical_resolution,
569 + config->outputs[i].modes[m].refresh_rate);
570 + }
571 + }
572 +}
573 +
574 +static void
575 +xmir_update_config(xf86CrtcConfigPtr crtc_cfg)
576 +{
577 + MirDisplayConfiguration *new_config;
578 + struct xmir_crtc *xmir_crtc = crtc_cfg->crtc[0]->driver_private;
579 +
580 + mir_display_config_destroy(xmir_crtc->config);
581 +
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;
586 + }
587 +
588 + if (crtc_cfg->num_output != new_config->num_outputs)
589 + FatalError("[xmir] New Mir config has different number of outputs?");
590 +
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);
594 + }
595 + xf86Msg(X_INFO, "Recieved updated config from Mir:\n");
596 + xmir_dump_config(new_config);
597 +}
598 +
599 +static void
600 +xmir_crtc_surface_created(MirSurface *surface, void *ctx)
601 +{
602 + xf86CrtcPtr crtc = ctx;
603 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
604 +
605 + if (xmir_crtc->root_fragment->surface != NULL)
606 + mir_surface_release(xmir_crtc->root_fragment->surface, xmir_stupid_callback, NULL);
607 +
608 + xmir_crtc->root_fragment->surface = surface;
609 +}
610 +
611 +static Bool
612 +xmir_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
613 + Rotation rotation, int x, int y)
614 +{
615 + MirSurfaceParameters params = {
616 + .name = "Xorg",
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
622 + };
623 + BoxRec output_bounds = {
624 + .x1 = x,
625 + .y1 = y,
626 + .x2 = x + mode->HDisplay,
627 + .y2 = y + mode->VDisplay
628 + };
629 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
630 + uint32_t output_id = mir_display_output_id_invalid;
631 + const char *error_msg;
632 +
633 + if (mode->HDisplay == 0 || mode->VDisplay == 0)
634 + return FALSE;
635 +
636 + xf86Msg(X_INFO, "Initial configuration for crtc %p:\n", crtc);
637 + xmir_dump_config(xmir_crtc->config);
638 +
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);
642 +
643 + xf86Msg(X_INFO, "Updated configuration:\n");
644 +
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",
651 + error_msg);
652 + return FALSE;
653 + /* TODO: Restore correct config cache */
654 + }
655 +
656 + xf86Msg(X_INFO, "Post-modeset config:\n");
657 + xmir_update_config(XF86_CRTC_CONFIG_PTR(crtc->scrn));
658 +
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;
663 + return TRUE;
664 + }
665 +
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(),
669 + &params,
670 + xmir_crtc_surface_created,
671 + crtc));
672 + if (!mir_surface_is_valid(xmir_crtc->root_fragment->surface)) {
673 + xf86Msg(X_ERROR,
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));
677 + return FALSE;
678 + }
679 +
680 +
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;
684 +
685 + RegionInit(&xmir_crtc->root_fragment->region, &output_bounds, 0);
686 + xmir_crtc->root_fragment->has_free_buffer = TRUE;
687 +
688 + return TRUE;
689 +}
690 +
691 +static void
692 +crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
693 +{
694 +}
695 +
696 +static void
697 +crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
698 +{
699 +}
700 +
701 +static void
702 +crtc_show_cursor (xf86CrtcPtr crtc)
703 +{
704 +}
705 +
706 +static void
707 +crtc_hide_cursor (xf86CrtcPtr crtc)
708 +{
709 +}
710 +
711 +static void
712 +crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
713 +{
714 +}
715 +
716 +static PixmapPtr
717 +crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
718 +{
719 + return NULL;
720 +}
721 +
722 +static void *
723 +crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
724 +{
725 + return NULL;
726 +}
727 +
728 +static void
729 +crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
730 +{
731 +}
732 +
733 +static void
734 +xmir_crtc_destroy(xf86CrtcPtr crtc)
735 +{
736 + struct xmir_crtc *xmir_crtc = crtc->driver_private;
737 +
738 + if (xmir_crtc->root_fragment->surface != NULL)
739 + mir_surface_release(xmir_crtc->root_fragment->surface, NULL, NULL);
740 +
741 + free(xmir_crtc);
742 +}
743 +
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,
756 +};
757 +
758 +static void
759 +xmir_output_dpms(xf86OutputPtr output, int mode)
760 +{
761 + return;
762 +}
763 +
764 +static xf86OutputStatus
765 +xmir_output_detect(xf86OutputPtr output)
766 +{
767 + MirDisplayOutput *mir_output = output->driver_private;
768 + return mir_output->connected ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
769 +}
770 +
771 +static Bool
772 +xmir_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
773 +{
774 + return MODE_OK;
775 +}
776 +
777 +static DisplayModePtr
778 +xmir_output_get_modes(xf86OutputPtr xf86output)
779 +{
780 + MirDisplayOutput *mir_output = xf86output->driver_private;
781 + DisplayModePtr modes = NULL;
782 +
783 + for (int i = 0; i < mir_output->num_modes; i++) {
784 + DisplayModePtr mode = xmir_create_xf86mode(&mir_output->modes[i]);
785 +
786 + mode->type = M_T_DRIVER;
787 + if (i == mir_output->preferred_mode)
788 + mode->type |= M_T_PREFERRED;
789 +
790 + modes = xf86ModesAdd(modes, mode);
791 + }
792 + /* TODO: Get Mir to send us the EDID blob and add that */
793 +
794 + return modes;
795 +}
796 +
797 +static void
798 +xmir_output_destroy(xf86OutputPtr xf86output)
799 +{
800 + /* The MirDisplayOutput* in driver_private gets cleaned up by
801 + mir_display_config_destroy() */
802 +}
803 +
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
810 +};
811 +
812 +
813 +struct xmir_visit_set_pixmap_window {
814 + PixmapPtr old, new;
815 +};
816 +
817 +static int
818 +xmir_visit_set_window_pixmap(WindowPtr window, pointer data)
819 +{
820 + struct xmir_visit_set_pixmap_window *visit = data;
821 +
822 + if (window->drawable.pScreen->GetWindowPixmap(window) == visit->old) {
823 + window->drawable.pScreen->SetWindowPixmap(window, visit->new);
824 + return WT_WALKCHILDREN;
825 + }
826 +
827 + return WT_DONTWALKCHILDREN;
828 +}
829 +
830 +static void
831 +xmir_set_screen_pixmap(PixmapPtr old_front, PixmapPtr new_front)
832 +{
833 + struct xmir_visit_set_pixmap_window visit = {
834 + .old = old_front,
835 + .new = new_front
836 + };
837 + (old_front->drawable.pScreen->SetScreenPixmap)(new_front);
838 +
839 + TraverseTree(old_front->drawable.pScreen->root, &xmir_visit_set_window_pixmap, &visit);
840 +}
841 +
842 +static Bool
843 +xmir_resize(ScrnInfoPtr scrn, int width, int height)
844 +{
845 + xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(scrn);
846 + ScreenPtr screen = xf86ScrnToScreen(scrn);
847 + PixmapPtr old_screen_pixmap, new_screen_pixmap;
848 +
849 + if (scrn->virtualX == width && scrn->virtualY == height)
850 + return TRUE;
851 +
852 + old_screen_pixmap = screen->GetScreenPixmap(screen);
853 + new_screen_pixmap = screen->CreatePixmap(screen, width, height, scrn->depth,
854 + CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
855 +
856 + if (!new_screen_pixmap)
857 + return FALSE;
858 +
859 + scrn->virtualX = width;
860 + scrn->virtualY = height;
861 + scrn->displayWidth = width;
862 +
863 + for (int i = 0; i < crtc_cfg->num_crtc; i++) {
864 + xf86CrtcPtr crtc = crtc_cfg->crtc[i];
865 +
866 + if (!crtc->enabled)
867 + continue;
868 +
869 + xmir_crtc_set_mode_major(crtc, &crtc->mode,
870 + crtc->rotation, crtc->x, crtc->y);
871 + }
872 +
873 + xmir_set_screen_pixmap(old_screen_pixmap, new_screen_pixmap);
874 + screen->DestroyPixmap(old_screen_pixmap);
875 +
876 + xf86_reload_cursors(screen);
877 +
878 + return TRUE;
879 +}
880 +
881 +static const xf86CrtcConfigFuncsRec config_funcs = {
882 + xmir_resize
883 +};
884 +
885 +static void
886 +xmir_handle_hotplug(void *ctx)
887 +{
888 + ScrnInfoPtr scrn = *(ScrnInfoPtr *)ctx;
889 + xf86CrtcConfigPtr crtc_config = XF86_CRTC_CONFIG_PTR(scrn);
890 +
891 + if (crtc_config->num_crtc == 0)
892 + FatalError("[xmir] Received hotplug event, but have no CRTCs?\n");
893 +
894 + xmir_update_config(crtc_config);
895 +
896 + /* Trigger RANDR refresh */
897 + RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
898 +}
899 +
900 +static void
901 +xmir_display_config_callback(MirConnection *unused, void *ctx)
902 +{
903 + xmir_screen *xmir = ctx;
904 +
905 + xmir_post_to_eventloop(xmir->hotplug_event_handler, &xmir->scrn);
906 +}
907 +
908 +Bool
909 +xmir_mode_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir)
910 +{
911 + int i;
912 + MirDisplayConfiguration *display_config;
913 + xf86CrtcPtr xf86crtc;
914 + int output_type_count[mir_display_output_type_edp + 1];
915 +
916 + memset(output_type_count, 0, sizeof output_type_count);
917 +
918 + /* Set up CRTC config functions */
919 + xf86CrtcConfigInit(scrn, &config_funcs);
920 +
921 + /* We don't scanout of a single surface, so we don't have a scanout limit */
922 + xf86CrtcSetSizeRange(scrn,
923 + 320, 320,
924 + INT16_MAX, INT16_MAX);
925 +
926 + /* Hook up hotplug notification */
927 + xmir->hotplug_event_handler =
928 + xmir_register_handler(&xmir_handle_hotplug,
929 + sizeof (ScreenPtr));
930 +
931 + mir_connection_set_display_config_change_callback(
932 + xmir_connection_get(),
933 + &xmir_display_config_callback, xmir);
934 +
935 + display_config =
936 + mir_connection_create_display_config(xmir_connection_get());
937 +
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;
941 +
942 + if (xmir->root_window_fragments == NULL)
943 + return FALSE;
944 +
945 + for (i = 0; i < display_config->num_outputs; i++) {
946 + xf86OutputPtr xf86output;
947 + char name[32];
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;
951 +
952 + if (mir_output->type >= 0 && mir_output->type <= mir_display_output_type_edp)
953 + type_count = output_type_count[mir_output->type]++;
954 +
955 + snprintf(name, sizeof name, "%s-%d", output_type_str, type_count);
956 + xf86output = xf86OutputCreate(scrn, &xmir_output_funcs, name);
957 +
958 + xmir_output_populate(xf86output, mir_output);
959 + }
960 +
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)
964 + return FALSE;
965 +
966 + xmir_crtc->xmir = xmir;
967 + xmir_crtc->root_fragment = calloc(1, sizeof *xmir_crtc->root_fragment);
968 + xmir_crtc->config = display_config;
969 +
970 + if (xmir_crtc->root_fragment == NULL)
971 + return FALSE;
972 +
973 + xmir->root_window_fragments[i] = xmir_crtc->root_fragment;
974 + RegionNull(&xmir_crtc->root_fragment->region);
975 +
976 + xf86crtc = xf86CrtcCreate(scrn, &crtc_funcs);
977 + xf86crtc->driver_private = xmir_crtc;
978 + }
979 +
980 + xf86SetScrnInfoModes(scrn);
981 +
982 + /* TODO: Use initial Mir state rather than setting up our own */
983 + xf86InitialConfiguration(scrn, TRUE);
984 +
985 + return TRUE;
986 +}
987 --- /dev/null
988 +++ b/hw/xfree86/xmir/xmir-private.h
989 @@ -0,0 +1,106 @@
990 +/*
991 + * Copyright © 2012 Canonical, Inc
992 + *
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.
1002 + *
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.
1012 + *
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.
1017 + *
1018 + * Authors:
1019 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1020 + */
1021 +
1022 +#ifndef _XMIR_PRIVATE_H
1023 +#define _XMIR_PRIVATE_H
1024 +
1025 +#include <mir_toolkit/mir_client_library.h>
1026 +#include "xmir.h"
1027 +#include "xf86str.h"
1028 +#include "list.h"
1029 +#include "scrnintstr.h"
1030 +#include "regionstr.h"
1031 +
1032 +#define MIR_MAX_BUFFER_AGE 3
1033 +
1034 +typedef struct xmir_marshall_handler xmir_marshall_handler;
1035 +
1036 +struct xmir_screen {
1037 + ScrnInfoPtr scrn;
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 */
1047 +};
1048 +
1049 +struct xmir_window {
1050 + WindowPtr win;
1051 + MirSurface *surface;
1052 + RegionRec region;
1053 + RegionRec past_damage[MIR_MAX_BUFFER_AGE];
1054 + DamagePtr damage;
1055 + int damage_index;
1056 + struct xorg_list link_damage;
1057 + unsigned int has_free_buffer:1;
1058 + unsigned int damaged:1;
1059 +};
1060 +
1061 +MirConnection *
1062 +xmir_connection_get(void);
1063 +
1064 +xmir_screen *
1065 +xmir_screen_get(ScreenPtr screen);
1066 +
1067 +xmir_window *
1068 +xmir_window_get(WindowPtr win);
1069 +
1070 +void
1071 +xmir_window_enable_damage_tracking(xmir_window *xmir_win);
1072 +
1073 +void
1074 +xmir_window_disable_damage_tracking(xmir_window *xmir_win);
1075 +
1076 +
1077 +Bool
1078 +xmir_screen_init_window(ScreenPtr screen, xmir_screen *xmir);
1079 +
1080 +Bool
1081 +xmir_mode_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir);
1082 +
1083 +void
1084 +xmir_init_thread_to_eventloop(void);
1085 +
1086 +xmir_marshall_handler *
1087 +xmir_register_handler(void (*msg_handler)(void *msg), size_t msg_size);
1088 +
1089 +void
1090 +xmir_post_to_eventloop(xmir_marshall_handler *handler, void *msg);
1091 +
1092 +void
1093 +xmir_process_from_eventloop(void);
1094 +
1095 + #endif /* _MIR_PRIVATE_H */
1096 --- /dev/null
1097 +++ b/hw/xfree86/xmir/xmir-thread-proxy.c
1098 @@ -0,0 +1,124 @@
1099 +/*
1100 + * Copyright © 2012 Canonical, Inc
1101 + *
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.
1111 + *
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.
1121 + *
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.
1126 + *
1127 + * Authors:
1128 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1129 + */
1130 +
1131 +#include <stdint.h>
1132 +#include <string.h>
1133 +#include <unistd.h>
1134 +#include <fcntl.h>
1135 +#include <errno.h>
1136 +
1137 +#include "xf86.h"
1138 +#include "xmir-private.h"
1139 +
1140 +struct xmir_marshall_handler {
1141 + void (*msg_handler)(void *msg);
1142 + size_t msg_size;
1143 + char msg[];
1144 +};
1145 +
1146 +static int pipefds[2];
1147 +
1148 +static void
1149 +xmir_wakeup_handler(pointer data, int err, pointer read_mask)
1150 +{
1151 + if (err >= 0 && FD_ISSET(pipefds[0], (fd_set *)read_mask))
1152 + xmir_process_from_eventloop();
1153 +}
1154 +
1155 +void
1156 +xmir_init_thread_to_eventloop(void)
1157 +{
1158 + int err = pipe(pipefds);
1159 + if (err == -1)
1160 + FatalError("[XMIR] Failed to create thread-proxy pipes: %s\n", strerror(errno));
1161 +
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
1165 + */
1166 + fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
1167 +
1168 + AddGeneralSocket(pipefds[0]);
1169 + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1170 + xmir_wakeup_handler,
1171 + NULL);
1172 +}
1173 +
1174 +xmir_marshall_handler *
1175 +xmir_register_handler(void (*msg_handler)(void *msg), size_t msg_size)
1176 +{
1177 + xmir_marshall_handler *handler;
1178 +
1179 + if (msg_size + sizeof *handler > PIPE_BUF)
1180 + return NULL;
1181 +
1182 + handler = malloc(sizeof *handler + msg_size);
1183 + if (!handler)
1184 + return NULL;
1185 +
1186 + handler->msg_handler = msg_handler;
1187 + handler->msg_size = msg_size;
1188 + return handler;
1189 +}
1190 +
1191 +void
1192 +xmir_post_to_eventloop(xmir_marshall_handler *handler, void *msg)
1193 +{
1194 + ssize_t written;
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);
1198 +
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");
1203 +}
1204 +
1205 +void
1206 +xmir_process_from_eventloop(void)
1207 +{
1208 + xmir_marshall_handler handler;
1209 + void *msg;
1210 +
1211 + for (;;) {
1212 + if (read(pipefds[0], &handler, sizeof handler) < 0) {
1213 + return;
1214 + }
1215 +
1216 + msg = malloc(handler.msg_size);
1217 + if(read(pipefds[0], msg, handler.msg_size) == handler.msg_size)
1218 + (*handler.msg_handler)(msg);
1219 + free(msg);
1220 + }
1221 +}
1222 +
1223 --- /dev/null
1224 +++ b/hw/xfree86/xmir/xmir-window.c
1225 @@ -0,0 +1,343 @@
1226 +/*
1227 + * Copyright © 2012 Canonical, Inc
1228 + *
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.
1238 + *
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.
1248 + *
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.
1253 + *
1254 + * Authors:
1255 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1256 + */
1257 +
1258 +#ifdef HAVE_XORG_CONFIG_H
1259 +#include "xorg-config.h"
1260 +#endif
1261 +#include <xorg-server.h>
1262 +#include "windowstr.h"
1263 +#include "regionstr.h"
1264 +#include "damagestr.h"
1265 +
1266 +#include "xmir.h"
1267 +#include "xmir-private.h"
1268 +
1269 +#include "xf86.h"
1270 +
1271 +#include <stdlib.h>
1272 +#include <unistd.h>
1273 +
1274 +static DevPrivateKeyRec xmir_window_private_key;
1275 +static const RegionRec xmir_empty_region = { {0, 0, 0, 0}, &RegionBrokenData };
1276 +
1277 +xmir_window *
1278 +xmir_window_get(WindowPtr win)
1279 +{
1280 + /* The root window is handled specially */
1281 + assert(win->parent != NULL);
1282 +
1283 + return dixGetPrivate(&win->devPrivates, &xmir_window_private_key);
1284 +}
1285 +
1286 +_X_EXPORT int
1287 +xmir_window_get_fd(xmir_window *xmir_win)
1288 +{
1289 + MirBufferPackage *package;
1290 +
1291 + if (mir_platform_type_gbm != mir_surface_get_platform_type(xmir_win->surface))
1292 + FatalError("[xmir] Only supported on DRM Mir platform\n");
1293 +
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");
1297 +
1298 + return package->fd[0];
1299 +}
1300 +
1301 +static void
1302 +xmir_handle_buffer_available(void *ctx)
1303 +{
1304 + xmir_screen *xmir;
1305 + xmir_window *mir_win = *(xmir_window **)ctx;
1306 +
1307 + if (mir_win->surface == NULL)
1308 + return;
1309 +
1310 + xmir = xmir_screen_get(xmir_window_to_windowptr(mir_win)->drawable.pScreen);
1311 +
1312 + mir_win->has_free_buffer = TRUE;
1313 + mir_win->damage_index = (mir_win->damage_index + 1) % MIR_MAX_BUFFER_AGE;
1314 +
1315 + if (xmir_window_is_dirty(mir_win))
1316 + (*xmir->driver->BufferAvailableForWindow)(mir_win,
1317 + xmir_window_get_dirty(mir_win));
1318 +}
1319 +
1320 +static inline int
1321 +index_in_damage_buffer(int current_index, int age)
1322 +{
1323 + int index = (current_index - age) % MIR_MAX_BUFFER_AGE;
1324 +
1325 + return index < 0 ? MIR_MAX_BUFFER_AGE + index : index;
1326 +}
1327 +
1328 +static void
1329 +handle_buffer_received(MirSurface *surf, void *ctx)
1330 +{
1331 + xmir_window *xmir_win = ctx;
1332 +
1333 + xmir_screen *xmir =
1334 + xmir_screen_get(xmir_window_to_windowptr(xmir_win)->drawable.pScreen);
1335 +
1336 + xmir_post_to_eventloop(xmir->submit_rendering_handler, &xmir_win);
1337 +}
1338 +
1339 +static RegionPtr
1340 +damage_region_for_current_buffer(xmir_window *xmir_win)
1341 +{
1342 + MirBufferPackage *package;
1343 + RegionPtr region;
1344 + int age;
1345 +
1346 + mir_surface_get_current_buffer(xmir_win->surface, &package);
1347 + age = package->age;
1348 +
1349 + region = &xmir_win->past_damage[index_in_damage_buffer(xmir_win->damage_index, age)];
1350 +
1351 + /* As per EGL_EXT_buffer_age, contents are undefined for age == 0 */
1352 + if (age == 0)
1353 + RegionCopy(region, &xmir_win->region);
1354 +
1355 + return region;
1356 +}
1357 +
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.
1362 + */
1363 +_X_EXPORT int
1364 +xmir_submit_rendering_for_window(xmir_window *xmir_win,
1365 + RegionPtr region)
1366 +{
1367 + RegionPtr tracking;
1368 +
1369 + if (!xmir_screen_get(xmir_win->win->drawable.pScreen)->dpms_on)
1370 + return Success;
1371 +
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);
1375 +
1376 + if (region == NULL)
1377 + RegionEmpty(tracking);
1378 + else
1379 + RegionSubtract(tracking, tracking, region);
1380 +
1381 + if (RegionNil(tracking))
1382 + xorg_list_del(&xmir_win->link_damage);
1383 +
1384 + return Success;
1385 +}
1386 +
1387 +_X_EXPORT Bool
1388 +xmir_window_has_free_buffer(xmir_window *xmir_win)
1389 +{
1390 + return xmir_win->has_free_buffer;
1391 +}
1392 +
1393 +_X_EXPORT RegionPtr
1394 +xmir_window_get_dirty(xmir_window *xmir_win)
1395 +{
1396 + if (xorg_list_is_empty(&xmir_win->link_damage))
1397 + return (RegionPtr)&xmir_empty_region;
1398 +
1399 + if (xmir_win->damaged) {
1400 + int i;
1401 + RegionPtr damage = DamageRegion(xmir_win->damage);
1402 + RegionIntersect(damage, damage, &xmir_win->region);
1403 +
1404 + for (i = 0; i < MIR_MAX_BUFFER_AGE; i++) {
1405 + RegionUnion(&xmir_win->past_damage[i],
1406 + &xmir_win->past_damage[i],
1407 + damage);
1408 + }
1409 +
1410 + DamageEmpty(xmir_win->damage);
1411 + xmir_win->damaged = 0;
1412 + }
1413 +
1414 + return damage_region_for_current_buffer(xmir_win);
1415 +}
1416 +
1417 +_X_EXPORT Bool
1418 +xmir_window_is_dirty(xmir_window *xmir_win)
1419 +{
1420 + return RegionNotEmpty(xmir_window_get_dirty(xmir_win));
1421 +}
1422 +
1423 +_X_EXPORT WindowPtr
1424 +xmir_window_to_windowptr(xmir_window *xmir_win)
1425 +{
1426 + return xmir_win->win;
1427 +}
1428 +
1429 +_X_EXPORT BoxPtr
1430 +xmir_window_get_drawable_region(xmir_window *xmir_win)
1431 +{
1432 + return RegionExtents(&xmir_win->region);
1433 +}
1434 +
1435 +_X_EXPORT int32_t
1436 +xmir_window_get_stride(xmir_window *xmir_win)
1437 +{
1438 + MirBufferPackage *package;
1439 +
1440 + mir_surface_get_current_buffer(xmir_win->surface, &package);
1441 +
1442 + return package->stride;
1443 +}
1444 +
1445 +static void
1446 +damage_report(DamagePtr damage, RegionPtr region, void *ctx)
1447 +{
1448 + xmir_window *xmir_win = ctx;
1449 +
1450 + xmir_win->damaged = 1;
1451 + xorg_list_move(&xmir_win->link_damage,
1452 + &xmir_screen_get(damage->pScreen)->damage_list);
1453 +}
1454 +
1455 +static void
1456 +damage_destroy(DamagePtr damage, void *ctx)
1457 +{
1458 + xmir_window *xmir_win = ctx;
1459 + xorg_list_del(&xmir_win->link_damage);
1460 +}
1461 +
1462 +void
1463 +xmir_window_enable_damage_tracking(xmir_window *xmir_win)
1464 +{
1465 + WindowPtr win = xmir_win->win;
1466 +
1467 + if (xmir_win->damage != NULL)
1468 + return;
1469 +
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);
1475 +
1476 + for (int i = 0; i < MIR_MAX_BUFFER_AGE; i++) {
1477 + RegionNull(&xmir_win->past_damage[i]);
1478 + }
1479 + xmir_win->damage_index = 0;
1480 + xmir_win->damaged = 0;
1481 +}
1482 +
1483 +void
1484 +xmir_window_disable_damage_tracking(xmir_window *xmir_win)
1485 +{
1486 + if (xmir_win->damage != NULL) {
1487 + DamageUnregister(xmir_win->damage);
1488 + DamageDestroy(xmir_win->damage);
1489 + xmir_win->damage = NULL;
1490 + }
1491 +}
1492 +
1493 +static Bool
1494 +xmir_create_window(WindowPtr win)
1495 +{
1496 + ScreenPtr screen = win->drawable.pScreen;
1497 + xmir_screen *xmir = xmir_screen_get(screen);
1498 + Bool ret;
1499 +
1500 + screen->CreateWindow = xmir->CreateWindow;
1501 + ret = (*screen->CreateWindow)(win);
1502 + screen->CreateWindow = xmir_create_window;
1503 +
1504 + /* Until we support rootless operation, we care only for the root
1505 + * window, which has no parent.
1506 + */
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;
1512 +
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]);
1516 + }
1517 + }
1518 + return ret;
1519 +}
1520 +
1521 +static Bool
1522 +xmir_destroy_window(WindowPtr win)
1523 +{
1524 + ScreenPtr screen = win->drawable.pScreen;
1525 + xmir_screen *xmir = xmir_screen_get(screen);
1526 + Bool ret;
1527 +
1528 + screen->DestroyWindow = xmir->DestroyWindow;
1529 + ret = (*screen->DestroyWindow)(win);
1530 + screen->DestroyWindow = xmir_destroy_window;
1531 +
1532 + /* Until we support rootless operation, we care only for the root
1533 + * window, which has no parent.
1534 + */
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;
1539 +
1540 + /* We cannot use xmir_window_disable_damage_tracking here because
1541 + * the Damage extension will also clean it up on window destruction
1542 + */
1543 + xorg_list_del(&xmir->root_window_fragments[i]->link_damage);
1544 + }
1545 + }
1546 +
1547 + return ret;
1548 +}
1549 +
1550 +Bool
1551 +xmir_screen_init_window(ScreenPtr screen, xmir_screen *xmir)
1552 +{
1553 + if (!dixRegisterPrivateKey(&xmir_window_private_key, PRIVATE_WINDOW, 0))
1554 + return FALSE;
1555 +
1556 + xmir->CreateWindow = screen->CreateWindow;
1557 + screen->CreateWindow = xmir_create_window;
1558 + xmir->DestroyWindow = screen->DestroyWindow;
1559 + screen->DestroyWindow = xmir_destroy_window;
1560 +
1561 + xmir->submit_rendering_handler =
1562 + xmir_register_handler(&xmir_handle_buffer_available,
1563 + sizeof (xmir_window *));
1564 + if (xmir->submit_rendering_handler == NULL)
1565 + return FALSE;
1566 +
1567 + return TRUE;
1568 +}
1569 --- /dev/null
1570 +++ b/hw/xfree86/xmir/xmir.c
1571 @@ -0,0 +1,263 @@
1572 +/*
1573 + * Copyright © 2012 Canonical, Inc
1574 + *
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.
1584 + *
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.
1594 + *
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.
1599 + *
1600 + * Authors:
1601 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1602 + */
1603 +
1604 +#ifdef HAVE_XORG_CONFIG_H
1605 +#include <xorg-config.h>
1606 +#endif
1607 +
1608 +#include "xmir.h"
1609 +#include "xmir-private.h"
1610 +
1611 +#include "list.h"
1612 +#include "xf86.h"
1613 +#include "xf86Crtc.h"
1614 +#include "xf86Priv.h"
1615 +
1616 +#include <xf86drm.h>
1617 +#include <string.h>
1618 +
1619 +#include <mir_toolkit/mir_client_library.h>
1620 +#include <mir_toolkit/mir_client_library_drm.h>
1621 +
1622 +static DevPrivateKeyRec xmir_screen_private_key;
1623 +/*
1624 + * We have only a single Mir connection, regardless of how many
1625 + * drivers load.
1626 + */
1627 +static MirConnection *conn;
1628 +
1629 +MirConnection *
1630 +xmir_connection_get(void)
1631 +{
1632 + return conn;
1633 +}
1634 +
1635 +xmir_screen *
1636 +xmir_screen_get(ScreenPtr screen)
1637 +{
1638 + return dixGetPrivate(&screen->devPrivates, &xmir_screen_private_key);
1639 +}
1640 +
1641 +_X_EXPORT int
1642 +xmir_get_drm_fd(const char *busid)
1643 +{
1644 + MirPlatformPackage platform;
1645 + int i, fd = -1;
1646 +
1647 + mir_connection_get_platform(conn, &platform);
1648 +
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);
1654 + }
1655 + return fd;
1656 +}
1657 +
1658 +static void
1659 +handle_auth_magic(int status, void *ctx)
1660 +{
1661 + int *retVal = ctx;
1662 + *retVal = status;
1663 +}
1664 +
1665 +_X_EXPORT int
1666 +xmir_auth_drm_magic(xmir_screen *xmir, uint32_t magic)
1667 +{
1668 + int status;
1669 + mir_wait_for(mir_connection_drm_auth_magic(xmir_connection_get(),
1670 + magic,
1671 + &handle_auth_magic,
1672 + &status));
1673 + return status;
1674 +}
1675 +
1676 +_X_EXPORT xmir_screen *
1677 +xmir_screen_create(ScrnInfoPtr scrn)
1678 +{
1679 + xmir_screen *xmir = calloc (1, sizeof *xmir);
1680 + if (xmir == NULL)
1681 + return NULL;
1682 +
1683 + xmir->scrn = scrn;
1684 + xmir->dpms_on = TRUE;
1685 +
1686 + return xmir;
1687 +}
1688 +
1689 +_X_EXPORT Bool
1690 +xmir_screen_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir, xmir_driver *driver)
1691 +{
1692 + xmir->driver = driver;
1693 + xorg_list_init(&xmir->damage_list);
1694 +
1695 + if (!xmir_mode_pre_init(scrn, xmir))
1696 + return FALSE;
1697 +
1698 + return TRUE;
1699 +}
1700 +
1701 +static void xmir_handle_focus_event(void *ctx)
1702 +{
1703 + Bool new_focus = *(Bool *)ctx;
1704 + xf86Msg(X_INFO, "[XMir] Handling focus event, new_focus = %s\n", new_focus ? "TRUE" : "FALSE");
1705 +
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())
1709 + xf86VTSwitch();
1710 +
1711 + if (!new_focus && xf86VTOwner())
1712 + xf86VTSwitch();
1713 +}
1714 +
1715 +static void xmir_handle_lifecycle_event(MirConnection *unused, MirLifecycleState state, void *ctx)
1716 +{
1717 + (void)unused;
1718 + xmir_screen *xmir = ctx;
1719 + Bool new_focus;
1720 + switch(state)
1721 + {
1722 + case mir_lifecycle_state_will_suspend:
1723 + new_focus = FALSE;
1724 + break;
1725 + case mir_lifecycle_state_resumed:
1726 + new_focus = TRUE;
1727 + break;
1728 + default:
1729 + xf86Msg(X_ERROR, "Received unknown Mir lifetime event\n");
1730 + return;
1731 + }
1732 + xmir_post_to_eventloop(xmir->focus_event_handler, &new_focus);
1733 +}
1734 +
1735 +_X_EXPORT Bool
1736 +xmir_screen_init(ScreenPtr screen, xmir_screen *xmir)
1737 +{
1738 + if (!dixRegisterPrivateKey(&xmir_screen_private_key, PRIVATE_SCREEN, 0))
1739 + return FALSE;
1740 + dixSetPrivate(&screen->devPrivates, &xmir_screen_private_key, xmir);
1741 +
1742 + if (!xmir_screen_init_window(screen, xmir))
1743 + return FALSE;
1744 +
1745 + if (!xf86_cursors_init(screen, 0,0,0))
1746 + xf86Msg(X_WARNING, "xf86Cursor initialisation failed\n");
1747 +
1748 + /* Hook up focus -> VT switch proxy */
1749 + xmir->focus_event_handler =
1750 + xmir_register_handler(&xmir_handle_focus_event,
1751 + sizeof(Bool));
1752 + if (xmir->focus_event_handler == NULL)
1753 + return FALSE;
1754 +
1755 + mir_connection_set_lifecycle_event_callback(xmir_connection_get(),
1756 + &xmir_handle_lifecycle_event,
1757 + xmir);
1758 +
1759 + return TRUE;
1760 +}
1761 +
1762 +_X_EXPORT void
1763 +xmir_screen_close(ScreenPtr screen, xmir_screen *xmir)
1764 +{
1765 +
1766 +}
1767 +
1768 +_X_EXPORT void
1769 +xmir_screen_destroy(xmir_screen *xmir)
1770 +{
1771 +
1772 +}
1773 +
1774 +_X_EXPORT void
1775 +xmir_screen_for_each_damaged_window(xmir_screen *xmir, xmir_window_proc callback)
1776 +{
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));
1782 + }
1783 +}
1784 +
1785 +static MODULESETUPPROTO(xMirSetup);
1786 +static MODULETEARDOWNPROTO(xMirTeardown);
1787 +
1788 +static XF86ModuleVersionInfo VersRec = {
1789 + "xmir",
1790 + MODULEVENDORSTRING,
1791 + MODINFOSTRING1,
1792 + MODINFOSTRING2,
1793 + XORG_VERSION_CURRENT,
1794 + 1, 0, 0,
1795 + ABI_CLASS_EXTENSION,
1796 + ABI_EXTENSION_VERSION,
1797 + MOD_CLASS_NONE,
1798 + {0, 0, 0, 0}
1799 +};
1800 +
1801 +_X_EXPORT XF86ModuleData xmirModuleData = { &VersRec, xMirSetup, xMirTeardown };
1802 +
1803 +static pointer
1804 +xMirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
1805 +{
1806 + static Bool setupDone = FALSE;
1807 +
1808 + if (setupDone) {
1809 + if (errmaj)
1810 + *errmaj = LDR_ONCEONLY;
1811 + return NULL;
1812 + }
1813 +
1814 + conn = mir_connect_sync(mirSocket, mirID);
1815 +
1816 + if (!mir_connection_is_valid(conn)) {
1817 + if (errmaj)
1818 + *errmaj = LDR_MODSPECIFIC;
1819 + FatalError("Failed to connect to Mir: %s\n",
1820 + mir_connection_get_error_message(conn));
1821 + return NULL;
1822 + }
1823 +
1824 + xmir_init_thread_to_eventloop();
1825 +
1826 + setupDone = TRUE;
1827 +
1828 + return module;
1829 +}
1830 +
1831 +static void
1832 +xMirTeardown(pointer module)
1833 +{
1834 +}
1835 --- /dev/null
1836 +++ b/hw/xfree86/xmir/xmir.h
1837 @@ -0,0 +1,103 @@
1838 +/*
1839 + * Copyright © 2012 Canonical, Inc
1840 + *
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.
1850 + *
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.
1860 + *
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.
1865 + *
1866 + * Authors:
1867 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
1868 + */
1869 +
1870 +#ifndef _XMIR_H
1871 +#define _XMIR_H
1872 +
1873 +#include <stdint.h>
1874 +#include <mir_toolkit/mir_client_library.h>
1875 +
1876 +#include "xf86str.h"
1877 +#include "scrnintstr.h"
1878 +#include "window.h"
1879 +
1880 +typedef struct xmir_screen xmir_screen;
1881 +typedef struct xmir_window xmir_window;
1882 +
1883 +typedef void (*xmir_window_proc)(xmir_window *xmir_win, RegionPtr damaged_region);
1884 +
1885 +#define XMIR_DRIVER_VERSION 1
1886 +typedef struct {
1887 + int version;
1888 + xmir_window_proc BufferAvailableForWindow;
1889 +} xmir_driver;
1890 +
1891 +_X_EXPORT int
1892 +xmir_get_drm_fd(const char *busid);
1893 +
1894 +_X_EXPORT int
1895 +xmir_auth_drm_magic(xmir_screen *xmir, uint32_t magic);
1896 +
1897 +_X_EXPORT xmir_screen *
1898 +xmir_screen_create(ScrnInfoPtr scrn);
1899 +
1900 +_X_EXPORT Bool
1901 +xmir_screen_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir, xmir_driver *driver);
1902 +
1903 +_X_EXPORT Bool
1904 +xmir_screen_init(ScreenPtr screen, xmir_screen *xmir);
1905 +
1906 +_X_EXPORT void
1907 +xmir_screen_close(ScreenPtr screen, xmir_screen *xmir);
1908 +
1909 +_X_EXPORT void
1910 +xmir_screen_destroy(xmir_screen *xmir);
1911 +
1912 +_X_EXPORT WindowPtr
1913 +xmir_window_to_windowptr(xmir_window *xmir_win);
1914 +
1915 +_X_EXPORT int
1916 +xmir_window_get_fd(xmir_window *xmir_win);
1917 +
1918 +_X_EXPORT int
1919 +xmir_submit_rendering_for_window(xmir_window *xmir_win,
1920 + RegionPtr region);
1921 +
1922 +_X_EXPORT Bool
1923 +xmir_window_has_free_buffer(xmir_window *xmir_win);
1924 +
1925 +_X_EXPORT RegionPtr
1926 +xmir_window_get_dirty(xmir_window *xmir_win);
1927 +
1928 +_X_EXPORT Bool
1929 +xmir_window_is_dirty(xmir_window *xmir_win);
1930 +
1931 +_X_EXPORT BoxPtr
1932 +xmir_window_get_drawable_region(xmir_window *xmir_win);
1933 +
1934 +_X_EXPORT int32_t
1935 +xmir_window_get_stride(xmir_window *xmir_win);
1936 +
1937 +_X_EXPORT void
1938 +xmir_screen_for_each_damaged_window(xmir_screen *xmir, xmir_window_proc callback);
1939 +
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,
1944 prev->next = next;
1945 }
1946
1947 +static inline void
1948 +xorg_list_move(struct xorg_list *entry, struct xorg_list *head)
1949 +{
1950 + __xorg_list_del(entry->prev, entry->next);
1951 + __xorg_list_add(entry, head->prev, head);
1952 +}
1953 +
1954 +
1955 /**
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
1960 @@ -224,4 +224,7 @@
1961 /* Use XTrans FD passing support */
1962 #undef XTRANS_SEND_FDS
1963
1964 +/* Build XMIR nested server */
1965 +#undef XMIR
1966 +
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
1972 SUBDIRS += xi2
1973 noinst_PROGRAMS += xkb input xtest misc fixes xfree86 hashtabletest os signal-logging touch
1974 +if XMIR
1975 +noinst_PROGRAMS += xmir-thread-proxy
1976 +endif #XMIR
1977 endif
1978 check_LTLIBRARIES = libxservertest.la
1979
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
1986
1987 libxservertest_la_LIBADD = $(XSERVER_LIBS)
1988 if XORG
1989 --- /dev/null
1990 +++ b/test/xmir-thread-proxy.c
1991 @@ -0,0 +1,154 @@
1992 +/*
1993 + * Copyright © 2012 Canonical, Inc
1994 + *
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.
2004 + *
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.
2014 + *
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.
2019 + *
2020 + * Authors:
2021 + * Christopher James Halse Rogers (christopher.halse.rogers@canonical.com)
2022 + */
2023 +
2024 +#ifdef HAVE_DIX_CONFIG_H
2025 +#include <dix-config.h>
2026 +#endif
2027 +
2028 +#include <stdio.h>
2029 +#include <stdlib.h>
2030 +#include <pthread.h>
2031 +#include <unistd.h>
2032 +
2033 +#include "xmir-private.h"
2034 +
2035 +struct test_content {
2036 + int *variable;
2037 + int value;
2038 +};
2039 +
2040 +static void
2041 +_test_callback(void *msg_content)
2042 +{
2043 + struct test_content *content = msg_content;
2044 + *content->variable = content->value;
2045 +}
2046 +
2047 +static void
2048 +xmir_test_marshall_to_eventloop(void)
2049 +{
2050 + xmir_marshall_handler *test_marshaller;
2051 + struct test_content msg;
2052 + int check = 0;
2053 +
2054 + xmir_init_thread_to_eventloop();
2055 +
2056 + test_marshaller = xmir_register_handler(&_test_callback, sizeof msg);
2057 +
2058 + msg.variable = &check;
2059 + msg.value = 1;
2060 +
2061 + xmir_post_to_eventloop(test_marshaller, &msg);
2062 + xmir_process_from_eventloop();
2063 +
2064 + assert(check == 1);
2065 +}
2066 +
2067 +static void
2068 +_racy_test_callback(void *msg_content)
2069 +{
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 */
2073 + usleep(100);
2074 + *content->variable = new_value;
2075 +}
2076 +
2077 +struct thread_context {
2078 + xmir_marshall_handler *marshaller;
2079 + struct test_content *msg;
2080 +};
2081 +
2082 +static void *
2083 +_post_racy_msg(void *thread_ctx)
2084 +{
2085 + struct thread_context *ctx = thread_ctx;
2086 +
2087 + xmir_post_to_eventloop(ctx->marshaller, ctx->msg);
2088 +
2089 + return NULL;
2090 +}
2091 +
2092 +#define NUM_THREADS 10
2093 +
2094 +static void
2095 +xmir_test_many_threads_to_eventloop(void)
2096 +{
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;
2102 + int check = 0, i;
2103 +
2104 + pthread_attr_init(&attr);
2105 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
2106 +
2107 + xmir_init_thread_to_eventloop();
2108 +
2109 + test_marshaller = xmir_register_handler(&_racy_test_callback, sizeof msg);
2110 +
2111 + msg.variable = &check;
2112 +
2113 + ctx.marshaller = test_marshaller;
2114 + ctx.msg = &msg;
2115 +
2116 + for (i = 0; i < NUM_THREADS; i++) {
2117 + pthread_create(&threads[i], &attr, _post_racy_msg, (void *)&ctx);
2118 + }
2119 +
2120 + pthread_attr_destroy(&attr);
2121 +
2122 + for (i = 0; i < NUM_THREADS; i++) {
2123 + pthread_join(threads[i], NULL);
2124 + }
2125 +
2126 + xmir_process_from_eventloop();
2127 +
2128 + assert(check == NUM_THREADS);
2129 +}
2130 +
2131 +static void
2132 +xmir_test_refuses_to_marshall_too_large_msg(void)
2133 +{
2134 + xmir_init_thread_to_eventloop();
2135 +
2136 + assert(xmir_register_handler(&_test_callback, PIPE_BUF) == NULL);
2137 +}
2138 +
2139 +int
2140 +main(int argc, char **argv)
2141 +{
2142 + xmir_test_marshall_to_eventloop();
2143 + xmir_test_many_threads_to_eventloop();
2144 + xmir_test_refuses_to_marshall_too_large_msg();
2145 +}