XFree86 server 4.x Design (DRAFT) : Helper Functions
Previous: The Loader
Next: The vgahw module

## 18. Helper Functions

This section describe ``helper'' functions that video driver might find useful. While video drivers are not required to use any of these to be considered ``compliant'', the use of appropriate helpers is strongly encouraged to improve the consistency of driver behaviour.

### 18.1. Functions for printing messages

> `ErrorF(const char *format, ...)`

> > This is the basic function for writing to the error log (typically stderr and/or a log file). Video drivers should usually avoid using this directly in favour of the more specialised functions described below. This function is useful for printing messages while debugging a driver.

> `FatalError(const char *format, ...)`

> > This prints a message and causes the Xserver to abort. It should rarely be used within a video driver, as most error conditions should be flagged by the return values of the driver functions. This allows the higher layers to decide how to proceed. In rare cases, this can be used within a driver if a fatal unexpected condition is found.

> `xf86ErrorF(const char *format, ...)`

> > This is like `ErrorF()`, except that the message is only printed when the Xserver's verbosity level is set to the default (`1`) or higher. It means that the messages are not printed when the server is started with the `-quiet` flag. Typically this function would only be used for continuing messages started with one of the more specialised functions described below.

> `xf86ErrorFVerb(int verb, const char *format, ...)`

> > Like `xf86ErrorF()`, except the minimum verbosity level for which the message is to be printed is given explicitly. Passing a `verb` value of zero means the message is always printed. A value higher than `1` can be used for information would normally not be needed, but which might be useful when diagnosing problems.

> `xf86Msg(MessageType type, const char *format, ...)`

> > This is like `xf86ErrorF()`, except that the message is prefixed with a marker determined by the value of `type`. The marker is used to indicate the type of message (warning, error, probed value, config value, etc). Note the `xf86Verbose` value is ignored for messages of type `X_ERROR`.

> > The marker values are:

> > > `X_PROBED`

> > > > Value was probed.

> > > `X_CONFIG`

> > > > Value was given in the config file.

> > > `X_DEFAULT`

> > > > Value is a default.

> > > `X_CMDLINE`

> > > > Value was given on the command line.

> > > `X_NOTICE`

> > > > Notice.

> > > `X_ERROR`

> > > > Error message.

> > > `X_WARNING`

> > > > Warning message.

> > > `X_INFO`

> > > > Informational message.

> > > `X_NONE`

> > > > No prefix.

> > > `X_NOT_IMPLEMENTED`

> > > > The message relates to functionality that is not yet implemented.

> `xf86MsgVerb(MessageType type, int verb, const char *format, ...)`

> > Like `xf86Msg()`, but with the verbosity level given explicitly.

> `xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)`

> > This is like `xf86Msg()` except that the driver's name (the `name` field of the `ScrnInfoRec`) followed by the `scrnIndex` in parentheses is printed following the prefix. This should be used by video drivers in most cases as it clearly indicates which driver/screen the message is for. If `scrnIndex` is negative, this function behaves exactly like `xf86Msg()`.

> > NOTE: This function can only be used after the `ScrnInfoRec` and its `name` field have been allocated. Normally, this means that it can not be used before the END of the `ChipProbe()` function. Prior to that, use `xf86Msg()`, providing the driver's name explicitly. No screen number can be supplied at that point.

> `xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb,
> const char *format, ...)`

> > Like `xf86DrvMsg()`, but with the verbosity level given explicitly.

### 18.2. Functions for setting values based on command line and config file

> `Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp,
> int fbbpp, int depth24flags)`

> > This function sets the `depth`, `pixmapBPP` and `bitsPerPixel` fields of the `ScrnInfoRec`. It also determines the defaults for display-wide attributes and pixmap formats the screen will support, and finds the Display subsection that matches the depth/bpp. This function should normally be called very early from the `ChipPreInit()` function.

> > It requires that the `confScreen` field of the `ScrnInfoRec` be initialised prior to calling it. This is done by the XFree86 common layer prior to calling `ChipPreInit()`.

