xserver: Branch 'randr-1.2'

Keith Packard keithp at kemper.freedesktop.org
Thu Nov 9 07:36:45 EET 2006


 hw/xfree86/common/Makefile.am |    2 
 randr/mirandr.c               |   13 ++-
 randr/randr.c                 |    4 
 randr/randrstr.h              |   36 ++++++--
 randr/rrcrtc.c                |  170 ++++++++++++++++++++++++------------------
 randr/rrinfo.c                |   14 ++-
 randr/rrmode.c                |  108 ++++++++++++++------------
 randr/rroutput.c              |   44 ++++++----
 randr/rrscreen.c              |   32 +++++--
 9 files changed, 254 insertions(+), 169 deletions(-)

New commits:
diff-tree ec77a95a02329a2ee3a94d7de9d2a234aecb9ca0 (from 20e9144c0746943624ff77a61791b8596f3f8458)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 21:36:35 2006 -0800

    Allow RandR objects to be created before the associated ScreenRec.
    
    xf86 drivers need to create RandR object in the PreInit stage,
    before the ScreenRec is allocated. Changing the RandR DIX code
    to permit this required the addition of functions that later associate the
    objects with the related screen.
    
    An additional change is that modes are now global, and no longer associated
    with a specific screen. This change actually makes mode management cleaner
    as there is no more per-screen list of modes to deal with.
    
    This changes the RandR 1.2 ABI/API for drivers.

diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
index 0e1582e..35b22f0 100644
--- a/hw/xfree86/common/Makefile.am
+++ b/hw/xfree86/common/Makefile.am
@@ -51,7 +51,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h
               xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86Resources.h \
               xf86cmap.h xf86fbman.h xf86str.h $(XISDKINCS) \
               $(XVSDKINCS) atKeynames.h xf86Version.h xorgVersion.h \
-              xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h
+              xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h xf86Keymap.h
 
 DISTCLEANFILES = xf86Build.h
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 11c2991..3f56fe4 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -113,17 +113,24 @@ miRandRInit (ScreenPtr pScreen)
     modeInfo.height = pScreen->height;
     modeInfo.nameLength = strlen (name);
     
-    mode = RRModeGet (pScreen, &modeInfo, name);
+    mode = RRModeGet (&modeInfo, name);
     if (!mode)
 	return FALSE;
     
-    crtc = RRCrtcCreate (pScreen, NULL);
+    crtc = RRCrtcCreate (NULL);
     if (!crtc)
 	return FALSE;
+    if (!RRCrtcAttachScreen (crtc, pScreen))
+    {
+	RRCrtcDestroy (crtc);
+	return FALSE;
+    }
     
-    output = RROutputCreate (pScreen, "screen", 6, NULL);
+    output = RROutputCreate ("screen", 6, NULL);
     if (!output)
 	return FALSE;
+    if (!RROutputAttachScreen (output, pScreen))
+	return FALSE;
     if (!RROutputSetClones (output, NULL, 0))
 	return FALSE;
     if (!RROutputSetModes (output, &mode, 1, 0))
diff --git a/randr/randr.c b/randr/randr.c
index 7b39e80..4426c47 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -103,8 +103,6 @@ RRCloseScreen (int i, ScreenPtr pScreen)
 	RRCrtcDestroy (pScrPriv->crtcs[j]);
     for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
 	RROutputDestroy (pScrPriv->outputs[j]);
