.\" refer -e -n -p vis.refs -s vis.nr | eqn | pic | psroff -ms .EQ delim $$ .EN .ds CH .de Ip .IP \(bu 3 .. .de Qp .nr PS -2 .nr VS -2 .QP .. .de Qe .nr PS +2 .nr VS +2 .. .de RQ .br .di .nr NF 0 .if \\n(dn-\\n(.t .nr NF 1 .if \\n(TC .nr NF 1 .if !\\n(NF .if \\n(TB .nr TB 0 .nf .rs .nr TC 5 .in 0 .ls 1 .if !\\n(TB \{\ . ev . br . ev 2 . KK .\} .ls .ce 0 .if !\\n(TB .rm KK .if \\n(TB .da KJ .if \\n(TB \!.KD \\n(dn .if \\n(TB .KK .if \\n(TB .di .nr TC \\n(TB .if \\n(KN .fi .in .ev .. .\" These macros should select a typewriter font if you have one. .de LS .LP .KS .LD .ft L .ta .6i 1.2i 1.8i 2.4i 3i 3.6i 4.2i .. .de LE .ft P .DE .KE .. .de Ls .nr PS -4 .nr VS -6 .LS .. .de Le .LE .nr PS +4 .nr VS +6 .LP .. .nr PO 1.25i .TL Visualizing X11 Clients .AU David Lemke David S. H. Rosenthal .AI Sun Microsystems 2550 Garcia Ave. Mountain View CA 94043 .AB The color model of version 11 of the X Window System exposes a number of aspects of the underlying display. The concept it uses to represent these device-dependencies is the .I Visual ; there may be several Visuals available on a given display. We present example programs to illustrate the techniques required if an X client is to operate correctly across the entire range of possible combinations of Visuals. .AE .LP .DS C Copyright \(co 1988, 1991 by Sun Microsystems, Inc.\s-2\u*\d\s0 .DE .FS * Permission to use, copy, modify and distribute this document for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies, and that the name of Sun Microsystems, Inc. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Sun Microsystems, Inc. makes no representations about the suitability of the software described herein for any purpose. It is provided "as is" without express or implied warranty. .br \(dg The X Window System is a trademark of the X Consortium. .br This paper was originally presented at the Summer 1988 Usenix Conference. There were some errors in this version, and subsequent developments have obsoleted parts of it, so it has been updated. .FE .LP .Qp ``The polymorphic visions of the eyes and the spirit are contained in uniform lines of small or capital letters, periods, commas, parentheses \- pages of signs packed as closely together as grains of sand representing the many-colored spectacle of the world on a surface that is always the same and always different, like dunes shifted by the desert wind.'' .sp Italo Calvino, \fISix Memos for the Next Millennium\fP .sp .25i .Qe .NH Introduction .LP A design objective of Version 11 of the X Window System\s-2\u\(dg\d\s0 .[ scheifler gettys transactions graphics 1987 .] is to make it possible to write client programs that operate correctly across a wide range of displays. This objective is often referred to as ``device-independence'', but this is something of a misnomer. X11 abstracts the properties of popular display types into an object called a .I Visual , and exposes to the client the existence of a number of Visuals. Visuals are divided into classes; each class representing the abstraction of a particular type of display hardware. .LP The implementor of an X11 server for a particular display must decide on the appropriate Visual classes to export to its clients. More than one Visual per screen may be exported to allow access to the full set of hardware capabilities. When a client connects to an X11 server, it must determine the Visuals the server is exporting and their classes, adapting its behavior to suit. Normally, this will involve the client choosing one of the Visuals, and changing appropriate initializations. .LP Simply adhering to the X11 protocol does not ensure that a client will operate correctly on all possible combinations of Visuals. The early X11 server implementations that were made available exported only a single Visual per screen, and these Visuals were of only two classes. As a result, many existing X11 clients operate correctly on single-Visual screens of these two classes, but not on others. .LP Among these not-really-device-independent clients are the .B xwd and .B xwud programs in the X11R3 distribution. They ``dump'' to a file, and ``undump'' from a file, the image of a window, but they don't work across all combinations of Visuals. In particular, they don't work: .Ip for TrueColor or DirectColor Visuals. .Ip if there are subwindows that have a different depth, Visual, or colormap. .Ip if the default colormap of the screen being dumped to doesn't mimic the colormap of the window being dumped. .LP We first review the Visual concept, and then present versions of the screen dump and undump clients that do work correctly across all Visuals. These clients are designed as teaching aids; they illustrate the techniques needed to make truly device-independent X11 clients, but they: .Ip are as simple as possible, and thus too inefficient for production use, .Ip ignore all the issues of interacting with window managers and other clients, .[ rosenthal communication conventions 1988 .] in the interests of clarity, .Ip and ignore our own advice about using a toolkit, .[ rosenthal hello world 1988 .] in order to focus on the underlying X11 mechanisms. .NH Visual Classes .LP An X client paints in a .I Drawable , a rectangular array of numbers called pixel values, using operations that alter the numbers, such as CopyArea and PolyLine. The only difference that affects the drawing process between one drawable and another is the .I depth , the number of bits in each of the numbers. The Visual concept is irrelevant to this process; a useful model is to think of CPU access to a display bitmap, with the monitor turned off (see Figure 1). .KF .DS .PS 3.5i 2.5i line from 5.237,4.825 to 6.175,6.325 line from 5.237,6.325 to 6.237,4.825 line from 2.275,5.788 to 2.175,5.763 to 2.275,5.737 line from 2.175,5.763 to 4.175,5.763 line from 4.075,5.737 to 4.175,5.763 to 4.075,5.788 line from 4.737,7.013 to 6.737,7.013 to 6.737,4.325 to 4.737,4.325 to 4.737,7.013 line from 4.175,8.012 to 7.175,8.012 to 7.175,3.325 to 4.175,3.325 to 4.175,8.012 line from 0.300,6.325 to 2.175,6.325 to 2.175,5.138 to 0.300,5.138 to 0.300,6.325 .ps 7 "Drawable" at 4.925,6.606 ljust "Memory" at 4.487,7.668 ljust "Pixel Values" at 2.387,5.918 ljust "CPU" at 0.925,5.731 ljust .PE .DE .DS C Figure 1: The X11 Drawing Process .DE .KE .LP Some Drawables are .I Windows , and these can be made visible by .I mapping them to the screen. When the client creates a Window, it must be assigned one of the possible Visuals for the screen; this Visual will control the process by which the Window's pixels become visible when it is mapped. A useful model is to think of video refresh access to a display bitmap, with the CPU halted (see Figure 2). .KF .DS .PS 3.5i 2.5i line from 6.612,5.763 to 7.112,6.888 line from 6.612,6.888 to 7.112,5.763 line from 0.988,5.075 to 1.988,7.075 line from 0.988,7.075 to 1.988,5.075 line from 3.612,7.325 to 4.862,7.325 to 4.862,5.263 to 3.612,5.263 to 3.612,7.325 line from 2.550,6.325 to 3.425,6.325 line from 3.325,6.300 to 3.425,6.325 to 3.325,6.350 line from 0.800,7.763 to 2.300,7.763 to 2.300,4.763 to 0.800,4.763 to 0.800,7.763 line from 5.925,6.325 to 6.425,5.575 line from 5.925,6.325 to 6.425,7.263 line from 6.425,7.263 to 7.237,7.263 to 7.237,5.575 to 6.425,5.575 to 6.425,7.263 line from 4.987,6.325 to 5.925,6.325 line from 5.825,6.300 to 5.925,6.325 to 5.825,6.350 line from 3.487,7.763 to 4.987,7.763 to 4.987,4.825 to 3.487,4.825 to 3.487,7.763 line from 0.550,8.075 to 2.550,8.075 to 2.550,4.513 to 0.550,4.513 to 0.550,8.075 .ps 7 "Colormap" at 3.737,7.106 ljust "Screen" at 6.512,7.106 ljust "Values" at 2.675,6.106 ljust "Pixel" at 2.675,6.481 ljust "RGB" at 5.112,6.418 ljust "Visual" at 3.550,7.543 ljust "Window" at 1.113,7.543 ljust "Memory" at 0.863,7.906 ljust .PE .DE .DS C Figure 2: The X11 Display Process .DE .KE .LP Conceptually, when a screen pixel is to be refreshed the top-most Window's corresponding pixel value is read, and used to index into a .I Colormap , an object containing three arrays (red, green and blue) of intensity values that models a video look-up table. The Visual for the window controls: .Ip How this indexing is done. .Ip Which of possibly many installed Colormaps is used. .Ip Whether and how the Colormap can be modified. .LP Visuals are divided into six classes, modeling six different types of display hardware. The classes, and their effects on the pixel value to visible color mapping, are: .Ip .I StaticGray . The pixel value indexes a predefined, read-only colormap. For each colormap cell, the red, green and blue values are the same, producing a gray image. .Ip .I StaticColor . The pixel values indexes a predefined, read-only colormap. The red, green and blue values for each cell are server-dependent. .Ip .I TrueColor . The pixel value is divided into sub-fields for red, green and blue. Each sub-field separately indexes the appropriate primary of a predefined, read-only colormap. The red, green and blue values for each cell are server-dependent, and are selected to provide a nearly linear increasing ramp. .Ip .I GrayScale . The pixel value indexes a colormap which the client can alter, subject to the restriction that the red, green and blue values of each cell must always be the same, producing a gray image. .Ip .I PseudoColor . The pixel value indexes a colormap which the client can alter. The red, green and blue values of each cell can be selected arbitrarily. .Ip .I DirectColor . The pixel value is divided into sub-fields for red, green and blue. Each sub-field separately indexes the appropriate primary of a colormap that the client can alter. .LP The early X11 server implementations provided two Visuals: .Ip Servers for monochrome displays exported a single StaticGray Visual of depth 1. .Ip Servers for color displays exported a single PseudoColor Visual of varying depth, typically 4 or 8. .LP These are the natural choices for simple workstation hardware, but they made it easy for initial clients to ignore many of the problems of dealing with Visuals. .LP Already, servers for common hardware such as the MIT sample server for the DEC QDSS display and the X11/NeWS .[ schaufler design overview 1988 .] server on Sun color hardware are exporting multiple Visuals. The QDSS server's default Visual is PseudoColor, but it also exports a StaticColor Visual. The X11/NeWS server's default is a StaticColor Visual, and it also exports a PseudoColor Visual. As X11 becomes available on more complex hardware, multiple Visuals will become increasingly common. .LP Many current X11 clients make unwarranted assumptions about their Visuals. Among the most common such assumptions\s-2\u\(dg\d\s0 .FS \(dg The technical term for these erroneous assumptions is .I bugs . .FE are: .Ip That the default Visual is the only available Visual. Clients making this assumption may fail even though a Visual that could have supported them was available. .Ip That all Visuals with more than two Colormap cells are color. Clients making this assumption will behave strangely on some StaticGray and GrayScale Visuals. .Ip That all Visuals with more than two Colormap cells have writable Colormaps. Clients making this (very common) assumption will fail with Xlib errors on StaticColor and TrueColor Visuals. .Ip That Colormaps (and especially the default Colormap) are infinitely large, so that attempts to allocate private cells in them will always succeed. .LP In fact, the only clients that can ignore the question of Visuals are those that use the .I BlackPixel() and .I WhitePixel() macros to paint a black and white image in the default Visual; this will work on all servers though the colors may not actually be Black or White. .I All other clients must pay some attention to the details of the Visual(s) they are using. To demonstrate how to deal with these details, we present versions of the screen dump and undump clients. .NH The ``dump'' Client .LP The objective of the screen dump client is to record the appearance of a specified rectangle of the screen so that it can be restored later, most likely on some other display device. Thus, the stored representation of the rectangle must be device-independent. The simplest possible device-independent representation is the red, green and blue (RGB) intensities of each pixel. .LP The only X11 protocol request that allows a client to read back the contents of a window is GetImage, so the dump client clearly must be based on it. From the point of view of the screen dump client, there are two problems with the specification of GetImage: .Ip It returns pixel values, not RGB values. Pixel values are not device-independent, and so cannot be used directly. .Ip Some of the values it returns may be garbage. .NH 2 Converting pixel values to RGB .LP To transform the returned pixel values to RGB intensities, the client must use the QueryColors request to look up the index in a specified Colormap. The Colormap to use will be given by the colormap attribute of the window in question. .LP The Visual to be used for this lookup is implicit. Since setting a window's colormap attribute to a Colormap that does not match the Visual of the window is an error, using the Colormap attribute of the window for the pixel value lookup implies using the correct Visual. .NH 2 Obtaining Correct Data from GetImage .LP The problem of GetImage returning garbage is described in the X11 protocol specification: .Qp ``If the window has a backing store, then the backing-store contents are returned for regions of the window that are obscured by noninferior windows; otherwise, the returned contents of such obscured regions are undefined. Also undefined are the returned contents of visible regions of inferiors of different depth than the specified window.'' .[ scheifler protocol 1988 .] .Qe .LP There are therefore two reasons why some of the returned pixel values may be wrong: .Ip They may be obscured by non-inferior windows, and the server may not be maintaining backing-store for the window. The backing-store attribute of a window is a hint to the server; there is no way for a client to discover whether the server is actually maintaining backing-store for any particular window at any particular time. .IP Thus, unless it can be determined that a pixel in a window is .I not obscured by a non-inferior window, that pixel value must be regarded as garbage. .Ip They may be in a visible region of an inferior of different depth. .IP Thus, unless the pixel in question can be shown .I not to be in an inferior of different depth, its value must be regarded as garbage. .LP In both these cases, at some cost, we can: .Ip unambiguously determine that a pixel value is good, .Ip assume that all others are garbage, .Ip and use GetImage on other windows to discover the correct values for these assumed-to-be-garbage pixels. .LP Unfortunately, there is a third reason why the pixels may be garbage: .Qp ``When no valid contents are available for regions of a window and the regions are either visible or the server is maintaining backing store, the server automatically tiles the regions with the window's background unless the window has a background of .B None . If the background is .B None , the previous screen contents from other windows of the same depth as the window are simply left in place if the contents come from the parent of the window or an inferior of the parent; otherwise, the initial contents of the exposed regions are undefined.'' .[ scheifler protocol 1988 .] .Qe .LP In other words, the pixels in areas whose top window has background .B None may not have been overwritten by any pixels drawn to the top window, they may simply have been left there when the window was mapped or exposed. .LP There is no way for a client to determine which pixels of a window have been updated by operations to that window (or its children). Thus there is no way to discover which pixels of a top window with background .B None are garbage, and even if there were there is no way to discover the correct pixel value or how to interpret it. The screen dump client simply has to live with the problem; its results cannot be guaranteed correct if any visible windows have background .B None . .LP There is one further problem. The protocol specification describes how a Pixmap or a single pixel value can be used as the border for a window. It does not specify which Visual and which Colormap are to be used to display these values. It appears that this is an oversight, and that the Visual and the Colormap of the window are to be used to display its border. The dump client assumes this. .NH 2 Dump Algorithm .LP We use the painter's algorithm, creating an array of pixels to hold the output, and painting the windows into it from the back forwards. .LP Each pixel in the output may be painted a number of times, but the last time it is painted will be by the window on top at that pixel. Since this last pixel painted is not overlaid, we are assured that the pixels returned by GetImage will be good (subject to the background .B None problem). .LP Here is an outline of the algorithm; the code itself is shown in Appendix A: .Ip Create a data structure with one entry per pixel in the specified rectangle, and an empty list whose entries represent Colormaps in use. Each entry in the list is itself the head of a list of pixel values in use with that Colormap. .Ip GrabServer to prevent changes to the window tree while all this is going on. .Ip Start at the root, and: .RS .Ip Use GetGeometry and GetWindowAttributes to find the details of the current window. .Ip If the current window is Viewable: .RS .Ip If the window's Colormap isn't in the list, create an entry describing it, and add it to the list. .Ip Use GetImage on the current window, and for every pixel in the returned array: .RS .Ip Label every corresponding pixel in the data structure with the pixel value returned by GetImage, and with this window's Colormap. .Ip If this is the first time we've seen this pixel value for this Colormap, use QueryColor to discover the RGB values that this window's Colormap maps the pixel value into, and store the pixel value and RGB in the list of pixel values in use for this Colormap. .RE .Ip Use QueryTree to find the list of children of the current window and recurse, starting with the head (bottom-most) of the list. .RE .RE .Ip UngrabServer, we're finished with it. .Ip Write to the output the width and height of the rectangle, and the number of pixel values we've added to the Colormap lists (this is an upper bound on the number of the distinct colors in the output). .Ip For each pixel in the data structure we built: .RS .Ip Find the list entry for the Colormap the pixel is labelled with. .Ip In the list of pixel values in use for that Colormap, find the pixel value the pixel is labelled with. .Ip Write to the output the RGB value stored for its pixel value in the list of pixel values in use for the Colormap. .RE .NH 2 Assessment of the Algorithm .LP This algorithm is about as simple as it can be while still getting the job done, but it causes much more protocol traffic than is strictly required. .LP By making the very pessimistic assumption that a pixel overlaid by .I any other window is potentially garbage, it asks the server to return the value of each of these pixels more often than is essential. A more efficient algorithm would only regard pixels overlaid by non-inferiors or inferiors of different depth as potential garbage. .LP Space consumption may also be a problem. There are potentially up to $ 2 sup 32 $ different pixel values, and we must retain a list of each pixel value in use for every Colormap. Fortunately, the list of values in use cannot get longer than the $ [ w ~ times ~ h ] $ of the specified rectangle (in the case where every pixel in the rectangle is different), and will normally be much less. .NH The ``undump'' Client .LP The objective of the screen undump client is to restore the appearance of the rectangle of the screen that was dumped earlier. It may not in fact be possible to do this, since the Visuals available to the undump program may not be capable of displaying all the colors in the original image. .LP The undump client has two main tasks: .Ip Choose an appropriate Visual and create a Colormap for it. .Ip Build an image in memory in which the RGB values have been converted to pixel values using the Colormap. .LP For each of these tasks, we review the general problem and then focus on the specific features needed for the undump client. .NH 2 Choosing a Visual .LP The server, during the connection handshake, provides the following information for each Visual on each screen: .Ip The depth. .Ip The Visual class. .Ip The masks that identify the red, green and blue sub-fields of the pixel value. .Ip The size (number of cells) of the Colormaps of the Visual. .Ip The number of bits in a red, green or blue value that the server will regard as significant. .LP There can be no general rules for choosing a Visual; a particular application might regard any of these pieces of information as the most important factor. For example: .Ip Clients which want to play Colormap tricks, such as colormap animation, need writable Colormap cells, and thus a dynamic Visual. For them, the class is the most important feature. .Ip Clients which require an exact color need a PseudoColor, DirectColor or TrueColor Visual. Other Visuals involve the server making an approximation to the requested RGB value. For these clients, the class is the most important feature. .Ip Clients that .I really care about the exact color will also be interested in the number of significant bits, which will tell them how closely the display can approximate the RGB value. .Ip Clients that require a certain number of colors to allow for contrast, but don't care about the exact colors, need a Visual with a Colormap large enough to hold the colors. For them, the Colormap size is the most important feature. .LP Xlib .[ gettys xlib 1988 .] provides two utility routines to make selecting a suitable Visual easier, using the .I XVisualInfo structure shown in Figure 3. .KF .Ls .ta 8n 16n 24n 32n 40n typedef struct { Visual *visual; VisualID visualid; int screen; int depth; int class; unsigned long red_mask; unsigned long green_mask; unsigned long blue_mask; int colormap_size; int bits_per_rgb; } XVisualInfo; .Le .DS C Figure 3: The XVisualInfo Structure .DE .KE .LP A client that simply wants to select a Visual of a given depth and class can use .I XMatchVisualInfo() . The client provides a depth and a Visual class, and an .I XVisualInfo structure describing one of the possibly many Visuals of that class and depth is returned. .LP A client that wants more detailed control over the selection of a Visual can use .I XGetVisualInfo() . The client constructs a template .I XVisualInfo structure, filling in the fields it is interested in. An array of .I XVisualInfo structures is returned, one for each Visual that matches the specified fields. For example, the code in Figure 4 will find all PseudoColor Visuals with 256-entry Colormaps. .KF .Ls .ta 8n 16n 24n 32n 40n 48n 56n { XVisualInfo vinfo_template, *vinfo_list; int num_matching_visuals; vinfo_template.class = PseudoColor; vinfo_template.colormap_size = 256; vinfo_list = XGetVisualInfo(dpy, VisualClassMask | VisualColormapSizeMask, &vinfo_template, &num_matching_visuals); if (vinfo_list == (VisualInfo *) 0) { /* No such Visuals */ } else { /* vinfo_list is an array of matches */ } } .Le .DS C Figure 4: Finding all 256-entry Colormap Visuals .DE .KE .LP In the case of the undump client, we have a problem that is more complex than either of these two simple cases. We have a set of RGB values that we wish to display as well as the available Visuals will let us. We have an upper bound .I N on the number of colors, but no other information about the colors\s-2\u\(dd\d\s0. .FS \(dd Scanning the RGB values could generate other information, such as that all the R, G and B values were equal in a gray image. Doing so would make the code, and the choice of a Visual too complex for a paper like this. .FE .LP Choosing a Visual capable of displaying .I N different RGB values takes four steps (the actual code is the routine .I FindVisual() in Appendix B): .Ip Rank the Visual classes in descending order of usability for our purposes: .RS .Ip TrueColor. A TrueColor Visual with large enough colormaps would be ideal for the dump client, since it would not merely represent the required RGB values, but it would not reserve private Colormap cells to do so. .Ip DirectColor & PseudoColor. These Visuals, if their Colormaps are big enough, can represent the RGB values we need, but to do so they have to reserve private cells, reducing the server resources available for other clients. .Ip StaticColor. A color Visual, even though we have no control over the color values, is likely to make a better approximation than a GrayScale Visual which cannot display colors at all. .Ip GrayScale. This Visual, if its Colormaps were big enough, could make a monochrome approximation to the image better than a StaticGray Visual in which we would have no control over the shades of gray. .Ip StaticGray. If there's nothing else, we'll have to make do with this. .RE .Ip Scan the list of Visuals returned by the server during the connection handshake, and for each Visual class record the Visual with the largest Colormaps. Of course, in the normal case, only a few of the classes will exist, and the others will be recorded as having a largest Colormap of size zero. .Ip In the rank order, look for the smallest Visual with colormaps big enough to display the required number of colors. If one is available, use it. .Ip Otherwise, use the Visual with the largest Colormaps. Since none of the maps are big enough to display all the colors, the server will doing some approximation, and the bigger the map the better the approximation. .LP Note that we look for the .I smallest Visual that will do the job. This will ensure that the client uses no more resources than required to get its job done. .NH 2 Converting RGB to pixel values .LP X provides three fundamentally different methods for converting RGB values to pixel values. A client can: .Ip Request the server to perform the conversion and return a pixel value. The result is to associate a sharable, read-only Colormap cell containing an approximation to the RGB values with the pixel value. .Ip Request the server to assign a writable Colormap cell and corresponding pixel value for the client's private use. The client can then set the Colormap cell to the RGB value. .Ip The client can predict the pixel value that will correspond to the RGB value, using its knowledge of the contents of the Colormap. .LP The choice of a suitable method depends on the requirements of the application and on the class of the Visual it is using. .NH 3 Server does conversion .LP The AllocColor request takes an RGB triple and a Colormap as an argument, and returns a pixel index that points to a Colormap cell containing the best approximation the server can make to that RGB value, and the actual RGB values that the cell contains. It does so by: .Ip If the Visual is static (StaticGray, StaticColor, or TrueColor), it returns the cell in the map that is closest to the request RGB value. .Ip If the Visual is dynamic, and the Colormap has free cells, the server will allocate an cell, mark it read-only, and set it to the requested RGB value. If there are no free cells, the request will fail. .LP This technique can be used by applications except those for which the .I exact representation of a color is of primary importance, or which use very large numbers of colors. The reasons for preferring this method are that it will work on any Visual, and that it makes the most efficient use of the server's resources. .LP Note, however, that since AllocColor returns a value, it requires a round-trip to the server and is therefore slow. Note also that AllocColor may fail, if the Visual is dynamic and there are no free cells in the colormap. If it does fail, the normal response is to move the client's allocated cells from the full colormap to a newly created one using CopyColormapAndFree. .NH 3 Client sets color .LP If the Visual is dynamic, clients can use AllocColorCells or AllocColorPlanes to reserve one or more pixel values for their private use. If the allocation succeeds, the pixel values will point to private, writable Colormap cells. The client can then use StoreColors to set the RGB values of these cells to exactly the values it desires. .LP This technique is more efficient than AllocColor, because a round-trip to the server is needed only for the initial allocation rather than every time a color is modified. However, it should be used only if it essential to the application because .Ip it will work only on a dynamic Visual, .Ip it consumes server resources that no other client can use until they are released, .Ip it can fail and measures must be taken to cope with this possibility. .LP In general, clients using this technique should create a private Colormap, perhaps using CopyColormapAndFree to preserve any pre-allocated cells. Ideally, the default Colormap for each Visual should be left for clients using the other techniques to maximize the sharing of resources. Unfortunately, the protocol defines a default Colormap only for the Visual of the root window. .NH 3 Client predicts pixel value .LP There are two circumstances in which a client can determine the pixel value corresponding to a given RGB value .I without a round-trip to the server. To do so, it must have knowledge of the contents of the Colormap: .Ip If the Visual is TrueColor, the Colormap is known to provide linear ramps in each primary color. The R, G and B values can thus be adjusted to the match the corresponding sub-field mask, and or-ed together to make the pixel value. .Ip If the Colormap is one of the set of ``standard'' Colormaps a similar calculation can be performed. Applications wishing to use one of these Colormaps look for a property describing it on the root window of the screen; if the property is not found the application creates a suitable Colormap and a property to describe it. .LP In particular, clients should find a property called RGB_DEFAULT_MAP on the root window of a multi-visual screen containing an array of XStandardColormap structures describing a default colormap for each visual, and the linear RGB ramps within it. They can use this to share colors with other applications on the screen; this is the preferred method for most clients. .NH 2 The Undump Algorithm .LP Here is an outline of the algorithm; the code itself is shown in Appendix B: .Ip Read in the width, height, number of colors & RGB values. .Ip Choose an appropriate Visual .Ip Create a Colormap for the chosen Visual. .Ip Create an image in memory to hold the pixel values that will eventually appear in the window. .Ip For each pixel in the data: .RS .Ip Convert the RGB values for the pixel into a pixel value, using the AllocColor request. .Ip Store the pixel value into the corresponding location in the image. .RE .Ip Create and map a window which uses the Colormap. .Ip Paint any exposed part of the window with the pixel values from the image. .NH 2 Assessment of the Algorithm .LP Once again, this algorithm is about as simple as it can be and still get the job done. As a result, it is grossly inefficient. It makes the pessimistic assumption that every pixel in the image is a different color, and calls AllocColor to convert its RGB values into a pixel value. Of course, it is likely that many pixels are the same color, and calling AllocColor only for every distinct color would reduce the traffic considerably. .LP One problem is that this client creates its own Colormap. If the default Colormap mechanism worked for multiple Visuals, we could have used the appropriate default Colormap. Ideally, clients should share Colormaps to improve the chance they will appear in their correct colors. We should have used the RGB_DEFAULT_MAP or RGB_BEST_MAP properties to share a Colormap with other similar clients. .LP The client will work on every Visual type, in most cases providing the best match available for the colors in the image. There is, however, one case in which the match will be less than optimal. If the Visual is PseudoColor and is too small to accommodate the number of colors in the image, the first colors encountered in the right-to-left within top-to-bottom scan of the image will get exact colors as new read-only cells are allocated by AllocColor. At some point, the map will fill up, and the next AllocColor call will fail. Since we found the largest visual, there is nothing to do but give up. .LP The Visual selection process has two problems. For the TrueColor and DirectColor cases, it pessimistically assumes that all the distinct colors in the image differ only in one component, and will thus overestimate the size of the Colormap required. For example, suppose we have a blue image with 24 distinct colors; all 24 have the same Red and Green values, differing only in their Blue value. We would need a Colormap with 24 entries for Blue, but only 1-entry maps for Red and Green. In practice, it is likely that the color distribution will be more even and smaller maps would suffice. .LP Further, it is complicated by the fact that the number of distinct colors is only an upper bound. Consider a dump of a screen with an 8-bit PseudoColor Visual and a 1-bit StaticGray Visual. Assume that the image in the PseudoColor Visual had 256 different colors, two of which were white and black. The dump client would not realize that the white and black of the StaticGray Visual were the same as the white and black of the PseudoColor Visual and would record the number of colors as 258. Undumping to the same display, it would regard the PseudoColor Visual as inadequate to represent the 258 colors. .LP Better analysis of the set of RGB values to be displayed would solve both problems, but would make the program too complex for this paper. .NH Visuals and the Toolkit .LP The attention paid by the X Toolkit Intrinsics to the problem of specifying Visuals is evident from the fact that the word Visual does not appear in the index to the first version of the Intrinsics manual. .[ toolkit intrinsics 1988 .] In R4, this was remedied. .[ asente swick 1990 .] .LP The Window for a Widget is created during the process of .I realizing the Widget, and the Visual to use has to be selected as part of this process. Different Widget classes will differ as to how they choose a Visual. All Athena Widgets use CopyFromParent as their Visual selection, deferring the choice to their parent. The root of the Widget tree is a so-called Shell Widget, which in the Intrinsics implementation itself by default inherits its Visual from its parent, in this case the root. From R4 on, Shell widgets have a XtNvisual resource than can be used to specify the visual to be used by widgets within the shell's tree. .LP The core information, which all Widgets possess, includes a Colormap. For the Athena Widgets, this had better be a Colormap from the root's Visual, or Xlib errors will occur. This Colormap is used to convert RGB values to pixels for the Widget, using the AllocColor technique. One might think that it would be possible to realize a Widget in a Visual other than the root's by giving it a Colormap from that Visual, but this will not work. .LP A Widget class that needed some Visual other than its Shell's would have to implement its own realize procedure, and make the choice there. The choice algorithm would be the same for all instances of the Widget, but this does not mean that all instances would have to have the same Visual. This sounds onerous, but it is in fact the correct approach. As we showed above, the algorithm for choosing an appropriate Visual is application-specific; it would not be possible to wire-in to the Intrinsics a single algorithm that would satisfy everyone. .NH Conclusion .LP The X11 color model provides powerful access to the capabilities of different types of display hardware. Used carelessly, this access can lead to programs which run only in the environment in which they were developed. .LP All but the simplest X11 clients must take care to choose the most suitable Visual for their purposes, and to adapt their behavior to its capabilities. We have presented the techniques for doing so for a simple application, but more complex applications will require a wider range of techniques. More work is needed to develop these. .SH Acknowledgements .LP Thanks are due to James Gosling, who helped to develop our understanding of these issues, and who designed the multi-Visual and Colormap capabilities of the X11/NeWS server, to Jeff Vroom, who spotted the problem of the default colormap, to Bob Scheifler, who clarified several obscure points, and to the Usenix reviewers. .[ $LIST$ .] .SH Appendix A: Dump Program .LP .Ls .ta 8n 16n 24n 32n 40n 48n 56n 64n .so xsd.c .Le .SH Appendix B: Undump Program .LP .Ls .ta 8n 16n 24n 32n 40n 48n 56n 64n .so xsud.c .Le