> > The parameters passed are:

> > `depth`

> > > driver's preferred default depth if no other is given. If zero, use the overall server default.

> > `bpp`

> > > Same, but for the pixmap bpp.

> > `fbbpp`

> > > Same, but for the framebuffer bpp.

> > `depth24flags`

> > > Flags that indicate the level of 24/32bpp support and whether conversion between different framebuffer and pixmap formats is supported. The flags for this argument are defined as follows, and multiple flags may be ORed together:

> > > `NoDepth24Support`

> > > > No depth 24 formats supported

> > > `Support24bppFb`

> > > > 24bpp framebuffer supported

> > > `Support32bppFb`

> > > > 32bpp framebuffer supported

> > > `SupportConvert24to32`

> > > > Can convert 24bpp pixmap to 32bpp fb

> > > `SupportConvert32to24`

> > > > Can convert 32bpp pixmap to 24bpp fb

> > > `ForceConvert24to32`

> > > > Force 24bpp pixmap to 32bpp fb conversion

> > > `ForceConvert32to24`

> > > > Force 32bpp pixmap to 24bpp fb conversion

> > It uses the command line, config file, and default values in the correct order of precedence to determine the depth and bpp values. It is up to the driver to check the results to see that it supports them. If not the `ChipPreInit()` function should return `FALSE`.

> > If only one of depth/bpp is given, the other is set to a reasonable (and consistent) default.

> > If a driver finds that the initial `depth24flags` it uses later results in a fb format that requires more video memory than is available it may call this function a second time with a different `depth24flags` setting.

> > On success, the return value is `TRUE`. On failure it prints an error message and returns `FALSE`.

> > The following fields of the `ScrnInfoRec` are initialised by this function:

> > > `depth`, `bitsPerPixel`, `display`, `imageByteOrder`, `bitmapScanlinePad`, `bitmapScanlineUnit`, `bitmapBitOrder`, `numFormats`, `formats`, `fbFormat`.

> `void xf86PrintDepthBpp(scrnInfoPtr scrp)`

> > This function can be used to print out the depth and bpp settings. It should be called after the final call to `xf86SetDepthBpp()`.

> `Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)`

> > This function sets the `weight`, `mask`, `offset` and `rgbBits` fields of the `ScrnInfoRec`. It would normally be called fairly early in the `ChipPreInit()` function for depths > 8bpp.

> > It requires that the `depth` and `display` fields of the `ScrnInfoRec` be initialised prior to calling it.

> > The parameters passed are:

> > `weight`

> > > driver's preferred default weight if no other is given. If zero, use the overall server default.

> > `mask`

> > > Same, but for mask.

> > It uses the command line, config file, and default values in the correct order of precedence to determine the weight value. It derives the mask and offset values from the weight and the defaults. It is up to the driver to check the results to see that it supports them. If not the `ChipPreInit()` function should return `FALSE`.

> > On success, this function prints a message showing the weight values selected, and returns `TRUE`.

> > On failure it prints an error message and returns `FALSE`.

> > The following fields of the `ScrnInfoRec` are initialised by this function:

> > > `weight`, `mask`, `offset`.

> `Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)`

> > This function sets the `defaultVisual` field of the `ScrnInfoRec`. It would normally be called fairly early from the `ChipPreInit()` function.

> > It requires that the `depth` and `display` fields of the `ScrnInfoRec` be initialised prior to calling it.

> > The parameters passed are:

> > `visual`

> > > driver's preferred default visual if no other is given. If `-1`, use the overall server default.

> > It uses the command line, config file, and default values in the correct order of precedence to determine the default visual value. It is up to the driver to check the result to see that it supports it. If not the `ChipPreInit()` function should return `FALSE`.

> > On success, this function prints a message showing the default visual selected, and returns `TRUE`.

> > On failure it prints an error message and returns `FALSE`.

> `Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)`

> > This function sets the `gamma` field of the `ScrnInfoRec`. It would normally be called fairly early from the `ChipPreInit()` function in cases where the driver supports gamma correction.

