[Xorg] X.org driver support for RandR rotation

Aaron Plattner aplattner at nvidia.com
Fri Jul 23 16:38:11 PDT 2004


Hello,

Currently, there is no way for a driver to be notified of RandR events.  This
patch adds ScrnInfoRec functions which a driver can hook into to register which
rotations are supported and be notified when RandR events happen.  This is
necessary mainly for hardware rotation support.

There are a few bugs that occur when the screen is rotated 90 or 270 degrees.  A
few functions compare pScreen->{width,height} to mode sizes, which is incorrect
when the dimensions of the root window are swapped.  This patch changes these
functions to use virtualX and virtualY, which are not swapped in rotated modes.
This bug also affects drivers such as nv and fbdev that support the "Rotate"
option in the config file.  (To reproduce, use nv with 'Option "Rotate" "CW"'
and then try using Ctrl-Alt-+ and -).

-- Aaron Plattner

Index: hw/xfree86/common/xf86Cursor.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86Cursor.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 xf86Cursor.c
--- hw/xfree86/common/xf86Cursor.c	25 Nov 2003 19:28:32 -0000	1.1.1.2
+++ hw/xfree86/common/xf86Cursor.c	23 Jul 2004 22:29:21 -0000
@@ -222,7 +222,7 @@
   if (mode == pScr->currentMode)
     return TRUE;
 
-  if (mode->HDisplay > pScreen->width || mode->VDisplay > pScreen->height)
+  if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY)
     return FALSE;
 
   pCursorScreen = miPointerCurrentScreen();
Index: hw/xfree86/common/xf86Init.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86Init.c,v
retrieving revision 1.2
diff -u -r1.2 xf86Init.c
--- hw/xfree86/common/xf86Init.c	23 Apr 2004 19:20:32 -0000	1.2
+++ hw/xfree86/common/xf86Init.c	23 Jul 2004 22:29:21 -0000
@@ -897,6 +897,8 @@
 	xf86Screens[i]->DPMSSet = NULL;
 	xf86Screens[i]->LoadPalette = NULL; 
 	xf86Screens[i]->SetOverscan = NULL;
+	xf86Screens[i]->RRGetInfo = NULL;
+	xf86Screens[i]->RRSetConfig = NULL;
 	scr_index = AddScreen(xf86Screens[i]->ScreenInit, argc, argv);
       if (scr_index == i) {
 	/*
Index: hw/xfree86/common/xf86RandR.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v
retrieving revision 1.2
diff -u -r1.2 xf86RandR.c
--- hw/xfree86/common/xf86RandR.c	23 Apr 2004 19:20:32 -0000	1.2
+++ hw/xfree86/common/xf86RandR.c	23 Jul 2004 22:29:21 -0000
@@ -38,6 +38,7 @@
     CloseScreenProcPtr		    CloseScreen;
     int				    virtualX;
     int				    virtualY;
+    Rotation			    rotation;
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
     
 static int	    xf86RandRIndex;
@@ -77,8 +78,8 @@
 	    return FALSE;
 	RRRegisterRate (pScreen, pSize, refresh);
 	if (mode == scrp->currentMode &&
-	    mode->HDisplay == pScreen->width && mode->VDisplay == pScreen->height)
-	    RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh, pSize);
+	    mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY)
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
 	if (mode->next == scrp->modes)
 	    break;
     }
@@ -93,12 +94,17 @@
 	if (!pSize)
 	    return FALSE;
 	RRRegisterRate (pScreen, pSize, refresh0);
-	if (pScreen->width == randrp->virtualX && 
-	    pScreen->height == randrp->virtualY)
+	if (scrp->virtualX == randrp->virtualX && 
+	    scrp->virtualY == randrp->virtualY)
 	{
-	    RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh0, pSize);
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
 	}
     }
+
+    /* If there is driver support for randr, let it set our supported rotations */
+    if(scrp->RRGetInfo)
+	return (*scrp->RRGetInfo)(scrp, rotations);
+
     return TRUE;
 }
 
@@ -125,8 +131,17 @@
 	scrp->virtualX = mode->HDisplay;
 	scrp->virtualY = mode->VDisplay;
     }
-    pScreen->width = scrp->virtualX;
-    pScreen->height = scrp->virtualY;
+    if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
+    {
+	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
+	pScreen->width = scrp->virtualY;
+	pScreen->height = scrp->virtualX;
+    }
+    else
+    {
+	pScreen->width = scrp->virtualX;
+	pScreen->height = scrp->virtualY;
+    }
     if (!xf86SwitchMode (pScreen, mode))
     {
 	scrp->virtualX = pScreen->width = oldWidth;
@@ -160,6 +175,8 @@
     int			    px, py;
     Bool		    useVirtual = FALSE;
 
+    randrp->rotation = rotation;
+
     miPointerPosition (&px, &py);
     for (mode = scrp->modes; ; mode = mode->next)
     {
@@ -179,6 +196,12 @@
 	    return FALSE;
 	}
     }
+
+    /* Have the driver do its thing. */
+    if (scrp->RRSetConfig &&
+        !(*scrp->RRSetConfig)(scrp, rotation, rate, pSize->width, pSize->height))
+	return FALSE;
+
     if (!xf86RandRSetMode (pScreen, mode, useVirtual))
 	return FALSE;
     /*
@@ -189,6 +212,7 @@
 	if (px < pSize->width && py < pSize->height)
 	    (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
     }
+
     return TRUE;
 }
 
@@ -277,6 +301,8 @@
     randrp->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = xf86RandRCloseScreen;
 
+    randrp->rotation = RR_Rotate_0;
+
     pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
     return TRUE;
 }
Index: hw/xfree86/common/xf86str.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/common/xf86str.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 xf86str.h
--- hw/xfree86/common/xf86str.h	25 Nov 2003 19:28:33 -0000	1.1.1.2
+++ hw/xfree86/common/xf86str.h	23 Jul 2004 22:29:22 -0000
@@ -476,7 +476,7 @@
 /* These values should be adjusted when new fields are added to ScrnInfoRec */
 #define NUM_RESERVED_INTS		16
 #define NUM_RESERVED_POINTERS		15
-#define NUM_RESERVED_FUNCS		12
+#define NUM_RESERVED_FUNCS		10
 
 typedef pointer (*funcPointer)(void);
 
@@ -767,6 +767,8 @@
 typedef void xf86DPMSSetProc		  (ScrnInfoPtr, int, int);
 typedef void xf86LoadPaletteProc   (ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
 typedef void xf86SetOverscanProc          (ScrnInfoPtr, int);
+typedef Bool xf86RRGetInfoProc            (ScrnInfoPtr, unsigned short *);
+typedef Bool xf86RRSetConfigProc          (ScrnInfoPtr, int, int, int, int);
 
 /*
  * ScrnInfoRec
@@ -921,6 +923,8 @@
     xf86DPMSSetProc			*DPMSSet;
     xf86LoadPaletteProc			*LoadPalette;
     xf86SetOverscanProc			*SetOverscan;
+    xf86RRGetInfoProc			*RRGetInfo;
+    xf86RRSetConfigProc			*RRSetConfig;
     
     /*
      * This can be used when the minor ABI version is incremented.



More information about the xorg mailing list