[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xorg-server: Changes to 'ubuntu'



 debian/changelog          |    7 
 debian/patches/xmir.patch | 1047 ++++++++++++++++++++++++++++++++--------------
 debian/serverminver       |    2 
 3 files changed, 739 insertions(+), 317 deletions(-)

New commits:
commit 1b6eccb015856b1e0c3b9219fa22f7c61b74491d
Author: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Date:   Thu Aug 29 19:47:40 2013 +1000

    Add XMir RANDR support

diff --git a/debian/changelog b/debian/changelog
index 79bdfde..7b907ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+xorg-server (2:1.14.2.901-2ubuntu4) saucy; urgency=low
+
+  * xmir.patch: Add XRandR support
+  * Bump serverminver for XMir API changes
+
+ -- Christopher James Halse Rogers <raof@ubuntu.com>  Thu, 29 Aug 2013 19:42:41 +1000
+
 xorg-server (2:1.14.2.901-2ubuntu3) saucy; urgency=low
 
   * xmir.patch: Use the API we have, not the API we've documented
diff --git a/debian/patches/xmir.patch b/debian/patches/xmir.patch
index 6e5dab8..746fba3 100644
--- a/debian/patches/xmir.patch
+++ b/debian/patches/xmir.patch
@@ -1,8 +1,8 @@
-Index: xserver/configure.ac
-===================================================================
---- xserver.orig/configure.ac	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/configure.ac	2013-08-22 15:18:34.425916132 +1000
-@@ -639,6 +639,7 @@
+diff --git a/configure.ac b/configure.ac
+index c6ecba4..cbba229 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -635,6 +635,7 @@ AC_ARG_ENABLE(windowswm,      AS_HELP_STRING([--enable-windowswm], [Build XWin w
  AC_ARG_ENABLE(libdrm,         AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
  AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
  AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
@@ -10,7 +10,7 @@ Index: xserver/configure.ac
  
  dnl DDXes.
  AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
-@@ -1152,6 +1153,15 @@
+@@ -1148,6 +1149,15 @@ if test "x$XINERAMA" = xyes; then
  	SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $XINERAMAPROTO"
  fi
  
@@ -26,7 +26,7 @@ Index: xserver/configure.ac
  AM_CONDITIONAL(XACE, [test "x$XACE" = xyes])
  if test "x$XACE" = xyes; then
  	AC_DEFINE(XACE, 1, [Build X-ACE extension])
-@@ -2300,6 +2310,7 @@
+@@ -2299,6 +2309,7 @@ hw/xfree86/utils/Makefile
  hw/xfree86/utils/man/Makefile
  hw/xfree86/utils/cvt/Makefile
  hw/xfree86/utils/gtf/Makefile
@@ -34,11 +34,11 @@ Index: xserver/configure.ac
  hw/dmx/config/Makefile
  hw/dmx/config/man/Makefile
  hw/dmx/doc/Makefile
-Index: xserver/hw/xfree86/Makefile.am
-===================================================================
---- xserver.orig/hw/xfree86/Makefile.am	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/hw/xfree86/Makefile.am	2013-08-22 15:18:34.425916132 +1000
-@@ -25,15 +25,20 @@
+diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
+index c3899b5..6821198 100644
+--- a/hw/xfree86/Makefile.am
++++ b/hw/xfree86/Makefile.am
+@@ -25,15 +25,20 @@ if INT10MODULE
  INT10_SUBDIR = int10
  endif
  
@@ -61,11 +61,11 @@ Index: xserver/hw/xfree86/Makefile.am
  
  bin_PROGRAMS = Xorg
  nodist_Xorg_SOURCES = sdksyms.c
-Index: xserver/hw/xfree86/common/xf86Config.c
-===================================================================
---- xserver.orig/hw/xfree86/common/xf86Config.c	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/hw/xfree86/common/xf86Config.c	2013-08-22 15:18:34.429916132 +1000
-@@ -117,6 +117,7 @@
+diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
+index 74d5ed3..538ba4b 100644
+--- a/hw/xfree86/common/xf86Config.c
++++ b/hw/xfree86/common/xf86Config.c
+@@ -118,6 +118,7 @@ static ModuleDefault ModuleDefaults[] = {
      {.name = "fb",.toLoad = TRUE,.load_opt = NULL},
      {.name = "shadow",.toLoad = TRUE,.load_opt = NULL},
  #endif
@@ -73,7 +73,7 @@ Index: xserver/hw/xfree86/common/xf86Config.c
      {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
  };
  
-@@ -259,6 +260,17 @@
+@@ -260,6 +261,17 @@ xf86ModulelistFromConfig(pointer **optlist)
          return NULL;
      }
  
@@ -91,22 +91,42 @@ Index: xserver/hw/xfree86/common/xf86Config.c
      if (xf86configptr->conf_modules) {
          /* Walk the disable list and let people know what we've parsed to
           * not be loaded 
-Index: xserver/hw/xfree86/common/xf86Globals.c
-===================================================================
---- xserver.orig/hw/xfree86/common/xf86Globals.c	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/hw/xfree86/common/xf86Globals.c	2013-08-22 15:18:34.429916132 +1000
-@@ -206,3 +206,6 @@
+diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
+index 7df7a80..17ed7c6 100644
+--- a/hw/xfree86/common/xf86Globals.c
++++ b/hw/xfree86/common/xf86Globals.c
+@@ -204,3 +204,6 @@ Bool xf86VidModeAllowNonLocal = FALSE;
  #endif
  RootWinPropPtr *xf86RegisteredPropertiesTable = NULL;
  Bool xorgHWAccess = FALSE;
 +Bool xorgMir = FALSE;
 +const char *mirID = NULL;
 +const char *mirSocket = NULL;
-Index: xserver/hw/xfree86/common/xf86Init.c
-===================================================================
---- xserver.orig/hw/xfree86/common/xf86Init.c	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/hw/xfree86/common/xf86Init.c	2013-08-22 15:18:34.429916132 +1000
-@@ -554,7 +554,7 @@
+diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
+index 721159d..d319e0c 100644
+--- a/hw/xfree86/common/xf86Helper.c
++++ b/hw/xfree86/common/xf86Helper.c
+@@ -100,7 +100,14 @@ xf86DeleteDriver(int drvIndex)
+         if (xf86DriverList[drvIndex]->module)
+             UnloadModule(xf86DriverList[drvIndex]->module);
+         free(xf86DriverList[drvIndex]);
+-        xf86DriverList[drvIndex] = NULL;
++
++        /* Compact xf86DriverList array, update xf86NumDrivers */
++        xf86NumDrivers--;
++        if(drvIndex != xf86NumDrivers)
++            memmove(xf86DriverList + drvIndex,
++                    xf86DriverList + drvIndex + 1,
++                    sizeof(DriverPtr) * (xf86NumDrivers - drvIndex));
++        xf86DriverList = realloc(xf86DriverList, xf86NumDrivers * sizeof(DriverPtr));
+     }
+ }
+ 
+diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
+index 91ec4c8..0508e8d 100644
+--- a/hw/xfree86/common/xf86Init.c
++++ b/hw/xfree86/common/xf86Init.c
+@@ -530,7 +530,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
           * needed at this early stage.
           */
  
@@ -115,7 +135,7 @@ Index: xserver/hw/xfree86/common/xf86Init.c
              xorgHWFlags flags = HW_IO;
  
              if (xf86DriverList[i]->Identify != NULL)
-@@ -565,11 +565,20 @@
+@@ -541,11 +541,20 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
                                                GET_REQUIRED_HW_INTERFACES,
                                                &flags);
  
@@ -136,7 +156,7 @@ Index: xserver/hw/xfree86/common/xf86Init.c
          }
  
          if (xorgHWOpenConsole)
-@@ -662,9 +671,13 @@
+@@ -631,9 +640,13 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
          }
  
          /* Remove (unload) drivers that are not required */
@@ -144,15 +164,15 @@ Index: xserver/hw/xfree86/common/xf86Init.c
 -            if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0)
 +        for (i = 0; i < xf86NumDrivers; )
 +            if (xf86DriverList[i] &&
-+                !xf86DriverHasEntities(xf86DriverList[i]) &&
-+                xf86DriverList[i]->refCount <= 0)
++		!xf86DriverHasEntities(xf86DriverList[i]) &&
++		xf86DriverList[i]->refCount <= 0)
                  xf86DeleteDriver(i);
 +            else
 +                i++;
  
          /*
           * At this stage we know how many screens there are.
-@@ -1490,6 +1503,17 @@
+@@ -1454,6 +1467,17 @@ ddxProcessArgument(int argc, char **argv, int i)
          xf86Info.ShareVTs = TRUE;
          return 1;
      }
@@ -170,7 +190,7 @@ Index: xserver/hw/xfree86/common/xf86Init.c
  
      /* OS-specific processing */
      return xf86ProcessArgument(argc, argv, i);
