Solaris X Window System Developer's Guide

Gamma-Corrected Visuals

The linearity attribute of a visual describes the intensity response of colors it displays. On a cathode ray tube (CRT) monitor, the colors displayed are actually darker than the colors requested. This darkening is caused by the physics of monitor construction. Some devices support visuals that compensate for this darkening effect. This is called gamma correction.

Gamma correction is done by altering colors coming out of the frame buffer with the inverse of the monitor's response. Because the overall intensity of a gamma-corrected visual is a straight line, a gamma corrected visual is called a linear visual; a visual that is not gamma corrected is called a nonlinear visual.

Linearity is not a standard X11 attribute for visuals. However, some applications require a linear visual to avoid visible artifacts. For example, a graphics application using antialiased lines may produce objectionable "roping" artifacts if it does not use a linear visual. This kind of application is called a linear application. An application requiring a nonlinear visual for best display of colors is called a nonlinear application. Most X11 applications are nonlinear applications.

On most devices, the linearity of default visuals is nonlinear. Therefore, linear applications should not depend on the default and should always explicitly search for a linear visual. Similarly, it is a good idea for nonlinear applications to explicitly search for a nonlinear visual. Since this is typically the default on most devices, it is not as critical, but it is still a good policy to do so.

To determine whether a visual is linear, applications can use the interface XSolarisGetVisualGamma(3). For more information on gamma correction, refer to Fundamentals of Computer Graphics by Foley and Van Dam.

Finding a Linear Visual

Linearity of a visual can be determined in Solaris by querying the visual's gamma. This is done by calling XSolarisGetVisualGamma(3). If the gamma value is equal to (or close to) 1.0, the visual is linear. Otherwise, it is nonlinear. A good rule-of-thumb for the closeness tolerance is 10%. To use the XSolarisGetVisualGamma API, the application must be linked with the Solaris libXmu.

Example 3-1 is an example of selecting the best visual for a typical XGLTM 3D linear application. In this example, the application uses a nonlinear visual if a linear one cannot be found. This is only one possible visual selection policy.


Note -

If the gamma of any visual on the device is changed, either through reconfiguration or calibration, the window system should be restarted. Otherwise, applications using XSolarisGetVisualGamma that are already running will not detect the change and may use the wrong visual.



Example 3-1 3D Linear Visual Selection

/*

** Returns the visual of the given depth, class and linearity, ** or NULL if

not found. */ Visual * match_visual (Display *dpy, int screen, int depth, int

class, 			 Bool wantLinear) {  XVisualInfo template;  XVisualInfo *vinfo, *vi;

 int nitems, isLinear, i;  double gamma;   template.screen = screen; 

template.depth = depth;  template.class = class;  if (!(vinfo =

XGetVisualInfo(dpy, VisualScreenMask |  			 	VisualDepthMask |

VisualClassMask,  				&template, &nitems)) || nitems <= 0) {

	return (NULL);  }   for (i = 0, vi = vinfo; i < nitems; i++, vi++) { 	if

(XSolarisGetVisualGamma(dpy, screen, vi->visual, &gamma) 		== Success)

{ 	 /* 	 ** A good rule of thumb for linearity of a visual is 	 ** whether the

gamma is within 10% of 1.0. 	 */ 	 isLinear = (gamma >= 0.9 &&

gamma <= 1.1); 	 if ((wantLinear && isLinear) || (!wantLinear

&& !isLinear)) { 		Visual *visual = vi->visual; 		XFree(vinfo);

		return (visual); 	 } 	}  }  XFree(vinfo); return (NULL);

}

Here is the main routine of the example:

main

() { 	Visual vis;  ...   if ((vis = match_visual(display, screen, 24,

TrueColor, True))) { 	fprintf(stderr, "Found a linear 24-bit TrueColor

visual\n"); 	visualClass = TrueColor; 	depth = 24; } else if ((vis =

match_visual(display, screen, 24, TrueColor,False))){ 	fprintf(stderr,

"Found a nonlinear 24-bit TrueColor visual\n"); 	visualClass =

TrueColor; 	depth = 24; } else if ((vis = match_visual(display, screen, 8,

PseudoColor,False))){ 	fprintf(stderr, "Found a nonlinear 8-bit

PseudoColor visual\n"); 	visualClass = PseudoColor; 	depth = 8; } else {

	fprintf(stderr, "Cannot match 24 or 8 bit visual\n"); 	exit(1); }

  ... }

Visual Selection Alternatives

The above code example illustrates only one possible visual selection policy. Other policies can be implemented. It is recommended that applications be written to handle a wide variety of visual configurations. Some devices, for example the GX, do not have any linear visuals. Other devices have only a single linear 24-bit TrueColor visual. Other types of devices may support both linear and nonlinear visuals at the same time. In general, the most prudent way to write a portable application is to deal gracefully with all these configurations. This may involve printing a warning message if the visual of the desired linearity is not found. Or, if a linear application cannot find a linear visual, a useful trick is to manually darken in the application the colors given to X11. This is tantamount to performing your own gamma correction. The gamma value returned by XSolarisGetVisualGamma can be used to determine how much to darken the colors.


Note -

XSolarisGetVisualGamma is a Public interface of Solaris and is fully supported. In the future, a color management system may also provide this functionality. When this occurs, this will become the preferred way of getting this information. But until then, XSolarisGetVisualGamma should be used. When this color management system is introduced, applications using XSolarisGetVisualGamma will continue to run with no modification and will actually benefit from the increased accuracy of the color managementsystem.