> > It requires that the `monitor` field of the `ScrnInfoRec` be initialised prior to calling it.

> > The parameters passed are:

> > `gamma`

> > > driver's preferred default gamma if no other is given. If zero (`< 0.01`), use the overall server default.

> > It uses the command line, config file, and default values in the correct order of precedence to determine the gamma value. It is up to the driver to check the results to see that it supports them. If not the `ChipPreInit()` function should return `FALSE`.

> > On success, this function prints a message showing the gamma value selected, and returns `TRUE`.

> > On failure it prints an error message and returns `FALSE`.

> `void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)`

> > This function sets the `xDpi` and `yDpi` fields of the `ScrnInfoRec`. The driver can specify preferred defaults by setting `x` and `y` to non-zero values. The `-dpi` command line option overrides all other settings. Otherwise, if the DisplaySize entry is present in the screen's Monitor config file section, it is used together with the virtual size to calculate the dpi values. This function should be called after all the mode resolution has been done.

> `void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn)`

> > This functions sets the `blackPixel` and `whitePixel` fields of the `ScrnInfoRec` according to whether or not the `-flipPixels` command line options is present.

> `const char *xf86GetVisualName(int visual)`

> > Returns a printable string with the visual name matching the numerical visual class provided. If the value is outside the range of valid visual classes, `NULL` is returned.

### 18.3. Primary Mode functions

The primary mode helper functions are those which would normally be used by a driver, unless it has unusual requirements which cannot be catered for the by the helpers.

> `int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
> char **modeNames, ClockRangePtr clockRanges,
> int *linePitches, int minPitch, int maxPitch,
> int pitchInc, int minHeight, int maxHeight,
> int virtualX, int virtualY,
> unsigned long apertureSize,
> LookupModeFlags strategy)`

> > This function basically selects the set of modes to use based on those available and the various constraints. It also sets some other related parameters. It is normally called near the end of the `ChipPreInit()` function.

> > The parameters passed to the function are:

> > `availModes`

> > > List of modes available for the monitor.

> > `modeNames`

> > > List of mode names that the screen is requesting.

> > `clockRanges`

> > > A list of clock ranges allowed by the driver. Each range includes whether interlaced or multiscan modes are supported for that range. See below for more on `clockRanges`.

> > `linePitches`

> > > List of line pitches supported by the driver. This is optional and should be `NULL` when not used.

> > `minPitch`

> > > Minimum line pitch supported by the driver. This must be supplied when `linePitches` is `NULL`, and is ignored otherwise.

> > `maxPitch`

> > > Maximum line pitch supported by the driver. This is required when `minPitch` is required.

> > `pitchInc`

> > > Granularity of horizontal pitch values as supported by the chipset. This is expressed in bits. This must be supplied.

> > `minHeight`

> > > minimum virtual height allowed. If zero, no limit is imposed.

> > `maxHeight`

> > > maximum virtual height allowed. If zero, no limit is imposed.

> > `virtualX`

> > > If greater than zero, this is the virtual width value that will be used. Otherwise, the virtual width is chosen to be the smallest that can accommodate the modes selected.

> > `virtualY`

> > > If greater than zero, this is the virtual height value that will be used. Otherwise, the virtual height is chosen to be the smallest that can accommodate the modes selected.

> > `apertureSize`

> > > The size (in bytes) of the aperture used to access video memory.

> > `strategy`

> > > The strategy to use when choosing from multiple modes with the same name. The options are:

> > > `LOOKUP_DEFAULT`

> > > > ???

> > > `LOOKUP_BEST_REFRESH`

> > > > mode with best refresh rate

> > > `LOOKUP_CLOSEST_CLOCK`

> > > > mode with closest matching clock

> > > `LOOKUP_LIST_ORDER`

> > > > first usable mode in list