-@@ -1563,6 +1587,8 @@
+@@ -1527,6 +1551,8 @@ ddxUseMsg(void)
      ErrorF
          ("-novtswitch            don't automatically switch VT at reset & exit\n");
      ErrorF("-sharevts              share VTs with another X server\n");
@@ -179,11 +199,11 @@ Index: xserver/hw/xfree86/common/xf86Init.c
      /* OS-specific usage */
      xf86UseMsg();
      ErrorF("\n");
-Index: xserver/hw/xfree86/common/xf86Priv.h
-===================================================================
---- xserver.orig/hw/xfree86/common/xf86Priv.h	2013-08-22 15:18:34.437916132 +1000
-+++ xserver/hw/xfree86/common/xf86Priv.h	2013-08-22 15:18:34.429916132 +1000
-@@ -93,6 +93,9 @@
+diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
+index 58cfe0a..4630e9e 100644
+--- a/hw/xfree86/common/xf86Priv.h
++++ b/hw/xfree86/common/xf86Priv.h
+@@ -91,6 +91,9 @@ extern _X_EXPORT int xf86NumScreens;
  extern _X_EXPORT const char *xf86VisualNames[];
  extern _X_EXPORT int xf86Verbose;       /* verbosity level */
  extern _X_EXPORT int xf86LogVerbose;    /* log file verbosity level */