-    for (j = pScrPriv->numModes - 1; j >= 0; j--)
-	RRModeDestroy (pScrPriv->modes[j]);
     
     xfree (pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
@@ -257,8 +255,6 @@ Bool RRScreenInit(ScreenPtr pScreen)
     
     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
 
-    pScrPriv->numModes = 0;
-    pScrPriv->modes = NULL;
     pScrPriv->numOutputs = 0;
     pScrPriv->outputs = NULL;
     pScrPriv->numCrtcs = 0;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 60877a3..345418b 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -79,7 +79,6 @@ struct _rrMode {
     xRRModeInfo	    mode;
     char	    *name;
     void	    *devPrivate;
-    ScreenPtr	    screen;
     Bool	    userDefined;
 };
 
@@ -210,10 +209,6 @@ typedef struct _rrScrPriv {
     CARD16		    width, height;	/* last known screen size */
     Bool		    layoutChanged;	/* screen layout changed */
 
-    /* modes, outputs and crtcs */
-    int			    numModes;
-    RRModePtr		    *modes;
-
     int			    numOutputs;
     RROutputPtr		    *outputs;
 
@@ -457,10 +452,17 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layo
  * Create a CRTC
  */
 RRCrtcPtr
-RRCrtcCreate (ScreenPtr	pScreen,
-	      void	*devPrivate);
+RRCrtcCreate (void	*devPrivate);
 
 /*
+ * Attach a CRTC to a screen. Once done, this cannot be
+ * undone without destroying the CRTC; it is separate from Create
+ * only to allow an xf86-based driver to create objects in preinit
+ */
+Bool
+RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen);
+    
+/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
@@ -556,8 +558,7 @@ RRClientKnowsRates (ClientPtr	pClient);
  */
 
 RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
+RRModeGet (xRRModeInfo	*modeInfo,
 	   const char	*name);
 
 void
@@ -571,6 +572,12 @@ void
 RRModeDestroy (RRModePtr mode);
 
 /*
+ * Return a list of modes that are valid for some output in pScreen
+ */
+RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret);
+    
+/*
  * Initialize mode type
  */
 Bool
@@ -601,12 +608,19 @@ RROutputChanged (RROutputPtr output);
  */
 
 RROutputPtr
-RROutputCreate (ScreenPtr   pScreen,
-		const char  *name,
+RROutputCreate (const char  *name,
 		int	    nameLength,
 		void	    *devPrivate);
 
 /*
+ * Attach an output to a screen, again split from creation so
+ * xf86 DDXen can create randr resources before the ScreenRec
+ * exists
+ */
+Bool
+RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen);
+
+/*
  * Notify extension that output parameters have been changed
  */
 Bool
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 76d0b6b..9f7177a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -32,43 +32,34 @@ void
 RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
 {
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
 
     crtc->changed = TRUE;
-    pScrPriv->changed = TRUE;
-    /*
-     * Send ConfigureNotify on any layout change
-     */
-    if (layoutChanged)
-	pScrPriv->layoutChanged = TRUE;
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+    
+	pScrPriv->changed = TRUE;
+	/*
+	 * Send ConfigureNotify on any layout change
+	 */
+	if (layoutChanged)
+	    pScrPriv->layoutChanged = TRUE;
+    }
 }
 
 /*
  * Create a CRTC
  */
 RRCrtcPtr
