[Request For Comments] xf86-video-fbdev with RanR 1.2 support

Julian Pidancet julian.pidancet at citrix.com
Tue Sep 14 06:06:20 PDT 2010



Hi,

I have a system using Xorg along with the xf86-video-fbdev display driver.
I'm using a xenfb fbdev driver in the kernel. I need to be able to
dynamically add new video modes to the driver at run-time and switch to it.

I believe this is only possible if the driver implements the RandR 1.2+
extension.
I wrote a little patch to implement the necessary interface to be able to
dynamically add video modes.

I am now able to add custom video modes and switch to it using the randr
tool. Unfortunately, for some reason, when I try to switch to a custom
video mode using libXRandR in a handmade C program, It fails with the
following error message: 

Changing Xorg resolution: X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  146 (RANDR)
  Minor opcode of failed request:  21 (RRSetCrtcConfig)
  Value in failed request:  0x0
  Serial number of failed request:  15
  Current serial number in output stream:  15

I haven't figured out why yet (maybe it has nothing to do with the
modifications I made to the driver).

Please tell me if there's something I'm doing wrong and if there's something
I can do to improve that stuff.

Thanks.

diff -ru xf86-video-fbdev-0.4.1-orig//src/fbdev.c xf86-video-fbdev-0.4.1//src/fbdev.c
--- xf86-video-fbdev-0.4.1-orig//src/fbdev.c	2010-09-10 18:05:46.000000000 +0000
+++ xf86-video-fbdev-0.4.1//src/fbdev.c	2010-09-10 18:06:07.000000000 +0000
@@ -40,6 +40,9 @@
 #include <pciaccess.h>
 #endif
 
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+
 static Bool debug = 0;
 
 #define TRACE_ENTER(str) \
@@ -282,6 +285,13 @@
 }
 #endif
 
+static Bool
+FBDevSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+	ScrnInfoPtr scrn = xf86Screens[scrnIndex];
+
+	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
+}
 
 static Bool
 FBDevProbe(DriverPtr drv, int flags)
@@ -376,7 +386,7 @@
 		    pScrn->Probe         = FBDevProbe;
 		    pScrn->PreInit       = FBDevPreInit;
 		    pScrn->ScreenInit    = FBDevScreenInit;
-		    pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
+		    pScrn->SwitchMode    = FBDevSwitchMode;
 		    pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
 		    pScrn->EnterVT       = fbdevHWEnterVTWeak();
 		    pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
@@ -393,12 +403,272 @@
 }
 
 static Bool
+FBDevCrtcResize(ScrnInfoPtr scrn, int width, int height)
+{
+        int bpp = scrn->bitsPerPixel;
+        ScreenPtr pScreen = scrn->pScreen;
+        PixmapPtr pPixmap = NULL;
+        Bool rc = TRUE;
+
+        if (width * height * bpp / 8 >= scrn->videoRam * 1024)
+        {
+                xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                           "Unable to set up a virtual screen size of %dx%d "
+                           "with %d Kb of video memory.\n",
+                           width, height, scrn->videoRam);
+                rc = FALSE;
+        }
+        if (rc) {
+                pPixmap = pScreen->GetScreenPixmap(pScreen);
+                if (NULL == pPixmap) {
+                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                                   "Failed to get the screen pixmap.\n");
+                        rc = FALSE;
+                }
+        }
+        if (rc) {
+                if (!pScreen->ModifyPixmapHeader(pPixmap, width, height,
+                                                 scrn->depth, bpp, width * bpp / 8,
+                                                 NULL)) {
+                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                                            "Failed to set up the screen pixmap.\n");
+                        rc = FALSE;
+                }
+        }
+        if (rc) {
+                scrn->virtualX = width;
+                scrn->virtualY = height;
+                scrn->displayWidth = width;
+                /* Write the new values to the hardware */
+                rc = xf86SetDesiredModes(scrn);
+        }
+
+        return rc;
+}
+
+
+static const xf86CrtcConfigFuncsRec FBDevCrtcConfigFuncs = {
+        FBDevCrtcResize
+};
+
+static void
+FBDevCrtcDpms(xf86CrtcPtr crtc, int mode)
+{
+        (void) crtc;
+        (void) mode;
+}
+
+static Bool
+FBDevCrtcLock(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+
+        return FALSE;
+}
+
+static Bool
+FBDevCrtcModeFixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+                   DisplayModePtr adjusted_mode)
+{
+        (void) mode;
+
+        return TRUE;
+}
+
+static void
+FBDevCrtcPrepare(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static void
+FBDevCrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode,
+                 DisplayModePtr adjusted_mode, int x, int y)
+{
+        ScrnInfoPtr pScrn = crtc->scrn;
+
+        (void) mode;
+
+        fbdevHWSwitchMode(pScrn->scrnIndex, adjusted_mode, 0);
+        pScrn->AdjustFrame(crtc->scrn->scrnIndex, x, y, 0);
+}
+
+static void
+FBDevCrtcCommit(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static void
+FBDevCrtcGammaSet(xf86CrtcPtr crtc, CARD16 *red,
+                  CARD16 *green, CARD16 *blue, int size)
+{
+        (void) crtc;
+        (void) red;
+        (void) green;
+        (void) blue;
+        (void) size;
+}
+
+static void *
+FBDevCrtcShadowAllocate(xf86CrtcPtr crtc, int width, int height)
+{
+        (void) crtc;
+        (void) width;
+        (void) height;
+
+        return NULL;
+}
+
+static void
+FBDevCrtcDestroy(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static const xf86CrtcFuncsRec FBDevCrtcFuncs = {
+        .dpms = FBDevCrtcDpms,
+        .save = NULL,
+        .restore = NULL,
+        .lock = FBDevCrtcLock,
+        .unlock = NULL,
+        .mode_fixup = FBDevCrtcModeFixup,
+        .prepare = FBDevCrtcPrepare,
+        .mode_set = FBDevCrtcModeSet,
+        .commit = FBDevCrtcCommit,
+        .gamma_set = FBDevCrtcGammaSet,
+        .shadow_allocate = FBDevCrtcShadowAllocate,
+        .shadow_create = NULL,
+        .shadow_destroy = NULL,
+        .set_cursor_colors = NULL,
+        .set_cursor_position = NULL,
+        .show_cursor = NULL,
+        .hide_cursor = NULL,
+        .load_cursor_argb = NULL,
+        .destroy = FBDevCrtcDestroy
+};
+
+static void
+FBDevOutputCreateResources(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputDpms(xf86OutputPtr output, int mode)
+{
+        (void) output;
+        (void) mode;
+}
+
+static int
+FBDevOutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
+{
+        ScrnInfoPtr pScrn = output->scrn;
+        int rc = MODE_OK;
+
+        return rc;
+}
+
+static Bool
+FBDevOutputModeFixup(xf86OutputPtr output, DisplayModePtr mode,
+                     DisplayModePtr adjusted_mode)
+{
+        (void) output;
+        (void) mode;
+        (void) adjusted_mode;
+
+        return TRUE;
+}
+
+static void
+FBDevOutputPrepare(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputCommit(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputModeSet(xf86OutputPtr output, DisplayModePtr mode,
+                   DisplayModePtr adjusted_mode)
+{
+        (void) output;
+        (void) mode;
+        (void) adjusted_mode;
+}
+
+static xf86OutputStatus
+FBDevOutputDetect(xf86OutputPtr output)
+{
+        (void) output;
+
+        return XF86OutputStatusConnected;
+}
+
+static DisplayModePtr
+FBDevOutputGetModes (xf86OutputPtr output)
+{
+        unsigned int i;
+        ScrnInfoPtr pScrn = output->scrn;
+        DisplayModePtr pModes = NULL;
+
+        return pModes;
+}
+
+static void
+FBDevOutputDestroy(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+FBDevOutputSetProperty(xf86OutputPtr output, Atom property,
+                       RRPropertyValuePtr value)
+{
+        (void) output;
+        (void) property;
+        (void) value;
+
+        return FALSE;
+}
+#endif
+
+
+static const xf86OutputFuncsRec FBDevOutputFuncs = {
+        .create_resources = FBDevOutputCreateResources,
+        .dpms = FBDevOutputDpms,
+        .save = NULL,
+        .restore = NULL,
+        .mode_valid = FBDevOutputModeValid,
+        .mode_fixup = FBDevOutputModeFixup,
+        .prepare = FBDevOutputPrepare,
+        .commit = FBDevOutputCommit,
+        .mode_set = FBDevOutputModeSet,
+        .detect = FBDevOutputDetect,
+        .get_modes = FBDevOutputGetModes,
+#ifdef RANDR_12_INTERFACE
+        .set_property = FBDevOutputSetProperty,
+#endif
+        .destroy = FBDevOutputDestroy
+};
+
+static Bool
 FBDevPreInit(ScrnInfoPtr pScrn, int flags)
 {
 	FBDevPtr fPtr;
 	int default_depth, fbbpp;
 	const char *mod = NULL, *s;
 	int type;
+        int i;
+        ClockRangePtr clockRanges;
+        xf86OutputPtr output;
+        xf86CrtcPtr crtc;
 
 	if (flags & PROBE_DETECT) return FALSE;
 
@@ -451,6 +721,19 @@
 	if (!xf86SetDefaultVisual(pScrn, -1))
 		return FALSE;
 
+        xf86CrtcConfigInit(pScrn, &FBDevCrtcConfigFuncs);
+        xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
+        crtc = xf86CrtcCreate(pScrn, &FBDevCrtcFuncs);
+        output = xf86OutputCreate(pScrn, &FBDevOutputFuncs, "FBDev");
+        xf86OutputUseScreenMonitor(output, FALSE);
+        output->possible_crtcs = 1;
+        output->possible_clones = 0;
+
+        if (!xf86InitialConfiguration(pScrn, TRUE)) {
+                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
+                return (FALSE);
+        }
+
 	/* We don't currently support DirectColor at > 8bpp */
 	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "requested default visual"
@@ -470,10 +753,10 @@
 	pScrn->progClock = TRUE;
 	pScrn->rgbBits   = 8;
 	pScrn->chipset   = "fbdev";
-	pScrn->videoRam  = fbdevHWGetVidmem(pScrn);
+	pScrn->videoRam  = fbdevHWGetVidmem(pScrn) / 1024;
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s (video memory:"
-		   " %dkB)\n", fbdevHWGetName(pScrn), pScrn->videoRam/1024);
+		   " %dkB)\n", fbdevHWGetName(pScrn), pScrn->videoRam);
 
 	/* handle options */
 	xf86CollectOptions(pScrn, NULL);
@@ -521,26 +804,12 @@
 	  }
 	}
 
-	/* select video modes */
-
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against framebuffer device...\n");
-	fbdevHWSetVideoModes(pScrn);
-
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against monitor...\n");
-	{
-		DisplayModePtr mode, first = mode = pScrn->modes;
-		
-		if (mode != NULL) do {
-			mode->status = xf86CheckModeForMonitor(mode, pScrn->monitor);
-			mode = mode->next;
-		} while (mode != NULL && mode != first);
-
-		xf86PruneDriverModes(pScrn);
+        if (pScrn->modes == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+		return FALSE;
 	}
-
-	if (NULL == pScrn->modes)
-		fbdevHWUseBuildinMode(pScrn);
 	pScrn->currentMode = pScrn->modes;
+        xf86CrtcSetMode(crtc, pScrn->currentMode, RR_Rotate_0, 0, 0);
 
 	/* First approximation, may be refined in ScreenInit */
 	pScrn->displayWidth = pScrn->virtualX;
@@ -930,6 +1199,8 @@
 
 	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
 
+	xf86CrtcScreenInit(pScreen);
+
 	pScreen->SaveScreen = fbdevHWSaveScreenWeak();
 
 	/* Wrap the current CloseScreen function */






More information about the xorg-devel mailing list