@@ -193,10 +213,42 @@ Index: xserver/hw/xfree86/common/xf86Priv.h
  
  extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
  
-Index: xserver/hw/xfree86/xmir/Makefile.am
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xserver/hw/xfree86/xmir/Makefile.am	2013-08-22 15:18:34.429916132 +1000
+diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
+index 860704e..5277c94 100644
+--- a/hw/xfree86/ramdac/xf86Cursor.c
++++ b/hw/xfree86/ramdac/xf86Cursor.c
+@@ -58,7 +58,12 @@ xf86InitCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
+     xf86CursorScreenPtr ScreenPriv;
+     miPointerScreenPtr PointPriv;
+ 
+-    if (!xf86InitHardwareCursor(pScreen, infoPtr))
++    infoPtr->pScrn = xf86ScreenToScrn(pScreen);
++    
++    /* If we can't create a hardware cursor don't bother initialising HW cursor support */
++    if (infoPtr->MaxWidth != 0 &&
++        infoPtr->MaxHeight != 0 &&
++        !xf86InitHardwareCursor(pScreen, infoPtr))
+         return FALSE;
+ 
+     if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0))
+diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
+index 197abff..399bfb9 100644
+--- a/hw/xfree86/ramdac/xf86HWCurs.c
++++ b/hw/xfree86/ramdac/xf86HWCurs.c
+@@ -114,8 +114,6 @@ xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
+         infoPtr->RealizeCursor = RealizeCursorInterleave0;
+     }
+ 
+-    infoPtr->pScrn = xf86ScreenToScrn(pScreen);
+-
+     return TRUE;
+ }
+ 
+diff --git a/hw/xfree86/xmir/Makefile.am b/hw/xfree86/xmir/Makefile.am
+new file mode 100644
+index 0000000..80715f8
+--- /dev/null
++++ b/hw/xfree86/xmir/Makefile.am
 @@ -0,0 +1,26 @@
 +INCLUDES =					\
 +	$(XORG_INCS)                            \
@@ -224,11 +276,12 @@ Index: xserver/hw/xfree86/xmir/Makefile.am
 +	xmir-private.h
 +
 +sdk_HEADERS = xmir.h
-Index: xserver/hw/xfree86/xmir/xmir-output.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xserver/hw/xfree86/xmir/xmir-output.c	2013-08-22 15:18:34.429916132 +1000
-@@ -0,0 +1,225 @@
+diff --git a/hw/xfree86/xmir/xmir-output.c b/hw/xfree86/xmir/xmir-output.c
+new file mode 100644
+index 0000000..b461651
+--- /dev/null
++++ b/hw/xfree86/xmir/xmir-output.c
+@@ -0,0 +1,559 @@
 +/*
 + * Copyright © 2012 Canonical, Inc
 + *
@@ -262,20 +315,224 @@ Index: xserver/hw/xfree86/xmir/xmir-output.c
 + */
 +
 +#include <stdlib.h>
++#include <stdio.h>
++#include <math.h>
 +
++#include <xorg-config.h>
++#include "xmir.h"
 +#include "xmir-private.h"
 +#include "xf86Crtc.h"
 +
++struct xmir_crtc {
++    xmir_screen             *xmir;
++    xmir_window             *root_fragment;
++    MirDisplayConfiguration *config;
++};
++
 +static void
 +crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
 +{
 +}
 +