-RRCrtcCreate (ScreenPtr	pScreen,
-	      void	*devPrivate)
+RRCrtcCreate (void	*devPrivate)
 {
-    rrScrPriv (pScreen);
     RRCrtcPtr	crtc;
-    RRCrtcPtr	*crtcs;
     
     crtc = xalloc (sizeof (RRCrtcRec));
     if (!crtc)
 	return NULL;
-    if (pScrPriv->numCrtcs)
-	crtcs = xrealloc (pScrPriv->crtcs, 
-			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
-    else
-	crtcs = xalloc (sizeof (RRCrtcPtr));
-    if (!crtcs)
-    {
-	xfree (crtc);
-	return NULL;
-    }
     crtc->id = FakeClientID (0);
-    crtc->pScreen = pScreen;
+    crtc->pScreen = NULL;
     crtc->mode = NULL;
     crtc->x = 0;
     crtc->y = 0;
@@ -84,11 +75,37 @@ RRCrtcCreate (ScreenPtr	pScreen,
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
 
+    return crtc;
+}
+
+/*
+ * Attach a Crtc to a screen. This is done as a separate step
+ * so that an xf86-based driver can create CRTCs in PreInit
+ * before the Screen has been created
+ */
+
+Bool
+RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    RRCrtcPtr	*crtcs;
+
+    /* make space for the crtc pointer */
+    if (pScrPriv->numCrtcs)
+	crtcs = xrealloc (pScrPriv->crtcs, 
+			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+    else
+	crtcs = xalloc (sizeof (RRCrtcPtr));
+    if (!crtcs)
+	return FALSE;
+    
+    /* attach the screen and crtc together */
+    crtc->pScreen = pScreen;
     pScrPriv->crtcs = crtcs;
     pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
 
     RRCrtcChanged (crtc, TRUE);
-    return crtc;
+    return TRUE;
 }
 
 /*
@@ -243,7 +260,6 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   RROutputConfigPtr  outputs)
 {
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
 
     /* See if nothing changed */
     if (crtc->mode == mode &&
@@ -255,45 +271,49 @@ RRCrtcSet (RRCrtcPtr    crtc,
     {
 	return TRUE;
     }
-#if RANDR_12_INTERFACE
-    if (pScrPriv->rrCrtcSet)
+    if (pScreen)
     {
-	return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
-				       rotation, numOutputs, outputs);
-    }
-#endif
-#if RANDR_10_INTERFACE
-    if (pScrPriv->rrSetConfig)
-    {
-	RRScreenSize	    size;
-	RRScreenRate	    rate;
-	Bool		    ret;
-
-	size.width = mode->mode.width;
-	size.height = mode->mode.height;
-	if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+#if RANDR_12_INTERFACE
+	rrScrPriv(pScreen);
+	if (pScrPriv->rrCrtcSet)
 	{
-	    size.mmWidth = outputs[0].output->mmWidth;
-	    size.mmHeight = outputs[0].output->mmHeight;
+	    return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+					   rotation, numOutputs, outputs);
 	}
-	else
+#endif
+#if RANDR_10_INTERFACE
+	if (pScrPriv->rrSetConfig)
 	{
-	    size.mmWidth = pScreen->mmWidth;
-	    size.mmHeight = pScreen->mmHeight;
+	    RRScreenSize	    size;
+	    RRScreenRate	    rate;
+	    Bool		    ret;
+
+	    size.width = mode->mode.width;
+	    size.height = mode->mode.height;
+	    if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+	    {
+		size.mmWidth = outputs[0].output->mmWidth;
+		size.mmHeight = outputs[0].output->mmHeight;
+	    }
+	    else
+	    {
+		size.mmWidth = pScreen->mmWidth;
+		size.mmHeight = pScreen->mmHeight;
+	    }
+	    size.nRates = 1;
+	    rate.rate = RRVerticalRefresh (&mode->mode);
+	    size.pRates = &rate;
+	    ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+	    /*
+	     * Old 1.0 interface tied screen size to mode size
+	     */
+	    if (ret)
+		RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
+	    return ret;
 	}
-	size.nRates = 1;
-	rate.rate = RRVerticalRefresh (&mode->mode);
-	size.pRates = &rate;
-	ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
-	/*
-	 * Old 1.0 interface tied screen size to mode size
-	 */
-	if (ret)
-	    RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
-	return ret;
-    }
 #endif
-    RRTellChanged (pScreen);
+	RRTellChanged (pScreen);
+    }
     return FALSE;
 }
 
@@ -311,22 +331,26 @@ RRCrtcDestroyResource (pointer value, XI
 {
     RRCrtcPtr	crtc = (RRCrtcPtr) value;
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
-    int		i;
 
-    for (i = 0; i < pScrPriv->numCrtcs; i++)
+    if (pScreen)
     {
-	if (pScrPriv->crtcs[i] == crtc)
+	rrScrPriv(pScreen);
+	int		i;
+    
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
-	    memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
-		     (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
-	    --pScrPriv->numCrtcs;
-	    break;
+	    if (pScrPriv->crtcs[i] == crtc)
+	    {
+		memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
+			 (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
+		--pScrPriv->numCrtcs;
+		break;
+	    }
 	}
     }
     if (crtc->gammaRed)
 	xfree (crtc->gammaRed);
-    xfree (value);
+    xfree (crtc);
     return 1;
 }
 
@@ -343,15 +367,18 @@ RRCrtcGammaSet (RRCrtcPtr   crtc,
     Bool	ret = TRUE;
 #if RANDR_12_INTERFACE
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
 #endif
     
     memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
     memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
     memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
 #if RANDR_12_INTERFACE
-    if (pScrPriv->rrCrtcSetGamma)
-	ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+	if (pScrPriv->rrCrtcSetGamma)
+	    ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+    }
 #endif
     return ret;
 }
@@ -433,6 +460,9 @@ ProcRRGetCrtcInfo (ClientPtr client)
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
 
+    /* All crtcs must be associated with screens before client
+     * requests are processed
+     */
     pScreen = crtc->pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
 
@@ -589,7 +619,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	for (j = 0; j < outputs[i].output->numCrtcs; j++)
 	    if (outputs[i].output->crtcs[j] == crtc)
 		break;
-	if (j == outputs[j].output->numCrtcs)
+	if (j == outputs[i].output->numCrtcs)
 	{
 	    if (outputs)
 		xfree (outputs);
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index e92caad..244b089 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -44,7 +44,7 @@ RROldModeAdd (RROutputPtr output, RRScre
     modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
 			 (CARD32) refresh);
     modeInfo.nameLength = strlen (name);
-    mode = RRModeGet (pScreen, &modeInfo, name);
+    mode = RRModeGet (&modeInfo, name);
     if (!mode)
 	return NULL;
     for (i = 0; i < output->numModes; i++)
@@ -90,12 +90,19 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
     if (pScrPriv->numOutputs == 0 &&
 	pScrPriv->numCrtcs == 0)
     {
-	crtc = RRCrtcCreate (pScreen, NULL);
+	crtc = RRCrtcCreate (NULL);
 	if (!crtc)
 	    return;
-	output = RROutputCreate (pScreen, "default", 7, NULL);
+	if (!RRCrtcAttachScreen (crtc, pScreen))
+	{
+	    RRCrtcDestroy (crtc);
+	    return;
+	}
+	output = RROutputCreate ("default", 7, NULL);
 	if (!output)
 	    return;
+	if (!RROutputAttachScreen (output, pScreen))
+	    return;
 	RROutputSetCrtcs (output, &crtc, 1);
 	RROutputSetCrtc (output, crtc);
 	RROutputSetConnection (output, RR_Connected);
@@ -206,7 +213,6 @@ RRGetInfo (ScreenPtr pScreen)
     if (pScrPriv->nSizes)
 	RRScanOldConfig (pScreen, rotations);
 #endif
-    RRModePruneUnused (pScreen);
     RRTellChanged (pScreen);
     return TRUE;
 }
diff --git a/randr/rrmode.c b/randr/rrmode.c
index fb4b5eb..3cd9ef2 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -42,19 +42,23 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo
     return TRUE;
 }
 
+/*
+ * Keep a list so it's easy to find modes in the resource database.
+ */
+static int	    num_modes;
+static RRModePtr    *modes;
+
 RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
+RRModeGet (xRRModeInfo	*modeInfo,
 	   const char	*name)
 {
-    rrScrPriv (pScreen);
     int	i;
     RRModePtr	mode;
-    RRModePtr	*modes;
+    RRModePtr	*newModes;
 
-    for (i = 0; i < pScrPriv->numModes; i++)
+    for (i = 0; i < num_modes; i++)
     {
-	mode = pScrPriv->modes[i];
+	mode = modes[i];
 	if (RRModeEqual (&mode->mode, modeInfo) &&
 	    !memcmp (name, mode->name, modeInfo->nameLength))
 	{
@@ -71,16 +75,14 @@ RRModeGet (ScreenPtr	pScreen,
     mode->name = (char *) (mode + 1);
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
-    mode->screen = pScreen;
     mode->userDefined = FALSE;
 
-    if (pScrPriv->numModes)
-	modes = xrealloc (pScrPriv->modes,
-			  (pScrPriv->numModes + 1) * sizeof (RRModePtr));
+    if (num_modes)
+	newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
     else
-	modes = xalloc (sizeof (RRModePtr));
+	newModes = xalloc (sizeof (RRModePtr));
 
-    if (!modes)
+    if (!newModes)
     {
 	xfree (mode);
 	return NULL;
@@ -89,37 +91,64 @@ RRModeGet (ScreenPtr	pScreen,
     mode->mode.id = FakeClientID(0);
     if (!AddResource (mode->mode.id, RRModeType, (pointer) mode))
 	return NULL;
+    modes = newModes;
+    modes[num_modes++] = mode;
+    
+    /*
+     * give the caller a reference to this mode
+     */
     ++mode->refcnt;
-    pScrPriv->modes = modes;
-    pScrPriv->modes[pScrPriv->numModes++] = mode;
-    pScrPriv->changed = TRUE;
     return mode;
 }
 
+RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret)
+{
+    rrScrPriv(pScreen);
+    int	o;
+    RRModePtr	*screen_modes;
+    int		num_screen_modes = 0;
+
+    screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr));
+    
+    for (o = 0; o < pScrPriv->numOutputs; o++)
+    {
+	RROutputPtr	output = pScrPriv->outputs[o];
+	int		m, n;
+
+	for (m = 0; m < output->numModes; m++)
+	{
+	    RRModePtr	mode = output->modes[m];
+	    for (n = 0; n < num_screen_modes; n++)
+		if (screen_modes[n] == mode)
+		    break;
+	    if (n == num_screen_modes)
+		screen_modes[num_screen_modes++] = mode;
+	}
+    }
+    *num_ret = num_screen_modes;
+    return screen_modes;
+}
+
 void
 RRModeDestroy (RRModePtr mode)
 {
-    ScreenPtr	    pScreen;
-    rrScrPrivPtr    pScrPriv;
     int	m;
     
     if (--mode->refcnt > 0)
 	return;
-    pScreen = mode->screen;
-    pScrPriv = rrGetScrPriv (pScreen);
-    for (m = 0; m < pScrPriv->numModes; m++)
+    for (m = 0; m < num_modes; m++)
     {
-	if (pScrPriv->modes[m] == mode)
+	if (modes[m] == mode)
 	{
-	    memmove (pScrPriv->modes + m, pScrPriv->modes + m + 1,
-		     (pScrPriv->numModes - m - 1) * sizeof (RRModePtr));
-	    pScrPriv->numModes--;
-	    if (!pScrPriv->numModes)
+	    memmove (modes + m, modes + m + 1,
+		     (num_modes - m - 1) * sizeof (RRModePtr));
+	    num_modes--;
+	    if (!num_modes)
 	    {
-		xfree (pScrPriv->modes);
-		pScrPriv->modes = NULL;
+		xfree (modes);
+		modes = NULL;
 	    }
-	    pScrPriv->changed = TRUE;
 	    break;
 	}
     }
@@ -137,6 +166,8 @@ RRModeDestroyResource (pointer value, XI
 Bool
 RRModeInit (void)
 {
+    assert (num_modes == 0);
+    assert (modes == NULL);
     RRModeType = CreateNewResourceType (RRModeDestroyResource);
     if (!RRModeType)
 	return FALSE;
@@ -146,26 +177,6 @@ RRModeInit (void)
     return TRUE;
 }
 
-void
-RRModePruneUnused (ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    RRModePtr	*unused, mode;
-    int		m;
-    int		num = pScrPriv->numModes;
-
-    unused = xalloc (num * sizeof (RRModePtr));
-    if (!unused)
-	return;
-    memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
-    for (m = 0; m < num; m++) {
-	mode = unused[m];
-	if (mode->refcnt == 1 && !mode->userDefined)
-	    FreeResource (mode->mode.id, 0);
-    }
-    xfree (unused);
-}
-
 int
 ProcRRCreateMode (ClientPtr client)
 {
@@ -205,4 +216,3 @@ ProcRRDeleteOutputMode (ClientPtr client
     (void) stuff;
     return BadImplementation; 
 }
-
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 1f6f330..1b0ecab 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -42,30 +42,17 @@ RROutputChanged (RROutputPtr output)
  */
 
 RROutputPtr
-RROutputCreate (ScreenPtr   pScreen,
-		const char  *name,
+RROutputCreate (const char  *name,
 		int	    nameLength,
 		void	    *devPrivate)
 {
-    rrScrPriv (pScreen);
     RROutputPtr	output;
-    RROutputPtr	*outputs;
 
     output = xalloc (sizeof (RROutputRec) + nameLength + 1);
     if (!output)
 	return NULL;
-    if (pScrPriv->numOutputs)
-	outputs = xrealloc (pScrPriv->outputs, 
-			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
-    else
-	outputs = xalloc (sizeof (RROutputPtr));
-    if (!outputs)
-    {
-	xfree (output);
-	return NULL;
-    }
     output->id = FakeClientID (0);
-    output->pScreen = pScreen;
+    output->pScreen = NULL;
     output->name = (char *) (output + 1);
     output->nameLength = nameLength;
     memcpy (output->name, name, nameLength);
@@ -91,12 +78,35 @@ RROutputCreate (ScreenPtr   pScreen,
     if (!AddResource (output->id, RROutputType, (pointer) output))
 	return NULL;
 
+    return output;
+}
+
+/*
+ * Attach an Output to a screen. This is done as a separate step
+ * so that an xf86-based driver can create Outputs in PreInit
+ * before the Screen has been created
+ */
+
+Bool
+RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    RROutputPtr	*outputs;
+    
+    if (pScrPriv->numOutputs)
+	outputs = xrealloc (pScrPriv->outputs, 
+			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
+    else
+	outputs = xalloc (sizeof (RROutputPtr));
+    if (!outputs)
+	return FALSE;
+    output->pScreen = pScreen;
     pScrPriv->outputs = outputs;
     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
     RROutputChanged (output);
-    return output;
+    return TRUE;
 }
-
+		      
 /*
  * Notify extension that output parameters have been changed
  */
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 705e7d7..d47e9d6 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -360,6 +360,13 @@ ProcRRGetScreenResources (ClientPtr clie
     }
     else
     {
+	RRModePtr   *modes;
+	int	    num_modes;
+
+	modes = RRModesForScreen (pScreen, &num_modes);
+	if (!modes)
+	    return BadAlloc;
+	
 	rep.type = X_Reply;
 	rep.sequenceNumber = client->sequence;
 	rep.length = 0;
@@ -367,15 +374,15 @@ ProcRRGetScreenResources (ClientPtr clie
 	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 	rep.nCrtcs = pScrPriv->numCrtcs;
 	rep.nOutputs = pScrPriv->numOutputs;
-	rep.nModes = pScrPriv->numModes;;
+	rep.nModes = num_modes;
 	rep.nbytesNames = 0;
 
-	for (i = 0; i < pScrPriv->numModes; i++)
-	    rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength;
+	for (i = 0; i < num_modes; i++)
+	    rep.nbytesNames += modes[i]->mode.nameLength;
 
 	rep.length = (pScrPriv->numCrtcs + 
 		      pScrPriv->numOutputs + 
-		      pScrPriv->numModes * (SIZEOF(xRRModeInfo) >> 2) +
+		      num_modes * (SIZEOF(xRRModeInfo) >> 2) +
 		      ((rep.nbytesNames + 3) >> 2));
 	
 	extraLen = rep.length << 2;
@@ -383,7 +390,10 @@ ProcRRGetScreenResources (ClientPtr clie
 	{
 	    extra = xalloc (extraLen);
 	    if (!extra)
+	    {
+		xfree (modes);
 		return BadAlloc;
+	    }
 	}
 	else
 	    extra = NULL;
@@ -391,7 +401,7 @@ ProcRRGetScreenResources (ClientPtr clie
 	crtcs = (RRCrtc *) extra;
 	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
 	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
-	names = (CARD8 *) (modeinfos + pScrPriv->numModes);
+	names = (CARD8 *) (modeinfos + num_modes);
 	
 	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
@@ -407,9 +417,10 @@ ProcRRGetScreenResources (ClientPtr clie
 		swapl (&outputs[i], n);
 	}
 	
-	for (i = 0; i < pScrPriv->numModes; i++)
+	for (i = 0; i < num_modes; i++)
 	{
-	    modeinfos[i] = pScrPriv->modes[i]->mode;
+	    RRModePtr	mode = modes[i];
+	    modeinfos[i] = mode->mode;
 	    if (client->swapped)
 	    {
 		swapl (&modeinfos[i].id, n);
@@ -426,10 +437,11 @@ ProcRRGetScreenResources (ClientPtr clie
 		swaps (&modeinfos[i].nameLength, n);
 		swapl (&modeinfos[i].modeFlags, n);
 	    }
-	    memcpy (names, pScrPriv->modes[i]->name, 
-		    pScrPriv->modes[i]->mode.nameLength);
-	    names += pScrPriv->modes[i]->mode.nameLength;
+	    memcpy (names, mode->name, 
+		    mode->mode.nameLength);
+	    names += mode->mode.nameLength;
 	}
+    	xfree (modes);
 	assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
     }
     



More information about the xorg-commit mailing list