Multi-monitor Mode Setting APIs Keith Packard, SaveScreen and the core X screen saver will be implemented by disabling outputs and crtcs using their dpms functions. void xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) Pass this function to xf86DPMSInit and all DPMS mode switching will be managed by using the dpms functions provided by the Outputs and CRTCs. Bool xf86CrtcScreenInit (ScreenPtr screen) This function completes the screen initialization process for the crtc and output objects. Call it near the end of the ScreenInit function, after the frame buffer and acceleration layers have been added. 3.3 EnterVT functions Functions used during EnterVT, or whenever the current configuration needs to be applied to the hardware. Bool xf86SetDesiredModes (ScrnInfoPtr scrn) xf86InitialConfiguration selects the desired configuration at PreInit time; when the server finally hits ScreenInit, xf86SetDesiredModes is used by the driver to take that configuration and apply it to the hardware. In addition, successful mode selection at other times updates the configuration that will be used by this function, so LeaveVT/EnterVT pairs can simply invoke this and return to the previous configuration. 3.4 SwitchMode functions Functions called from the pScrn->SwitchMode hook, which is used by the XFree86-VidModeExtension and the keypad mode switch commands. Bool xf86SetSingleMode (ScrnInfoPtr scrn, DisplayModePtr desired, Rotation rotation) This function applies the specified mode to all active outputs. Which is to say, it picks reasonable modes for all active outputs, attempting to get the screen to the specified size while not breaking anything that is currently working. 3.7 get_modes functions Functions called during output->get_modes to help build lists of modes xf86MonPtr xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) This returns the EDID data structure for the 'output' using the I2C bus 'pDDCBus'. This has no effect on 'output' itself. void xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) Once the EDID data has been fetched, this call applies the EDID data to the output object, setting the physical size and also various properties, like the DDC root window property (when output is the 'compat' output), and the RandR 1.2 EDID output properties. DisplayModePtr xf86OutputGetEDIDModes (xf86OutputPtr output) Given an EDID data structure, this function computes a list of suitable modes. This function also applies a sequence of 'quirks' during this process so that the returned modes may not actually match the mode data present in the EDID data. 3.6 Other functions These remaining functions in the API can be used by the driver as needed. Bool xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) Applies a mode to a CRTC. All of the outputs which are currently using the specified CRTC are included in the mode setting process. 'x' and 'y' are the offset within the frame buffer that the crtc is placed at. No checking is done in this function to ensure that the mode is usable by the active outputs. void xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) This discards the mode lists for all outputs, re-detects monitor presence and then acquires new mode lists for all monitors which are not disconnected. Monitor configuration data is used to modify the mode lists returned by the outputs. 'maxX' and 'maxY' limit the maximum size modes that will be returned. void xf86SetScrnInfoModes (ScrnInfoPtr pScrn) This copies the 'compat' output mode list into the pScrn modes list which is used by the XFree86-VidModeExtension and the keypad mode switching operations. The current 'desired' mode for the CRTC associated with the 'compat' output is placed first in this list to indicate the current mode. Usually, the driver won't need to call this function as xf86InitialConfiguration will do so automatically, as well as any RandR functions which reprobe for modes. However, if the driver reprobes for modes at other times using xf86ProbeOutputModes, this function needs to be called. Bool xf86DiDGAReInit (ScreenPtr pScreen) This is similar to xf86SetScrnInfoModes, but it applies the 'compat' output mode list to the set of modes advertised by the DGA extension; it needs to be called whenever xf86ProbeOutputModes is invoked. void xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) After any sequence of calls using xf86CrtcSetMode, this function cleans up any leftover Output and CRTC objects by disabling them, saving power. It is safe to call this whenever the server is running as it only disables objects which are not currently in use. 4. CRTC operations 4.1 CRTC functions These functions provide an abstract interface for the CRTC object; most manipulation of the CRTC object is done through these functions. void crtc->funcs->dpms (xf86CrtcPtr crtc, int mode) Where 'mode' is one of DPMSModeOff, DPMSModeSuspend, DPMSModeStandby or DPMSModeOn. This requests that the crtc go to the specified power state. When changing power states, the output dpms functions are invoked before the crtc dpms functions. void crtc->funcs->save (xf86CrtcPtr crtc) void crtc->funcs->restore (xf86CrtcPtr crtc) Preserve/restore any register contents related to the CRTC. These are strictly a convenience for the driver writer; if the existing driver has fully operation save/restore functions, you need not place any additional code here. In particular, the server itself never uses this function. Bool crtc->funcs->lock (xf86CrtcPtr crtc) void crtc->funcs->unlock (xf86CrtcPtr crtc) These functions are invoked around mode setting operations; the intent is that DRI locking be done here to prevent DRI applications from manipulating the hardware while the server is busy changing the output configuration. If the lock function returns FALSE, the unlock function will not be invoked. Bool crtc->funcs->mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) This call gives the CRTC a chance to see what mode will be set and to comment on the mode by changing 'adjusted_mode' as needed. This function shall not modify the state of the crtc hardware at all. If the CRTC cannot accept this mode, this function may return FALSE. void crtc->funcs->prepare (xf86CrtcPtr crtc) This call is made just before the mode is set to make the hardware ready for the operation. A usual function to perform here is to disable the crtc so that mode setting can occur with clocks turned off and outputs deactivated. void crtc->funcs->mode_set (xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) This function applies the specified mode (possibly adjusted by the CRTC and/or Outputs). void crtc->funcs->commit (xf86CrtcPtr crtc) Once the mode has been applied to the CRTC and Outputs, this function is invoked to let the hardware turn things back on. void crtc->funcs->gamma_set (xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) This function adjusts the gamma ramps for the specified crtc. void * crtc->funcs->shadow_allocate (xf86CrtcPtr crtc, int width, int height) This function allocates frame buffer space for a shadow frame buffer. When allocated, the crtc must scan from the shadow instead of the main frame buffer. This is used for rotation. The address returned is passed to the shadow_create function. This function should return NULL on failure. PixmapPtr crtc->funcs->shadow_create (xf86CrtcPtr crtc, void *data, int width, int height) This function creates a pixmap object that will be used as a shadow of the main frame buffer for CRTCs which are rotated or reflected. 'data' is the value returned by shadow_allocate. void crtc->funcs->shadow_destroy (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data) Destroys any associated shadow objects. If pPixmap is NULL, then a pixmap was not created, but 'data' may still be non-NULL indicating that the shadow had been allocated. void crtc->funcs->destroy (xf86CrtcPtr crtc) When a CRTC is destroyed (which only happens in error cases), this function can clean up any driver-specific data. 4.2 CRTC fields The CRTC object is not opaque; there are several fields of interest to the driver writer. struct _xf86Crtc { /** * Associated ScrnInfo */ ScrnInfoPtr scrn; /** * Active state of this CRTC * * Set when this CRTC is driving one or more outputs */ Bool enabled; /** Track whether cursor is within CRTC range */ Bool cursorInRange; /** Track state of cursor associated with this CRTC */ Bool cursorShown; /** * Active mode * * This reflects the mode as set in the CRTC currently * It will be cleared when the VT is not active or * during server startup */ DisplayModeRec mode; Rotation rotation; PixmapPtr rotatedPixmap; void *rotatedData; /** * Position on screen * * Locates this CRTC within the frame buffer */ int x, y; /** * Desired mode * * This is set to the requested mode, independent of * whether the VT is active. In particular, it receives * the startup configured mode and saves the active mode * on VT switch. */ DisplayModeRec desiredMode; Rotation desiredRotation; int desiredX, desiredY; /** crtc-specific functions */ const xf86CrtcFuncsRec *funcs; /** * Driver private * * Holds driver-private information */ void *driver_private; #ifdef RANDR_12_INTERFACE /** * RandR crtc * * When RandR 1.2 is available, this * points at the associated crtc object */ RRCrtcPtr randr_crtc; #else void *randr_crtc; #endif }; 5. Output functions. 6. Configuration Because the configuration file syntax is fixed, this was done by creating new "Driver" section options that hook specific outputs to specific "Monitor" sections in the file. The option: section of the form: Option "monitor-VGA" "My VGA Monitor" connects the VGA output of this driver to the "Monitor" section with Identifier "My VGA Monitor". All of the usual monitor options can now be placed in that "Monitor" section and will be applied to the VGA output configuration.