++static void
++xmir_output_populate(xf86OutputPtr xf86output, MirDisplayOutput *output)
++{
++    /* We can always arbitrarily clone and output */
++    xf86output->possible_crtcs = 0xffffffff;
++    xf86output->possible_clones = 0xffffffff;
++
++    xf86output->driver_private = output;
++
++    xf86output->interlaceAllowed = FALSE;
++    xf86output->doubleScanAllowed = FALSE;
++    xf86output->mm_width = output->physical_width_mm;
++    xf86output->mm_height = output->physical_height_mm;
++    /* TODO: Subpixel order from Mir */
++    xf86output->subpixel_order = SubPixelUnknown;
++}
++
++static Bool
++xmir_mir_mode_matches(MirDisplayMode *mir_mode, DisplayModePtr X_mode)
++{
++    return (mir_mode->vertical_resolution == X_mode->VDisplay &&
++            mir_mode->horizontal_resolution == X_mode->HDisplay /*&&
++            fabs(mir_mode->refresh_rate - X_mode->VRefresh) < 0.01*/);
++}
++
++static Bool
++xmir_set_mode_for_output(MirDisplayOutput *output,
++                         DisplayModePtr mode)
++{
++    for (int i = 0; i < output->num_modes; i++) {
++        xf86Msg(X_INFO, "Checking against mode (%dx%d)\n",
++                output->modes[i].horizontal_resolution,
++                output->modes[i].vertical_resolution);
++        if (xmir_mir_mode_matches(&output->modes[i], mode)) {
++            output->current_mode = i;
++            output->used = 1;
++            xf86Msg(X_INFO, "Matched mode %d\n", i);
++            return TRUE;
++        }
++    }
++    return FALSE;
++}
++
++static uint32_t
++xmir_update_outputs_for_crtc(xf86CrtcPtr crtc, DisplayModePtr mode, int x, int y)
++{
++    xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
++    uint32_t representative_output_id = mir_display_output_id_invalid;
++
++    for (int i = 0; i < crtc_cfg->num_output; i++) {
++        /* If this output should be driven by our "CRTC", set its mode */
++        if (crtc_cfg->output[i]->crtc == crtc) {
++            MirDisplayOutput *output = crtc_cfg->output[i]->driver_private;
++            xmir_set_mode_for_output(output, mode);
++            output->position_x = x;
++            output->position_y = y;
++            representative_output_id = output->output_id;
++        }
++    }
++    return representative_output_id;
++}
++
++static void
++xmir_disable_unused_outputs(xf86CrtcPtr crtc)
++{
++    xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(crtc->scrn);
++
++    for (int i = 0; i < crtc_cfg->num_output; i++)
++        /* If any outputs are no longer associated with a CRTC, disable them */
++        if (crtc_cfg->output[i]->crtc == NULL)
++            ((MirDisplayOutput*)crtc_cfg->output[i]->driver_private)->used = 0;
++}
++
++static void
++xmir_stupid_callback(MirSurface *surf, void *ctx)
++{
++}
++
++static void
++xmir_dump_config(MirDisplayConfiguration *config)
++{
++  for (int i = 0; i < config->num_outputs; i++)
++    {
++      xf86Msg(X_INFO, "Output %d (%s, %s) has mode %d (%d x %d @ %.2f), position (%d,%d)\n",
++	      config->outputs[i].output_id,
++	      config->outputs[i].connected ? "connected" : "disconnected",
++	      config->outputs[i].used ? "enabled" : "disabled",
++	      config->outputs[i].current_mode,
++          config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].horizontal_resolution : 0,
++          config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].vertical_resolution : 0,
++          config->outputs[i].used ? config->outputs[i].modes[config->outputs[i].current_mode].refresh_rate : 0,
++	      config->outputs[i].position_x,
++	      config->outputs[i].position_y);
++    }
++}
++
++static void
++xmir_update_config(xf86CrtcConfigPtr crtc_cfg)
++{
++    MirDisplayConfiguration *new_config;
++    struct xmir_crtc *xmir_crtc = crtc_cfg->crtc[0]->driver_private;
++
++    mir_display_config_destroy(xmir_crtc->config);
++
++    new_config = mir_connection_create_display_config(xmir_connection_get());
++    for (int i = 0; i < crtc_cfg->num_crtc; i++) {
++        xmir_crtc = crtc_cfg->crtc[i]->driver_private;
++        xmir_crtc-> config = new_config;
++    }
++
++    if (crtc_cfg->num_output != new_config->num_outputs)
++        FatalError("[xmir] New Mir config has different number of outputs?");
++
++    for (int i = 0; i < crtc_cfg->num_output ; i++) {
++        /* TODO: Ensure that the order actually matches up */
++        xmir_output_populate(crtc_cfg->output[i], new_config->outputs + i);
++    }
++}
++
 +static Bool
-+crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
-+		    Rotation rotation, int x, int y)  
++xmir_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
++                         Rotation rotation, int x, int y)
 +{
-+	return TRUE;
++    MirSurfaceParameters params = {
++        .name = "Xorg",
++        .width = mode->HDisplay,
++        .height = mode->VDisplay,
++        .pixel_format = mir_pixel_format_xrgb_8888,
++        .buffer_usage = mir_buffer_usage_hardware,
++        .output_id = mir_display_output_id_invalid
++    };
++    BoxRec output_bounds = {
++        .x1 = x,
++        .y1 = y,
++        .x2 = x + mode->HDisplay,
++        .y2 = y + mode->VDisplay
++    };
++    struct xmir_crtc *xmir_crtc = crtc->driver_private;
++    uint32_t output_id = mir_display_output_id_invalid;
++    MirSurface *surface;
++    const char *error_msg;
++
++    if (mode->HDisplay == 0 || mode->VDisplay == 0)
++        return FALSE;    
++
++    xf86Msg(X_INFO, "Initial configuration:\n");
++    xmir_dump_config(xmir_crtc->config);
++
++    xf86Msg(X_INFO, "Setting mode to %dx%d (%.2f)", mode->HDisplay, mode->VDisplay, mode->VRefresh);
++    output_id = xmir_update_outputs_for_crtc(crtc, mode, x, y);
++    xmir_disable_unused_outputs(crtc);
++
++    xf86Msg(X_INFO, "Updated configuration:\n");
++
++    xmir_dump_config(xmir_crtc->config);
++    mir_wait_for(mir_connection_apply_display_config(xmir_connection_get(),
++                                                     xmir_crtc->config));
++    error_msg = mir_connection_get_error_message(xmir_connection_get());
++    if (*error_msg != '\0') {
++        xf86Msg(X_ERROR, "[xmir] Failed to set new display config: %s\n",
++                error_msg);
++        return FALSE;
++        /* TODO: Restore correct config cache */
++    }
++
++    xmir_update_config(XF86_CRTC_CONFIG_PTR(crtc->scrn));
++
++    xf86Msg(X_INFO, "Post-modeset config:\n");
++    xmir_dump_config(xmir_crtc->config);
++
++    if (xmir_crtc->root_fragment->surface != NULL)
++        mir_wait_for(mir_surface_release(xmir_crtc->root_fragment->surface, xmir_stupid_callback, NULL));
++
++    if (output_id == mir_display_output_id_invalid) {
++        xmir_crtc->root_fragment->surface = NULL;
++        return TRUE;
++    }
++
++    params.output_id = output_id;
++    xf86Msg(X_INFO, "Putting surface on output %d\n", output_id);
++    surface = mir_connection_create_surface_sync(xmir_connection_get(),
++                                                 &params);
++    if (!mir_surface_is_valid(surface)) {
++        xf86Msg(X_ERROR,
++                "[xmir] Failed to create surface for %dx%d mode: %s\n",
++                mode->HDisplay, mode->VDisplay,
++                mir_surface_get_error_message(surface));
++        return FALSE;
++    }
++    xmir_crtc->root_fragment->surface = surface;
++
++    /* During X server init this will be NULL.
++       This is fixed up in xmir_window_create */
++    xmir_crtc->root_fragment->win = xf86ScrnToScreen(crtc->scrn)->root;
++
++    RegionInit(&xmir_crtc->root_fragment->region, &output_bounds, 0);
++    xmir_crtc->root_fragment->has_free_buffer = TRUE;
++
++    return TRUE;
 +}
 +
 +static void