> > > The following options can also be combined (OR'ed) with one of the above:

> > > `LOOKUP_CLKDIV2`

> > > > Allow halved clocks

> > > `LOOKUP_OPTIONAL_TOLERANCES`

> > > > Allow missing horizontal sync and/or vertical refresh ranges in the XF86Config Monitor section

> > > `LOOKUP_OPTIONAL_TOLERANCES` should only be specified when the driver can ensure all modes it generates can sync on, or at least not damage, the monitor or digital flat panel. Horizontal sync and/or vertical refresh ranges specified by the user will still be honoured (and acted upon).

> > This function requires that the following fields of the `ScrnInfoRec` are initialised prior to calling it:

> > `clock[]`

> > > List of discrete clocks (when non-programmable)

> > `numClocks`

> > > Number of discrete clocks (when non-programmable)

> > `progClock`

> > > Whether the clock is programmable or not

> > `monitor`

> > > Pointer to the applicable XF86Config monitor section

> > `fdFormat`

> > > Format of the screen buffer

> > `videoRam`

> > > total video memory size (in bytes)

> > `maxHValue`

> > > Maximum horizontal timing value allowed

> > `maxVValue`

> > > Maximum vertical timing value allowed

> > `xInc`

> > > Horizontal timing increment in pixels (defaults to 8)

> > This function fills in the following `ScrnInfoRec` fields:

> > `modePool`

> > > A subset of the modes available to the monitor which are compatible with the driver.

> > `modes`

> > > One mode entry for each of the requested modes, with the status field of each filled in to indicate if the mode has been accepted or not. This list of modes is a circular list.

> > `virtualX`

> > > The resulting virtual width.

> > `virtualY`

> > > The resulting virtual height.

> > `displayWidth`

> > > The resulting line pitch.

> > `virtualFrom`

> > > Where the virtual size was determined from.

> > The first stage of this function checks that the `virtualX` and `virtualY` values supplied (if greater than zero) are consistent with the line pitch and `maxHeight` limitations. If not, an error message is printed, and the return value is `-1`.

> > The second stage sets up the mode pool, eliminating immediately any modes that exceed the driver's line pitch limits, and also the virtual width and height limits (if greater than zero). For each mode removed an informational message is printed at verbosity level `2`. If the mode pool ends up being empty, a warning message is printed, and the return value is `0`.

> > The final stage is to lookup each mode name, and fill in the remaining parameters. If an error condition is encountered, a message is printed, and the return value is `-1`. Otherwise, the return value is the number of valid modes found (`0` if none are found).

> > Even if the supplied mode names include duplicates, no two names will ever match the same mode. Furthermore, if the supplied mode names do not yield a valid mode (including the case where no names are passed at all), the function will continue looking through the mode pool until it finds a mode that survives all checks, or until the mode pool is exhausted.

> > A message is only printed by this function when a fundamental problem is found. It is intended that this function may be called more than once if there is more than one set of constraints that the driver can work within.

> > If this function returns `-1`, the `ChipPreInit()` function should return `FALSE`.

> > `clockRanges` is a linked list of clock ranges allowed by the driver. If a mode doesn't fit in any of the defined `clockRanges`, it is rejected. The first `clockRange` that matches all requirements is used. This structure needs to be initialized to NULL when allocated.

> > `clockRanges` contains the following fields:

> > `minClock
> > maxClock`

> > > The lower and upper mode clock bounds for which the rest of the `clockRange` parameters apply. Since these are the mode clocks, they are not scaled with the `ClockMulFactor` and `ClockDivFactor`. It is up to the driver to adjust these values if they depend on the clock scaling factors.

> > `clockIndex`

> > > (not used yet) `-1` for programmable clocks

> > `interlaceAllowed`

> > > `TRUE` if interlacing is allowed for this range

> > `doubleScanAllowed`

> > > `TRUE` if doublescan or multiscan is allowed for this range

> > `ClockMulFactor
> > ClockDivFactor`

> > > Scaling factors that are applied to the mode clocks ONLY before selecting a clock index (when there is no programmable clock) or a `SynthClock` value. This is useful for drivers that support pixel multiplexing or that need to scale the clocks because of hardware restrictions (like sending 24bpp data to an 8 bit RAMDAC using a tripled clock).

> > > Note that these parameters describe what must be done to the mode clock to achieve the data transport clock between graphics controller and RAMDAC. For example for `2:1` pixel multiplexing, two pixels are sent to the RAMDAC on each clock. This allows the RAMDAC clock to be half of the actual pixel clock. Hence, `ClockMulFactor=1` and `ClockDivFactor=2`. This means that the clock used for clock selection (ie, determining the correct clock index from the list of discrete clocks) or for the `SynthClock` field in case of a programmable clock is: (`mode->Clock * ClockMulFactor) / ClockDivFactor`.

> > `PrivFlags`

> > > This field is copied into the `mode->PrivFlags` field when this `clockRange` is selected by `xf86ValidateModes()`. It allows the driver to find out what clock range was selected, so it knows it needs to set up pixel multiplexing or any other range-dependent feature. This field is purely driver-defined: it may contain flag bits, an index or anything else (as long as it is an `INT`).

> > Note that the `mode->SynthClock` field is always filled in by `xf86ValidateModes()`: it will contain the ``data transport clock'', which is the clock that will have to be programmed in the chip when it has a programmable clock, or the clock that will be picked from the clocks list when it is not a programmable one. Thus:

> > `mode->SynthClock =
> > (mode->Clock * ClockMulFactor) / ClockDivFactor`

> `void xf86PruneDriverModes(ScrnInfoPtr scrp)`

> > This function deletes modes in the modes field of the `ScrnInfoRec` that have been marked as invalid. This is normally run after having run `xf86ValidateModes()` for the last time. For each mode that is deleted, a warning message is printed out indicating the reason for it being deleted.

> `void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)`

> > This function fills in the `Crtc*` fields for all the modes in the `modes` field of the `ScrnInfoRec`. The `adjustFlags` parameter determines how the vertical CRTC values are scaled for interlaced modes. They are halved if it is `INTERLACE_HALVE_V`. The vertical CRTC values are doubled for doublescan modes, and are further multiplied by the `VScan` value.

> > This function is normally called after calling `xf86PruneDriverModes()`.

> `void xf86PrintModes(ScrnInfoPtr scrp)`

> > This function prints out the virtual size setting, and the line pitch being used. It also prints out two lines for each mode being used. The first line includes the mode's pixel clock, horizontal sync rate, refresh rate, and whether it is interlaced, doublescanned and/or multi-scanned. The second line is the mode's Modeline.

> > This function is normally called after calling `xf86SetCrtcForModes()`.

### 18.4. Secondary Mode functions

The secondary mode helper functions are functions which are normally used by the primary mode helper functions, and which are not normally called directly by a driver. If a driver has unusual requirements and needs to do its own mode validation, it might be able to make use of some of these secondary mode helper functions.

> `int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2,
> int *divider)`

> > This function returns the index of the closest clock to the frequency `freq` given (in kHz). It assumes that the number of clocks is greater than zero. It requires that the `numClocks` and `clock` fields of the `ScrnInfoRec` are initialised. The `allowDiv2` field determines if the clocks can be halved. The `*divider` return value indicates whether clock division is used when determining the clock returned.

> > This function is only for non-programmable clocks.

> `const char *xf86ModeStatusToString(ModeStatus status)`

> > This function converts the `status` value to a descriptive printable string.

> `ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
> ClockRangePtr clockRanges, LookupModeFlags strategy)`

> > This function takes a pointer to a mode with the name filled in, and looks for a mode in the `modePool` list which matches. The parameters of the matching mode are filled in to `*modep`. The `clockRanges` and `strategy` parameters are as for the `xf86ValidateModes()` function above.

> > This function requires the `modePool`, `clock[]`, `numClocks` and `progClock` fields of the `ScrnInfoRec` to be initialised before being called.

> > The return value is `MODE_OK` if a mode was found. Otherwise it indicates why a matching mode could not be found.

> `ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp,
> DisplayModePtr mode, ClockRangePtr clockRanges,
> LookupModeFlags strategy, int maxPitch,
> int virtualX, int virtualY)`

> > This function checks the passed mode against some basic driver constraints. Apart from the ones passed explicitly, the `maxHValue` and `maxVValue` fields of the `ScrnInfoRec` are also used. If the `ValidMode` field of the `ScrnInfoRec` is set, that function is also called to check the mode. Next, the mode is checked against the monitor's constraints.

> > If the mode is consistent with all constraints, the return value is `MODE_OK`. Otherwise the return value indicates which constraint wasn't met.

> `void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)`

> > This function deletes the `mode` given from the `modeList`. It never prints any messages, so it is up to the caller to print a message if required.

### 18.5. Functions for handling strings and tokens

Tables associating strings and numerical tokens combined with the following functions provide a compact way of handling strings from the config file, and for converting tokens into printable strings. The table data structure is:

>     typedef struct {
>         int                 token;
>         const char *        name;
>     } SymTabRec, *SymTabPtr;

A table is an initialised array of `SymTabRec`. The tokens must be non-negative integers. Multiple names may be mapped to a single token. The table is terminated with an element with a `token` value of `-1` and `NULL` for the `name`.

> `const char *xf86TokenToString(SymTabPtr table, int token)`

> > This function returns the first string in `table` that matches `token`. If no match is found, `NULL` is returned (NOTE, older versions of this function would return the string "unknown" when no match is found).

> `int xf86StringToToken(SymTabPtr table, const char *string)`

> > This function returns the first token in `table` that matches `string`. The `xf86NameCmp()` function is used to determine the match. If no match is found, `-1` is returned.

### 18.6. Functions for finding which config file entries to use

These functions can be used to select the appropriate config file entries that match the detected hardware. They are described above in the Probe and Available Functions sections.

### 18.7. Probing discrete clocks on old hardware

The `xf86GetClocks()` function may be used to assist in finding the discrete pixel clock values on older hardware.

> `void xf86GetClocks(ScrnInfoPtr pScrn, int num,
> Bool (*ClockFunc)(ScrnInfoPtr, int),
> void (*ProtectRegs)(ScrnInfoPtr, Bool),
> void (*BlankScreen)(ScrnInfoPtr, Bool),
> int vertsyncreg, int maskval, int knownclkindex,
> int knownclkvalue)`

> > This function uses a comparative sampling method to measure the discrete pixel clock values. The number of discrete clocks to measure is given by `num`. `clockFunc` is a function that selects the `n`'th clock. It should also save or restore any state affected by programming the clocks when the index passed is `CLK_REG_SAVE` or `CLK_REG_RESTORE`. `ProtectRegs` is a function that does whatever is required to protect the hardware state while selecting a new clock. `BlankScreen` is a function that blanks the screen. `vertsyncreg` and `maskval` are the register and bitmask to check for the presence of vertical sync pulses. `knownclkindex` and `knownclkvalue` are the index and value of a known clock. These are the known references on which the comparative measurements are based. The number of clocks probed is set in `pScrn->numClocks`, and the probed clocks are set in the `pScrn->clock[]` array. All of the clock values are in units of kHz.

> `void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)`

> > Print out the pixel clocks `scrp->clock[]`. `from` indicates whether the clocks were probed or from the config file.

### 18.8. Other helper functions

> `Bool xf86IsUnblank(int mode)`

> > Returns `TRUE` when the screen saver mode specified by `mode` requires the screen be unblanked, and `FALSE` otherwise. The screen saver modes that require blanking are `SCREEN_SAVER_ON` and `SCREEN_SAVER_CYCLE`, and the screen saver modes that require unblanking are `SCREEN_SAVER_OFF` and `SCREEN_SAVER_FORCER`. Drivers may call this helper from their `SaveScreen()` function to interpret the screen saver modes.

XFree86 server 4.x Design (DRAFT) : Helper Functions
Previous: The Loader
Next: The vgahw module