[Copyright status: this file is in the public domain.] X describes displays' colour resources in terms of so-called `Visual's. Visuals are grouped into classes which describe how their colour resources are structured. There are six visual classes: StaticColor, PseudoColor, StaticGray, GrayScale, TrueColor, and DirectColor. Conceptually, each pixel in the framebuffer goes through a lookup table before driving the actual display hardware. Depending on the hardware, the lookup table (`colormap') may correspond to an actual piece of hardware or may not, and the ways in which it may be manipulated may be limited. To quote from the protocol document, The following concepts may serve to make the explanation of visual types clearer. The screen can be color or grayscale, can have a colormap that is writable or read-only, and can also have a colormap whose indices are decomposed into separate RGB pieces, provided one is not on a grayscale screen. This leads to the following diagram: Color GrayScale R/O R/W R/O R/W +---------------+----------+--------+--------+-------+ | Undecomposed | Static | Pseudo | Static | Gray | | Colormap | Color | Color | Gray | Scale | +---------------+----------+--------+--------+-------+ | Decomposed | True | Direct | | Colormap | Color | Color | +---------------+----------+--------+ liblx represents a visual class with the LX_VISUALCLASS type, which has six values, such as LX_VISUALCLASS_StaticGray and LX_VISUALCLASS_DirectColor. There are also two macros, LX_VISUALCLASS_dynamic(vc) which returns true if the argument LX_VISUALCLASS represents a read/write visual and false if read-only, and LX_VISUALCLASS_grayscale(vc) which returns true for StaticGray and GrayScale, false for the others. An `undecomposed' colormap maps pixel values to RGB triples, with each index's triple being settable independent of all others. (For StaticGray and GrayScale, which primary actually gets displayed is undefined, so, for writable colourmaps, the application should always store the same value for all three primaries.) A `decomposed' colormap breaks each pixel value up into three fields, one per primary, with a separate mapping table for each field. (When the three fields are the same size, this can be treated as if it were PseudoColor or StaticColor by using the same value for all three fields for each pixel value. That loses much of the potential colour richness of such hardware, though.) A Visual is characterized by an LX_XID (which is used to name it in requests such as CreateWindow), a screen number, a depth value, a visual class (see below), masks for red/green/blue for classes which have them (the members exist for all Visuals, but their values are undefined for other than TrueColor/DirectColor), a colormap size, and a bits-per-rgb value (see below for more). liblx collects these into an LX_VISINFO struct. The client receives the description of the available Visuals at connection startup time. liblx exports them to applications via lx_map_visuals(): lx_map_visuals -------------- int lx_map_visuals(LX_CONN *c, int (*cb)(void *, const LX_VISINFO *), void *arg) Calls (*cb)() for each available Visual, passing it arg and the LX_VISINFO pointer. If any such call returns a negative value, lx_map_visuals returns that same negative value immediately, without making any further callbacks. If no callback returns a negative value, lx_map_visuals returns the sum of the return values from all the callbacks. liblx promises that all the pointed-to LX_VISINFOs will exist until the LX_CONN in question is closed. Nothing is promised about what order the callbacks are made for the LX_VISINFOs, not even that the order used by one call bears any relation to the order used by another. Most of the values in an LX_VISINFO need no comment. But a few do call for more description. There is one member not described above: key. This is a small integer, such that the triple is a unique identifier for a visual. liblx does not promise that key values are tightly packed at zero, but it does promise that they are reasonably small; it is, for example, reasonable for an application to use them as array subscripts for a (per-) table of visuals. The mapsize value is the number of entries in a newly-created colormap. For decomposed visual classes, this is the size in bits of the largest of the three primary fields in a pixel value; for undecomposed classes, it is the size of the colormap mapping pixel values to RGB triples. The bits_per_rgb value is the number of significant bits in the values the colormap contains. (To put it another way, mapsize is the size of the colormap _input_ value; bits_per_rgb is the size of the colormap _output_ values.) As seen by the X client, colormaps always contain 16 bits for each primary, but only the bits_per_rgb most significant of those bits are actually meaningful.