@@ -306,13 +563,13 @@ Index: xserver/hw/xfree86/xmir/xmir-output.c
 +static PixmapPtr
 +crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 +{
-+	return NULL;
++    return NULL;
 +}
 +
 +static void *
 +crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
 +{
-+	return NULL;
++    return NULL;
 +}
 +
 +static void
@@ -320,9 +577,20 @@ Index: xserver/hw/xfree86/xmir/xmir-output.c
 +{
 +}
 +
++static void
++xmir_crtc_destroy(xf86CrtcPtr crtc)
++{
++    struct xmir_crtc *xmir_crtc = crtc->driver_private;
++
++    if (xmir_crtc->root_fragment->surface != NULL)
++        mir_surface_release(xmir_crtc->root_fragment->surface, NULL, NULL);
++
++    free(xmir_crtc);
++}
++
 +static const xf86CrtcFuncsRec crtc_funcs = {
 +    .dpms                = crtc_dpms,
-+    .set_mode_major      = crtc_set_mode_major,
++    .set_mode_major      = xmir_crtc_set_mode_major,
 +    .set_cursor_colors   = crtc_set_cursor_colors,
 +    .set_cursor_position = crtc_set_cursor_position,
 +    .show_cursor         = crtc_show_cursor,
@@ -331,134 +599,254 @@ Index: xserver/hw/xfree86/xmir/xmir-output.c
 +    .shadow_create       = crtc_shadow_create,
 +    .shadow_allocate     = crtc_shadow_allocate,
 +    .shadow_destroy      = crtc_shadow_destroy,
-+    .destroy             = NULL, /* XXX */
++    .destroy             = xmir_crtc_destroy,
 +};
 +
 +static void
-+output_dpms(xf86OutputPtr output, int mode)
++xmir_output_dpms(xf86OutputPtr output, int mode)
 +{
-+	return;
++    return;
 +}
 +
 +static xf86OutputStatus
-+output_detect(xf86OutputPtr output)
++xmir_output_detect(xf86OutputPtr output)
 +{
-+	return XF86OutputStatusConnected;
++    MirDisplayOutput *mir_output = output->driver_private;
++    return mir_output->connected ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
 +}
 +
 +static Bool
-+output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
++xmir_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
 +{
-+	return MODE_OK;
++    return MODE_OK;
 +}
 +
-+struct mir_output {
-+    int width;
-+    int height;
-+    xf86Monitor monitor;
-+};
-+
 +static DisplayModePtr
