[PATCH] RandR 1.2 driver screen resize hook

Aaron Plattner aplattner at nvidia.com
Wed Feb 28 20:19:39 PST 2007


I talked to Keith some more and he pointed out that screen-level driver hooks
could be attached to the xf86CrtcConfigRec.  These changes add that support.  If
there are no objections, I'll check these in later this week or possibly early
next week.

-- Aaron

On Tue, Feb 27, 2007 at 11:08:00AM -0800, Aaron Plattner wrote:
> I'm actually going to sneak two patches into this message.  The first is a
> straightforward fix to have ProcRRSetCrtcConfig reject client requests to clone
> non-cloneable outputs.
> 
> The second patch is more interesting.  It adds a driver hook to report to the
> DDX the range of desktop sizes it supports, as well as a hook to actually resize
> the screen in response to a client resize request.  Currently, the randr 1.2
> code is forced to try to set virtualX and virtualY big enough so that the driver
> will statically allocate enough space during PreInit for the largest modes on
> each output.  This wastes memory and doesn't even work right in the monitor
> hotplug case.  With these hooks, a driver can reallocate its vidmem, allowing
> the desktop to grow larger than the virtual size configured in PreInit.
> 
> Keith Packard actually suggested that this interface be mandatory for randr 1.2
> drivers, which would make this second patch a bit smaller.  A naive (read "XAA")
> driver that can't actually resize the desktop will simply report its configured
> virtualX and virtualY in response to RR12_GET_SCREEN_SIZE_RANGES and just set
> virtualX and virtualY (and nothing else) in response to RR12_SET_SCREEN_SIZE.  A
> more advanced driver will want to reallocate its vidmem and change devKind and
> devPrivate.ptr in the screen pixmap as well.  If there are no objections, I'll
> make it mandatory.
> 
> Driver developers: Does this interface look like it will work for your drivers?
> Feedback is welcome.
> 
> -- Aaron
-------------- next part --------------
From 562b183307e758b9f9db6d2e089d33945184d449 Mon Sep 17 00:00:00 2001
From: Aaron Plattner <aplattner at nvidia.com>
Date: Wed, 28 Feb 2007 13:36:58 -0800
Subject: [PATCH] Add a screen resize hook to xf86CrtcConfigRec.

This hook is called when the DDX needs to resize the screen.  The driver is
responsible for changing virtualX and virtualY, along with any other related
screen properties (devPrivate.ptr, devKind, displayWidth, etc.).

Use the size range from the crtc config instead of randrp->virtual[XY] when
reporting the min and max screen sizes to the DDX.
---
 hw/xfree86/modes/xf86Crtc.c    |    6 +++++-
 hw/xfree86/modes/xf86Crtc.h    |   24 +++++++++++++++++++++++-
 hw/xfree86/modes/xf86RandR12.c |   24 +++++++++++++++---------
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 29042a0..ebc0f8f 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -52,13 +52,17 @@
 int xf86CrtcConfigPrivateIndex = -1;
 
 void
-xf86CrtcConfigInit (ScrnInfoPtr scrn)
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+		    const xf86CrtcConfigFuncsRec *funcs)
 {
     xf86CrtcConfigPtr	config;
     
     if (xf86CrtcConfigPrivateIndex == -1)
 	xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
     config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+
+    config->funcs = funcs;
+
     scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
 }
  
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 756730e..345332b 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -407,6 +407,25 @@ struct _xf86Output {
 #endif
 };
 
+typedef struct _xf86CrtcConfigFuncs {
+    /**
+     * Requests that the driver resize the screen.
+     *
+     * The driver is responsible for updating scrn->virtualX and scrn->virtualY.
+     * If the requested size cannot be set, the driver should leave those values
+     * alone and return FALSE.
+     *
+     * A naive driver that cannot reallocate the screen may simply change
+     * virtual[XY].  A more advanced driver will want to also change the
+     * devPrivate.ptr and devKind of the screen pixmap, update any offscreen
+     * pixmaps it may have moved, and change pScrn->displayWidth.
+     */
+    Bool
+    (*resize)(ScrnInfoPtr	scrn,
+	      int		width,
+	      int		height);
+} xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
+
 typedef struct _xf86CrtcConfig {
     int			num_output;
     xf86OutputPtr	*output;
@@ -435,6 +454,8 @@ typedef struct _xf86CrtcConfig {
     int			dga_width, dga_height, dga_stride;
     DisplayModePtr	dga_save_mode;
 
+    const xf86CrtcConfigFuncsRec *funcs;
+
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -446,7 +467,8 @@ extern int xf86CrtcConfigPrivateIndex;
  */
 
 void
-xf86CrtcConfigInit (ScrnInfoPtr		scrn);
+xf86CrtcConfigInit (ScrnInfoPtr				scrn,
+		    const xf86CrtcConfigFuncsRec	*funcs);
 
 void
 xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index abdf92e..052d12a 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -335,8 +335,9 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     WindowPtr		pRoot = WindowTable[pScreen->myNum];
-    Bool 		ret = TRUE;
+    Bool		ret = FALSE;
 
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -345,20 +346,26 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
     }
     if (pRoot)
 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
 
-    pScreen->width = pScrn->virtualX;
-    pScreen->height = pScrn->virtualY;
+    /* Let the driver update virtualX and virtualY */
+    if (!(*config->funcs->resize)(pScrn, width, height))
+	goto finish;
+
+    ret = TRUE;
+
+    pScreen->width = width;
+    pScreen->height = height;
     pScreen->mmWidth = mmWidth;
     pScreen->mmHeight = mmHeight;
 
     xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
     xf86SetViewport (pScreen, 0, 0);
+
+finish:
     if (pRoot)
 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
 #if RANDR_12_INTERFACE
-    if (WindowTable[pScreen->myNum])
+    if (WindowTable[pScreen->myNum] && ret)
 	RRScreenSizeNotify (pScreen);
 #endif
     return ret;
@@ -904,15 +911,14 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 {
     int			c;
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
 
     for (c = 0; c < config->num_crtc; c++)
 	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
     
     
-    RRScreenSetSizeRange (pScreen, 320, 240,
-			  randrp->virtualX, randrp->virtualY);
+    RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
+			  config->maxWidth, config->maxHeight);
     return TRUE;
 }
 
-- 
1.4.4.4

-------------- next part --------------
From f87dfcef7d5968dfa6690b2e038cca61d3246909 Mon Sep 17 00:00:00 2001
From: Aaron Plattner <aplattner at nvidia.com>
Date: Wed, 28 Feb 2007 14:26:47 -0800
Subject: [PATCH] Add a canGrow argument to xf86InitialConfiguration.

canGrow indicates to the DDX that the driver can enlarge the desktop via the
xf86_config->funcs->resize hook.  If so, xf86InitialConfiguration will set
virtual[XY] to match the configuration it chooses and will leave the crtc config
size ranges alone.  If FALSE, it will bloat the screen to fit the largest probed
mode and also set the crtc config max size to limit the desktop to the initial
virtual[XY] size.
---
 hw/xfree86/modes/xf86Crtc.c |   78 +++++++++++++++++++++++++++++-------------
 hw/xfree86/modes/xf86Crtc.h |    2 +-
 2 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index ebc0f8f..c53d2a8 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -734,12 +734,16 @@ xf86PickCrtcs (ScrnInfoPtr	scrn,
 
 /*
  * Compute the virtual size necessary to place all of the available
- * crtcs in the specified configuration and also large enough to
- * resize any crtc to the largest available mode
+ * crtcs in the specified configuration.
+ *
+ * canGrow indicates that the driver can make the screen larger than its initial
+ * configuration.  If FALSE, this function will enlarge the screen to include
+ * the largest available mode.
  */
 
 static void
-xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
+			 Bool canGrow)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int	    width = 0, height = 0;
@@ -757,26 +761,28 @@ xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
 	    crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
 	    crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
 	}
-	for (o = 0; o < config->num_output; o++) 
-	{
-	    xf86OutputPtr   output = config->output[o];
+	if (!canGrow) {
+	    for (o = 0; o < config->num_output; o++)
+	    {
+		xf86OutputPtr   output = config->output[o];
 
-	    for (s = 0; s < config->num_crtc; s++)
-		if (output->possible_crtcs & (1 << s))
-		{
-		    DisplayModePtr  mode;
-		    for (mode = output->probed_modes; mode; mode = mode->next)
+		for (s = 0; s < config->num_crtc; s++)
+		    if (output->possible_crtcs & (1 << s))
 		    {
-			if (mode->HDisplay > crtc_width)
-			    crtc_width = mode->HDisplay;
-			if (mode->VDisplay > crtc_width)
-			    crtc_width = mode->VDisplay;
-			if (mode->VDisplay > crtc_height)
-			    crtc_height = mode->VDisplay;
-			if (mode->HDisplay > crtc_height)
-			    crtc_height = mode->HDisplay;
+			DisplayModePtr  mode;
+			for (mode = output->probed_modes; mode; mode = mode->next)
+			{
+			    if (mode->HDisplay > crtc_width)
+				crtc_width = mode->HDisplay;
+			    if (mode->VDisplay > crtc_width)
+				crtc_width = mode->VDisplay;
+			    if (mode->VDisplay > crtc_height)
+				crtc_height = mode->VDisplay;
+			    if (mode->HDisplay > crtc_height)
+				crtc_height = mode->HDisplay;
+			}
 		    }
-		}
+	    }
 	}
 	if (crtc_width > width)
 	    width = crtc_width;
@@ -1350,10 +1356,17 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn)
  *
  * Given auto-detected (and, eventually, configured) values,
  * construct a usable configuration for the system
+ *
+ * canGrow indicates that the driver can resize the screen to larger than its
+ * initially configured size via the config->funcs->resize hook.  If TRUE, this
+ * function will set virtualX and virtualY to match the initial configuration
+ * and leave config->max{Width,Height} alone.  If FALSE, it will bloat
+ * virtual[XY] to include the largest modes and set config->max{Width,Height}
+ * accordingly.
  */
 
 Bool
-xf86InitialConfiguration (ScrnInfoPtr	    scrn)
+xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o, c;
@@ -1491,9 +1504,10 @@ xf86InitialConfiguration (ScrnInfoPtr	    scrn)
     if (scrn->display->virtualX == 0)
     {
 	/*
-	 * Expand virtual size to cover potential mode switches
+	 * Expand virtual size to cover the current config and potential mode
+	 * switches, if the driver can't enlarge the screen later.
 	 */
-	xf86DefaultScreenLimits (scrn, &width, &height);
+	xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
     
 	scrn->display->virtualX = width;
 	scrn->display->virtualY = height;
@@ -1503,7 +1517,23 @@ xf86InitialConfiguration (ScrnInfoPtr	    scrn)
 	scrn->virtualX = width;
     if (height > scrn->virtualY)
 	scrn->virtualY = height;
-    
+
+    /*
+     * Make sure the configuration isn't too small.
+     */
+    if (width < config->minWidth || height < config->minHeight)
+	return FALSE;
+
+    /*
+     * Limit the crtc config to virtual[XY] if the driver can't grow the
+     * desktop.
+     */
+    if (!canGrow)
+    {
+	xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
+			      width, height);
+    }
+
     /* Mirror output modes to scrn mode list */
     xf86SetScrnInfoModes (scrn);
     
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 345332b..b04f7f3 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -545,7 +545,7 @@ void
 xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
 
 Bool
-xf86InitialConfiguration (ScrnInfoPtr pScrn);
+xf86InitialConfiguration (ScrnInfoPtr pScrn, Bool canGrow);
 
 void
 xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
-- 
1.4.4.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg/attachments/20070228/acfc246c/attachment.pgp>


More information about the xorg mailing list