[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