-+output_get_modes(xf86OutputPtr xf86output)
-+{
-+    struct mir_output *output = xf86output->driver_private;
-+    struct monitor_ranges *ranges;
-+    DisplayModePtr modes;
-+
-+    modes = xf86CVTMode(output->width, output->height, 60, TRUE, FALSE);
-+    /* And now, because CVT the CVT standard doesn't support such common resolutions as 1366x768... */
-+    /* TODO: We should really get Mir to just send us an EDID or at least enough info to generate one */
-+    modes->VDisplay = output->height;
-+    modes->HDisplay = output->width;
-+
-+    output->monitor.det_mon[0].type = DS_RANGES;
-+    ranges = &output->monitor.det_mon[0].section.ranges;
-+    ranges->min_h = modes->HSync - 10;
-+    ranges->max_h = modes->HSync + 10;
-+    ranges->min_v = modes->VRefresh - 10;
-+    ranges->max_v = modes->VRefresh + 10;
-+    ranges->max_clock = modes->Clock + 100;
-+    output->monitor.det_mon[1].type = DT;
-+    output->monitor.det_mon[2].type = DT;
-+    output->monitor.det_mon[3].type = DT;
-+    output->monitor.no_sections = 0;
-+    modes->type = M_T_PREFERRED | M_T_DRIVER;
-+
-+    modes->name = strdup("XMIR mode of death");
-+
-+    xf86output->MonInfo = &output->monitor;
++xmir_output_get_modes(xf86OutputPtr xf86output)
++{
++    MirDisplayOutput *mir_output = xf86output->driver_private;
++    DisplayModePtr modes = NULL, mode = NULL;
++
++    for (int i = 0; i < mir_output->num_modes; i++) {
++        /* Check if mode differs only by refresh rate from previous mode and reject */
++        /* TODO: Remove this check and instead handle refresh rate correctly */
++        if (mode != NULL)
++            if (xmir_mir_mode_matches((mir_output->modes + i), mode))
++                continue;
++
++        char *mode_name = malloc(32);
++        mode = xf86CVTMode(mir_output->modes[i].horizontal_resolution,
++                           mir_output->modes[i].vertical_resolution,
++                           60.0f,
++                           FALSE, FALSE);
++        /* And now, because the CVT standard doesn't support such common resolutions as 1366x768... */
++        mode->VDisplay = mir_output->modes[i].vertical_resolution;
++        mode->HDisplay = mir_output->modes[i].horizontal_resolution;
++
++        mode->type = M_T_DRIVER;
++        /* TODO: Get preferred mode from Mir, or get a guarantee that the first mode is preferred */
++        if (i == 0)
++            mode->type |= M_T_PREFERRED;
++
++        snprintf(mode_name, 32, "%dx%d", mode->HDisplay, mode->VDisplay);
++        mode->name = mode_name;
++        modes = xf86ModesAdd(modes, mode);
++    }
++    /* TODO: Get Mir to send us the EDID blob and add that */
 +
 +    return modes;
 +}
 +
 +static void
-+output_destroy(xf86OutputPtr xf86output)
++xmir_output_destroy(xf86OutputPtr xf86output)
 +{
-+    struct mir_output *output = xf86output->driver_private;
-+    
-+    free(output);
++    /* The MirDisplayOutput* in driver_private gets cleaned up by 
++       mir_display_config_destroy() */
 +}
 +
-+static const xf86OutputFuncsRec output_funcs = {
-+    .dpms	    = output_dpms,
-+    .detect	    = output_detect,
-+    .mode_valid	= output_mode_valid,
-+    .get_modes	= output_get_modes,
-+    .destroy	= output_destroy
++static const xf86OutputFuncsRec xmir_output_funcs = {
++    .dpms       = xmir_output_dpms,
++    .detect     = xmir_output_detect,
++    .mode_valid = xmir_output_mode_valid,
++    .get_modes  = xmir_output_get_modes,
++    .destroy    = xmir_output_destroy
++};
++
++
++struct xmir_visit_set_pixmap_window {
++    PixmapPtr old, new;
 +};
 +
++static int
++xmir_visit_set_window_pixmap(WindowPtr window, pointer data)
++{
++    struct xmir_visit_set_pixmap_window *visit = data;
++
++    if (window->drawable.pScreen->GetWindowPixmap(window) == visit->old) {
++        window->drawable.pScreen->SetWindowPixmap(window, visit->new);
++        return WT_WALKCHILDREN;
++    }
++
++    return WT_DONTWALKCHILDREN;
++}
++
++static void
++xmir_set_screen_pixmap(PixmapPtr old_front, PixmapPtr new_front)
++{
++    struct xmir_visit_set_pixmap_window visit = {
++        .old = old_front,
++        .new = new_front
++    };
++    (old_front->drawable.pScreen->SetScreenPixmap)(new_front);
++
++    TraverseTree(old_front->drawable.pScreen->root, &xmir_visit_set_window_pixmap, &visit);
++}
++
 +static Bool
-+resize(ScrnInfoPtr scrn, int width, int height)
++xmir_resize(ScrnInfoPtr scrn, int width, int height)
 +{
++    xf86CrtcConfigPtr crtc_cfg = XF86_CRTC_CONFIG_PTR(scrn);
++    ScreenPtr screen = xf86ScrnToScreen(scrn);
++    PixmapPtr old_screen_pixmap, new_screen_pixmap;
++
 +    if (scrn->virtualX == width && scrn->virtualY == height)
 +        return TRUE;
-+    /* We don't handle resize at all, we must match the compositor size */
-+    return FALSE;
++
++    old_screen_pixmap = screen->GetScreenPixmap(screen);
++    new_screen_pixmap = screen->CreatePixmap(screen, width, height, scrn->depth,
++                                             CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
++
++    if (!new_screen_pixmap)
++        return FALSE;
++
++    scrn->virtualX = width;
++    scrn->virtualY = height;
++    scrn->displayWidth = width;
++
++    for (int i = 0; i < crtc_cfg->num_crtc; i++) {
++        xf86CrtcPtr crtc = crtc_cfg->crtc[i];
++
++        if (!crtc->enabled)
++            continue;
++
++        xmir_crtc_set_mode_major(crtc, &crtc->mode,
++                                 crtc->rotation, crtc->x, crtc->y);
++    }
++
++    xmir_set_screen_pixmap(old_screen_pixmap, new_screen_pixmap);
++    screen->DestroyPixmap(old_screen_pixmap);
++
++    xf86_reload_cursors(screen);
++
++    return TRUE;
 +}
 +
 +static const xf86CrtcConfigFuncsRec config_funcs = {
-+    resize
++    xmir_resize
 +};
 +
++static void
++xmir_handle_hotplug(void *ctx)
++{
++    ScrnInfoPtr scrn = *(ScrnInfoPtr *)ctx;
++    xf86CrtcConfigPtr crtc_config = XF86_CRTC_CONFIG_PTR(scrn);
++
++    if (crtc_config->num_crtc == 0)
++        FatalError("[xmir] Received hotplug event, but have no CRTCs?\n");
++
++    xmir_update_config(crtc_config);
++
++    /* Trigger RANDR refresh */
++    RRGetInfo(xf86ScrnToScreen(scrn), TRUE);   
++}
++
++static void
++xmir_display_config_callback(MirConnection *unused, void *ctx)
++{
++    xmir_screen *xmir = ctx;
++
++    xmir_post_to_eventloop(xmir->hotplug_event_handler, &xmir->scrn);
++}
++
 +Bool
 +xmir_mode_pre_init(ScrnInfoPtr scrn, xmir_screen *xmir)
 +{
-+    MirDisplayInfo display_info;
-+    xf86OutputPtr xf86output;
++    int i;
++    MirDisplayConfiguration *display_config;
 +    xf86CrtcPtr xf86crtc;
-+    struct mir_output *output;
 +
-+    mir_connection_get_display_info(xmir_connection_get(), &display_info);
-+    
 +    /* Set up CRTC config functions */
 +    xf86CrtcConfigInit(scrn, &config_funcs);
 +
-+    /* We don't support resizing whatsoever */
++    /* We don't scanout of a single surface, so we don't have a scanout limit */
 +    xf86CrtcSetSizeRange(scrn,
 +                         320, 320,
-+                         8192, 8192);
++                         INT16_MAX, INT16_MAX);
 +
-+    output = malloc(sizeof *output);
-+    output->width = display_info.width;
-+    output->height = display_info.height;
-+    
-+    xf86output = xf86OutputCreate(scrn, &output_funcs, "XMIR-1");
-+    xf86output->possible_crtcs = 1;
-+    xf86output->possible_clones = 1;
-+    xf86output->driver_private = output;
 +
-+    xf86crtc = xf86CrtcCreate(scrn, &crtc_funcs);
-+    xf86crtc->driver_private = NULL;
++    /* Hook up hotplug notification */
++    xmir->hotplug_event_handler =
++        xmir_register_handler(&xmir_handle_hotplug,
++                              sizeof (ScreenPtr));
++
++    mir_connection_set_display_config_change_callback(
++        xmir_connection_get(),
++        &xmir_display_config_callback, xmir);
++
++    display_config =
++        mir_connection_create_display_config(xmir_connection_get());
++
++    xmir->root_window_fragments = malloc((display_config->num_outputs + 1) *
++                                         sizeof(xmir_window *));
++    xmir->root_window_fragments[display_config->num_outputs] = NULL;
++
++    if (xmir->root_window_fragments == NULL)
++        return FALSE;
++
++    for (i = 0; i < display_config->num_outputs; i++) {
++        xf86OutputPtr xf86output;
++        char name[32];
++
++        snprintf(name, sizeof name, "XMIR-%d", i);
++
++        xf86output = xf86OutputCreate(scrn, &xmir_output_funcs, name);
++
++        xmir_output_populate(xf86output, display_config->outputs + i);
++    }
++
++    /* TODO: Get the number of CRTCs from Mir */
++    for (i = 0; i < display_config->num_outputs; i++) {
++        struct xmir_crtc *xmir_crtc = malloc(sizeof *xmir_crtc);
++        if (xmir_crtc == NULL)
++            return FALSE;
++
++        xmir_crtc->xmir = xmir;
++        xmir_crtc->root_fragment = calloc(1, sizeof *xmir_crtc->root_fragment);
++        xmir_crtc->config = display_config;
 +
++        if (xmir_crtc->root_fragment == NULL)
++            return FALSE;
++
++        xmir->root_window_fragments[i] = xmir_crtc->root_fragment;
++        RegionNull(&xmir_crtc->root_fragment->region);
++
++        xf86crtc = xf86CrtcCreate(scrn, &crtc_funcs);
++        xf86crtc->driver_private = xmir_crtc;
++    }
++
++    xf86SetScrnInfoModes(scrn);
++
++    /* TODO: Use initial Mir state rather than setting up our own */
 +    xf86InitialConfiguration(scrn, TRUE);
 +  
 +    return TRUE;
 +}
-Index: xserver/hw/xfree86/xmir/xmir-private.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xserver/hw/xfree86/xmir/xmir-private.h	2013-08-22 15:18:34.429916132 +1000
-@@ -0,0 +1,90 @@
+diff --git a/hw/xfree86/xmir/xmir-private.h b/hw/xfree86/xmir/xmir-private.h
+new file mode 100644
+index 0000000..a24afbf
+--- /dev/null
++++ b/hw/xfree86/xmir/xmir-private.h
+@@ -0,0 +1,104 @@
 +/*
 + * Copyright © 2012 Canonical, Inc
 + *
@@ -506,23 +894,27 @@ Index: xserver/hw/xfree86/xmir/xmir-private.h
 +typedef struct xmir_marshall_handler xmir_marshall_handler;
 +
 +struct xmir_screen {
++    ScrnInfoPtr            scrn;
 +    CreateWindowProcPtr    CreateWindow;
 +    DestroyWindowProcPtr   DestroyWindow;
 +    xmir_driver *          driver;
 +    xmir_marshall_handler *submit_rendering_handler;
++    xmir_marshall_handler *hotplug_event_handler;
 +    struct xorg_list       damage_list;
++    struct xmir_window   **root_window_fragments; /* NULL terminated array of xmir_window * */
 +};
 +
-+typedef struct {
++struct xmir_window {
 +    WindowPtr           win;
 +    MirSurface         *surface;
-+    DamagePtr           damage;
++    RegionRec           region;
 +    RegionRec           past_damage[MIR_MAX_BUFFER_AGE];
++    DamagePtr           damage;
 +    int                 damage_index;
 +    struct xorg_list    link_damage;
 +    unsigned int        has_free_buffer:1;
 +    unsigned int        damaged:1;
-+} xmir_window;
++};
 +
 +MirConnection *
 +xmir_connection_get(void);
@@ -530,6 +922,16 @@ Index: xserver/hw/xfree86/xmir/xmir-private.h
 +xmir_screen *
 +xmir_screen_get(ScreenPtr screen);
 +
++xmir_window *
++xmir_window_get(WindowPtr win);
++
++void
++xmir_window_enable_damage_tracking(xmir_window *xmir_win);
++
++void
++xmir_window_disable_damage_tracking(xmir_window *xmir_win);
++
++
 +Bool
 +xmir_screen_init_window(ScreenPtr screen, xmir_screen *xmir);
 +
@@ -549,10 +951,11 @@ Index: xserver/hw/xfree86/xmir/xmir-private.h
 +xmir_process_from_eventloop(void);
 +
 + #endif /* _MIR_PRIVATE_H */
-Index: xserver/hw/xfree86/xmir/xmir-thread-proxy.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xserver/hw/xfree86/xmir/xmir-thread-proxy.c	2013-08-22 15:18:34.433916132 +1000
+diff --git a/hw/xfree86/xmir/xmir-thread-proxy.c b/hw/xfree86/xmir/xmir-thread-proxy.c
+new file mode 100644
+index 0000000..7464644
+--- /dev/null
++++ b/hw/xfree86/xmir/xmir-thread-proxy.c
 @@ -0,0 +1,117 @@
 +/*
 + * Copyright © 2012 Canonical, Inc
@@ -671,11 +1074,12 @@ Index: xserver/hw/xfree86/xmir/xmir-thread-proxy.c
 +	}
 +}
 +
-Index: xserver/hw/xfree86/xmir/xmir-window.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xserver/hw/xfree86/xmir/xmir-window.c	2013-08-22 15:19:20.877917729 +1000
-@@ -0,0 +1,326 @@
+diff --git a/hw/xfree86/xmir/xmir-window.c b/hw/xfree86/xmir/xmir-window.c
+new file mode 100644
+index 0000000..89c5448
+--- /dev/null
++++ b/hw/xfree86/xmir/xmir-window.c
+@@ -0,0 +1,340 @@
 +/*
 + * Copyright © 2012 Canonical, Inc
 + *
@@ -722,26 +1126,31 @@ Index: xserver/hw/xfree86/xmir/xmir-window.c
 +#include "xf86.h"
 +
 +#include <stdlib.h>
++#include <unistd.h>
 +
 +static DevPrivateKeyRec xmir_window_private_key;
 +static const RegionRec xmir_empty_region = { {0, 0, 0, 0}, &RegionBrokenData };
 +
-+static xmir_window *
++xmir_window *
 +xmir_window_get(WindowPtr win)
 +{
++    /* The root window is handled specially */
++    assert(win->parent != NULL);
++
 +    return dixGetPrivate(&win->devPrivates, &xmir_window_private_key);
 +}
 +
 +_X_EXPORT int
-+xmir_prime_fd_for_window(WindowPtr win)
++xmir_window_get_fd(xmir_window *xmir_win)
 +{
-+    xmir_window *xmir_win = xmir_window_get(win);
 +    MirBufferPackage *package;
 +
-+    assert(mir_platform_type_gbm == mir_surface_get_platform_type(xmir_win->surface));
++    if (mir_platform_type_gbm != mir_surface_get_platform_type(xmir_win->surface))
++        FatalError("[xmir] Only supported on DRM Mir platform\n");
 +
 +    mir_surface_get_current_buffer(xmir_win->surface, &package);
-+    assert(package->fd_items == 1);
++    if (package->fd_items != 1)


Reply to: