.de Ip .IP \(bu 3 .. .\" These macros should select a typewriter font if you have one. .de LS .KS .DS .ft C .. .de LE .ft P .DE .KE .. .TL Godzilla's Guide to Porting the X V11 Sample Server .sp March 1, 1988 .sp Updated for R4: April 12, 1990 .AU David S. H. Rosenthal .AI Sun Microsystems .AU Adam R. de Boor .AI University of California at Berkeley .AU edits by Bob Scheifler .AI Massachusetts Institute of Technology .AU Updated for R4 by Keith Packard .AI MIT X Consortium .AB .LP For hackers in a hurry, here's how to do a quick-and-dirty port of the X V11 sample server to memory-mapped monochrome & color frame buffers. The authors disclaim responsibility for damage to the environment during this process. .AE .QP ``Did I \- ?'' .QP ``I told you you could,'' [Obi-Wan] Kenobi informed him with pleasure. ``Once you start to trust your inner self, there'll be no stopping you.'' .DS C Star Wars, \fIGeorge Lucas\fP .DE .sp 2 .DS C Copyright \(co 1987 by Sun Microsystems, Inc.\s-2\u1\d\s0 .DE .DS C Copyright \(co 1990 X Consortium\s-2\u1\d\s0 .DE .FS 1. Permission to use, copy, modify, distribute and sell 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 names of Sun Microsystems, Inc. and M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Sun Microsystems, Inc. and M.I.T. make no representations about the suitability of the software described herein for any purpose. It is provided "as is" without express or implied warranty. .FE .sp 2 .NH Introduction .LP In two independent efforts, we ported the first alpha release of X V11 to monochrome Sun hardware. The results of these efforts were merged together, incorporated into the second alpha release, and delivered to MIT for distribution. We went on to port the second alpha release to a number of Sun 8-bit memory-mapped color displays, and we contributed this code to the beta releases. .LP With future releases, the internal structure of the server changed, and porting efforts have to be modified as well. No attempt has been made to isolate the porting efforts from the changes between various versions of the server. This document focuses on Release 4 of the MIT Sample Server. .LP Based on this experience, we present a guide for others attempting to port X V11. Our goal is to enable them to get the server up and functional as expeditiously as possible. We address only ``initial'' ports, using the \fIserver/ddx/mfb\fP, \fIserver/ddx/cfb\fP and \fIserver/ddx/mi\fP code to drive a dumb memory frame buffer. .LP It is possible to port X V11 to dumb frame buffers very quickly, even without a detailed understanding of the internals of the server. We give instructions on how to do this, and then go on to cover some of the internals that will be important in doing a more complex port, and in performance tuning. We do \fInot\fP cover the following areas in detail: .Ip Porting to operating systems other than 4.2 or 4.3 BSD. .Ip Driving ``intelligent'' display hardware. .Ip Supporting input devices other than the mouse and keyboard. .Ip Performance tuning the system. .LP This document refers to the fourth full X V11 distribution from the MIT X Consortium. .NH Raw Materials .LP The server source code is organised into a number of directories: .IP ddx 8 The code for driving displays, keyboards, mice, and other peripherals. .IP dix 8 The machine independent code implementing the protocol interpreter and resource managers. .IP include 8 The \fI.h\fP files defining the machine independent data structures for the server. .IP os 8 The code implementing the server's file and inter-process I/O, which depends on the operating system. .LP In the \fBddx\fP directory, there are the following directories: .IP mfb 8 The ``monochrome frame buffer'' driver. This is intended to be a machine independent driver for 1-bit deep memory mapped displays. .IP mi 8 The ``machine independent'' driver. This is intended to be a machine independent (but slightly incomplete) driver for \fIany\fP frame buffer. .IP cfb 8 The ``color frame buffer'' driver. This is intended to be a machine independent driver for \fIn\fP-bit deep (\fIn\fP <= 32) Z-Format memory mapped displays. While much of this code is portable to arbitrary depth displays, release 4 provides a fast implementation only for the 8-bit case. .IP ... There are several directories which are specific to a particular vendor and contain minimal code for talking to that hardware. In the \fBos\fP directory, there is at present only the following directory: .LP The only subdirectory in the \fBos\fP directory is: .IP 4.2bsd 8 An implementation of the file and interprocess primitives for the server using the facilities of 4.2 and 4.3 BSD. This code also works on various SYSV-BSD blends (A/UX, HPUX etc) but no attempt has been made to get it working in a generic SYSV environment. .LP The intent is that one should port the sample server to new hardware by using the \fImi\fP code, implementing at first only the lowest level routines such as \fBFillSpans(\|)\fP. We did not do so for our initial monochrome ports (the \fImi\fP code was too incomplete), instead we used the \fImfb\fP code. Our subsequent color ports were based on \fImi\fP and we describe both. The current release relies on \fIcfb\fP heavily as much of \fImi\fP is only interesting from an academic viewpoint. .LP The details of server internals you need to know to do this, and more advanced ports, are described in a document (the \fIPorting Layer\fP) written by the DEC team that developed it.\s-2\u2\d\s0 .FS 2. \fIThe Porting Layer for the X V11 Sample Server\fP, by Susan Angebranndt, Raymond Drewry, Phil Karlton and Todd Newman. See the file \fIdoc/Server/ddx.doc.tbl.ms\fP. .FE You should read this document even for a simple monochrome or color port, a complete understanding isn't important, but a better understanding of the basic porting process will result from even a cursory perusal. We refer to it frequently when more details are needed. .NH Road Map .LP In order to get the sample server running on your hardware, you will need to deal with four distinct areas: .IP a) Painting the Bits \- you need to make the code work for the mapping between pixel coordinates and byte/bit addresses defined by your hardware. .IP b) Pounding the Keys \- you need to map between the keystrokes and mouse movements your hardware provides, and the canonical forms required by the server. .IP c) Dragging the Cursor \- you need to move a cursor image around the screen, and change the image on demand. .IP d) Starting Up & Shutting Down \- you need to initialize and close down the connections between the server and your hardware. .NH Doing the Port (Monochrome and 8-bit color) .LP Lets suppose you want to port X V11 to the Generic Workstation Company's (GWC) hardware. You can do most of the work in one fell swoop: .LS #!/bin/sh cd server/ddx/sun mkdir ../gwc sed -e 's/sun/gwc/g' Makefile >../gwc/Makefile for A in *.[hc] do sed -e 's/sun/gwc/g' $A >../gwc/gwc`expr $A : 'sun\e(.*\e)'` done .LE .LP You now have a directory in the right place with a first approximation to the source files in it. It will avoid confusion if you remove all code in this directory between .LS #ifdef SUN_WINDOWS #endif SUN_WINDOWS .LE This deals with running X V11 ``on top of'' the SunWindows window system, and is of no interest here. .LP The next steps tackle the four major areas in which GWC's workstations are different from Sun's. .NH 2 Painting the Bits .LP Assuming that you have a machine which has a simple memory bitmap, all you have to do to ensure that the pixels are painted correctly is to deal with the potential differences between simple memory bitmaps. The files \fIserver/include/servermd.h\fP and \fIfonts/bdftosnf/bdftosnf.h\fP contain the definitions for the various CPUs which already support the sample server. You will need to add #ifdef sections after the others in each file which contains the following definitions. .Ip Byte order. Both the \fImfb\fP and \fIcfb\fP code can handle either byte order. If you have a 68000 CPU (Big Endian), the file \fIserver/include/servermd.h\fP should contain: .LS #define IMAGE_BYTE_ORDER MSBFirst .LE If you have a 80386 GWC, \fIserver/include/servermd.h\fP should contain: .LS #define IMAGE_BYTE_ORDER LSBFirst .LE .Ip Pixel order. Again, both the \fImfb\fP and \fIcfb\fP code can handle either the 68000 style, where the most significant bit is to the left on the scan line, or the 80386 style, where the least significant bit is to the left on the scan line. For the 68000 GWC, the file \fIserver/include/servermd.h\fP should contain: .LS #define BITMAP_BIT_ORDER MSBFirst .LE .IP And the file \fIfonts/bdftosnf/bdftosnf.h\fP should contain: .LS #define DEFAULTBITORDER MSBFirst .LE For the 80386 GWC, the file \fIserver/include/servermd.h\fP should contain: .LS #define BITMAP_BIT_ORDER LSBFirst .LE .IP And the file \fIfonts/bdftosnf/bdftosnf.h\fP should contain: .LS #define DEFAULTBITORDER LSBFirst .LE .Ip Pixel meaning. Some machines have monochrome displays where a 1 bit means black, while others ones have displays where a 1 means white. Check the manual, and set the appropriate values in the file \fIserver/ddx/gwc/gwcBW2.c\fP: .LS pScreen->whitePixel = 0 or 1; pScreen->blackPixel = 1 or 0; .LE .Ip Alignment restrictions. CPUs vary in the alignment restrictions they place on memory accesses. For example, some can do 4-byte accesses at every byte address, and some only at 4-byte boundaries. In general, the \fImfb\fP and \fIcfb\fP code take the conservative viewpoint that the framebuffer and memory bitmaps are accessed only 4 bytes wide at 4-byte boundaries. .IP However, this isn't true of the font code. For Sun hardware, we decided to extend the same restriction to the font code, and changed the padding rules used for the fonts to avoid those cases in which the \fImfb\fP and \fIcfb\fP code would use addresses that weren't 4-byte aligned. We will cover the padding rules in some detail later; for the moment all you need to do is to include in the file \fIfonts/bdftosnf/bdftosnf.h\fP: .LS #define DEFAULTGLPAD 4 .LE while \fIserver/include/servermd.h\fP should have .LS #define GLYPHPADBYTES 4 .LE .IP .LP The \fImfb\fP, \fIcfb\fP and \fImi\fP directories are now set up for your machine. The next steps are more work. .NH 2 Pounding the Keys .LP More frequently than you would believe possible, the DIX layer will call the function \fBProcessInputEvents(\|)\fP. This function lives in \fIgwcIo.c\fP, and you will be able to use it almost unchanged. It has to: .Ip Obtain the device-specific events from the keyboard and the mouse, by calling through their private descriptor structures to a device-specific \fBGetEvents\fP routine. .Ip In time-stamp order, hand each event to the appropriate \fBProcessEvents\fP routine, again calling through the private descriptor structure for each device. .Ip Maintain the time of the last event. .Ip Restore the screen if it is currently saved. .LP Only the first of these requires modifications to the code you now have, and these take place in the files \fIgwcKbd.c\fP and \fIgwcMouse.c\fP .LP Each device has a \fBGetEvents\fP routine; it needs to return an array containing the device-specific events that are immediately available. The precise structure of the events is not important, but they need to be time-stamped by the kernel. The declarations in \fIgwcIo.c\fP, \fIgwcKbd.c\fP and \fIgwcMouse.c\fP of things as pointers to \fBFirm_events\fP should be changed to \fBgwc_events\fP, the name of the structures the GWC kernel returns. .LP To obtain the events, you can either do a non-blocking \fBread(\|)\fP or use a shared-memory circular queue of events, if your kernel supports it. The \fIserver/ddx/sun\fP code supports only non-blocking reads, since current Sun kernels do not have a shared-memory event queue. You are strongly urged to add support for a shared-memory event queue to the GWC kernel, since doing the non-blocking \fBread(\|)\fPs is a serious performance problem. .LP For the present, we assume that the GWC kernel has separate \fI/dev/mouse\fP and \fI/dev/kbd\fP files, which: .Ip Support the \fBfcntl(FNDELAY)\fP call. .Ip Provide a stream of \fBgwc_event\fP structures containing position, keycode, and timestamp information. .LP In \fIgwcMouse.c\fP, you will need to change only the names of the fields in the device-specific event structures, from those of the \fIFirm_event\fP to those of the \fIgwc_event\fP, and the values of the ID codes (such as MS_LEFT) used for the button and motion events. If you have one of the GWC mice that reports absolute positions rather than X and Y deltas, you will need to add another case to the following statement. .LS switch (fe->id) { case MS_LEFT: case MS_MIDDLE: case MS_RIGHT: case LOC_X_DELTA: case LOC_Y_DELTA: default: } .LE Beware of the Sun convention that motion up gives a positive Y delta. .LP In \fIgwcKbd.c\fP, you will need to make similar changes to the names of the event fields. Then, replace the various \fBioctl(KIOC)\fP calls with their GWC equivalents Their meanings are: .TS center, box; c c l l. Name Operation _ KIOCTYPE T{ Get int indicating keyboard type T} KIOCGTRANS T{ Get/set keycode translation. We want ASCII events. T} KIOCSDIRECT T{ Switch keystrokes between \fI/dev/kbd\fP and \fI/dev/console\fP. We want \fI/dev/kbd\fP. T} .TE .LP Now, you have to establish a mapping between the codes your keyboard sends and the names X V11 uses for keys (the so-called \fIkeysyms\fP). Read the files \fIserver/ddx/gwc/gwcKeyMap.c\fP and \fIX11/keysym.h\fP. Look at your keyboard manual, and find the lowest keycode it sends (\fIkcmin\fP) and the highest keycode it sends (\fIkcmax\fP). Look at the keyboard itself, and find the key with the largest number of symbols on it, counting strings like ``Return'' or ``F9'' as one symbol. The number of symbols on this key is the \fIwidth\fP of the keyboard. Now, for each of your keyboard types, you will need two things in \fIgwcKeyMap.c\fP: .Ip A \fIkeymap\fP, which is an array with (\fIkcmax\fP-\fIkcmin\fP+1) rows and \fIwidth\fP columns. Each row in the array should contain the keysyms corresponding to the symbols on the keycap, with the first column containing the symbol generated when the key is un-shifted, the second the symbol generated when the key is shifted, and the other columns the other symbols in no special order. So, for example, a key with the symbols ``1'' and ``!'' on it would have the keysyms \fIXK_1\fP and \fIXK_exclam\fP in the table. .Ip A \fImodifier map\fP, which is an array with one entry per keycode. Each entry should contain the modifier bits that are set when that key is down. So, for example, a ``Shift'' key would have an entry \fIShiftMask\fP. .NH 2 Dragging the (Software) Cursor .LP Suns use a software cursor, as there is no cursor hardware. The problem with is that it must be removed from the display before painting operations that might affect the pixels it is using. And, of course, put back again at some time later. .LP Fortunately, a machine-independent software cursor layer is included in \fIserver/ddx/mi\fP which is easily connected to the mouse device. It will work on any display, but it is a little slow, and you will want to use the hardware cursor on machines that have it. The changes needed to do so are fairly extensive, so we cover them later also. .NH 2 Starting Up & Shutting Down .LP When the server is started, it initializes its output and input devices by calling their initialization procedures. This is where things get really device-specific, and the code for the GWC will differ significantly from the Sun code. The overall structure will be preserved, however. .LP It is important to observe that, once the last client has closed its connection and everything has been shut down, the server will re-initialize everything by repeating the process. Although there is a close-down procedure, it is generally better to avoid closing the device, instead simply reset it to its initial state. So if, for example, initializing a display or a mouse involves opening a file, the descriptor should be remembered in a static structure and not re-opened if it is already open.\s-2\u4\d\s0 .FS 4. See section 2.4.3 of the \fIPorting Layer\fP. .FE .NH 3 Output .LP Output devices are initialized in a two-step process: .Ip The server calls \fBInitOutput(\|)\fP, a routine in \fIgwcInit.c\fP which you can re-use untouched. It calls each potentially available display's probe routine, finding the probe routine and the probable file name for it in the \fBgwcFbData[\|]\fP array. .IP The dumb monochrome device, whose driver is in \fIgwcBW2.c\fP, has a probe routine called \fBgwcBW2Probe(\|)\fP. This has to attempt to initialize the monochrome display and, if it succeeds, fill out the \fBfbFd\fP structure describing it. In the Sun case, most of the work is done in a routine \fBsunOpenFrameBuffer(\|)\fP in \fIsunInit.c\fP, because it is common among all Sun framebuffers. This routine scans the command-line arguments, the environment, and the \fI/dev\fP directory to find a frame-buffer of the required type, opens it, and returns the file descriptor. .IP The dumb color device, whose driver is in \fIgwcCG3.c\fP, is similarly structured, the probe is called \fIgwcCG3Probe(\|)\fP. .IP The probe routines then have to map this descriptor into the server's address space, and install a pointer to the pixels in the \fBfbFd\fP structure. Note that the Sun monochrome code has to deal with two different sizes of monchrome framebuffers. The \fBfbFd\fP structure is the static structure we mentioned earlier, needed to preserve internal driver information across server re-initializations. Finally, it calls \fBAddScreen(\|)\fP, giving it the address of the BW2/CG3 initialization routine. .Ip \fBAddScreen(\|)\fP fills out the screen information, and calls the initialization routine. In the monochrome case, \fBmfbScreenInit(\|)\fP is called to initialize the \fImfb\fP part of the code. This fills in the \fBScreen\fP's operations vector with the routines the \fImfb\fP code supports. The remaining entries are filled out by the initialization routine itself. This code can be reused unchanged. The color case simply uses \fBcfbScreenInit(\|)\fP. Note that in the color case the values for whitePixel and blackPixel are left unspecified. \fIcfb\fP will fill in the values 0 for white and 1 for black. If this is not satisfactory, replace them with your own values after calling \fBcfbScreenInit\fP and before calling \fBcfbCreateDefColormap\fP. .LP When the server is shutting down prior to re-initialization, it will call the \fBCloseScreen\fP function in the \fBScreen\fP structure. You can also use this routine unchanged. .LP One other area which needs attention are the \fBgwcBW2SaveScreen(\|)\fP and \fBgwcCG3SaveScreen(\|\)\fP routines. These need to enable and disable the video for the GWC framebuffer. .NH 3 Input .LP A similar two-step process is used to initialize the input devices. First, the server calls \fBInitInput(\|)\fP, in \fIgwcInit.c\fP. It registers the keyboard and mouse devices by calling \fBAddInputDevice(\|)\fP, among the arguments to which are the appropriate initialization/closedown routines \fBgwcMouseProc\fP and \fBgwcKbdProc\fP. .LP Then, the server calls each of the device initialization/closedown routines twice, once with command \fBDEVICE_INIT\fP and once with command \fBDEVICE_ON\fP. These must: .Ip Open the necessary devices. .Ip Set up the appropriate keymaps. .LP When the server is shutting down prior to re-initialization, it will call the device's initialization/closedown routine with command \fBDEVICE_OFF\fP. .LP Except for the details of how the devices are opened and coerced to supply ASCII events, and the changes made earlier to the \fBioctl(\|)\fPs, the rest of this code can be used unchanged. .NH 2 Tidying Up .LP You have now made all the major changes needed. All that remains is to make suitable changes to the makefiles: .Ip In \fIserver/Imakefile\fP, make the following changes: .KF .LS ALLDDXDIRS = \fIwhatever is already there\fP ddx/gwc GWC = ddx/gwc/libgwc.a ALLPOSSIBLE = \fIwhatever is already there\fP Xgwc #ifndef XgwcServer #define XgwcServer /* as nothing */ #endif ALL = \fIwhatever is already there\fP XgwcServer # # GWC server # GWCDIRS = dix ddx/snf ddx/mi ddx/mfb ddx/cfb ddx/gwc os/4.2bsd GWCOBJS = ddx/gwc/gwcInit.o GWCLIBS = $(GWC) $(CFB) $(DIX) $(SNF) $(UNIX) $(MFB) $(MI) $(EXTENSIONS) GWCSYSLIBS = $(SYSLIBS) XgwcDIRS = $(GWCDIRS) ServerTarget(Xgwc,$(EXTDIR) $(GWCDIRS),$(GWCOBJS),$(GWCLIBS),$(GWCSYSLIBS)) .LE .DS C .I Figure 1: Top-level Imakefile Changes .R .DE .KE .Ip Now go ahead, make everything, and enjoy! .LP There are probably some details we've omitted \- we no longer have our GWCs so we're writing this from memory. If you find either the details or the hardware, please let us know. .NH Additional work needed for doing a Color Port on non 8-bit displays. .LP After the \fImfb\fP-based monochrome drivers were shipped to MIT, we went on to develop drivers for Sun's color hardware. Our initial attempt was based on the \fImi\fP code. Our goals were: .Ip To get the server functional on color hardware as expeditiously as possible. .Ip To test the color code in \fIserver/dix\fP, and as much as possible of the code in \fIserver/ddx/mi\fP. .Ip To test the recommended porting strategy, using \fImi\fP and implementing only \fBGetSpans(\|)\fP, \fBSetSpans(\|)\fP and \fBFillSpans(\|)\fP. .Ip To provide a highly portable implementation of the DDX layer for color hardware to enable others to get the server running as effortlessly as possible. .LP Performance was explicitly not a goal. Just as \fImfb\fP assumes that the display it is driving has a 1-bit deep memory framebuffer accessed 32 bits wide at 32-bit boundaries, \fIcfb\fP assumes a \fIn\fP-bit deep (\fIn\fP\ <=\ 32) memory framebuffer accessed 32 bits wide at 32-bit boundaries. While these restrictions are fairly onerous, they make the code highly portable in both cases. In the monochrome case, the DEC team managed to provide relatively good performance. In the color case, there is \fIn\fP times more work to do, and we have not attempted all of the optimizations that \fImfb\fP uses. .NH 2 Porting cfb to non-8 bit framebuffers .LP By default, \fIcfb\fP is set up to drive a framebuffer that is 8 bits deep with the pixel order defined by \fBBITMAP_BIT_ORDER\fP. If your framebuffer is different, you will need to change some parameters in \fIserver/ddx/cfb/cfbmskbits.h\fP: .TS center, box; c s s s c c c c l n n l. Parameters in cfb _ Parameter mfb cfb Comment _ PPW 32 4 pixels per word PLST 31 3 last pixel in a word (should be PPW-1) PIM 0x1f 0x03 pixel index mask (index within a word) PWSH 5 2 pixel-to-word shift PSZ 1 8 pixel size (bits) PMSK 0x01 0xFF single-pixel mask .TE .LP Read the comments in \fIcfbmskbits.[hc]\fP carefully before changing these parameters. You will also need to change the mask values in \fIserver/ddx/cfb/cfbmskbits.c\fP. .LP Changing these parameters and masks is all you should need, but we cannot be sure. The code has been used on several types of color hardware, but in each case there are four pixels to the word (and, therefore, the masks don't need changing). .NH 2 Using cfb .LP The code in \fIserver/ddx/sun/sunCG4C.c\fP illustrates how to use \fIcfb\fP to drive an 8-bit deep memory frambuffer (the usage on non 8-bit deep frame buffers is identcal but no example code exists). You call \fBcfbscrinit(\|)\fP to fill out the screen operation vector, and \fBcfbCreateGC(\|)\fP to create a GC. In both cases, reading the code will show that most of the procedures to be used are from \fImi\fP. .LP Unlike \fImfb\fP, which effectively supports only a StaticGray visual, the \fIcfb\fP code supports all 6 possible visual types if your hardware has writeable color maps. Otherwise, (or for testing purposes) you can define \fBSTATIC_COLOR\fP and support a StaticColor visual (which also limits the supported visual types to StaticColor and TrueColor). .NH Details .LP This section is not intended to be a complete survey of the details of the server. We wouldn't claim enough knowledge to write that (yet). It is rather a collection of comments on the areas we have had to deal with in detail, in the hope that we can save others from wasting their time on problems that are either already solved or insoluble. .NH 2 Software & Hardware Cursors .LP The details of the DIX interface to the cursor support are described in section 2.5 of the \fIPorting Layer\fP. .NH 3 Software Cursors .LP The Machine Independent software cursor code is very easy to use and it provides reasonable performance. It works by "wrapping" every potential drawing operation to the screen and checking for overlap with the cursor during these operations. The \fIPorting Layer\fP describes this "wrapping" notion in greater detail. .NH 3 Hardware Cursors .LP To switch to using a hardware cursor, you will need to study the QVSS code,\s-2\u12\d\s0 .FS 12. See the files \fIserver/ddx/sun/sunCursor.c\fP and \fIserver/ddx/dec/qvss/qvss_io.c\fP, and section 2.5 of the \fIPorting Layer\fP. .FE and to remove the following code from the \fIserver/ddx/sun\fP files: .Ip \fIsunInit.c\fP: the code that calls miDCInitialize .Ip \fIsunMouse.c\fP: the code in \fBsunMouseProcessEvent(\|)\fP that positions the software cursor. .NH 2 Fonts & Padding .LP The \fIPorting Layer\fP describes the layout of the glyph information in memory as follows:\s-2\u13\d\s0 .FS 13. See section 5.3. .FE .QP ``Each scanline of each glyph is padded to a byte boundary with zero bits. Bit and byte order is whatever is natural for the server. (Note: the current BDF to SNF font compiler handles either bit order within a byte as a compile time option. It does not deal with byte order.) The glyph for a character whose XCHARINFO is ci begins at cg[ci.byteOffset]. Glyphs may begin at arbitrary offsets within the array.'' .LP The section on ``Alignment'' describes the problem:\s-2\u14\d\s0 .FS 14. See section 4.5.2. .FE .QP ``The mfb text code might access mis-aligned longwords; this is not a problem on VAXes, 680x0 (x != 0), or Intel architectures, but might be on some as yet unknown processors, and is definitely bad on a 68000. An easy fix is to have the font compiler generate longword padded glyphs instead of byte-padded ones.'' .LP We followed this advice, and the results are incorporated in the Sun code in the release. The trade-offs to consider when deciding what to do are: .Ip Many processors cannot access mis-aligned longwords.\s-2\u15\d\s0 In these cases, there is no real choice. .FS 15. Try it on a 68010 sometime, or on a PC/RT, or on a SPARC, or .... .FE .Ip Even processors which can access longwords at byte boundaries do so more slowly than aligned accesses, and these accesses are made in a performance-critical area (painting characters). Check your hardware manual, or write a small benchmark. Furthermore, the font code for big-endian machines is always slower when using non-longword padded fonts as it must shift things around. .Ip On the other hand, padding the glyphs to longwords wastes a significant amount of space. .LP If you'd like to pack fonts even on machines which can't access longwords on non-longword boundaries, then, in the file \fIserver/include/servermd.h\fP, choose the alignment restriction (in bytes) for those accesses: .LS #define GETLEFTBITS_ALIGNMENT 1 /* arbitrary byte alignment */ #define GETLEFTBITS_ALIGNMENT 2 /* halfword alignment */ #define GETLEFTBITS_ALIGNMENT 4 /* longword alignment */ .LE .LP If you are using GLYPHPADBYTES 4, make sure you set GETLEFTBITS_ALIGNMENT to 1 even if your CPU can't access longwords on non-longword boundaries. This is because the text code would use extra instructions to check the alignment of the accesses even though the fonts are guaranteed to be longword aligned. .NH 2 Shared Event Queue .LP By default, the DIX layer calls \fBProcessInputEvents(\|)\fP before it it waits for something to happen, and also before performing each client request. When using non-blocking \fBread(\|)\fP calls this is a substantial overhead, and a facility for reducing this has been provided. \fBSetInputCheck(\|)\fP can be called with the addresses of two locations, and \fBProcessInputEvents(\|)\fP will only be called when they differ. There are two ways of using this: .Ip If your mouse and keyboard drivers support \fBSIGIO\fP, enable this mode when you open them, and register a handler that increments a location. Give \fBSetInputCheck(\|)\fP the address of this and a zero location, and add code to re-zero the location to \fBProcessInputEvents(\|)\fP. The Sun code does this. .Ip If you have a kernel event queue that can be mapped into a user process, give \fBSetInputCheck(\|)\fP the addresses of the head and tail pointers.\s-2\u17\d\s0 .FS 17. See the file \fIserver/ddx/dec/qvss/qvss_io.c\fP. .FE This is the best alternative, because it eliminates the \fBread(\|)\fP system calls as well. .LP In both cases, there is an interaction with the software cursor code. When the cursor is out of the bitmap, this mechanism must be disabled. We need to ensure that \fBProcessInputEvents(\|)\fP will be called at some time soon after the cursor is removed in order to put it back. .Ip If you are using \fBSIGIO\fP, you can simply call the SIGIO handler from the cursor removal code. .Ip If you are using a shared event queue, you have to call \fBSetEventCheck(\|)\fP in the cursor removal code, giving it the addresses of two locations that are always different, and again in the code that paints the cursor, giving it the head and tail pointers. .NH 2 Multiple Screens .LP The \fIsun\fP code supports multiple screens (``Zaphod'' mode).\s-2\u18\d\s0 .FS 18. See \fIThe Hitch-Hiker's Guide to the Galaxy\fP by Douglas Adams. .FE There are two possible versions of Zaphod mode: .Ip ``Passive'', in which the cursor stays on one screen until some client actively warps it to another screen. .IP ``Active'', in which the server warps the cursor between screens itself. .LP The \fIwm\fP window manager implements passize Zaphod mode, clicking on the background warps the pointer to the next screen in sequence. .LP The \fIsun\fP code implements active Zaphod mode by using the mi Cursor code. In \fBsunCursorOffScreen(\|)\fP, when the pointer gets to the right (left) edge of the current screen, it is warped to the next (previous) screen in sequence. This is done by simply modifying the input paramenters and returning the appropriate value. If you aren't using the mi software cursor code, examine it for the details on how to get the cursor to the new screen. .if 0 \{ how do you deal with deciding what pixmap formats are supported, and which ones not, in the following three cases: 1 head, chosen from among several 1 < n < m heads chosen from m n heads chosen from n do you do table lookup here too? this sounds like it could be strange, especially if you have two screens with different bit or byte order. right now, i do it in init, by looking at some gloabls set by each screen, which seems quite wrong. --raymond There does not seem to be a problem here. The protocol defines that there is a single format per server per depth. (I thought this was strange, too, but I got flamed at by RWS for mentioning it, so I guess that really is what the protocol says) We simply use a static table that defines this format for all depths it is possible to configure the server to support. This table is used irrespective of whether a screen supporting that depth was found during auto-configuration. Thus, if you start the server on a monochrome Sun, the screenInfo struct contains: numPixmapFormats = 2 formats[] = { 1, 1, BITMAP_SCANLINE_PAD, 8, 8, BITMAP_SCANLINE_PAD, } Since the formats array is always searched with a particular depth (derived from elsewhere and presumably valid) in mind, these extra entries do no harm. \} .if 0 \{ GCperDepth[] - entry 0 is always for depth 1. \} .NH Conclusions .LP During the alpha & beta testing periods of X V11, many interpid porters attempted to adapt the sample server to their hardware. It is to their credit, and especially to the spirit of cooperation in which the implementors received the enormous volume of comments and suggestions that resulted, that the X V11 sample server is now remarkably easy to get running on new hardware. A few bold strokes of the keyboard, and the task is done. Well, almost, but not quite. What remains is to tune the server to give of its best on your particular hardware. We leave this as an exercise for the reader. .NH Acknowledgements .LP Thanks to John Ousterhout and Andrew Cherenson for various suggestions in the initial UCB port. .LP The Sun port of the alpha server was done by David Rosenthal, Mike Schwartz, Stuart Marks, Robin Schaufler, and Alok Singhania. It was made much easier by the extent to which we could steal from the Sun X.10 server, now the result of too many people's work to acknowledge individually. However, Paul Borman of Cray Research did particularly useful work on keyboard support. .LP The \fIcfb\fP driver was originally the work of Stuart Marks (from a vague idea by David Rosenthal), with help from Jack Palevitch (now at Apple) and Bob Leichner of H-P Labs. The current \fIcfb\fP release was written at the MIT X Consortium for release 4 and shares a few file names in common with the original code. .LP The version of the Sun code in the MIT release is the work of Adam de Boor, David Rosenthal, Stuart Marks, Robin Schaufler, Frances Ho, Mark Opperman and Geoff Lee. Integration of the Sun code into the MIT release would have been impossible without the generous help of the Statistics Center at MIT, who allowed us to monopolise their Suns at all hours of the day and night, and Todd Brunhoff of Tektronix. .LP Special thanks to the Generic Workstation Company for the loan of their hardware.