3413 lines
		
	
	
		
			137 KiB
		
	
	
	
		
			XML
		
	
	
	
			
		
		
	
	
			3413 lines
		
	
	
		
			137 KiB
		
	
	
	
		
			XML
		
	
	
	
| <?xml version="1.0" encoding="ISO-8859-1"?>
 | |
| <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
 | |
|  "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
 | |
|  <!ENTITY % defs SYSTEM "/xserver/doc/xml/xserver.ent"> %defs;
 | |
| ]>
 | |
| 
 | |
| <article>
 | |
| 
 | |
|   <articleinfo>
 | |
|     <!-- Title information -->
 | |
|     <title>Distributed Multihead X Design</title>
 | |
|     <authorgroup>
 | |
|       <author><firstname>Kevin E.</firstname><surname>Martin</surname></author>
 | |
|       <author><firstname>David H.</firstname><surname>Dawes</surname></author>
 | |
|       <author><firstname>Rickard E.</firstname><surname>Faith</surname></author>
 | |
|     </authorgroup>
 | |
|     <pubdate>29 June 2004 (created 25 July 2001)</pubdate>
 | |
|     <releaseinfo>X Server Version &xserver.version;</releaseinfo>
 | |
|     <abstract><para>
 | |
|         This document covers the motivation, background, design, and
 | |
|         implementation of the distributed multihead X (DMX) system.  It
 | |
|         is a living document and describes the current design and
 | |
|         implementation details of the DMX system.  As the project
 | |
|         progresses, this document will be continually updated to reflect
 | |
|         the changes in the code and/or design.  <emphasis remap="it">Copyright 2001 by VA
 | |
|         Linux Systems, Inc., Fremont, California.  Copyright 2001-2004
 | |
|         by Red Hat, Inc., Raleigh, North Carolina</emphasis>
 | |
|       </para></abstract>
 | |
|   </articleinfo>
 | |
| 
 | |
| <!-- Begin the document -->
 | |
| <sect1>
 | |
| <title>Introduction</title>
 | |
| 
 | |
| <sect2>
 | |
| <title>The Distributed Multihead X Server</title>
 | |
| 
 | |
| <para>Current Open Source multihead solutions are limited to a single
 | |
| physical machine.  A single X server controls multiple display devices,
 | |
| which can be arranged as independent heads or unified into a single
 | |
| desktop (with Xinerama).  These solutions are limited to the number of
 | |
| physical devices that can co-exist in a single machine (e.g., due to the
 | |
| number of AGP/PCI slots available for graphics cards).  Thus, large
 | |
| tiled displays are not currently possible.  The work described in this
 | |
| paper will eliminate the requirement that the display devices reside in
 | |
| the same physical machine.  This will be accomplished by developing a
 | |
| front-end proxy X server that will control multiple back-end X servers
 | |
| that make up the large display.
 | |
| </para>
 | |
| 
 | |
| <para>The overall structure of the distributed multihead X (DMX) project is
 | |
| as follows: A single front-end X server will act as a proxy to a set of
 | |
| back-end X servers, which handle all of the visible rendering.  X
 | |
| clients will connect to the front-end server just as they normally would
 | |
| to a regular X server.  The front-end server will present an abstracted
 | |
| view to the client of a single large display.  This will ensure that all
 | |
| standard X clients will continue to operate without modification
 | |
| (limited, as always, by the visuals and extensions provided by the X
 | |
| server).  Clients that are DMX-aware will be able to use an extension to
 | |
| obtain information about the back-end servers (e.g., for placement of
 | |
| pop-up windows, window alignments by the window manager, etc.).
 | |
| </para>
 | |
| 
 | |
| <para>The architecture of the DMX server is divided into two main sections:
 | |
| input (e.g., mouse and keyboard events) and output (e.g., rendering and
 | |
| windowing requests).  Each of these are describe briefly below, and the
 | |
| rest of this design document will describe them in greater detail.
 | |
| </para>
 | |
| 
 | |
| <para>The DMX server can receive input from three general types of input
 | |
| devices: "local" devices that are physically attached to the machine on
 | |
| which DMX is running, "backend" devices that are physically attached to
 | |
| one or more of the back-end X servers (and that generate events via the
 | |
| X protocol stream from the backend), and "console" devices that can be
 | |
| abstracted from any non-back-end X server.  Backend and console devices
 | |
| are treated differently because the pointer device on the back-end X
 | |
| server also controls the location of the hardware X cursor.  Full
 | |
| support for XInput extension devices is provided.
 | |
| </para>
 | |
| 
 | |
| <para>Rendering requests will be accepted by the front-end server; however,
 | |
| rendering to visible windows will be broken down as needed and sent to
 | |
| the appropriate back-end server(s) via X11 library calls for actual
 | |
| rendering.  The basic framework will follow a Xnest-style approach.  GC
 | |
| state will be managed in the front-end server and sent to the
 | |
| appropriate back-end server(s) as required.  Pixmap rendering will (at
 | |
| least initially) be handled by the front-end X server.  Windowing
 | |
| requests (e.g., ordering, mapping, moving, etc.) will handled in the
 | |
| front-end server.  If the request requires a visible change, the
 | |
| windowing operation will be translated into requests for the appropriate
 | |
| back-end server(s).  Window state will be mirrored in the back-end
 | |
| server(s) as needed.
 | |
| </para>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Layout of Paper</title>
 | |
| 
 | |
| <para>The next section describes the general development plan that was
 | |
| actually used for implementation.  The final section discusses
 | |
| outstanding issues at the conclusion of development.  The first appendix
 | |
| provides low-level technical detail that may be of interest to those
 | |
| intimately familiar with the X server architecture.  The final appendix
 | |
| describes the four phases of development that were performed during the
 | |
| first two years of development.
 | |
| </para>
 | |
| 
 | |
| <para>The final year of work was divided into 9 tasks that are not
 | |
| described in specific sections of this document.  The major tasks during
 | |
| that time were the enhancement of the reconfiguration ability added in
 | |
| Phase IV, addition of support for a dynamic number of back-end displays
 | |
| (instead of a hard-coded limit), and the support for back-end display
 | |
| and input removal and addition.  This work is mentioned in this paper,
 | |
| but is not covered in detail.
 | |
| </para>
 | |
| </sect2>
 | |
| </sect1>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| <sect1>
 | |
| <title>Development plan</title>
 | |
| 
 | |
| <para>This section describes the development plan from approximately June
 | |
| 2001 through July 2003.
 | |
| </para>
 | |
| 
 | |
| <sect2>
 | |
| <title>Bootstrap code</title>
 | |
| 
 | |
| <para>To allow for rapid development of the DMX server by multiple
 | |
| developers during the first development stage, the problem will be
 | |
| broken down into three tasks: the overall DMX framework, back-end
 | |
| rendering services and input device handling services.  However, before
 | |
| the work begins on these tasks, a simple framework that each developer
 | |
| could use was implemented to bootstrap the development effort.  This
 | |
| framework renders to a single back-end server and provides dummy input
 | |
| devices (i.e., the keyboard and mouse).  The simple back-end rendering
 | |
| service was implemented using the shadow framebuffer support currently
 | |
| available in the XFree86 environment.
 | |
| </para>
 | |
| 
 | |
| <para>Using this bootstrapping framework, each developer has been able to
 | |
| work on each of the tasks listed above independently as follows: the
 | |
| framework will be extended to handle arbitrary back-end server
 | |
| configurations; the back-end rendering services will be transitioned to
 | |
| the more efficient Xnest-style implementation; and, an input device
 | |
| framework to handle various input devices via the input extension will
 | |
| be developed.
 | |
| </para>
 | |
| 
 | |
| <para>Status: The boot strap code is complete.   <!-- August 2001 -->
 | |
| </para>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Input device handling</title>
 | |
| 
 | |
| <para>An X server (including the front-end X server) requires two core
 | |
| input devices -- a keyboard and a pointer (mouse).  These core devices
 | |
| are handled and required by the core X11 protocol.  Additional types of
 | |
| input devices may be attached and utilized via the XInput extension.
 | |
| These are usually referred to as ``XInput extension devices'',
 | |
| </para>
 | |
| 
 | |
| <para>There are some options as to how the front-end X server gets its core
 | |
| input devices:
 | |
| 
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|     <para>Local Input. The physical input devices (e.g., keyboard and
 | |
|     mouse) can be attached directly to the front-end X server.  In this
 | |
|     case, the keyboard and mouse on the machine running the front-end X
 | |
|     server will be used.  The front-end will have drivers to read the
 | |
|     raw input from those devices and convert it into the required X
 | |
|     input events (e.g., key press/release, pointer button press/release,
 | |
|     pointer motion).  The front-end keyboard driver will keep track of
 | |
|     keyboard properties such as key and modifier mappings, autorepeat
 | |
|     state, keyboard sound and led state.  Similarly the front-end
 | |
|     pointer driver will keep track if pointer properties such as the
 | |
|     button mapping and movement acceleration parameters.  With this
 | |
|     option, input is handled fully in the front-end X server, and the
 | |
|     back-end X servers are used in a display-only mode.  This option was
 | |
|     implemented and works for a limited number of Linux-specific
 | |
|     devices.  Adding additional local input devices for other
 | |
|     architectures is expected to be relatively simple.
 | |
| </para>
 | |
| 
 | |
|     <para>The following options are available for implementing local input
 | |
|     devices:
 | |
| 
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|         <para>The XFree86 X server has modular input drivers that could
 | |
|         be adapted for this purpose.  The mouse driver supports a wide
 | |
|         range of mouse types and interfaces, as well as a range of
 | |
|         Operating System platforms.  The keyboard driver in XFree86 is
 | |
|         not currently as modular as the mouse driver, but could be made
 | |
|         so.  The XFree86 X server also has a range of other input
 | |
|         drivers for extended input devices such as tablets and touch
 | |
|         screens.  Unfortunately, the XFree86 drivers are generally
 | |
|         complex, often simultaneously providing support for multiple
 | |
|         devices across multiple architectures; and rely so heavily on
 | |
|         XFree86-specific helper-functions, that this option was not
 | |
|         pursued.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|         <para>The <command>kdrive</command> X server in XFree86 has built-in drivers that
 | |
|         support PS/2 mice and keyboard under Linux.  The mouse driver
 | |
|         can indirectly handle other mouse types if the Linux utility
 | |
|         <command>gpm</command> is used as to translate the native mouse protocol into
 | |
|         PS/2 mouse format.  These drivers could be adapted and built in
 | |
|         to the front-end X server if this range of hardware and OS
 | |
|         support is sufficient.  While much simpler than the XFree86
 | |
|         drivers, the <command>kdrive</command> drivers were not used for the DMX
 | |
|         implementation.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|         <para>Reimplementation of keyboard and mouse drivers from
 | |
|         scratch for the DMX framework.  Because keyboard and mouse
 | |
|         drivers are relatively trivial to implement, this pathway was
 | |
|         selected.  Other drivers in the X source tree were referenced,
 | |
|         and significant contributions from other drivers are noted in
 | |
|         the DMX source code.
 | |
| </para>
 | |
| </listitem>
 | |
| </orderedlist>
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para>Backend Input.  The front-end can make use of the core input
 | |
|     devices attached to one or more of the back-end X servers.  Core
 | |
|     input events from multiple back-ends are merged into a single input
 | |
|     event stream.  This can work sanely when only a single set of input
 | |
|     devices is used at any given time.  The keyboard and pointer state
 | |
|     will be handled in the front-end, with changes propagated to the
 | |
|     back-end servers as needed.  This option was implemented and works
 | |
|     well.  Because the core pointer on a back-end controls the hardware
 | |
|     mouse on that back-end, core pointers cannot be treated as XInput
 | |
|     extension devices.  However, all back-end XInput extensions devices
 | |
|     can be mapped to either DMX core or DMX XInput extension devices.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para>Console Input.  The front-end server could create a console
 | |
|     window that is displayed on an X server independent of the back-end
 | |
|     X servers.  This console window could display things like the
 | |
|     physical screen layout, and the front-end could get its core input
 | |
|     events from events delivered to the console window.  This option was
 | |
|     implemented and works well.  To help the human navigate, window
 | |
|     outlines are also displayed in the console window.  Further, console
 | |
|     windows can be used as either core or XInput extension devices.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para>Other options were initially explored, but they were all
 | |
|     partial subsets of the options listed above and, hence, are
 | |
|     irrelevant.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| </orderedlist>
 | |
| </para>
 | |
| 
 | |
| <para>Although extended input devices are not specifically mentioned in the
 | |
| Distributed X requirements, the options above were all implemented so
 | |
| that XInput extension devices were supported.
 | |
| </para>
 | |
| 
 | |
| <para>The bootstrap code (Xdmx) had dummy input devices, and these are
 | |
| still supported in the final version.  These do the necessary
 | |
| initialization to satisfy the X server's requirements for core pointer
 | |
| and keyboard devices, but no input events are ever generated.
 | |
| </para>
 | |
| 
 | |
| <para>Status: The input code is complete.  Because of the complexity of the
 | |
| XFree86 input device drivers (and their heavy reliance on XFree86
 | |
| infrastructure), separate low-level device drivers were implemented for
 | |
| Xdmx.  The following kinds of drivers are supported (in general, the
 | |
| devices can be treated arbitrarily as "core" input devices or as XInput
 | |
| "extension" devices; and multiple instances of different kinds of
 | |
| devices can be simultaneously available):
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|         <para> A "dummy" device drive that never generates events.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|         <para> "Local" input is from the low-level hardware on which the
 | |
|         Xdmx binary is running.  This is the only area where using the
 | |
|         XFree86 driver infrastructure would have been helpful, and then
 | |
|         only partially, since good support for generic USB devices does
 | |
|         not yet exist in XFree86 (in any case, XFree86 and kdrive driver
 | |
|         code was used where possible).  Currently, the following local
 | |
|         devices are supported under Linux (porting to other operating
 | |
|         systems should be fairly straightforward):
 | |
|         <itemizedlist>
 | |
|             <listitem><para>Linux keyboard</para></listitem>
 | |
|             <listitem><para>Linux serial mouse (MS)</para></listitem>
 | |
|             <listitem><para>Linux PS/2 mouse</para></listitem>
 | |
|             <listitem><para>USB keyboard</para></listitem>
 | |
|             <listitem><para>USB mouse</para></listitem>
 | |
|             <listitem><para>USB generic device (e.g., joystick, gamepad, etc.)</para></listitem>
 | |
|         </itemizedlist>
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|         <para> "Backend" input is taken from one or more of the back-end
 | |
|         displays.  In this case, events are taken from the back-end X
 | |
|         server and are converted to Xdmx events.  Care must be taken so
 | |
|         that the sprite moves properly on the display from which input
 | |
|         is being taken.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|         <para> "Console" input is taken from an X window that Xdmx
 | |
|         creates on the operator's display (i.e., on the machine running
 | |
|         the Xdmx binary).  When the operator's mouse is inside the
 | |
|         console window, then those events are converted to Xdmx events.
 | |
|         Several special features are available: the console can display
 | |
|         outlines of windows that are on the Xdmx display (to facilitate
 | |
|         navigation), the cursor can be confined to the console, and a
 | |
|         "fine" mode can be activated to allow very precise cursor
 | |
|         positioning.
 | |
| </para>
 | |
| </listitem>
 | |
| </orderedlist>
 | |
| 
 | |
| </para>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <!-- May 2002; July 2003 -->
 | |
| 
 | |
| <sect2>
 | |
| <title>Output device handling</title>
 | |
| 
 | |
| <para>The output of the DMX system displays rendering and windowing
 | |
| requests across multiple screens.  The screens are typically arranged in
 | |
| a grid such that together they represent a single large display.
 | |
| </para>
 | |
| 
 | |
| <para>The output section of the DMX code consists of two parts.  The first
 | |
| is in the front-end proxy X server (Xdmx), which accepts client
 | |
| connections, manages the windows, and potentially renders primitives but
 | |
| does not actually display any of the drawing primitives.  The second
 | |
| part is the back-end X server(s), which accept commands from the
 | |
| front-end server and display the results on their screens.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>Initialization</title>
 | |
| 
 | |
| <para>The DMX front-end must first initialize its screens by connecting to
 | |
| each of the back-end X servers and collecting information about each of
 | |
| these screens.  However, the information collected from the back-end X
 | |
| servers might be inconsistent.  Handling these cases can be difficult
 | |
| and/or inefficient.  For example, a two screen system has one back-end X
 | |
| server running at 16bpp while the second is running at 32bpp.
 | |
| Converting rendering requests (e.g., XPutImage() or XGetImage()
 | |
| requests) to the appropriate bit depth can be very time consuming.
 | |
| Analyzing these cases to determine how or even if it is possible to
 | |
| handle them is required.  The current Xinerama code handles many of
 | |
| these cases (e.g., in PanoramiXConsolidate()) and will be used as a
 | |
| starting point.  In general, the best solution is to use homogeneous X
 | |
| servers and display devices.  Using back-end servers with the same depth
 | |
| is a requirement of the final DMX implementation.
 | |
| </para>
 | |
| 
 | |
| <para>Once this screen consolidation is finished, the relative position of
 | |
| each back-end X server's screen in the unified screen is initialized.  A
 | |
| full-screen window is opened on each of the back-end X servers, and the
 | |
| cursor on each screen is turned off.  The final DMX implementation can
 | |
| also make use of a partial-screen window, or multiple windows per
 | |
| back-end screen.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Handling rendering requests</title>
 | |
| 
 | |
| <para>After initialization, X applications connect to the front-end server.
 | |
| There are two possible implementations of how rendering and windowing
 | |
| requests are handled in the DMX system:
 | |
| 
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|     <para>A shadow framebuffer is used in the front-end server as the
 | |
|     render target.  In this option, all protocol requests are completely
 | |
|     handled in the front-end server.  All state and resources are
 | |
|     maintained in the front-end including a shadow copy of the entire
 | |
|     framebuffer.  The framebuffers attached to the back-end servers are
 | |
|     updated by XPutImage() calls with data taken directly from the
 | |
|     shadow framebuffer.
 | |
| </para>
 | |
| 
 | |
|     <para>This solution suffers from two main problems.  First, it does not
 | |
|     take advantage of any accelerated hardware available in the system.
 | |
|     Second, the size of the XPutImage() calls can be quite large and
 | |
|     thus will be limited by the bandwidth available.
 | |
| </para>
 | |
| 
 | |
|     <para>The initial DMX implementation used a shadow framebuffer by
 | |
|     default.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para>Rendering requests are sent to each back-end server for
 | |
|     handling (as is done in the Xnest server described above).  In this
 | |
|     option, certain protocol requests are handled in the front-end
 | |
|     server and certain requests are repackaged and then sent to the
 | |
|     back-end servers.  The framebuffer is distributed across the
 | |
|     multiple back-end servers.  Rendering to the framebuffer is handled
 | |
|     on each back-end and can take advantage of any acceleration
 | |
|     available on the back-end servers' graphics display device.  State
 | |
|     is maintained both in the front and back-end servers.
 | |
| </para>
 | |
| 
 | |
|     <para>This solution suffers from two main drawbacks.  First, protocol
 | |
|     requests are sent to all back-end servers -- even those that will
 | |
|     completely clip the rendering primitive -- which wastes bandwidth
 | |
|     and processing time.  Second, state is maintained both in the front-
 | |
|     and back-end servers.  These drawbacks are not as severe as in
 | |
|     option 1 (above) and can either be overcome through optimizations or
 | |
|     are acceptable.  Therefore, this option will be used in the final
 | |
|     implementation.
 | |
| </para>
 | |
| 
 | |
|     <para>The final DMX implementation defaults to this mechanism, but also
 | |
|     supports the shadow framebuffer mechanism.  Several optimizations
 | |
|     were implemented to eliminate the drawbacks of the default
 | |
|     mechanism.  These optimizations are described the section below and
 | |
|     in Phase II of the Development Results (see appendix).
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| </orderedlist>
 | |
| </para>
 | |
| 
 | |
| <para>Status: Both the shadow framebuffer and Xnest-style code is complete.
 | |
| <!-- May 2002 -->
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Optimizing DMX</title>
 | |
| 
 | |
| <para>Initially, the Xnest-style solution's performance will be measured
 | |
| and analyzed to determine where the performance bottlenecks exist.
 | |
| There are four main areas that will be addressed.
 | |
| </para>
 | |
| 
 | |
| <para>First, to obtain reasonable interactivity with the first development
 | |
| phase, XSync() was called after each protocol request.  The XSync()
 | |
| function flushes any pending protocol requests.  It then waits for the
 | |
| back-end to process the request and send a reply that the request has
 | |
| completed.  This happens with each back-end server and performance
 | |
| greatly suffers.  As a result of the way XSync() is called in the first
 | |
| development phase, the batching that the X11 library performs is
 | |
| effectively defeated.  The XSync() call usage will be analyzed and
 | |
| optimized by batching calls and performing them at regular intervals,
 | |
| except where interactivity will suffer (e.g., on cursor movements).
 | |
| </para>
 | |
| 
 | |
| <para>Second, the initial Xnest-style solution described above sends the
 | |
| repackaged protocol requests to all back-end servers regardless of
 | |
| whether or not they would be completely clipped out.  The requests that
 | |
| are trivially rejected on the back-end server wastes the limited
 | |
| bandwidth available.  By tracking clipping changes in the DMX X server's
 | |
| windowing code (e.g., by opening, closing, moving or resizing windows),
 | |
| we can determine whether or not back-end windows are visible so that
 | |
| trivial tests in the front-end server's GC ops drawing functions can
 | |
| eliminate these unnecessary protocol requests.
 | |
| </para>
 | |
| 
 | |
| <para>Third, each protocol request will be analyzed to determine if it is
 | |
| possible to break the request into smaller pieces at display boundaries.
 | |
| The initial ones to be analyzed are put and get image requests since
 | |
| they will require the greatest bandwidth to transmit data between the
 | |
| front and back-end servers.  Other protocol requests will be analyzed
 | |
| and those that will benefit from breaking them into smaller requests
 | |
| will be implemented.
 | |
| </para>
 | |
| 
 | |
| <para>Fourth, an extension is being considered that will allow font glyphs to
 | |
| be transferred from the front-end DMX X server to each back-end server.
 | |
| This extension will permit the front-end to handle all font requests and
 | |
| eliminate the requirement that all back-end X servers share the exact
 | |
| same fonts as the front-end server.  We are investigating the
 | |
| feasibility of this extension during this development phase.
 | |
| </para>
 | |
| 
 | |
| <para>Other potential optimizations will be determined from the performance
 | |
| analysis.
 | |
| </para>
 | |
| 
 | |
| <para>Please note that in our initial design, we proposed optimizing BLT
 | |
| operations (e.g., XCopyArea() and window moves) by developing an
 | |
| extension that would allow individual back-end servers to directly copy
 | |
| pixel data to other back-end servers.  This potential optimization was
 | |
| in response to the simple image movement implementation that required
 | |
| potentially many calls to GetImage() and PutImage().  However, the
 | |
| current Xinerama implementation handles these BLT operations
 | |
| differently.  Instead of copying data to and from screens, they generate
 | |
| expose events -- just as happens in the case when a window is moved from
 | |
| off a screen to on screen.  This approach saves the limited bandwidth
 | |
| available between front and back-end servers and is being standardized
 | |
| with Xinerama.  It also eliminates the potential setup problems and
 | |
| security issues resulting from having each back-end server open
 | |
| connections to all other back-end servers.  Therefore, we suggest
 | |
| accepting Xinerama's expose event solution.
 | |
| </para>
 | |
| 
 | |
| <para>Also note that the approach proposed in the second and third
 | |
| optimizations might cause backing store algorithms in the back-end to be
 | |
| defeated, so a DMX X server configuration flag will be added to disable
 | |
| these optimizations.
 | |
| </para>
 | |
| 
 | |
| <para>Status: The optimizations proposed above are complete.  It was
 | |
| determined that the using the xfs font server was sufficient and
 | |
| creating a new mechanism to pass glyphs was redundant; therefore, the
 | |
| fourth optimization proposed above was not included in DMX.
 | |
| <!-- September 2002 -->
 | |
| </para>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>DMX X extension support</title>
 | |
| 
 | |
| <para>The DMX X server keeps track of all the windowing information on the
 | |
| back-end X servers, but does not currently export this information to
 | |
| any client applications.  An extension will be developed to pass the
 | |
| screen information and back-end window IDs to DMX-aware clients.  These
 | |
| clients can then use this information to directly connect to and render
 | |
| to the back-end windows.  Bypassing the DMX X server allows DMX-aware
 | |
| clients to break up complex rendering requests on their own and send
 | |
| them directly to the windows on the back-end server's screens.  An
 | |
| example of a client that can make effective use of this extension is
 | |
| Chromium.
 | |
| </para>
 | |
| 
 | |
| <para>Status: The extension, as implemented, is fully documented in
 | |
| "Client-to-Server DMX Extension to the X Protocol".  Future changes
 | |
| might be required based on feedback and other proposed enhancements to
 | |
| DMX.  Currently, the following facilities are supported:
 | |
| <orderedlist>
 | |
| <listitem><para>
 | |
|         Screen information (clipping rectangle for each screen relative
 | |
|         to the virtual screen)
 | |
| </para></listitem>
 | |
| <listitem><para>
 | |
|         Window information (window IDs and clipping information for each
 | |
|         back-end window that corresponds to each DMX window)
 | |
| </para></listitem>
 | |
| <listitem><para>
 | |
|         Input device information (mappings from DMX device IDs to
 | |
|         back-end device IDs)
 | |
| </para></listitem>
 | |
| <listitem><para>
 | |
|         Force window creation (so that a client can override the
 | |
|         server-side lazy window creation optimization)
 | |
| </para></listitem>
 | |
| <listitem><para>
 | |
|         Reconfiguration (so that a client can request that a screen
 | |
|         position be changed)
 | |
| </para></listitem>
 | |
| <listitem><para>
 | |
|         Addition and removal of back-end servers and back-end and
 | |
|         console inputs.
 | |
| </para></listitem>
 | |
| </orderedlist>
 | |
| </para>
 | |
| <!-- September 2002; July 2003 -->
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Common X extension support</title>
 | |
| 
 | |
| <para>The XInput, XKeyboard and Shape extensions are commonly used
 | |
| extensions to the base X11 protocol.  XInput allows multiple and
 | |
| non-standard input devices to be accessed simultaneously.  These input
 | |
| devices can be connected to either the front-end or back-end servers.
 | |
| XKeyboard allows much better keyboard mappings control.  Shape adds
 | |
| support for arbitrarily shaped windows and is used by various window
 | |
| managers.  Nearly all potential back-end X servers make these extensions
 | |
| available, and support for each one will be added to the DMX system.
 | |
| </para>
 | |
| 
 | |
| <para>In addition to the extensions listed above, support for the X
 | |
| Rendering extension (Render) is being developed.  Render adds digital
 | |
| image composition to the rendering model used by the X Window System.
 | |
| While this extension is still under development by Keith Packard of HP,
 | |
| support for the current version will be added to the DMX system.
 | |
| </para>
 | |
| 
 | |
| <para>Support for the XTest extension was added during the first
 | |
| development phase.
 | |
| </para>
 | |
| 
 | |
| <!-- WARNING: this list is duplicated in the Phase IV discussion -->
 | |
| <para>Status: The following extensions are supported and are discussed in
 | |
| more detail in Phase IV of the Development Results (see appendix):
 | |
|     BIG-REQUESTS,
 | |
|     DEC-XTRAP,
 | |
|     DMX,
 | |
|     DPMS,
 | |
|     Extended-Visual-Information,
 | |
|     GLX,
 | |
|     LBX,
 | |
|     RECORD,
 | |
|     RENDER,
 | |
|     SECURITY,
 | |
|     SHAPE,
 | |
|     SYNC,
 | |
|     X-Resource,
 | |
|     XC-APPGROUP,
 | |
|     XC-MISC,
 | |
|     XFree86-Bigfont,
 | |
|     XINERAMA,
 | |
|     XInputExtension,
 | |
|     XKEYBOARD, and
 | |
|     XTEST.
 | |
| <!-- November 2002; updated February 2003, July 2003 -->
 | |
| </para>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>OpenGL support</title>
 | |
| 
 | |
| <para>OpenGL support using the Mesa code base exists in XFree86 release 4
 | |
| and later.  Currently, the direct rendering infrastructure (DRI)
 | |
| provides accelerated OpenGL support for local clients and unaccelerated
 | |
| OpenGL support (i.e., software rendering) is provided for non-local
 | |
| clients.
 | |
| </para>
 | |
| 
 | |
| <para>The single head OpenGL support in XFree86 4.x will be extended to use
 | |
| the DMX system.  When the front and back-end servers are on the same
 | |
| physical hardware, it is possible to use the DRI to directly render to
 | |
| the back-end servers.  First, the existing DRI will be extended to
 | |
| support multiple display heads, and then to support the DMX system.
 | |
| OpenGL rendering requests will be direct rendering to each back-end X
 | |
| server.  The DRI will request the screen layout (either from the
 | |
| existing Xinerama extension or a DMX-specific extension).  Support for
 | |
| synchronized swap buffers will also be added (on hardware that supports
 | |
| it).  Note that a single front-end server with a single back-end server
 | |
| on the same physical machine can emulate accelerated indirect rendering.
 | |
| </para>
 | |
| 
 | |
| <para>When the front and back-end servers are on different physical
 | |
| hardware or are using non-XFree86 4.x X servers, a mechanism to render
 | |
| primitives across the back-end servers will be provided.  There are
 | |
| several options as to how this can be implemented.
 | |
| </para>
 | |
| 
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|     <para>The existing OpenGL support in each back-end server can be
 | |
|     used by repackaging rendering primitives and sending them to each
 | |
|     back-end server.  This option is similar to the unoptimized
 | |
|     Xnest-style approach mentioned above.  Optimization of this solution
 | |
|     is beyond the scope of this project and is better suited to other
 | |
|     distributed rendering systems.
 | |
| </para></listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para>Rendering to a pixmap in the front-end server using the
 | |
|     current XFree86 4.x code, and then displaying to the back-ends via
 | |
|     calls to XPutImage() is another option.  This option is similar to
 | |
|     the shadow frame buffer approach mentioned above.  It is slower and
 | |
|     bandwidth intensive, but has the advantage that the back-end servers
 | |
|     are not required to have OpenGL support.
 | |
| </para></listitem>
 | |
| </orderedlist>
 | |
| 
 | |
| <para>These, and other, options will be investigated in this phase of the
 | |
| work.
 | |
| </para>
 | |
| 
 | |
| <para>Work by others have made Chromium DMX-aware.  Chromium will use the
 | |
| DMX X protocol extension to obtain information about the back-end
 | |
| servers and will render directly to those servers, bypassing DMX.
 | |
| </para>
 | |
| 
 | |
| <para>Status: OpenGL support by the glxProxy extension was implemented by
 | |
| SGI and has been integrated into the DMX code base.
 | |
| </para>
 | |
| <!-- May 2003-->
 | |
| </sect2>
 | |
| 
 | |
| </sect1>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| <sect1>
 | |
| <title>Current issues</title>
 | |
| 
 | |
| <para>In this sections the current issues are outlined that require further
 | |
| investigation.
 | |
| </para>
 | |
| 
 | |
| <sect2>
 | |
| <title>Fonts</title>
 | |
| 
 | |
| <para>The font path and glyphs need to be the same for the front-end and
 | |
| each of the back-end servers.  Font glyphs could be sent to the back-end
 | |
| servers as necessary but this would consume a significant amount of
 | |
| available bandwidth during font rendering for clients that use many
 | |
| different fonts (e.g., Netscape).  Initially, the font server (xfs) will
 | |
| be used to provide the fonts to both the front-end and back-end servers.
 | |
| Other possibilities will be investigated during development.
 | |
| </para>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Zero width rendering primitives</title>
 | |
| 
 | |
| <para>To allow pixmap and on-screen rendering to be pixel perfect, all
 | |
| back-end servers must render zero width primitives exactly the same as
 | |
| the front-end renders the primitives to pixmaps.  For those back-end
 | |
| servers that do not exactly match, zero width primitives will be
 | |
| automatically converted to one width primitives.  This can be handled in
 | |
| the front-end server via the GC state.
 | |
| </para>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Output scaling</title>
 | |
| 
 | |
| <para>With very large tiled displays, it might be difficult to read the
 | |
| information on the standard X desktop.  In particular, the cursor can be
 | |
| easily lost and fonts could be difficult to read.  Automatic primitive
 | |
| scaling might prove to be very useful.  We will investigate the
 | |
| possibility of scaling the cursor and providing a set of alternate
 | |
| pre-scaled fonts to replace the standard fonts that many applications
 | |
| use (e.g., fixed).  Other options for automatic scaling will also be
 | |
| investigated.
 | |
| </para>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Per-screen colormaps</title>
 | |
| 
 | |
| <para>Each screen's default colormap in the set of back-end X servers
 | |
| should be able to be adjusted via a configuration utility.  This support
 | |
| is would allow the back-end screens to be calibrated via custom gamma
 | |
| tables.  On 24-bit systems that support a DirectColor visual, this type
 | |
| of correction can be accommodated.  One possible implementation would be
 | |
| to advertise to X client of the DMX server a TrueColor visual while
 | |
| using DirectColor visuals on the back-end servers to implement this type
 | |
| of color correction.  Other options will be investigated.
 | |
| </para>
 | |
| </sect2>
 | |
| </sect1>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| <appendix>
 | |
| <title>Appendix</title>
 | |
| 
 | |
| <sect1>
 | |
| <title>Background</title>
 | |
| 
 | |
| <para>This section describes the existing Open Source architectures that
 | |
| can be used to handle multiple screens and upon which this development
 | |
| project is based.  This section was written before the implementation
 | |
| was finished, and may not reflect actual details of the implementation.
 | |
| It is left for historical interest only.
 | |
| </para>
 | |
| 
 | |
| <sect2>
 | |
| <title>Core input device handling</title>
 | |
| 
 | |
| <para>The following is a description of how core input devices are handled
 | |
| by an X server.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>InitInput()</title>
 | |
| 
 | |
| <para>InitInput() is a DDX function that is called at the start of each
 | |
| server generation from the X server's main() function.  Its purpose is
 | |
| to determine what input devices are connected to the X server, register
 | |
| them with the DIX and MI layers, and initialize the input event queue.
 | |
| InitInput() does not have a return value, but the X server will abort if
 | |
| either a core keyboard device or a core pointer device are not
 | |
| registered.  Extended input (XInput) devices can also be registered in
 | |
| InitInput().
 | |
| </para>
 | |
| 
 | |
| <para>InitInput() usually has implementation specific code to determine
 | |
| which input devices are available.  For each input device it will be
 | |
| using, it calls AddInputDevice():
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>AddInputDevice()</term>
 | |
| <listitem><para>This DIX function allocates the device structure,
 | |
| registers a callback function (which handles device init, close, on and
 | |
| off), and returns the input handle, which can be treated as opaque.  It
 | |
| is called once for each input device.
 | |
| </para></listitem>
 | |
| </varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>Once input handles for core keyboard and core pointer devices have
 | |
| been obtained from AddInputDevice().  If both core devices are not
 | |
| registered, then the X server will exit with a fatal error when it
 | |
| attempts to start the input devices in InitAndStartDevices(), which is
 | |
| called directly after InitInput() (see below).
 | |
| </para>
 | |
| 
 | |
| <para>The core pointer device is then registered with the miPointer code
 | |
| (which does the high level cursor handling).  While this registration
 | |
| is not necessary for correct miPointer operation in the current XFree86
 | |
| code, it is still done mostly for compatibility reasons.
 | |
| </para>
 | |
| 
 | |
| <para><variablelist>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>miRegisterPointerDevice()</term>
 | |
| <listitem><para>This MI function registers the core
 | |
| pointer's input handle with with the miPointer code.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>The final part of InitInput() is the initialization of the input
 | |
| event queue handling.  In most cases, the event queue handling provided
 | |
| in the MI layer is used.  The primary XFree86 X server uses its own
 | |
| event queue handling to support some special cases related to the XInput
 | |
| extension and the XFree86-specific DGA extension.  For our purposes, the
 | |
| MI event queue handling should be suitable.  It is initialized by
 | |
| calling mieqInit():
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>mieqInit()</term>
 | |
| <listitem><para>This MI function initializes the MI event queue for the
 | |
| core devices, and is passed the public component of the input handles
 | |
| for the two core devices.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>If a wakeup handler is required to deliver synchronous input
 | |
| events, it can be registered here by calling the DIX function
 | |
| RegisterBlockAndWakeupHandlers().  (See the devReadInput() description
 | |
| below.)
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>InitAndStartDevices()</title>
 | |
| 
 | |
| <para>InitAndStartDevices() is a DIX function that is called immediately
 | |
| after InitInput() from the X server's main() function.  Its purpose is
 | |
| to initialize each input device that was registered with
 | |
| AddInputDevice(), enable each input device that was successfully
 | |
| initialized, and create the list of enabled input devices.  Once each
 | |
| registered device is processed in this way, the list of enabled input
 | |
| devices is checked to make sure that both a core keyboard device and
 | |
| core pointer device were registered and successfully enabled.  If not,
 | |
| InitAndStartDevices() returns failure, and results in the the X server
 | |
| exiting with a fatal error.
 | |
| </para>
 | |
| 
 | |
| <para>Each registered device is initialized by calling its callback
 | |
| (dev->deviceProc) with the DEVICE_INIT argument:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>(*dev->deviceProc)(dev, DEVICE_INIT)</term>
 | |
| <listitem>
 | |
| <para>This function initializes the
 | |
| device structs with core information relevant to the device.
 | |
| </para>
 | |
| 
 | |
| <para>For pointer devices, this means specifying the number of buttons,
 | |
| default button mapping, the function used to get motion events (usually
 | |
| miPointerGetMotionEvents()), the function used to change/control the
 | |
| core pointer motion parameters (acceleration and threshold), and the
 | |
| motion buffer size.
 | |
| </para>
 | |
| 
 | |
| <para>For keyboard devices, this means specifying the keycode range,
 | |
| default keycode to keysym mapping, default modifier mapping, and the
 | |
| functions used to sound the keyboard bell and modify/control the
 | |
| keyboard parameters (LEDs, bell pitch and duration, key click, which
 | |
| keys are auto-repeating, etc).
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>Each initialized device is enabled by calling EnableDevice():
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>EnableDevice()</term>
 | |
| <listitem>
 | |
| <para>EnableDevice() calls the device callback with
 | |
| DEVICE_ON:
 | |
|     <variablelist>
 | |
|     <varlistentry>
 | |
|     <term>(*dev->deviceProc)(dev, DEVICE_ON)</term>
 | |
|     <listitem>
 | |
|     <para>This typically opens and
 | |
|     initializes the relevant physical device, and when appropriate,
 | |
|     registers the device's file descriptor (or equivalent) as a valid
 | |
|     input source.
 | |
|     </para></listitem></varlistentry>
 | |
|     </variablelist>
 | |
|     </para>
 | |
| 
 | |
|     <para>EnableDevice() then adds the device handle to the X server's
 | |
|     global list of enabled devices.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>InitAndStartDevices() then verifies that a valid core keyboard and
 | |
| pointer has been initialized and enabled.  It returns failure if either
 | |
| are missing.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>devReadInput()</title>
 | |
| 
 | |
| <para>Each device will have some function that gets called to read its
 | |
| physical input. This function should do at least two things: make sure that
 | |
| input events get enqueued, and make sure that the cursor gets moved for motion
 | |
| events (except if these are handled later by the driver's own event queue
 | |
| processing function, which cannot be done when using the MI event queue
 | |
| handling).
 | |
| </para>
 | |
| 
 | |
| <para>Events are queued by calling mieqEnqueue():
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>mieqEnqueue()</term>
 | |
| <listitem>
 | |
| <para>This MI function is used to add input events to the
 | |
| event queue.  It is simply passed the event to be queued.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>The cursor position should be updated when motion events are
 | |
| enqueued by calling miPointerDeltaCursor():
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>miPointerDeltaCursor()</term>
 | |
| <listitem>
 | |
| <para>This MI function is used to move the cursor
 | |
| relative to its current position.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>ProcessInputEvents()</title>
 | |
| 
 | |
| <para>ProcessInputEvents() is a DDX function that is called from the X
 | |
| server's main dispatch loop when new events are available in the input
 | |
| event queue.  It typically processes the enqueued events, and updates
 | |
| the cursor/pointer position.  It may also do other DDX-specific event
 | |
| processing.
 | |
| </para>
 | |
| 
 | |
| <para>Enqueued events are processed by mieqProcessInputEvents() and passed
 | |
| to the DIX layer for transmission to clients:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>mieqProcessInputEvents()</term>
 | |
| <listitem>
 | |
| <para>This function processes each event in the
 | |
| event queue, and passes it to the device's input processing function.
 | |
| The DIX layer provides default functions to do this processing, and they
 | |
| handle the task of getting the events passed back to the relevant
 | |
| clients.
 | |
| </para></listitem></varlistentry>
 | |
| <varlistentry>
 | |
| <term>miPointerUpdate()</term>
 | |
| <listitem>
 | |
| <para>This function resynchronized the cursor position
 | |
| with the new pointer position.  It also takes care of moving the cursor
 | |
| between screens when needed in multi-head configurations.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>DisableDevice()</title>
 | |
| 
 | |
| <para>DisableDevice is a DIX function that removes an input device from the
 | |
| list of enabled devices.  The result of this is that the device no
 | |
| longer generates input events.  The device's data structures are kept in
 | |
| place, and disabling a device like this can be reversed by calling
 | |
| EnableDevice().  DisableDevice() may be called from the DDX when it is
 | |
| desirable to do so (e.g., the XFree86 server does this when VT
 | |
| switching).  Except for special cases, this is not normally called for
 | |
| core input devices.
 | |
| </para>
 | |
| 
 | |
| <para>DisableDevice() calls the device's callback function with
 | |
| <constant>DEVICE_OFF</constant>:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>(*dev->deviceProc)(dev, DEVICE_OFF)</term>
 | |
| <listitem>
 | |
| <para>This typically closes the
 | |
| relevant physical device, and when appropriate, unregisters the device's
 | |
| file descriptor (or equivalent) as a valid input source.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>DisableDevice() then removes the device handle from the X server's
 | |
| global list of enabled devices.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>CloseDevice()</title>
 | |
| 
 | |
| <para>CloseDevice is a DIX function that removes an input device from the
 | |
| list of available devices.  It disables input from the device and frees
 | |
| all data structures associated with the device.  This function is
 | |
| usually called from CloseDownDevices(), which is called from main() at
 | |
| the end of each server generation to close all input devices.
 | |
| </para>
 | |
| 
 | |
| <para>CloseDevice() calls the device's callback function with
 | |
| <constant>DEVICE_CLOSE</constant>:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>(*dev->deviceProc)(dev, DEVICE_CLOSE)</term>
 | |
| <listitem>
 | |
| <para>This typically closes the
 | |
| relevant physical device, and when appropriate, unregisters the device's
 | |
| file descriptor (or equivalent) as a valid input source.  If any device
 | |
| specific data structures were allocated when the device was initialized,
 | |
| they are freed here.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>CloseDevice() then frees the data structures that were allocated
 | |
| for the device when it was registered/initialized.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>LegalModifier()</title>
 | |
| <!-- dmx/dmxinput.c - currently returns TRUE -->
 | |
| <para>LegalModifier() is a required DDX function that can be used to
 | |
| restrict which keys may be modifier keys.  This seems to be present for
 | |
| historical reasons, so this function should simply return TRUE
 | |
| unconditionally.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Output handling</title>
 | |
| 
 | |
| <para>The following sections describe the main functions required to
 | |
| initialize, use and close the output device(s) for each screen in the X
 | |
| server.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>InitOutput()</title>
 | |
| 
 | |
| <para>This DDX function is called near the start of each server generation
 | |
| from the X server's main() function.  InitOutput()'s main purpose is to
 | |
| initialize each screen and fill in the global screenInfo structure for
 | |
| each screen.  It is passed three arguments: a pointer to the screenInfo
 | |
| struct, which it is to initialize, and argc and argv from main(), which
 | |
| can be used to determine additional configuration information.
 | |
| </para>
 | |
| 
 | |
| <para>The primary tasks for this function are outlined below:
 | |
| 
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|     <para><emphasis remap="bf">Parse configuration info:</emphasis> The first task of InitOutput()
 | |
|     is to parses any configuration information from the configuration
 | |
|     file.  In addition to the XF86Config file, other configuration
 | |
|     information can be taken from the command line.  The command line
 | |
|     options can be gathered either in InitOutput() or earlier in the
 | |
|     ddxProcessArgument() function, which is called by
 | |
|     ProcessCommandLine().  The configuration information determines the
 | |
|     characteristics of the screen(s).  For example, in the XFree86 X
 | |
|     server, the XF86Config file specifies the monitor information, the
 | |
|     screen resolution, the graphics devices and slots in which they are
 | |
|     located, and, for Xinerama, the screens' layout.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para><emphasis remap="bf">Initialize screen info:</emphasis> The next task is to initialize
 | |
|     the screen-dependent internal data structures.  For example, part of
 | |
|     what the XFree86 X server does is to allocate its screen and pixmap
 | |
|     private indices, probe for graphics devices, compare the probed
 | |
|     devices to the ones listed in the XF86Config file, and add the ones that
 | |
|     match to the internal xf86Screens[] structure.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para><emphasis remap="bf">Set pixmap formats:</emphasis> The next task is to initialize the
 | |
|     screenInfo's image byte order, bitmap bit order and bitmap scanline
 | |
|     unit/pad.  The screenInfo's pixmap format's depth, bits per pixel
 | |
|     and scanline padding is also initialized at this stage.
 | |
| </para>
 | |
| </listitem>
 | |
| 
 | |
| <listitem>
 | |
|     <para><emphasis remap="bf">Unify screen info:</emphasis> An optional task that might be done at
 | |
|     this stage is to compare all of the information from the various
 | |
|     screens and determines if they are compatible (i.e., if the set of
 | |
|     screens can be unified into a single desktop).  This task has
 | |
|     potential to be useful to the DMX front-end server, if Xinerama's
 | |
|     PanoramiXConsolidate() function is not sufficient.
 | |
| </para>
 | |
| </listitem>
 | |
| </orderedlist>
 | |
| </para>
 | |
| 
 | |
| <para>Once these tasks are complete, the valid screens are known and each
 | |
| of these screens can be initialized by calling AddScreen().
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>AddScreen()</title>
 | |
| 
 | |
| <para>This DIX function is called from InitOutput(), in the DDX layer, to
 | |
| add each new screen to the screenInfo structure.  The DDX screen
 | |
| initialization function and command line arguments (i.e., argc and argv)
 | |
| are passed to it as arguments.
 | |
| </para>
 | |
| 
 | |
| <para>This function first allocates a new Screen structure and any privates
 | |
| that are required.  It then initializes some of the fields in the Screen
 | |
| struct and sets up the pixmap padding information.  Finally, it calls
 | |
| the DDX screen initialization function ScreenInit(), which is described
 | |
| below.  It returns the number of the screen that were just added, or -1
 | |
| if there is insufficient memory to add the screen or if the DDX screen
 | |
| initialization fails.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>ScreenInit()</title>
 | |
| 
 | |
| <para>This DDX function initializes the rest of the Screen structure with
 | |
| either generic or screen-specific functions (as necessary).  It also
 | |
| fills in various screen attributes (e.g., width and height in
 | |
| millimeters, black and white pixel values).
 | |
| </para>
 | |
| 
 | |
| <para>The screen init function usually calls several functions to perform
 | |
| certain screen initialization functions.  They are described below:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>{mi,*fb}ScreenInit()</term>
 | |
| <listitem>
 | |
| <para>The DDX layer's ScreenInit() function usually
 | |
| calls another layer's ScreenInit() function (e.g., miScreenInit() or
 | |
| fbScreenInit()) to initialize the fallbacks that the DDX driver does not
 | |
| specifically handle.
 | |
| </para>
 | |
| 
 | |
| <para>After calling another layer's ScreenInit() function, any
 | |
| screen-specific functions either wrap or replace the other layer's
 | |
| function pointers.  If a function is to be wrapped, each of the old
 | |
| function pointers from the other layer are stored in a screen private
 | |
| area.  Common functions to wrap are CloseScreen() and SaveScreen().
 | |
| </para></listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>miDCInitialize()</term>
 | |
| <listitem>
 | |
| <para>This MI function initializes the MI cursor
 | |
| display structures and function pointers.  If a hardware cursor is used,
 | |
| the DDX layer's ScreenInit() function will wrap additional screen and
 | |
| the MI cursor display function pointers.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>Another common task for ScreenInit() function is to initialize the
 | |
| output device state.  For example, in the XFree86 X server, the
 | |
| ScreenInit() function saves the original state of the video card and
 | |
| then initializes the video mode of the graphics device.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>CloseScreen()</title>
 | |
| 
 | |
| <para>This function restores any wrapped screen functions (and in
 | |
| particular the wrapped CloseScreen() function) and restores the state of
 | |
| the output device to its original state.  It should also free any
 | |
| private data it created during the screen initialization.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>GC operations</title>
 | |
| 
 | |
| <para>When the X server is requested to render drawing primitives, it does
 | |
| so by calling drawing functions through the graphics context's operation
 | |
| function pointer table (i.e., the GCOps functions).  These functions
 | |
| render the basic graphics operations such as drawing rectangles, lines,
 | |
| text or copying pixmaps.  Default routines are provided either by the MI
 | |
| layer, which draws indirectly through a simple span interface, or by the
 | |
| framebuffer layers (e.g., CFB, MFB, FB), which draw directly to a
 | |
| linearly mapped frame buffer.
 | |
| </para>
 | |
| 
 | |
| <para>To take advantage of special hardware on the graphics device,
 | |
| specific GCOps functions can be replaced by device specific code.
 | |
| However, many times the graphics devices can handle only a subset of the
 | |
| possible states of the GC, so during graphics context validation,
 | |
| appropriate routines are selected based on the state and capabilities of
 | |
| the hardware.  For example, some graphics hardware can accelerate single
 | |
| pixel width lines with certain dash patterns.  Thus, for dash patterns
 | |
| that are not supported by hardware or for width 2 or greater lines, the
 | |
| default routine is chosen during GC validation.
 | |
| </para>
 | |
| 
 | |
| <para>Note that some pointers to functions that draw to the screen are
 | |
| stored in the Screen structure.  They include GetImage(), GetSpans(),
 | |
| CopyWindow() and RestoreAreas().
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Xnest</title>
 | |
| 
 | |
| <para>The Xnest X server is a special proxy X server that relays the X
 | |
| protocol requests that it receives to a ``real'' X server that then
 | |
| processes the requests and displays the results, if applicable.  To the X
 | |
| applications, Xnest appears as if it is a regular X server.  However,
 | |
| Xnest is both server to the X application and client of the real X
 | |
| server, which will actually handle the requests.
 | |
| </para>
 | |
| 
 | |
| <para>The Xnest server implements all of the standard input and output
 | |
| initialization steps outlined above.
 | |
| </para>
 | |
| 
 | |
| <para><variablelist>
 | |
| <varlistentry>
 | |
| <term>InitOutput()</term>
 | |
| <listitem>
 | |
| <para>Xnest takes its configuration information from
 | |
| command line arguments via ddxProcessArguments().  This information
 | |
| includes the real X server display to connect to, its default visual
 | |
| class, the screen depth, the Xnest window's geometry, etc.  Xnest then
 | |
| connects to the real X server and gathers visual, colormap, depth and
 | |
| pixmap information about that server's display, creates a window on that
 | |
| server, which will be used as the root window for Xnest.
 | |
| </para>
 | |
| 
 | |
| <para>Next, Xnest initializes its internal data structures and uses the
 | |
| data from the real X server's pixmaps to initialize its own pixmap
 | |
| formats.  Finally, it calls AddScreen(xnestOpenScreen, argc, argv) to
 | |
| initialize each of its screens.
 | |
| </para></listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>ScreenInit()</term>
 | |
| <listitem>
 | |
| <para>Xnest's ScreenInit() function is called
 | |
| xnestOpenScreen().  This function initializes its screen's depth and
 | |
| visual information, and then calls miScreenInit() to set up the default
 | |
| screen functions.  It then calls miDCInitialize() to initialize the
 | |
| software cursor.
 | |
| Finally, it replaces many of the screen functions with its own
 | |
| functions that repackage and send the requests to the real X server to
 | |
| which Xnest is attached.
 | |
| </para></listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>CloseScreen()</term>
 | |
| <listitem>
 | |
| <para>This function frees its internal data structure
 | |
| allocations.  Since it replaces instead of wrapping screen functions,
 | |
| there are no function pointers to unwrap.  This can potentially lead to
 | |
| problems during server regeneration.
 | |
| </para></listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>GC operations</term>
 | |
| <listitem>
 | |
| <para>The GC operations in Xnest are very simple since
 | |
| they leave all of the drawing to the real X server to which Xnest is
 | |
| attached.  Each of the GCOps takes the request and sends it to the
 | |
| real X server using standard Xlib calls.  For example, the X
 | |
| application issues a XDrawLines() call.  This function turns into a
 | |
| protocol request to Xnest, which calls the xnestPolylines() function
 | |
| through Xnest's GCOps function pointer table.  The xnestPolylines()
 | |
| function is only a single line, which calls XDrawLines() using the same
 | |
| arguments that were passed into it.  Other GCOps functions are very
 | |
| similar.  Two exceptions to the simple GCOps functions described above
 | |
| are the image functions and the BLT operations.
 | |
| </para>
 | |
| 
 | |
| <para>The image functions, GetImage() and PutImage(), must use a temporary
 | |
| image to hold the image to be put of the image that was just grabbed
 | |
| from the screen while it is in transit to the real X server or the
 | |
| client.  When the image has been transmitted, the temporary image is
 | |
| destroyed.
 | |
| </para>
 | |
| 
 | |
| <para>The BLT operations, CopyArea() and CopyPlane(), handle not only the
 | |
| copy function, which is the same as the simple cases described above,
 | |
| but also the graphics exposures that result when the GC's graphics
 | |
| exposure bit is set to True.  Graphics exposures are handled in a helper
 | |
| function, xnestBitBlitHelper().  This function collects the exposure
 | |
| events from the real X server and, if any resulting in regions being
 | |
| exposed, then those regions are passed back to the MI layer so that it
 | |
| can generate exposure events for the X application.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>The Xnest server takes its input from the X server to which it is
 | |
| connected.  When the mouse is in the Xnest server's window, keyboard and
 | |
| mouse events are received by the Xnest server, repackaged and sent back
 | |
| to any client that requests those events.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Shadow framebuffer</title>
 | |
| 
 | |
| <para>The most common type of framebuffer is a linear array memory that
 | |
| maps to the video memory on the graphics device.  However, accessing
 | |
| that video memory over an I/O bus (e.g., ISA or PCI) can be slow.  The
 | |
| shadow framebuffer layer allows the developer to keep the entire
 | |
| framebuffer in main memory and copy it back to video memory at regular
 | |
| intervals.  It also has been extended to handle planar video memory and
 | |
| rotated framebuffers.
 | |
| </para>
 | |
| 
 | |
| <para>There are two main entry points to the shadow framebuffer code:
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>shadowAlloc(width, height, bpp)</term>
 | |
| <listitem>
 | |
| <para>This function allocates the in
 | |
| memory copy of the framebuffer of size width*height*bpp.  It returns a
 | |
| pointer to that memory, which will be used by the framebuffer
 | |
| ScreenInit() code during the screen's initialization.
 | |
| </para></listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>shadowInit(pScreen, updateProc, windowProc)</term>
 | |
| <listitem>
 | |
| <para>This function
 | |
| initializes the shadow framebuffer layer.  It wraps several screen
 | |
| drawing functions, and registers a block handler that will update the
 | |
| screen.  The updateProc is a function that will copy the damaged regions
 | |
| to the screen, and the windowProc is a function that is used when the
 | |
| entire linear video memory range cannot be accessed simultaneously so
 | |
| that only a window into that memory is available (e.g., when using the
 | |
| VGA aperture).
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| 
 | |
| <para>The shadow framebuffer code keeps track of the damaged area of each
 | |
| screen by calculating the bounding box of all drawing operations that
 | |
| have occurred since the last screen update.  Then, when the block handler
 | |
| is next called, only the damaged portion of the screen is updated.
 | |
| </para>
 | |
| 
 | |
| <para>Note that since the shadow framebuffer is kept in main memory, all
 | |
| drawing operations are performed by the CPU and, thus, no accelerated
 | |
| hardware drawing operations are possible.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Xinerama</title>
 | |
| 
 | |
| <para>Xinerama is an X extension that allows multiple physical screens
 | |
| controlled by a single X server to appear as a single screen.  Although
 | |
| the extension allows clients to find the physical screen layout via
 | |
| extension requests, it is completely transparent to clients at the core
 | |
| X11 protocol level.  The original public implementation of Xinerama came
 | |
| from Digital/Compaq.  XFree86 rewrote it, filling in some missing pieces
 | |
| and improving both X11 core protocol compliance and performance.  The
 | |
| Xinerama extension will be passing through X.Org's standardization
 | |
| process in the near future, and the sample implementation will be based
 | |
| on this rewritten version.
 | |
| </para>
 | |
| 
 | |
| <para>The current implementation of Xinerama is based primarily in the DIX
 | |
| (device independent) and MI (machine independent) layers of the X
 | |
| server.  With few exceptions the DDX layers do not need any changes to
 | |
| support Xinerama.  X server extensions often do need modifications to
 | |
| provide full Xinerama functionality.
 | |
| </para>
 | |
| 
 | |
| <para>The following is a code-level description of how Xinerama functions.
 | |
| </para>
 | |
| 
 | |
| <para>Note: Because the Xinerama extension was originally called the
 | |
| PanoramiX extension, many of the Xinerama functions still have the
 | |
| PanoramiX prefix.
 | |
| </para>
 | |
| 
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>PanoramiXExtensionInit()</term>
 | |
| <listitem>
 | |
|     <para>PanoramiXExtensionInit() is a
 | |
|     device-independent extension function that is called at the start of
 | |
|     each server generation from InitExtensions(), which is called from
 | |
|     the X server's main() function after all output devices have been
 | |
|     initialized, but before any input devices have been initialized.
 | |
|     </para>
 | |
| 
 | |
|     <para>PanoramiXNumScreens is set to the number of physical screens.  If
 | |
|     only one physical screen is present, the extension is disabled, and
 | |
|     PanoramiXExtensionInit() returns without doing anything else.
 | |
|     </para>
 | |
| 
 | |
|     <para>The Xinerama extension is registered by calling AddExtension().
 | |
|     </para>
 | |
| 
 | |
|     <para>GC and Screen private
 | |
|     indexes are allocated, and both GC and Screen private areas are
 | |
|     allocated for each physical screen.  These hold Xinerama-specific
 | |
|     per-GC and per-Screen data.  Each screen's CreateGC and CloseScreen
 | |
|     functions are wrapped by XineramaCreateGC() and
 | |
|     XineramaCloseScreen() respectively.  Some new resource classes are
 | |
|     created for Xinerama drawables and GCs, and resource types for
 | |
|     Xinerama windows, pixmaps and colormaps.
 | |
|     </para>
 | |
| 
 | |
|     <para>A region (PanoramiXScreenRegion) is
 | |
|     initialized to be the union of the screen regions.
 | |
|     The relative positioning information for the
 | |
|     physical screens is taken from the ScreenRec x and y members, which
 | |
|     the DDX layer must initialize in InitOutput().  The bounds of the
 | |
|     combined screen is also calculated (PanoramiXPixWidth and
 | |
|     PanoramiXPixHeight).
 | |
|     </para>
 | |
| 
 | |
|     <para>The DIX layer has a list of function pointers
 | |
|     (ProcVector[]) that
 | |
|     holds the entry points for the functions that process core protocol
 | |
|     requests.  The requests that Xinerama must intercept and break up
 | |
|     into physical screen-specific requests are wrapped.  The original
 | |
|     set is copied to SavedProcVector[].  The types of requests
 | |
|     intercepted are Window requests, GC requests, colormap requests,
 | |
|     drawing requests, and some geometry-related requests.  This wrapping
 | |
|     allows the bulk of the protocol request processing to be handled
 | |
|     transparently to the DIX layer.  Some operations cannot be dealt with
 | |
|     in this way and are handled with Xinerama-specific code within the
 | |
|     DIX layer.
 | |
|     </para>
 | |
| </listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>PanoramiXConsolidate()</term>
 | |
| <listitem>
 | |
|     <para>PanoramiXConsolidate() is a
 | |
|     device-independent extension function that is called directly from
 | |
|     the X server's main() function after extensions and input/output
 | |
|     devices have been initialized, and before the root windows are
 | |
|     defined and initialized.
 | |
| </para>
 | |
| 
 | |
|     <para>This function finds the set of depths (PanoramiXDepths[]) and
 | |
|     visuals (PanoramiXVisuals[])
 | |
|     common to all of the physical screens.
 | |
|     PanoramiXNumDepths is set to the number of common depths, and
 | |
|     PanoramiXNumVisuals is set to the number of common visuals.
 | |
|     Resources are created for the single root window and the default
 | |
|     colormap.  Each of these resources has per-physical screen entries.
 | |
|     </para>
 | |
| </listitem></varlistentry>
 | |
| 
 | |
| <varlistentry>
 | |
| <term>PanoramiXCreateConnectionBlock()</term>
 | |
| <listitem>
 | |
|     <para>PanoramiXConsolidate() is a
 | |
|     device-independent extension function that is called directly from
 | |
|     the X server's main() function after the per-physical screen root
 | |
|     windows are created.  It is called instead of the standard DIX
 | |
|     CreateConnectionBlock() function.  If this function returns FALSE,
 | |
|     the X server exits with a fatal error.  This function will return
 | |
|     FALSE if no common depths were found in PanoramiXConsolidate().
 | |
|     With no common depths, Xinerama mode is not possible.
 | |
|     </para>
 | |
| 
 | |
|     <para>The connection block holds the information that clients get when
 | |
|     they open a connection to the X server.  It includes information
 | |
|     such as the supported pixmap formats, number of screens and the
 | |
|     sizes, depths, visuals, default colormap information, etc, for each
 | |
|     of the screens (much of information that <command>xdpyinfo</command> shows).  The
 | |
|     connection block is initialized with the combined single screen
 | |
|     values that were calculated in the above two functions.
 | |
|     </para>
 | |
| 
 | |
|     <para>The Xinerama extension allows the registration of connection
 | |
|     block callback functions.  The purpose of these is to allow other
 | |
|     extensions to do processing at this point.  These callbacks can be
 | |
|     registered by calling XineramaRegisterConnectionBlockCallback() from
 | |
|     the other extension's ExtensionInit() function.  Each registered
 | |
|     connection block callback is called at the end of
 | |
|     PanoramiXCreateConnectionBlock().
 | |
|     </para>
 | |
| </listitem></varlistentry>
 | |
| </variablelist>
 | |
| 
 | |
| <sect3>
 | |
| <title>Xinerama-specific changes to the DIX code</title>
 | |
| 
 | |
| <para>There are a few types of Xinerama-specific changes within the DIX
 | |
| code.  The main ones are described here.
 | |
| </para>
 | |
| 
 | |
| <para>Functions that deal with colormap or GC -related operations outside of
 | |
| the intercepted protocol requests have a test added to only do the
 | |
| processing for screen numbers > 0.  This is because they are handled for
 | |
| the single Xinerama screen and the processing is done once for screen 0.
 | |
| </para>
 | |
| 
 | |
| <para>The handling of motion events does some coordinate translation between
 | |
| the physical screen's origin and screen zero's origin.  Also, motion
 | |
| events must be reported relative to the composite screen origin rather
 | |
| than the physical screen origins.
 | |
| </para>
 | |
| 
 | |
| <para>There is some special handling for cursor, window and event processing
 | |
| that cannot (either not at all or not conveniently) be done via the
 | |
| intercepted protocol requests.  A particular case is the handling of
 | |
| pointers moving between physical screens.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Xinerama-specific changes to the MI code</title>
 | |
| 
 | |
| <para>The only Xinerama-specific change to the MI code is in miSendExposures()
 | |
| to handle the coordinate (and window ID) translation for expose events.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Intercepted DIX core requests</title>
 | |
| 
 | |
| <para>Xinerama breaks up drawing requests for dispatch to each physical
 | |
| screen.  It also breaks up windows into pieces for each physical screen.
 | |
| GCs are translated into per-screen GCs.  Colormaps are replicated on
 | |
| each physical screen.  The functions handling the intercepted requests
 | |
| take care of breaking the requests and repackaging them so that they can
 | |
| be passed to the standard request handling functions for each screen in
 | |
| turn.  In addition, and to aid the repackaging, the information from
 | |
| many of the intercepted requests is used to keep up to date the
 | |
| necessary state information for the single composite screen.  Requests
 | |
| (usually those with replies) that can be satisfied completely from this
 | |
| stored state information do not call the standard request handling
 | |
| functions.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| </sect1>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| 
 | |
| <sect1>
 | |
| <title>Development Results</title>
 | |
| 
 | |
| <para>In this section the results of each phase of development are
 | |
| discussed.  This development took place between approximately June 2001
 | |
| and July 2003.
 | |
| </para>
 | |
| 
 | |
| <sect2>
 | |
| <title>Phase I</title>
 | |
| 
 | |
| <para>The initial development phase dealt with the basic implementation
 | |
| including the bootstrap code, which used the shadow framebuffer, and the
 | |
| unoptimized implementation, based on an Xnest-style implementation.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>Scope</title>
 | |
| 
 | |
| <para>The goal of Phase I is to provide fundamental functionality that can
 | |
| act as a foundation for ongoing work:
 | |
| <orderedlist>
 | |
| <listitem>
 | |
|     <para>Develop the proxy X server
 | |
|     <itemizedlist>
 | |
| 	<listitem>
 | |
| 	<para>The proxy X server will operate on the X11 protocol and
 | |
| 	relay requests as necessary to correctly perform the request.
 | |
| 	</para></listitem>
 | |
| 	<listitem>
 | |
| 	<para>Work will be based on the existing work for Xinerama and
 | |
| 	Xnest.
 | |
| 	</para></listitem>
 | |
| 	<listitem>
 | |
| 	<para>Input events and windowing operations are handled in the
 | |
| 	proxy server and rendering requests are repackaged and sent to
 | |
| 	each of the back-end servers for display.
 | |
| 	</para></listitem>
 | |
| 	<listitem>
 | |
| 	<para>The multiple screen layout (including support for
 | |
| 	overlapping screens) will be user configurable via a
 | |
| 	configuration file or through the configuration tool.
 | |
| 	</para></listitem>
 | |
|     </itemizedlist>
 | |
|     </para></listitem>
 | |
|     <listitem>
 | |
|     <para>Develop graphical configuration tool
 | |
|     <itemizedlist>
 | |
| 	<listitem>
 | |
| 	<para>There will be potentially a large number of X servers to
 | |
| 	configure into a single display.  The tool will allow the user
 | |
| 	to specify which servers are involved in the configuration and
 | |
| 	how they should be laid out.
 | |
| 	</para></listitem>
 | |
|     </itemizedlist>
 | |
|     </para></listitem>
 | |
|     <listitem>
 | |
|     <para>Pass the X Test Suite
 | |
|     <itemizedlist>
 | |
| 	<listitem>
 | |
| 	<para>The X Test Suite covers the basic X11 operations.  All
 | |
| 	tests known to succeed must correctly operate in the distributed
 | |
| 	X environment.
 | |
| 	</para></listitem>
 | |
|     </itemizedlist>
 | |
|     </para></listitem>
 | |
| </orderedlist>
 | |
| 
 | |
| </para>
 | |
| 
 | |
| <para>For this phase, the back-end X servers are assumed to be unmodified X
 | |
| servers that do not support any DMX-related protocol extensions; future
 | |
| optimization pathways are considered, but are not implemented; and the
 | |
| configuration tool is assumed to rely only on libraries in the X source
 | |
| tree (e.g., Xt).
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Results</title>
 | |
| 
 | |
| <para>The proxy X server, Xdmx, was developed to distribute X11 protocol
 | |
| requests to the set of back-end X servers.  It opens a window on each
 | |
| back-end server, which represents the part of the front-end's root
 | |
| window that is visible on that screen.  It mirrors window, pixmap and
 | |
| other state in each back-end server.  Drawing requests are sent to
 | |
| either windows or pixmaps on each back-end server.  This code is based
 | |
| on Xnest and uses the existing Xinerama extension.
 | |
| </para>
 | |
| 
 | |
| <para>Input events can be taken from (1) devices attached to the back-end
 | |
| server, (2) core devices attached directly to the Xdmx server, or (3)
 | |
| from a ``console'' window on another X server.  Events for these devices
 | |
| are gathered, processed and delivered to clients attached to the Xdmx
 | |
| server.
 | |
| </para>
 | |
| 
 | |
| <para>An intuitive configuration format was developed to help the user
 | |
| easily configure the multiple back-end X servers.  It was defined (see
 | |
| grammar in Xdmx man page) and a parser was implemented that is used by
 | |
| the Xdmx server and by a standalone xdmxconfig utility.  The parsing
 | |
| support was implemented such that it can be easily factored out of the X
 | |
| source tree for use with other tools (e.g., vdl).  Support for
 | |
| converting legacy vdl-format configuration files to the DMX format is
 | |
| provided by the vdltodmx utility.
 | |
| </para>
 | |
| 
 | |
| <para>Originally, the configuration file was going to be a subsection of
 | |
| XFree86's XF86Config file, but that was not possible since Xdmx is a
 | |
| completely separate X server.  Thus, a separate config file format was
 | |
| developed.  In addition, a graphical configuration
 | |
| tool, xdmxconfig, was developed to allow the user to create and arrange
 | |
| the screens in the configuration file.  The <emphasis remap="bf">-configfile</emphasis> and <emphasis remap="bf">-config</emphasis>
 | |
| command-line options can be used to start Xdmx using a configuration
 | |
| file.
 | |
| </para>
 | |
| 
 | |
| <para>An extension that enables remote input testing is required for the X
 | |
| Test Suite to function.  During this phase, this extension (XTEST) was
 | |
| implemented in the Xdmx server.  The results from running the X Test
 | |
| Suite are described in detail below.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>X Test Suite</title>
 | |
| 
 | |
|         <sect4>
 | |
|           <title>Introduction</title>
 | |
|             <para>
 | |
|               The X Test Suite contains tests that verify Xlib functions
 | |
|               operate correctly.  The test suite is designed to run on a
 | |
|               single X server; however, since X applications will not be
 | |
|               able to tell the difference between the DMX server and a
 | |
|               standard X server, the X Test Suite should also run on the
 | |
|               DMX server.
 | |
|             </para>
 | |
|             <para>
 | |
|               The Xdmx server was tested with the X Test Suite, and the
 | |
|               existing failures are noted in this section.  To put these
 | |
|               results in perspective, we first discuss expected X Test
 | |
|               failures and how errors in underlying systems can impact
 | |
|               Xdmx test results.
 | |
|             </para>
 | |
|         </sect4>
 | |
| 
 | |
|         <sect4>
 | |
|           <title>Expected Failures for a Single Head</title>
 | |
|             <para>
 | |
|               A correctly implemented X server with a single screen is
 | |
|               expected to fail certain X Test tests.  The following
 | |
|               well-known errors occur because of rounding error in the X
 | |
|               server code:
 | |
|               <literallayout>
 | |
| XDrawArc: Tests 42, 63, 66, 73
 | |
| XDrawArcs: Tests 45, 66, 69, 76
 | |
|               </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               The following failures occur because of the high-level X
 | |
|               server implementation:
 | |
|               <literallayout>
 | |
| XLoadQueryFont: Test 1
 | |
| XListFontsWithInfo: Tests 3, 4
 | |
| XQueryFont: Tests 1, 2
 | |
|               </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               The following test fails when running the X server as root
 | |
|               under Linux because of the way directory modes are
 | |
|               interpreted:
 | |
|               <literallayout>
 | |
| XWriteBitmapFile: Test 3
 | |
|               </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               Depending on the video card used for the back-end, other
 | |
|               failures may also occur because of bugs in the low-level
 | |
|               driver implementation.  Over time, failures of this kind
 | |
|               are usually fixed by XFree86, but will show up in Xdmx
 | |
|               testing until then.
 | |
|             </para>
 | |
|         </sect4>
 | |
| 
 | |
|         <sect4>
 | |
|           <title>Expected Failures for Xinerama</title>
 | |
|             <para>
 | |
|               Xinerama fails several X Test Suite tests because of
 | |
|               design decisions made for the current implementation of
 | |
|               Xinerama.  Over time, many of these errors will be
 | |
|               corrected by XFree86 and the group working on a new
 | |
|               Xinerama implementation.  Therefore, Xdmx will also share
 | |
|               X Suite Test failures with Xinerama.
 | |
|             </para>
 | |
| 
 | |
|             <para>
 | |
|               We may be able to fix or work-around some of these
 | |
|               failures at the Xdmx level, but this will require
 | |
|               additional exploration that was not part of Phase I.
 | |
|             </para>
 | |
| 
 | |
|             <para>
 | |
|               Xinerama is constantly improving, and the list of
 | |
|               Xinerama-related failures depends on XFree86 version and
 | |
|               the underlying graphics hardware.  We tested with a
 | |
|               variety of hardware, including nVidia, S3, ATI Radeon,
 | |
|               and Matrox G400 (in dual-head mode).  The list below
 | |
|               includes only those failures that appear to be from the
 | |
|               Xinerama layer, and does not include failures listed in
 | |
|               the previous section, or failures that appear to be from
 | |
|               the low-level graphics driver itself:
 | |
|             </para>
 | |
| 
 | |
|             <para>
 | |
|               These failures were noted with multiple Xinerama
 | |
|               configurations:
 | |
|               <literallayout>
 | |
| XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue)
 | |
| XSetFontPath: Test 4
 | |
| XGetDefault: Test 5
 | |
| XMatchVisualInfo: Test 1
 | |
|               </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               These failures were noted only when using one dual-head
 | |
|               video card with a 4.2.99.x XFree86 server:
 | |
|               <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XDrawRectangles: Test 45
 | |
|               </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               These failures were noted only when using two video cards
 | |
|               from different vendors with a 4.1.99.x XFree86 server:
 | |
|               <literallayout>
 | |
| XChangeWindowAttributes: Test 32
 | |
| XCreateWindow: Test 30
 | |
| XDrawLine: Test 22
 | |
| XFillArc: Test 22
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XRebindKeysym: Test 1
 | |
|               </literallayout>
 | |
|             </para>
 | |
|         </sect4>
 | |
| 
 | |
|         <sect4>
 | |
| 	  <title>Additional Failures from Xdmx</title>
 | |
| 
 | |
|             <para>
 | |
|               When running Xdmx, no unexpected failures were noted.
 | |
|               Since the Xdmx server is based on Xinerama, we expect to
 | |
|               have most of the Xinerama failures present in the Xdmx
 | |
|               server.  Similarly, since the Xdmx server must rely on the
 | |
|               low-level device drivers on each back-end server, we also
 | |
|               expect that Xdmx will exhibit most of the back-end
 | |
|               failures.  Here is a summary:
 | |
|               <literallayout>
 | |
| XListPixmapFormats: Test 1 (configuration dependent)
 | |
| XChangeWindowAttributes: Test 32
 | |
| XCreateWindow: Test 30
 | |
| XCopyPlane: Test 13, 22, 31
 | |
| XSetFontPath: Test 4
 | |
| XGetDefault: Test 5 (configuration dependent)
 | |
| XMatchVisualInfo: Test 1
 | |
| XRebindKeysym: Test 1 (configuration dependent)
 | |
|                 </literallayout>
 | |
|             </para>
 | |
|             <para>
 | |
|               Note that this list is shorter than the combined list for
 | |
|               Xinerama because Xdmx uses different code paths to perform
 | |
|               some Xinerama operations.  Further, some Xinerama failures
 | |
|               have been fixed in the XFree86 4.2.99.x CVS repository.
 | |
|             </para>
 | |
|         </sect4>
 | |
| 
 | |
|         <sect4>
 | |
|           <title>Summary and Future Work</title>
 | |
| 
 | |
|             <para>
 | |
|               Running the X Test Suite on Xdmx does not produce any
 | |
|               failures that cannot be accounted for by the underlying
 | |
|               Xinerama subsystem used by the front-end or by the
 | |
|               low-level device-driver code running on the back-end X
 | |
|               servers.  The Xdmx server therefore is as ``correct'' as
 | |
|               possible with respect to the standard set of X Test Suite
 | |
|               tests.
 | |
|             </para>
 | |
| 
 | |
|             <para>
 | |
|               During the following phases, we will continue to verify
 | |
|               Xdmx correctness using the X Test Suite.  We may also use
 | |
|               other tests suites or write additional tests that run
 | |
|               under the X Test Suite that specifically verify the
 | |
|               expected behavior of DMX.
 | |
|             </para>
 | |
|         </sect4>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Fonts</title>
 | |
| 
 | |
| <para>In Phase I, fonts are handled directly by both the front-end and the
 | |
| back-end servers, which is required since we must treat each back-end
 | |
| server during this phase as a ``black box''.  What this requires is that
 | |
| <emphasis remap="bf">the front- and back-end servers must share the exact same font
 | |
| path</emphasis>.  There are two ways to help make sure that all servers share the
 | |
| same font path:
 | |
| 
 | |
| <orderedlist>
 | |
|   <listitem>
 | |
|     <para>First, each server can be configured to use the same font
 | |
|     server.  The font server, xfs, can be configured to serve fonts to
 | |
|     multiple X servers via TCP.
 | |
|     </para></listitem>
 | |
| 
 | |
|   <listitem>
 | |
|     <para>Second, each server can be configured to use the same font
 | |
|     path and either those font paths can be copied to each back-end
 | |
|     machine or they can be mounted (e.g., via NFS) on each back-end
 | |
|     machine.
 | |
|     </para></listitem>
 | |
| </orderedlist>
 | |
| </para>
 | |
| 
 | |
| <para>One additional concern is that a client program can set its own font
 | |
| path, and if it does so, then that font path must be available on each
 | |
| back-end machine.
 | |
| </para>
 | |
| 
 | |
| <para>The -fontpath command line option was added to allow users to
 | |
| initialize the font path of the front end server.  This font path is
 | |
| propagated to each back-end server when the default font is loaded.  If
 | |
| there are any problems, an error message is printed, which will describe
 | |
| the problem and list the current font path.  For more information about
 | |
| setting the font path, see the -fontpath option description in the man
 | |
| page.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Performance</title>
 | |
| 
 | |
| <para>Phase I of development was not intended to optimize performance.  Its
 | |
| focus was on completely and correctly handling the base X11 protocol in
 | |
| the Xdmx server.  However, several insights were gained during Phase I,
 | |
| which are listed here for reference during the next phase of
 | |
| development.
 | |
| </para>
 | |
| 
 | |
| <orderedlist>
 | |
|   <listitem>
 | |
|     <para>Calls to XSync() can slow down rendering since it requires a
 | |
|     complete round trip to and from a back-end server.  This is
 | |
|     especially problematic when communicating over long haul networks.
 | |
|     </para></listitem>
 | |
| 
 | |
|   <listitem>
 | |
|     <para>Sending drawing requests to only the screens that they overlap
 | |
|     should improve performance.
 | |
|     </para></listitem>
 | |
| </orderedlist>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Pixmaps</title>
 | |
| 
 | |
| <para>Pixmaps were originally expected to be handled entirely in the
 | |
| front-end X server; however, it was found that this overly complicated
 | |
| the rendering code and would have required sending potentially large
 | |
| images to each back server that required them when copying from pixmap
 | |
| to screen.  Thus, pixmap state is mirrored in the back-end server just
 | |
| as it is with regular window state.  With this implementation, the same
 | |
| rendering code that draws to windows can be used to draw to pixmaps on
 | |
| the back-end server, and no large image transfers are required to copy
 | |
| from pixmap to window.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| <sect2>
 | |
| <title>Phase II</title>
 | |
| 
 | |
| <para>The second phase of development concentrates on performance
 | |
| optimizations.  These optimizations are documented here, with
 | |
| <command>x11perf</command> data to show how the optimizations improve performance.
 | |
| </para>
 | |
| 
 | |
| <para>All benchmarks were performed by running Xdmx on a dual processor
 | |
| 1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to
 | |
| two single-processor 1GHz Pentium III machines with 256MB of RAM and ATI
 | |
| Rage 128 (RF) video cards.  The front end was running Linux
 | |
| 2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and
 | |
| version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on
 | |
| August 7, 2002.  All systems were running Red Hat Linux 7.2.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>Moving from XFree86 4.1.99.1 to 4.2.0.0</title>
 | |
| 
 | |
| <para>For phase II, the working source tree was moved to the branch tagged
 | |
| with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August
 | |
| 2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002).
 | |
| After this update, the following tests were noted to be more than 10%
 | |
| faster:
 | |
| <screen>
 | |
| 1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple)
 | |
| 1.16   Fill 1x1 tiled trapezoid (161x145 tile)
 | |
| 1.13   Fill 10x10 tiled trapezoid (161x145 tile)
 | |
| 1.17   Fill 100x100 tiled trapezoid (161x145 tile)
 | |
| 1.16   Fill 1x1 tiled trapezoid (216x208 tile)
 | |
| 1.20   Fill 10x10 tiled trapezoid (216x208 tile)
 | |
| 1.15   Fill 100x100 tiled trapezoid (216x208 tile)
 | |
| 1.37   Circulate Unmapped window (200 kids)
 | |
| </screen>
 | |
| And the following tests were noted to be more than 10% slower:
 | |
| <screen>
 | |
| 0.88   Unmap window via parent (25 kids)
 | |
| 0.75   Circulate Unmapped window (4 kids)
 | |
| 0.79   Circulate Unmapped window (16 kids)
 | |
| 0.80   Circulate Unmapped window (25 kids)
 | |
| 0.82   Circulate Unmapped window (50 kids)
 | |
| 0.85   Circulate Unmapped window (75 kids)
 | |
| </screen>
 | |
| </para>
 | |
| 
 | |
| <para>These changes were not caused by any changes in the DMX system, and
 | |
| may point to changes in the XFree86 tree or to tests that have more
 | |
| "jitter" than most other <command>x11perf</command> tests.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Global changes</title>
 | |
| 
 | |
| <para>During the development of the Phase II DMX server, several global
 | |
| changes were made.  These changes were also compared with the Phase I
 | |
| server.  The following tests were noted to be more than 10% faster:
 | |
| <screen>
 | |
| 1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple)
 | |
| 1.15   Fill 1x1 tiled trapezoid (161x145 tile)
 | |
| 1.13   Fill 10x10 tiled trapezoid (161x145 tile)
 | |
| 1.17   Fill 100x100 tiled trapezoid (161x145 tile)
 | |
| 1.16   Fill 1x1 tiled trapezoid (216x208 tile)
 | |
| 1.19   Fill 10x10 tiled trapezoid (216x208 tile)
 | |
| 1.15   Fill 100x100 tiled trapezoid (216x208 tile)
 | |
| 1.15   Circulate Unmapped window (4 kids)
 | |
| </screen>
 | |
| </para>
 | |
| 
 | |
| <para>The following tests were noted to be more than 10% slower:
 | |
| <screen>
 | |
| 0.69   Scroll 10x10 pixels
 | |
| 0.68   Scroll 100x100 pixels
 | |
| 0.68   Copy 10x10 from window to window
 | |
| 0.68   Copy 100x100 from window to window
 | |
| 0.76   Circulate Unmapped window (75 kids)
 | |
| 0.83   Circulate Unmapped window (100 kids)
 | |
| </screen>
 | |
| </para>
 | |
| 
 | |
| <para>For the remainder of this analysis, the baseline of comparison will
 | |
| be the Phase II deliverable with all optimizations disabled (unless
 | |
| otherwise noted).  This will highlight how the optimizations in
 | |
| isolation impact performance.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>XSync() Batching</title>
 | |
| 
 | |
| <para>During the Phase I implementation, XSync() was called after every
 | |
| protocol request made by the DMX server.  This provided the DMX server
 | |
| with an interactive feel, but defeated X11's protocol buffering system
 | |
| and introduced round-trip wire latency into every operation.  During
 | |
| Phase II, DMX was changed so that protocol requests are no longer
 | |
| followed by calls to XSync().  Instead, the need for an XSync() is
 | |
| noted, and XSync() calls are only made every 100mS or when the DMX
 | |
| server specifically needs to make a call to guarantee interactivity.
 | |
| With this new system, X11 buffers protocol as much as possible during a
 | |
| 100mS interval, and many unnecessary XSync() calls are avoided.
 | |
| </para>
 | |
| 
 | |
| <para>Out of more than 300 <command>x11perf</command> tests, 8 tests became more than 100
 | |
| times faster, with 68 more than 50X faster, 114 more than 10X faster,
 | |
| and 181 more than 2X faster.  See table below for summary.
 | |
| </para>
 | |
| 
 | |
| <para>The following tests were noted to be more than 10% slower with
 | |
| XSync() batching on:
 | |
| <screen>
 | |
| 0.88   500x500 tiled rectangle (161x145 tile)
 | |
| 0.89   Copy 500x500 from window to window
 | |
| </screen>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Offscreen Optimization</title>
 | |
| 
 | |
| <para>Windows span one or more of the back-end servers' screens; however,
 | |
| during Phase I development, windows were created on every back-end
 | |
| server and every rendering request was sent to every window regardless
 | |
| of whether or not that window was visible.  With the offscreen
 | |
| optimization, the DMX server tracks when a window is completely off of a
 | |
| back-end server's screen and, in that case, it does not send rendering
 | |
| requests to those back-end windows.  This optimization saves bandwidth
 | |
| between the front and back-end servers, and it reduces the number of
 | |
| XSync() calls.  The performance tests were run on a DMX system with only
 | |
| two back-end servers.  Greater performance gains will be had as the
 | |
| number of back-end servers increases.
 | |
| </para>
 | |
| 
 | |
| <para>Out of more than 300 <command>x11perf</command> tests, 3 tests were at least twice as
 | |
| fast, and 146 tests were at least 10% faster.  Two tests were more than
 | |
| 10% slower with the offscreen optimization:
 | |
| <screen>
 | |
| 0.88   Hide/expose window via popup (4 kids)
 | |
| 0.89   Resize unmapped window (75 kids)
 | |
| </screen>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Lazy Window Creation Optimization</title>
 | |
| 
 | |
| <para>As mentioned above, during Phase I, windows were created on every
 | |
| back-end server even if they were not visible on that back-end.  With
 | |
| the lazy window creation optimization, the DMX server does not create
 | |
| windows on a back-end server until they are either visible or they
 | |
| become the parents of a visible window.  This optimization builds on the
 | |
| offscreen optimization (described above) and requires it to be enabled.
 | |
| </para>
 | |
| 
 | |
| <para>The lazy window creation optimization works by creating the window
 | |
| data structures in the front-end server when a client creates a window,
 | |
| but delays creation of the window on the back-end server(s).  A private
 | |
| window structure in the DMX server saves the relevant window data and
 | |
| tracks changes to the window's attributes and stacking order for later
 | |
| use.  The only times a window is created on a back-end server are (1)
 | |
| when it is mapped and is at least partially overlapping the back-end
 | |
| server's screen (tracked by the offscreen optimization), or (2) when the
 | |
| window becomes the parent of a previously visible window.  The first
 | |
| case occurs when a window is mapped or when a visible window is copied,
 | |
| moved or resized and now overlaps the back-end server's screen.  The
 | |
| second case occurs when starting a window manager after having created
 | |
| windows to which the window manager needs to add decorations.
 | |
| </para>
 | |
| 
 | |
| <para>When either case occurs, a window on the back-end server is created
 | |
| using the data saved in the DMX server's window private data structure.
 | |
| The stacking order is then adjusted to correctly place the window on the
 | |
| back-end and lastly the window is mapped.  From this time forward, the
 | |
| window is handled exactly as if the window had been created at the time
 | |
| of the client's request.
 | |
| </para>
 | |
| 
 | |
| <para>Note that when a window is no longer visible on a back-end server's
 | |
| screen (e.g., it is moved offscreen), the window is not destroyed;
 | |
| rather, it is kept and reused later if the window once again becomes
 | |
| visible on the back-end server's screen.  Originally with this
 | |
| optimization, destroying windows was implemented but was later rejected
 | |
| because it increased bandwidth when windows were opaquely moved or
 | |
| resized, which is common in many window managers.
 | |
| </para>
 | |
| 
 | |
| <para>The performance tests were run on a DMX system with only two back-end
 | |
| servers.  Greater performance gains will be had as the number of
 | |
| back-end servers increases.
 | |
| </para>
 | |
| 
 | |
| <para>This optimization improved the following <command>x11perf</command> tests by more
 | |
| than 10%:
 | |
| <screen>
 | |
| 1.10   500x500 rectangle outline
 | |
| 1.12   Fill 100x100 stippled trapezoid (161x145 stipple)
 | |
| 1.20   Circulate Unmapped window (50 kids)
 | |
| 1.19   Circulate Unmapped window (75 kids)
 | |
| </screen>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Subdividing Rendering Primitives</title>
 | |
| 
 | |
| <para>X11 imaging requests transfer significant data between the client and
 | |
| the X server.  During Phase I, the DMX server would then transfer the
 | |
| image data to each back-end server.  Even with the offscreen
 | |
| optimization (above), these requests still required transferring
 | |
| significant data to each back-end server that contained a visible
 | |
| portion of the window.  For example, if the client uses XPutImage() to
 | |
| copy an image to a window that overlaps the entire DMX screen, then the
 | |
| entire image is copied by the DMX server to every back-end server.
 | |
| </para>
 | |
| 
 | |
| <para>To reduce the amount of data transferred between the DMX server and
 | |
| the back-end servers when XPutImage() is called, the image data is
 | |
| subdivided and only the data that will be visible on a back-end server's
 | |
| screen is sent to that back-end server.  Xinerama already implements a
 | |
| subdivision algorithm for XGetImage() and no further optimization was
 | |
| needed.
 | |
| </para>
 | |
| 
 | |
| <para>Other rendering primitives were analyzed, but the time required to
 | |
| subdivide these primitives was a significant proportion of the time
 | |
| required to send the entire rendering request to the back-end server, so
 | |
| this optimization was rejected for the other rendering primitives.
 | |
| </para>
 | |
| 
 | |
| <para>Again, the performance tests were run on a DMX system with only two
 | |
| back-end servers.  Greater performance gains will be had as the number
 | |
| of back-end servers increases.
 | |
| </para>
 | |
| 
 | |
| <para>This optimization improved the following <command>x11perf</command> tests by more
 | |
| than 10%:
 | |
| <screen>
 | |
| 1.12   Fill 100x100 stippled trapezoid (161x145 stipple)
 | |
| 1.26   PutImage 10x10 square
 | |
| 1.83   PutImage 100x100 square
 | |
| 1.91   PutImage 500x500 square
 | |
| 1.40   PutImage XY 10x10 square
 | |
| 1.48   PutImage XY 100x100 square
 | |
| 1.50   PutImage XY 500x500 square
 | |
| 1.45   Circulate Unmapped window (75 kids)
 | |
| 1.74   Circulate Unmapped window (100 kids)
 | |
| </screen>
 | |
| </para>
 | |
| 
 | |
| <para>The following test was noted to be more than 10% slower with this
 | |
| optimization:
 | |
| <screen>
 | |
| 0.88   10-pixel fill chord partial circle
 | |
| </screen>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Summary of x11perf Data</title>
 | |
| 
 | |
| <para>With all of the optimizations on, 53 <command>x11perf</command> tests are more than
 | |
| 100X faster than the unoptimized Phase II deliverable, with 69 more than
 | |
| 50X faster, 73 more than 10X faster, and 199 more than twice as fast.
 | |
| No tests were more than 10% slower than the unoptimized Phase II
 | |
| deliverable.  (Compared with the Phase I deliverable, only Circulate
 | |
| Unmapped window (100 kids) was more than 10% slower than the Phase II
 | |
| deliverable.  As noted above, this test seems to have wider variability
 | |
| than other <command>x11perf</command> tests.)
 | |
| </para>
 | |
| 
 | |
| <para>The following table summarizes relative <command>x11perf</command> test changes for
 | |
| all optimizations individually and collectively.  Note that some of the
 | |
| optimizations have a synergistic effect when used together.
 | |
| <screen>
 | |
| 
 | |
| 1: XSync() batching only
 | |
| 2: Off screen optimizations only
 | |
| 3: Window optimizations only
 | |
| 4: Subdivprims only
 | |
| 5: All optimizations
 | |
| 
 | |
|     1     2    3    4      5 Operation
 | |
| ------ ---- ---- ---- ------ ---------
 | |
|   2.14 1.85 1.00 1.00   4.13 Dot
 | |
|   1.67 1.80 1.00 1.00   3.31 1x1 rectangle
 | |
|   2.38 1.43 1.00 1.00   2.44 10x10 rectangle
 | |
|   1.00 1.00 0.92 0.98   1.00 100x100 rectangle
 | |
|   1.00 1.00 1.00 1.00   1.00 500x500 rectangle
 | |
|   1.83 1.85 1.05 1.06   3.54 1x1 stippled rectangle (8x8 stipple)
 | |
|   2.43 1.43 1.00 1.00   2.41 10x10 stippled rectangle (8x8 stipple)
 | |
|   0.98 1.00 1.00 1.00   1.00 100x100 stippled rectangle (8x8 stipple)
 | |
|   1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (8x8 stipple)
 | |
|   1.75 1.75 1.00 1.00   3.40 1x1 opaque stippled rectangle (8x8 stipple)
 | |
|   2.38 1.42 1.00 1.00   2.34 10x10 opaque stippled rectangle (8x8 stipple)
 | |
|   1.00 1.00 0.97 0.97   1.00 100x100 opaque stippled rectangle (8x8 stipple)
 | |
|   1.00 1.00 1.00 1.00   0.99 500x500 opaque stippled rectangle (8x8 stipple)
 | |
|   1.82 1.82 1.04 1.04   3.56 1x1 tiled rectangle (4x4 tile)
 | |
|   2.33 1.42 1.00 1.00   2.37 10x10 tiled rectangle (4x4 tile)
 | |
|   1.00 0.92 1.00 1.00   1.00 100x100 tiled rectangle (4x4 tile)
 | |
|   1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (4x4 tile)
 | |
|   1.94 1.62 1.00 1.00   3.66 1x1 stippled rectangle (17x15 stipple)
 | |
|   1.74 1.28 1.00 1.00   1.73 10x10 stippled rectangle (17x15 stipple)
 | |
|   1.00 1.00 1.00 0.89   0.98 100x100 stippled rectangle (17x15 stipple)
 | |
|   1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (17x15 stipple)
 | |
|   1.94 1.62 1.00 1.00   3.67 1x1 opaque stippled rectangle (17x15 stipple)
 | |
|   1.69 1.26 1.00 1.00   1.66 10x10 opaque stippled rectangle (17x15 stipple)
 | |
|   1.00 0.95 1.00 1.00   1.00 100x100 opaque stippled rectangle (17x15 stipple)
 | |
|   1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (17x15 stipple)
 | |
|   1.93 1.61 0.99 0.99   3.69 1x1 tiled rectangle (17x15 tile)
 | |
|   1.73 1.27 1.00 1.00   1.72 10x10 tiled rectangle (17x15 tile)
 | |
|   1.00 1.00 1.00 1.00   0.98 100x100 tiled rectangle (17x15 tile)
 | |
|   1.00 1.00 0.97 0.97   1.00 500x500 tiled rectangle (17x15 tile)
 | |
|   1.95 1.63 1.00 1.00   3.83 1x1 stippled rectangle (161x145 stipple)
 | |
|   1.80 1.30 1.00 1.00   1.83 10x10 stippled rectangle (161x145 stipple)
 | |
|   0.97 1.00 1.00 1.00   1.01 100x100 stippled rectangle (161x145 stipple)
 | |
|   1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (161x145 stipple)
 | |
|   1.95 1.63 1.00 1.00   3.56 1x1 opaque stippled rectangle (161x145 stipple)
 | |
|   1.65 1.25 1.00 1.00   1.68 10x10 opaque stippled rectangle (161x145 stipple)
 | |
|   1.00 1.00 1.00 1.00   1.01 100x100 opaque stippled rectangle (161x145...
 | |
|   1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (161x145...
 | |
|   1.95 1.63 0.98 0.99   3.80 1x1 tiled rectangle (161x145 tile)
 | |
|   1.67 1.26 1.00 1.00   1.67 10x10 tiled rectangle (161x145 tile)
 | |
|   1.13 1.14 1.14 1.14   1.14 100x100 tiled rectangle (161x145 tile)
 | |
|   0.88 1.00 1.00 1.00   0.99 500x500 tiled rectangle (161x145 tile)
 | |
|   1.93 1.63 1.00 1.00   3.53 1x1 tiled rectangle (216x208 tile)
 | |
|   1.69 1.26 1.00 1.00   1.66 10x10 tiled rectangle (216x208 tile)
 | |
|   1.00 1.00 1.00 1.00   1.00 100x100 tiled rectangle (216x208 tile)
 | |
|   1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (216x208 tile)
 | |
|   1.82 1.70 1.00 1.00   3.38 1-pixel line segment
 | |
|   2.07 1.56 0.90 1.00   3.31 10-pixel line segment
 | |
|   1.29 1.10 1.00 1.00   1.27 100-pixel line segment
 | |
|   1.05 1.06 1.03 1.03   1.09 500-pixel line segment
 | |
|   1.30 1.13 1.00 1.00   1.29 100-pixel line segment (1 kid)
 | |
|   1.32 1.15 1.00 1.00   1.32 100-pixel line segment (2 kids)
 | |
|   1.33 1.16 1.00 1.00   1.33 100-pixel line segment (3 kids)
 | |
|   1.92 1.64 1.00 1.00   3.73 10-pixel dashed segment
 | |
|   1.34 1.16 1.00 1.00   1.34 100-pixel dashed segment
 | |
|   1.24 1.11 0.99 0.97   1.23 100-pixel double-dashed segment
 | |
|   1.72 1.77 1.00 1.00   3.25 10-pixel horizontal line segment
 | |
|   1.83 1.66 1.01 1.00   3.54 100-pixel horizontal line segment
 | |
|   1.86 1.30 1.00 1.00   1.84 500-pixel horizontal line segment
 | |
|   2.11 1.52 1.00 0.99   3.02 10-pixel vertical line segment
 | |
|   1.21 1.10 1.00 1.00   1.20 100-pixel vertical line segment
 | |
|   1.03 1.03 1.00 1.00   1.02 500-pixel vertical line segment
 | |
|   4.42 1.68 1.00 1.01   4.64 10x1 wide horizontal line segment
 | |
|   1.83 1.31 1.00 1.00   1.83 100x10 wide horizontal line segment
 | |
|   1.07 1.00 0.96 1.00   1.07 500x50 wide horizontal line segment
 | |
|   4.10 1.67 1.00 1.00   4.62 10x1 wide vertical line segment
 | |
|   1.50 1.24 1.06 1.06   1.48 100x10 wide vertical line segment
 | |
|   1.06 1.03 1.00 1.00   1.05 500x50 wide vertical line segment
 | |
|   2.54 1.61 1.00 1.00   3.61 1-pixel line
 | |
|   2.71 1.48 1.00 1.00   2.67 10-pixel line
 | |
|   1.19 1.09 1.00 1.00   1.19 100-pixel line
 | |
|   1.04 1.02 1.00 1.00   1.03 500-pixel line
 | |
|   2.68 1.51 0.98 1.00   3.17 10-pixel dashed line
 | |
|   1.23 1.11 0.99 0.99   1.23 100-pixel dashed line
 | |
|   1.15 1.08 1.00 1.00   1.15 100-pixel double-dashed line
 | |
|   2.27 1.39 1.00 1.00   2.23 10x1 wide line
 | |
|   1.20 1.09 1.00 1.00   1.20 100x10 wide line
 | |
|   1.04 1.02 1.00 1.00   1.04 500x50 wide line
 | |
|   1.52 1.45 1.00 1.00   1.52 100x10 wide dashed line
 | |
|   1.54 1.47 1.00 1.00   1.54 100x10 wide double-dashed line
 | |
|   1.97 1.30 0.96 0.95   1.95 10x10 rectangle outline
 | |
|   1.44 1.27 1.00 1.00   1.43 100x100 rectangle outline
 | |
|   3.22 2.16 1.10 1.09   3.61 500x500 rectangle outline
 | |
|   1.95 1.34 1.00 1.00   1.90 10x10 wide rectangle outline
 | |
|   1.14 1.14 1.00 1.00   1.13 100x100 wide rectangle outline
 | |
|   1.00 1.00 1.00 1.00   1.00 500x500 wide rectangle outline
 | |
|   1.57 1.72 1.00 1.00   3.03 1-pixel circle
 | |
|   1.96 1.35 1.00 1.00   1.92 10-pixel circle
 | |
|   1.21 1.07 0.86 0.97   1.20 100-pixel circle
 | |
|   1.08 1.04 1.00 1.00   1.08 500-pixel circle
 | |
|   1.39 1.19 1.03 1.03   1.38 100-pixel dashed circle
 | |
|   1.21 1.11 1.00 1.00   1.23 100-pixel double-dashed circle
 | |
|   1.59 1.28 1.00 1.00   1.58 10-pixel wide circle
 | |
|   1.22 1.12 0.99 1.00   1.22 100-pixel wide circle
 | |
|   1.06 1.04 1.00 1.00   1.05 500-pixel wide circle
 | |
|   1.87 1.84 1.00 1.00   1.85 100-pixel wide dashed circle
 | |
|   1.90 1.93 1.01 1.01   1.90 100-pixel wide double-dashed circle
 | |
|   2.13 1.43 1.00 1.00   2.32 10-pixel partial circle
 | |
|   1.42 1.18 1.00 1.00   1.42 100-pixel partial circle
 | |
|   1.92 1.85 1.01 1.01   1.89 10-pixel wide partial circle
 | |
|   1.73 1.67 1.00 1.00   1.73 100-pixel wide partial circle
 | |
|   1.36 1.95 1.00 1.00   2.64 1-pixel solid circle
 | |
|   2.02 1.37 1.00 1.00   2.03 10-pixel solid circle
 | |
|   1.19 1.09 1.00 1.00   1.19 100-pixel solid circle
 | |
|   1.02 0.99 1.00 1.00   1.01 500-pixel solid circle
 | |
|   1.74 1.28 1.00 0.88   1.73 10-pixel fill chord partial circle
 | |
|   1.31 1.13 1.00 1.00   1.31 100-pixel fill chord partial circle
 | |
|   1.67 1.31 1.03 1.03   1.72 10-pixel fill slice partial circle
 | |
|   1.30 1.13 1.00 1.00   1.28 100-pixel fill slice partial circle
 | |
|   2.45 1.49 1.01 1.00   2.71 10-pixel ellipse
 | |
|   1.22 1.10 1.00 1.00   1.22 100-pixel ellipse
 | |
|   1.09 1.04 1.00 1.00   1.09 500-pixel ellipse
 | |
|   1.90 1.28 1.00 1.00   1.89 100-pixel dashed ellipse
 | |
|   1.62 1.24 0.96 0.97   1.61 100-pixel double-dashed ellipse
 | |
|   2.43 1.50 1.00 1.00   2.42 10-pixel wide ellipse
 | |
|   1.61 1.28 1.03 1.03   1.60 100-pixel wide ellipse
 | |
|   1.08 1.05 1.00 1.00   1.08 500-pixel wide ellipse
 | |
|   1.93 1.88 1.00 1.00   1.88 100-pixel wide dashed ellipse
 | |
|   1.94 1.89 1.01 1.00   1.94 100-pixel wide double-dashed ellipse
 | |
|   2.31 1.48 1.00 1.00   2.67 10-pixel partial ellipse
 | |
|   1.38 1.17 1.00 1.00   1.38 100-pixel partial ellipse
 | |
|   2.00 1.85 0.98 0.97   1.98 10-pixel wide partial ellipse
 | |
|   1.89 1.86 1.00 1.00   1.89 100-pixel wide partial ellipse
 | |
|   3.49 1.60 1.00 1.00   3.65 10-pixel filled ellipse
 | |
|   1.67 1.26 1.00 1.00   1.67 100-pixel filled ellipse
 | |
|   1.06 1.04 1.00 1.00   1.06 500-pixel filled ellipse
 | |
|   2.38 1.43 1.01 1.00   2.32 10-pixel fill chord partial ellipse
 | |
|   2.06 1.30 1.00 1.00   2.05 100-pixel fill chord partial ellipse
 | |
|   2.27 1.41 1.00 1.00   2.27 10-pixel fill slice partial ellipse
 | |
|   1.98 1.33 1.00 0.97   1.97 100-pixel fill slice partial ellipse
 | |
|  57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle
 | |
|  56.94 1.98 1.01 1.00  73.89 Fill 10x10 equivalent triangle
 | |
|   6.07 1.75 1.00 1.00   6.07 Fill 100x100 equivalent triangle
 | |
|  51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid
 | |
|  51.42 1.82 1.01 1.00  94.89 Fill 10x10 trapezoid
 | |
|   6.47 1.80 1.00 1.00   6.44 Fill 100x100 trapezoid
 | |
|   1.56 1.28 1.00 0.99   1.56 Fill 300x300 trapezoid
 | |
|  51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple)
 | |
|  51.73 2.00 1.02 1.02  67.92 Fill 10x10 stippled trapezoid (8x8 stipple)
 | |
|   5.36 1.72 1.00 1.00   5.36 Fill 100x100 stippled trapezoid (8x8 stipple)
 | |
|   1.54 1.26 1.00 1.00   1.59 Fill 300x300 stippled trapezoid (8x8 stipple)
 | |
|  51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple)
 | |
|  50.71 1.95 0.99 1.00  65.44 Fill 10x10 opaque stippled trapezoid (8x8...
 | |
|   5.33 1.73 1.00 1.00   5.36 Fill 100x100 opaque stippled trapezoid (8x8...
 | |
|   1.58 1.25 1.00 1.00   1.58 Fill 300x300 opaque stippled trapezoid (8x8...
 | |
|  51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile)
 | |
|  51.59 1.99 1.01 1.01  62.25 Fill 10x10 tiled trapezoid (4x4 tile)
 | |
|   5.38 1.72 1.00 1.00   5.38 Fill 100x100 tiled trapezoid (4x4 tile)
 | |
|   1.54 1.25 1.00 0.99   1.58 Fill 300x300 tiled trapezoid (4x4 tile)
 | |
|  51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple)
 | |
|  44.86 1.97 1.00 1.00  44.86 Fill 10x10 stippled trapezoid (17x15 stipple)
 | |
|   2.74 1.56 1.00 1.00   2.73 Fill 100x100 stippled trapezoid (17x15 stipple)
 | |
|   1.29 1.14 1.00 1.00   1.27 Fill 300x300 stippled trapezoid (17x15 stipple)
 | |
|  51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15...
 | |
|  45.14 1.96 1.01 1.00  45.14 Fill 10x10 opaque stippled trapezoid (17x15...
 | |
|   2.68 1.56 1.00 1.00   2.68 Fill 100x100 opaque stippled trapezoid (17x15...
 | |
|   1.26 1.10 1.00 1.00   1.28 Fill 300x300 opaque stippled trapezoid (17x15...
 | |
|  51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile)
 | |
|  47.58 1.96 1.00 1.00  47.86 Fill 10x10 tiled trapezoid (17x15 tile)
 | |
|   2.74 1.56 1.00 1.00   2.74 Fill 100x100 tiled trapezoid (17x15 tile)
 | |
|   1.29 1.14 1.00 1.00   1.28 Fill 300x300 tiled trapezoid (17x15 tile)
 | |
|  51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple)
 | |
|  45.14 1.97 1.00 1.00  44.29 Fill 10x10 stippled trapezoid (161x145 stipple)
 | |
|   3.02 1.77 1.12 1.12   3.38 Fill 100x100 stippled trapezoid (161x145 stipple)
 | |
|   1.31 1.13 1.00 1.00   1.30 Fill 300x300 stippled trapezoid (161x145 stipple)
 | |
|  51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145...
 | |
|  45.01 1.97 1.00 1.00  45.01 Fill 10x10 opaque stippled trapezoid (161x145...
 | |
|   2.67 1.56 1.00 1.00   2.69 Fill 100x100 opaque stippled trapezoid (161x145..
 | |
|   1.29 1.13 1.00 1.01   1.27 Fill 300x300 opaque stippled trapezoid (161x145..
 | |
|  51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile)
 | |
|  45.01 1.96 0.98 1.00  45.01 Fill 10x10 tiled trapezoid (161x145 tile)
 | |
|   2.62 1.36 1.00 1.00   2.69 Fill 100x100 tiled trapezoid (161x145 tile)
 | |
|   1.27 1.13 1.00 1.00   1.22 Fill 300x300 tiled trapezoid (161x145 tile)
 | |
|  51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile)
 | |
|  45.14 1.97 1.01 0.99  45.14 Fill 10x10 tiled trapezoid (216x208 tile)
 | |
|   2.62 1.55 1.00 1.00   2.71 Fill 100x100 tiled trapezoid (216x208 tile)
 | |
|   1.28 1.13 1.00 1.00   1.20 Fill 300x300 tiled trapezoid (216x208 tile)
 | |
|  50.71 1.95 1.00 1.00  54.70 Fill 10x10 equivalent complex polygon
 | |
|   5.51 1.71 0.96 0.98   5.47 Fill 100x100 equivalent complex polygons
 | |
|   8.39 1.97 1.00 1.00  16.75 Fill 10x10 64-gon (Convex)
 | |
|   8.38 1.83 1.00 1.00   8.43 Fill 100x100 64-gon (Convex)
 | |
|   8.50 1.96 1.00 1.00  16.64 Fill 10x10 64-gon (Complex)
 | |
|   8.26 1.83 1.00 1.00   8.35 Fill 100x100 64-gon (Complex)
 | |
|  14.09 1.87 1.00 1.00  14.05 Char in 80-char line (6x13)
 | |
|  11.91 1.87 1.00 1.00  11.95 Char in 70-char line (8x13)
 | |
|  11.16 1.85 1.01 1.00  11.10 Char in 60-char line (9x15)
 | |
|  10.09 1.78 1.00 1.00  10.09 Char16 in 40-char line (k14)
 | |
|   6.15 1.75 1.00 1.00   6.31 Char16 in 23-char line (k24)
 | |
|  11.92 1.90 1.03 1.03  11.88 Char in 80-char line (TR 10)
 | |
|   8.18 1.78 1.00 0.99   8.17 Char in 30-char line (TR 24)
 | |
|  42.83 1.44 1.01 1.00  42.11 Char in 20/40/20 line (6x13, TR 10)
 | |
|  27.45 1.43 1.01 1.01  27.45 Char16 in 7/14/7 line (k14, k24)
 | |
|  12.13 1.85 1.00 1.00  12.05 Char in 80-char image line (6x13)
 | |
|  10.00 1.84 1.00 1.00  10.00 Char in 70-char image line (8x13)
 | |
|   9.18 1.83 1.00 1.00   9.12 Char in 60-char image line (9x15)
 | |
|   9.66 1.82 0.98 0.95   9.66 Char16 in 40-char image line (k14)
 | |
|   5.82 1.72 1.00 1.00   5.99 Char16 in 23-char image line (k24)
 | |
|   8.70 1.80 1.00 1.00   8.65 Char in 80-char image line (TR 10)
 | |
|   4.67 1.66 1.00 1.00   4.67 Char in 30-char image line (TR 24)
 | |
|  84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels
 | |
|   3.73 1.50 1.00 0.98   3.73 Scroll 100x100 pixels
 | |
|   1.00 1.00 1.00 1.00   1.00 Scroll 500x500 pixels
 | |
|  84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window
 | |
|   3.62 1.51 0.98 0.98   3.62 Copy 100x100 from window to window
 | |
|   0.89 1.00 1.00 1.00   1.00 Copy 500x500 from window to window
 | |
|  57.06 1.99 1.00 1.00  88.64 Copy 10x10 from pixmap to window
 | |
|   2.49 2.00 1.00 1.00   2.48 Copy 100x100 from pixmap to window
 | |
|   1.00 0.91 1.00 1.00   0.98 Copy 500x500 from pixmap to window
 | |
|   2.04 1.01 1.00 1.00   2.03 Copy 10x10 from window to pixmap
 | |
|   1.05 1.00 1.00 1.00   1.05 Copy 100x100 from window to pixmap
 | |
|   1.00 1.00 0.93 1.00   1.04 Copy 500x500 from window to pixmap
 | |
|  58.52 1.03 1.03 1.02  57.95 Copy 10x10 from pixmap to pixmap
 | |
|   2.40 1.00 1.00 1.00   2.45 Copy 100x100 from pixmap to pixmap
 | |
|   1.00 1.00 1.00 1.00   1.00 Copy 500x500 from pixmap to pixmap
 | |
|  51.57 1.92 1.00 1.00  85.75 Copy 10x10 1-bit deep plane
 | |
|   6.37 1.75 1.01 1.01   6.37 Copy 100x100 1-bit deep plane
 | |
|   1.26 1.11 1.00 1.00   1.24 Copy 500x500 1-bit deep plane
 | |
|   4.23 1.63 0.98 0.97   4.38 Copy 10x10 n-bit deep plane
 | |
|   1.04 1.02 1.00 1.00   1.04 Copy 100x100 n-bit deep plane
 | |
|   1.00 1.00 1.00 1.00   1.00 Copy 500x500 n-bit deep plane
 | |
|   6.45 1.98 1.00 1.26  12.80 PutImage 10x10 square
 | |
|   1.10 1.87 1.00 1.83   2.11 PutImage 100x100 square
 | |
|   1.02 1.93 1.00 1.91   1.91 PutImage 500x500 square
 | |
|   4.17 1.78 1.00 1.40   7.18 PutImage XY 10x10 square
 | |
|   1.27 1.49 0.97 1.48   2.10 PutImage XY 100x100 square
 | |
|   1.00 1.50 1.00 1.50   1.52 PutImage XY 500x500 square
 | |
|   1.07 1.01 1.00 1.00   1.06 GetImage 10x10 square
 | |
|   1.01 1.00 1.00 1.00   1.01 GetImage 100x100 square
 | |
|   1.00 1.00 1.00 1.00   1.00 GetImage 500x500 square
 | |
|   1.56 1.00 0.99 0.97   1.56 GetImage XY 10x10 square
 | |
|   1.02 1.00 1.00 1.00   1.02 GetImage XY 100x100 square
 | |
|   1.00 1.00 1.00 1.00   1.00 GetImage XY 500x500 square
 | |
|   1.00 1.00 1.01 0.98   0.95 X protocol NoOperation
 | |
|   1.02 1.03 1.04 1.03   1.00 QueryPointer
 | |
|   1.03 1.02 1.04 1.03   1.00 GetProperty
 | |
| 100.41 1.51 1.00 1.00 198.76 Change graphics context
 | |
|  45.81 1.00 0.99 0.97  57.10 Create and map subwindows (4 kids)
 | |
|  78.45 1.01 1.02 1.02  63.07 Create and map subwindows (16 kids)
 | |
|  73.91 1.01 1.00 1.00  56.37 Create and map subwindows (25 kids)
 | |
|  73.22 1.00 1.00 1.00  49.07 Create and map subwindows (50 kids)
 | |
|  72.36 1.01 0.99 1.00  32.14 Create and map subwindows (75 kids)
 | |
|  70.34 1.00 1.00 1.00  30.12 Create and map subwindows (100 kids)
 | |
|  55.00 1.00 1.00 0.99  23.75 Create and map subwindows (200 kids)
 | |
|  55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids)
 | |
|  55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids)
 | |
|  54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids)
 | |
|  54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids)
 | |
|  55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids)
 | |
|  55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids)
 | |
|  54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids)
 | |
|  28.13 1.00 1.00 1.00  30.75 Map window via parent (4 kids)
 | |
|  36.14 1.01 1.01 1.01  32.58 Map window via parent (16 kids)
 | |
|  26.13 1.00 0.98 0.95  29.85 Map window via parent (25 kids)
 | |
|  40.07 1.00 1.01 1.00  27.57 Map window via parent (50 kids)
 | |
|  23.26 0.99 1.00 1.00  18.23 Map window via parent (75 kids)
 | |
|  22.91 0.99 1.00 0.99  16.52 Map window via parent (100 kids)
 | |
|  27.79 1.00 1.00 0.99  12.50 Map window via parent (200 kids)
 | |
|  22.35 1.00 1.00 1.00  56.19 Unmap window via parent (4 kids)
 | |
|   9.57 1.00 0.99 1.00  89.78 Unmap window via parent (16 kids)
 | |
|  80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids)
 | |
|  96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids)
 | |
|  99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids)
 | |
| 112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids)
 | |
| 105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids)
 | |
|  51.29 1.03 1.02 1.02  74.19 Destroy window via parent (4 kids)
 | |
|  86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids)
 | |
| 106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids)
 | |
| 120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids)
 | |
| 126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids)
 | |
| 126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids)
 | |
| 128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids)
 | |
|  16.04 0.88 1.00 1.00  20.36 Hide/expose window via popup (4 kids)
 | |
|  19.04 1.01 1.00 1.00  23.48 Hide/expose window via popup (16 kids)
 | |
|  19.22 1.00 1.00 1.00  20.44 Hide/expose window via popup (25 kids)
 | |
|  17.41 1.00 0.91 0.97  17.68 Hide/expose window via popup (50 kids)
 | |
|  17.29 1.01 1.00 1.01  17.07 Hide/expose window via popup (75 kids)
 | |
|  16.74 1.00 1.00 1.00  16.17 Hide/expose window via popup (100 kids)
 | |
|  10.30 1.00 1.00 1.00  10.51 Hide/expose window via popup (200 kids)
 | |
|  16.48 1.01 1.00 1.00  26.05 Move window (4 kids)
 | |
|  17.01 0.95 1.00 1.00  23.97 Move window (16 kids)
 | |
|  16.95 1.00 1.00 1.00  22.90 Move window (25 kids)
 | |
|  16.05 1.01 1.00 1.00  21.32 Move window (50 kids)
 | |
|  15.58 1.00 0.98 0.98  19.44 Move window (75 kids)
 | |
|  14.98 1.02 1.03 1.03  18.17 Move window (100 kids)
 | |
|  10.90 1.01 1.01 1.00  12.68 Move window (200 kids)
 | |
|  49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids)
 | |
|  50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids)
 | |
|  50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids)
 | |
|  50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids)
 | |
|  50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids)
 | |
|  50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids)
 | |
|  50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids)
 | |
|  41.04 1.00 1.00 1.00  56.61 Move window via parent (4 kids)
 | |
|  69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids)
 | |
|  95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids)
 | |
|  95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids)
 | |
|  96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids)
 | |
|  97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids)
 | |
|  96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids)
 | |
|  17.75 1.01 1.00 1.00  27.61 Resize window (4 kids)
 | |
|  17.94 1.00 1.00 0.99  25.42 Resize window (16 kids)
 | |
|  17.92 1.01 1.00 1.00  24.47 Resize window (25 kids)
 | |
|  17.24 0.97 1.00 1.00  24.14 Resize window (50 kids)
 | |
|  16.81 1.00 1.00 0.99  22.75 Resize window (75 kids)
 | |
|  16.08 1.00 1.00 1.00  21.20 Resize window (100 kids)
 | |
|  12.92 1.00 0.99 1.00  16.26 Resize window (200 kids)
 | |
|  52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids)
 | |
|  53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids)
 | |
|  52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids)
 | |
|  51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids)
 | |
|  53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids)
 | |
|  53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids)
 | |
|  53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids)
 | |
|  16.76 1.00 0.96 1.00  19.46 Circulate window (4 kids)
 | |
|  17.24 1.00 1.00 0.97  16.24 Circulate window (16 kids)
 | |
|  16.30 1.03 1.03 1.03  15.85 Circulate window (25 kids)
 | |
|  13.45 1.00 1.00 1.00  14.90 Circulate window (50 kids)
 | |
|  12.91 1.00 1.00 1.00  13.06 Circulate window (75 kids)
 | |
|  11.30 0.98 1.00 1.00  11.03 Circulate window (100 kids)
 | |
|   7.58 1.01 1.01 0.99   7.47 Circulate window (200 kids)
 | |
|   1.01 1.01 0.98 1.00   0.95 Circulate Unmapped window (4 kids)
 | |
|   1.07 1.07 1.01 1.07   1.02 Circulate Unmapped window (16 kids)
 | |
|   1.04 1.09 1.06 1.05   0.97 Circulate Unmapped window (25 kids)
 | |
|   1.04 1.23 1.20 1.18   1.05 Circulate Unmapped window (50 kids)
 | |
|   1.18 1.53 1.19 1.45   1.24 Circulate Unmapped window (75 kids)
 | |
|   1.08 1.02 1.01 1.74   1.01 Circulate Unmapped window (100 kids)
 | |
|   1.01 1.12 0.98 0.91   0.97 Circulate Unmapped window (200 kids)
 | |
| </screen>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Profiling with OProfile</title>
 | |
| 
 | |
| <para>OProfile (available from http://oprofile.sourceforge.net/) is a
 | |
| system-wide profiler for Linux systems that uses processor-level
 | |
| counters to collect sampling data.  OProfile can provide information
 | |
| that is similar to that provided by <command>gprof</command>, but without the
 | |
| necessity of recompiling the program with special instrumentation (i.e.,
 | |
| OProfile can collect statistical profiling information about optimized
 | |
| programs).  A test harness was developed to collect OProfile data for
 | |
| each <command>x11perf</command> test individually.
 | |
| </para>
 | |
| 
 | |
| <para>Test runs were performed using the RETIRED_INSNS counter on the AMD
 | |
| Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a
 | |
| test configuration different from the one described above).  We have
 | |
| examined OProfile output and have compared it with <command>gprof</command> output.
 | |
| This investigation has not produced results that yield performance
 | |
| increases in <command>x11perf</command> numbers.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| <!--
 | |
| <sect3>Retired Instructions
 | |
| 
 | |
| <p>The initial tests using OProfile were done using the RETIRED_INSNS
 | |
| counter with DMX running on the dual-processor AMD Athlon machine - the
 | |
| same test configuration that was described above and that was used for
 | |
| other tests.  The RETIRED_INSNS counter counts retired instructions and
 | |
| showed drawing, text, copying, and image tests to be dominated (>
 | |
| 30%) by calls to Hash(), SecurityLookupIDByClass(),
 | |
| SecurityLookupIDByType(), and StandardReadRequestFromClient().  Some of
 | |
| these tests also executed significant instructions in
 | |
| WaitForSomething().
 | |
| 
 | |
| <p>In contrast, the window tests executed significant
 | |
| instructions in SecurityLookupIDByType(), Hash(),
 | |
| StandardReadRequestFromClient(), but also executed significant
 | |
| instructions in other routines, such as ConfigureWindow().  Some time
 | |
| was spent looking at Hash() function, but optimizations in this routine
 | |
| did not lead to a dramatic increase in <tt/x11perf/ performance.
 | |
| -->
 | |
| 
 | |
| <!--
 | |
| <sect3>Clock Cycles
 | |
| 
 | |
| <p>Retired instructions can be misleading because Intel/AMD instructions
 | |
| execute in variable amounts of time.  The OProfile tests were repeated
 | |
| using the Intel CPU_CLK_HALTED counter with DMX running on the second
 | |
| back-end machine.  Note that this is a different test configuration that
 | |
| the one described above.  However, these tests show the amount of time
 | |
| (as measured in CPU cycles) that are spent in each routine.  Because
 | |
| <tt/x11perf/ was running on the first back-end machine and because
 | |
| window optimizations were on, the load on the second back-end machine
 | |
| was not significant.
 | |
| 
 | |
| <p>Using CPU_CLK_HALTED, DMX showed simple drawing
 | |
| tests spending more than 10% of their time in
 | |
| StandardReadRequestFromClient(), with significant time (> 20% total)
 | |
| spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch().
 | |
| For these tests, < 5% of the time was spent in Hash(), which explains
 | |
| why optimizing the Hash() routine did not impact <tt/x11perf/ results.
 | |
| 
 | |
| <p>The trapezoid, text, scrolling, copying, and image tests were
 | |
| dominated by time in ProcFillPoly(), PanoramiXFillPoly(), dmxFillPolygon(),
 | |
| SecurityLookupIDByClass(), SecurityLookupIDByType(), and
 | |
| StandardReadRequestFromClient().  Hash() time was generally above 5% but
 | |
| less than 10% of total time.
 | |
| -->
 | |
| 
 | |
| <sect3>
 | |
| <title>X Test Suite</title>
 | |
| 
 | |
| <para>The X Test Suite was run on the fully optimized DMX server using the
 | |
| configuration described above.  The following failures were noted:
 | |
| <screen>
 | |
| XListPixmapFormats: Test 1              [1]
 | |
| XChangeWindowAttributes: Test 32        [1]
 | |
| XCreateWindow: Test 30                  [1]
 | |
| XFreeColors: Test 4                     [3]
 | |
| XCopyArea: Test 13, 17, 21, 25, 30      [2]
 | |
| XCopyPlane: Test 11, 15, 27, 31         [2]
 | |
| XSetFontPath: Test 4                    [1]
 | |
| XChangeKeyboardControl: Test 9, 10      [1]
 | |
| 
 | |
| [1] Previously documented errors expected from the Xinerama
 | |
|     implementation (see Phase I discussion).
 | |
| [2] Newly noted errors that have been verified as expected
 | |
|     behavior of the Xinerama implementation.
 | |
| [3] Newly noted error that has been verified as a Xinerama
 | |
|     implementation bug.
 | |
| </screen>
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| <!-- ============================================================ -->
 | |
| <sect2>
 | |
| <title>Phase III</title>
 | |
| 
 | |
| <para>During the third phase of development, support was provided for the
 | |
| following extensions: SHAPE, RENDER, XKEYBOARD, XInput.
 | |
| </para>
 | |
| 
 | |
| <sect3>
 | |
| <title>SHAPE</title>
 | |
| 
 | |
| <para>The SHAPE extension is supported.  Test applications (e.g., xeyes and
 | |
| oclock) and window managers that make use of the SHAPE extension will
 | |
| work as expected.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>RENDER</title>
 | |
| 
 | |
| <para>The RENDER extension is supported.  The version included in the DMX
 | |
| CVS tree is version 0.2, and this version is fully supported by Xdmx.
 | |
| Applications using only version 0.2 functions will work correctly;
 | |
| however, some apps that make use of functions from later versions do not
 | |
| properly check the extension's major/minor version numbers.  These apps
 | |
| will fail with a Bad Implementation error when using post-version 0.2
 | |
| functions.  This is expected behavior.  When the DMX CVS tree is updated
 | |
| to include newer versions of RENDER, support for these newer functions
 | |
| will be added to the DMX X server.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>XKEYBOARD</title>
 | |
| 
 | |
| <para>The XKEYBOARD extension is supported.  If present on the back-end X
 | |
| servers, the XKEYBOARD extension will be used to obtain information
 | |
| about the type of the keyboard for initialization.  Otherwise, the
 | |
| keyboard will be initialized using defaults.  Note that this departs
 | |
| from older behavior: when Xdmx is compiled without XKEYBOARD support,
 | |
| the map from the back-end X server will be preserved.  With XKEYBOARD
 | |
| support, the map is not preserved because better information and control
 | |
| of the keyboard is available.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>XInput</title>
 | |
| 
 | |
| <para>The XInput extension is supported.  Any device can be used as a core
 | |
| device and be used as an XInput extension device, with the exception of
 | |
| core devices on the back-end servers.  This limitation is present
 | |
| because cursor handling on the back-end requires that the back-end
 | |
| cursor sometimes track the Xdmx core cursor -- behavior that is
 | |
| incompatible with using the back-end pointer as a non-core device.
 | |
| </para>
 | |
| 
 | |
| <para>Currently, back-end extension devices are not available as Xdmx
 | |
| extension devices, but this limitation should be removed in the future.
 | |
| </para>
 | |
| 
 | |
| <para>To demonstrate the XInput extension, and to provide more examples for
 | |
| low-level input device driver writers, USB device drivers have been
 | |
| written for mice (usb-mou), keyboards (usb-kbd), and
 | |
| non-mouse/non-keyboard USB devices (usb-oth).  Please see the man page
 | |
| for information on Linux kernel drivers that are required for using
 | |
| these Xdmx drivers.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>DPMS</title>
 | |
| 
 | |
| <para>The DPMS extension is exported but does not do anything at this time.
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Other Extensions</title>
 | |
| 
 | |
| <para>The LBX,
 | |
|        SECURITY,
 | |
|        XC-APPGROUP, and
 | |
|        XFree86-Bigfont
 | |
| extensions do not require any special Xdmx support and have been exported.
 | |
| </para>
 | |
| 
 | |
| <para>The
 | |
|     BIG-REQUESTS,
 | |
|     DEC-XTRAP,
 | |
|     DOUBLE-BUFFER,
 | |
|     Extended-Visual-Information,
 | |
|     FontCache,
 | |
|     GLX,
 | |
|     MIT-SCREEN-SAVER,
 | |
|     MIT-SHM,
 | |
|     MIT-SUNDRY-NONSTANDARD,
 | |
|     RECORD,
 | |
|     SECURITY,
 | |
|     SGI-GLX,
 | |
|     SYNC,
 | |
|     TOG-CUP,
 | |
|     X-Resource,
 | |
|     XC-MISC,
 | |
|     XFree86-DGA,
 | |
|     XFree86-DRI,
 | |
|     XFree86-Misc,
 | |
|     XFree86-VidModeExtension, and
 | |
|     XVideo
 | |
| extensions are <emphasis remap="it">not</emphasis> supported at this time, but will be evaluated
 | |
| for inclusion in future DMX releases.  <emphasis remap="bf">See below for additional work
 | |
| on extensions after Phase III.</emphasis>
 | |
| </para>
 | |
| </sect3>
 | |
| </sect2>
 | |
| 
 | |
| <sect2>
 | |
| <title>Phase IV</title>
 | |
| 
 | |
| <sect3>
 | |
| <title>Moving to XFree86 4.3.0</title>
 | |
| 
 | |
| <para>For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003)
 | |
| was merged onto the dmx.sourceforge.net CVS trunk and all work is
 | |
| proceeding using this tree.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Extensions </title>
 | |
| 
 | |
| <sect4>
 | |
| <title>XC-MISC (supported)</title>
 | |
| 
 | |
| <para>XC-MISC is used internally by the X library to recycle XIDs from the
 | |
| X server.  This is important for long-running X server sessions.  Xdmx
 | |
| supports this extension.  The X Test Suite passed and failed the exact
 | |
| same tests before and after this extension was enabled.
 | |
| <!-- Tested February/March 2003 -->
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Extended-Visual-Information (supported)</title>
 | |
| 
 | |
| <para>The Extended-Visual-Information extension provides a method for an X
 | |
| client to obtain detailed visual information.  Xdmx supports this
 | |
| extension.  It was tested using the <filename>hw/dmx/examples/evi</filename> example
 | |
| program.  <emphasis remap="bf">Note that this extension is not Xinerama-aware</emphasis> -- it will
 | |
| return visual information for each screen even though Xinerama is
 | |
| causing the X server to export a single logical screen.
 | |
| <!-- Tested March 2003 -->
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>RES (supported)</title>
 | |
| 
 | |
| <para>The X-Resource extension provides a mechanism for a client to obtain
 | |
| detailed information about the resources used by other clients.  This
 | |
| extension was tested with the <filename>hw/dmx/examples/res</filename> program.  The
 | |
| X Test Suite passed and failed the exact same tests before and after
 | |
| this extension was enabled.
 | |
| <!-- Tested March 2003 -->
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>BIG-REQUESTS (supported)</title>
 | |
| 
 | |
| <para>This extension enables the X11 protocol to handle requests longer
 | |
| than 262140 bytes.  The X Test Suite passed and failed the exact same
 | |
| tests before and after this extension was enabled.
 | |
| <!-- Tested March 2003 -->
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>XSYNC (supported)</title>
 | |
| 
 | |
| <para>This extension provides facilities for two different X clients to
 | |
| synchronize their requests.  This extension was minimally tested with
 | |
| <command>xdpyinfo</command> and the X Test Suite passed and failed the exact same
 | |
| tests before and after this extension was enabled.
 | |
| <!-- Tested March 2003 -->
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported)</title>
 | |
| 
 | |
| <para>The XTEST and RECORD extension were developed by the X Consortium for
 | |
| use in the X Test Suite and are supported as a standard in the X11R6
 | |
| tree.  They are also supported in Xdmx.  When X Test Suite tests that
 | |
| make use of the XTEST extension are run, Xdmx passes and fails exactly
 | |
| the same tests as does a standard XFree86 X server.  When the
 | |
| <literal remap="tt">rcrdtest</literal> test (a part of the X Test Suite that verifies the RECORD
 | |
| extension) is run, Xdmx passes and fails exactly the same tests as does
 | |
| a standard XFree86 X server. <!-- Tested February/March 2003 -->
 | |
| </para>
 | |
| 
 | |
| <para>There are two older XTEST-like extensions: DEC-XTRAP and
 | |
| XTestExtension1.  The XTestExtension1 extension was developed for use by
 | |
| the X Testing Consortium for use with a test suite that eventually
 | |
| became (part of?) the X Test Suite.  Unlike XTEST, which only allows
 | |
| events to be sent to the server, the XTestExtension1 extension also
 | |
| allowed events to be recorded (similar to the RECORD extension).  The
 | |
| second is the DEC-XTRAP extension that was developed by the Digital
 | |
| Equipment Corporation.
 | |
| </para>
 | |
| 
 | |
| <para>The DEC-XTRAP extension is available from Xdmx and has been tested
 | |
| with the <command>xtrap*</command> tools which are distributed as standard X11R6
 | |
| clients. <!-- Tested March 2003 -->
 | |
| </para>
 | |
| 
 | |
| <para>The XTestExtension1 is <emphasis>not</emphasis> supported because it does not appear
 | |
| to be used by any modern X clients (the few that support it also support
 | |
| XTEST) and because there are no good methods available for testing that
 | |
| it functions correctly (unlike XTEST and DEC-XTRAP, the code for
 | |
| XTestExtension1 is not part of the standard X server source tree, so
 | |
| additional testing is important). <!-- Tested March 2003 -->
 | |
| </para>
 | |
| 
 | |
| <para>Most of these extensions are documented in the X11R6 source tree.
 | |
| Further, several original papers exist that this author was unable to
 | |
| locate -- for completeness and historical interest, citations are
 | |
| provide:
 | |
| <variablelist>
 | |
| <varlistentry>
 | |
| <term>XRECORD</term>
 | |
| <listitem>
 | |
| <para>Martha Zimet. Extending X For Recording.  8th Annual X
 | |
| Technical Conference Boston, MA January 24-26, 1994.
 | |
| </para></listitem></varlistentry>
 | |
| <varlistentry>
 | |
| <term>DEC-XTRAP</term>
 | |
| <listitem>
 | |
| <para>Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap
 | |
| Architecture. Digital Equipment Corporation, July 1991.
 | |
| </para></listitem></varlistentry>
 | |
| <varlistentry>
 | |
| <term>XTestExtension1</term>
 | |
| <listitem>
 | |
| <para>Larry Woestman. X11 Input Synthesis Extension
 | |
| Proposal. Hewlett Packard, November 1991.
 | |
| </para></listitem></varlistentry>
 | |
| </variablelist>
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>MIT-MISC (not supported)</title>
 | |
| 
 | |
| <para>The MIT-MISC extension is used to control a bug-compatibility flag
 | |
| that provides compatibility with xterm programs from X11R1 and X11R2.
 | |
| There does not appear to be a single client available that makes use of
 | |
| this extension and there is not way to verify that it works correctly.
 | |
| The Xdmx server does <emphasis>not</emphasis> support MIT-MISC.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>SCREENSAVER (not supported)</title>
 | |
| 
 | |
| <para>This extension provides special support for the X screen saver.  It
 | |
| was tested with beforelight, which appears to be the only client that
 | |
| works with it.  When Xinerama was not active, <command>beforelight</command> behaved
 | |
| as expected.  However, when Xinerama was active, <command>beforelight</command> did
 | |
| not behave as expected.  Further, when this extension is not active,
 | |
| <command>xscreensaver</command> (a widely-used X screen saver program) did not behave
 | |
| as expected.  Since this extension is not Xinerama-aware and is not
 | |
| commonly used with expected results by clients, we have left this
 | |
| extension disabled at this time.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>GLX (supported)</title>
 | |
| 
 | |
| <para>The GLX extension provides OpenGL and GLX windowing support.  In
 | |
| Xdmx, the extension is called glxProxy, and it is Xinerama aware.  It
 | |
| works by either feeding requests forward through Xdmx to each of the
 | |
| back-end servers or handling them locally.  All rendering requests are
 | |
| handled on the back-end X servers.  This code was donated to the DMX
 | |
| project by SGI.  For the X Test Suite results comparison, see below.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>RENDER (supported)</title>
 | |
| 
 | |
| <para>The X Rendering Extension (RENDER) provides support for digital image
 | |
| composition.  Geometric and text rendering are supported.  RENDER is
 | |
| partially Xinerama-aware, with text and the most basic compositing
 | |
| operator; however, its higher level primitives (triangles, triangle
 | |
| strips, and triangle fans) are not yet Xinerama-aware.  The RENDER
 | |
| extension is still under development, and is currently at version 0.8.
 | |
| Additional support will be required in DMX as more primitives and/or
 | |
| requests are added to the extension.
 | |
| </para>
 | |
| 
 | |
| <para>There is currently no test suite for the X Rendering Extension;
 | |
| however, there has been discussion of developing a test suite as the
 | |
| extension matures.  When that test suite becomes available, additional
 | |
| testing can be performed with Xdmx.  The X Test Suite passed and failed
 | |
| the exact same tests before and after this extension was enabled.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Summary</title>
 | |
| 
 | |
| <!-- WARNING: this list is duplicated in the "Common X extension
 | |
| support" section -->
 | |
| <para>To summarize, the following extensions are currently supported:
 | |
|     BIG-REQUESTS,
 | |
|     DEC-XTRAP,
 | |
|     DMX,
 | |
|     DPMS,
 | |
|     Extended-Visual-Information,
 | |
|     GLX,
 | |
|     LBX,
 | |
|     RECORD,
 | |
|     RENDER,
 | |
|     SECURITY,
 | |
|     SHAPE,
 | |
|     SYNC,
 | |
|     X-Resource,
 | |
|     XC-APPGROUP,
 | |
|     XC-MISC,
 | |
|     XFree86-Bigfont,
 | |
|     XINERAMA,
 | |
|     XInputExtension,
 | |
|     XKEYBOARD, and
 | |
|     XTEST.
 | |
| </para>
 | |
| 
 | |
| <para>The following extensions are <emphasis>not</emphasis> supported at this time:
 | |
|     DOUBLE-BUFFER,
 | |
|     FontCache,
 | |
|     MIT-SCREEN-SAVER,
 | |
|     MIT-SHM,
 | |
|     MIT-SUNDRY-NONSTANDARD,
 | |
|     TOG-CUP,
 | |
|     XFree86-DGA,
 | |
|     XFree86-Misc,
 | |
|     XFree86-VidModeExtension,
 | |
|     XTestExtensionExt1, and
 | |
|     XVideo.
 | |
| </para>
 | |
| </sect4>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Additional Testing with the X Test Suite</title>
 | |
| 
 | |
| <sect4>
 | |
| <title>XFree86 without XTEST</title>
 | |
| 
 | |
| <para>After the release of XFree86 4.3.0, we retested the XFree86 X server
 | |
| with and without using the XTEST extension.  When the XTEST extension
 | |
| was <emphasis>not</emphasis> used for testing, the XFree86 4.3.0 server running on our
 | |
| usual test system with a Radeon VE card reported unexpected failures in
 | |
| the following tests:
 | |
| <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XGetDefault: Test 5
 | |
| XRebindKeysym: Test 1
 | |
| </literallayout>
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>XFree86 with XTEST</title>
 | |
| 
 | |
| <para>When using the XTEST extension, the XFree86 4.3.0 server reported the
 | |
| following errors:
 | |
| <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XGetDefault: Test 5
 | |
| XRebindKeysym: Test 1
 | |
| 
 | |
| XAllowEvents: Tests 20, 21, 24
 | |
| XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
 | |
| XGrabKey: Test 8
 | |
| XSetPointerMapping: Test 3
 | |
| XUngrabButton: Test 4
 | |
| </literallayout>
 | |
| </para>
 | |
| 
 | |
| <para>While these errors may be important, they will probably be fixed
 | |
| eventually in the XFree86 source tree.  We are particularly interested
 | |
| in demonstrating that the Xdmx server does not introduce additional
 | |
| failures that are not known Xinerama failures.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Xdmx with XTEST, without Xinerama, without GLX</title>
 | |
| 
 | |
| <para>Without Xinerama, but using the XTEST extension, the following errors
 | |
| were reported from Xdmx (note that these are the same as for the XFree86
 | |
| 4.3.0, except that XGetDefault no longer fails):
 | |
| <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XRebindKeysym: Test 1
 | |
| 
 | |
| XAllowEvents: Tests  20, 21, 24
 | |
| XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
 | |
| XGrabKey: Test 8
 | |
| XSetPointerMapping: Test 3
 | |
| XUngrabButton: Test 4
 | |
| </literallayout>
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Xdmx with XTEST, with Xinerama, without GLX</title>
 | |
| 
 | |
| <para>With Xinerama, using the XTEST extension, the following errors
 | |
| were reported from Xdmx:
 | |
| <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XRebindKeysym: Test 1
 | |
| 
 | |
| XAllowEvents: Tests 20, 21, 24
 | |
| XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
 | |
| XGrabKey: Test 8
 | |
| XSetPointerMapping: Test 3
 | |
| XUngrabButton: Test 4
 | |
| 
 | |
| XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue)
 | |
| XDrawLine: Test 67
 | |
| XDrawLines: Test 91
 | |
| XDrawSegments: Test 68
 | |
| </literallayout>
 | |
| Note that the first two sets of errors are the same as for the XFree86
 | |
| 4.3.0 server, and that the XCopyPlane error is a well-known error
 | |
| resulting from an XTEST/Xinerama interaction when the request crosses a
 | |
| screen boundary.  The XDraw* errors are resolved when the tests are run
 | |
| individually and they do not cross a screen boundary.  We will
 | |
| investigate these errors further to determine their cause.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Xdmx with XTEST, with Xinerama, with GLX</title>
 | |
| 
 | |
| <para>With GLX enabled, using the XTEST extension, the following errors
 | |
| were reported from Xdmx (these results are from early during the Phase
 | |
| IV development, but were confirmed with a late Phase IV snapshot):
 | |
| <literallayout>
 | |
| XListPixmapFormats: Test 1
 | |
| XChangeKeyboardControl: Tests 9, 10
 | |
| XRebindKeysym: Test 1
 | |
| 
 | |
| XAllowEvents: Tests 20, 21, 24
 | |
| XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
 | |
| XGrabKey: Test 8
 | |
| XSetPointerMapping: Test 3
 | |
| XUngrabButton: Test 4
 | |
| 
 | |
| XClearArea: Test 8
 | |
| XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30
 | |
| XCopyPlane: Tests 6, 7, 10, 19, 22, 31
 | |
| XDrawArcs: Tests 89, 100, 102
 | |
| XDrawLine: Test 67
 | |
| XDrawSegments: Test 68
 | |
| </literallayout>
 | |
| Note that the first two sets of errors are the same as for the XFree86
 | |
| 4.3.0 server, and that the third set has different failures than when
 | |
| Xdmx does not include GLX support.  Since the GLX extension adds new
 | |
| visuals to support GLX's visual configs and the X Test Suite runs tests
 | |
| over the entire set of visuals, additional rendering tests were run and
 | |
| presumably more of them crossed a screen boundary.  This conclusion is
 | |
| supported by the fact that nearly all of the rendering errors reported
 | |
| are resolved when the tests are run individually and they do no cross a
 | |
| screen boundary.
 | |
| </para>
 | |
| 
 | |
| <para>Further, when hardware rendering is disabled on the back-end displays,
 | |
| many of the errors in the third set are eliminated, leaving only:
 | |
| <literallayout>
 | |
| XClearArea: Test 8
 | |
| XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30
 | |
| XCopyPlane: Test 6, 7, 10, 19, 22, 31
 | |
| </literallayout>
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Conclusion</title>
 | |
| 
 | |
| <para>We conclude that all of the X Test Suite errors reported for Xdmx are
 | |
| the result of errors in the back-end X server or the Xinerama
 | |
| implementation.  Further, all of these errors that can be reasonably
 | |
| fixed at the Xdmx layer have been.  (Where appropriate, we have
 | |
| submitted patches to the XFree86 and Xinerama upstream maintainers.)
 | |
| </para>
 | |
| </sect4>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Dynamic Reconfiguration</title>
 | |
| 
 | |
| <para>During this development phase, dynamic reconfiguration support was
 | |
| added to DMX.  This support allows an application to change the position
 | |
| and offset of a back-end server's screen.  For example, if the
 | |
| application would like to shift a screen slightly to the left, it could
 | |
| query Xdmx for the screen's <x,y> position and then dynamically
 | |
| reconfigure that screen to be at position <x+10,y>.  When a screen
 | |
| is dynamically reconfigured, input handling and a screen's root window
 | |
| dimensions are adjusted as needed.  These adjustments are transparent to
 | |
| the user.
 | |
| </para>
 | |
| 
 | |
| <sect4>
 | |
| <title>Dynamic reconfiguration extension</title>
 | |
| 
 | |
| <para>The application interface to DMX's dynamic reconfiguration is through
 | |
| a function in the DMX extension library:
 | |
| <programlisting>
 | |
| Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y)
 | |
| </programlisting>
 | |
| where <parameter>dpy</parameter> is DMX server's display, <parameter>screen</parameter> is the number of the
 | |
| screen to be reconfigured, and <parameter>x</parameter> and <parameter>y</parameter> are the new upper,
 | |
| left-hand coordinates of the screen to be reconfigured.
 | |
| </para>
 | |
| 
 | |
| <para>The coordinates are not limited other than as required by the X
 | |
| protocol, which limits all coordinates to a signed 16 bit number.  In
 | |
| addition, all coordinates within a screen must also be legal values.
 | |
| Therefore, setting a screen's upper, left-hand coordinates such that the
 | |
| right or bottom edges of the screen is greater than 32,767 is illegal.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Bounding box</title>
 | |
| 
 | |
| <para>When the Xdmx server is started, a bounding box is calculated from
 | |
| the screens' layout given either on the command line or in the
 | |
| configuration file.  This bounding box is currently fixed for the
 | |
| lifetime of the Xdmx server.
 | |
| </para>
 | |
| 
 | |
| <para>While it is possible to move a screen outside of the bounding box, it
 | |
| is currently not possible to change the dimensions of the bounding box.
 | |
| For example, it is possible to specify coordinates of <-100,-100>
 | |
| for the upper, left-hand corner of the bounding box, which was
 | |
| previously at coordinates <0,0>.  As expected, the screen is moved
 | |
| down and to the right; however, since the bounding box is fixed, the
 | |
| left side and upper portions of the screen exposed by the
 | |
| reconfiguration are no longer accessible on that screen.  Those
 | |
| inaccessible regions are filled with black.
 | |
| </para>
 | |
| 
 | |
| <para>This fixed bounding box limitation will be addressed in a future
 | |
| development phase.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Sample applications</title>
 | |
| 
 | |
| <para>An example of where this extension is useful is in setting up a video
 | |
| wall.  It is not always possible to get everything perfectly aligned,
 | |
| and sometimes the positions are changed (e.g., someone might bump into a
 | |
| projector).  Instead of physically moving projectors or monitors, it is
 | |
| now possible to adjust the positions of the back-end server's screens
 | |
| using the dynamic reconfiguration support in DMX.
 | |
| </para>
 | |
| 
 | |
| <para>Other applications, such as automatic setup and calibration tools,
 | |
| can make use of dynamic reconfiguration to correct for projector
 | |
| alignment problems, as long as the projectors are still arranged
 | |
| rectilinearly.  Horizontal and vertical keystone correction could be
 | |
| applied to projectors to correct for non-rectilinear alignment problems;
 | |
| however, this must be done external to Xdmx.
 | |
| </para>
 | |
| 
 | |
| <para>A sample test program is included in the DMX server's examples
 | |
| directory to demonstrate the interface and how an application might use
 | |
| dynamic reconfiguration.  See <filename>dmxreconfig.c</filename> for details.
 | |
| </para>
 | |
| </sect4>
 | |
| 
 | |
| <sect4>
 | |
| <title>Additional notes</title>
 | |
| 
 | |
| <para>In the original development plan, Phase IV was primarily devoted to
 | |
| adding OpenGL support to DMX; however, SGI became interested in the DMX
 | |
| project and developed code to support OpenGL/GLX.  This code was later
 | |
| donated to the DMX project and integrated into the DMX code base, which
 | |
| freed the DMX developers to concentrate on dynamic reconfiguration (as
 | |
| described above).
 | |
| </para>
 | |
| </sect4>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Doxygen documentation</title>
 | |
| 
 | |
| <para>Doxygen is an open-source (GPL) documentation system for generating
 | |
| browseable documentation from stylized comments in the source code.  We
 | |
| have placed all of the Xdmx server and DMX protocol source code files
 | |
| under Doxygen so that comprehensive documentation for the Xdmx source
 | |
| code is available in an easily browseable format.
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>Valgrind</title>
 | |
| 
 | |
| <para>Valgrind, an open-source (GPL) memory debugger for Linux, was used to
 | |
| search for memory management errors.  Several memory leaks were detected
 | |
| and repaired.  The following errors were not addressed:
 | |
| <orderedlist>
 | |
|     <listitem><para>
 | |
|         When the X11 transport layer sends a reply to the client, only
 | |
|         those fields that are required by the protocol are filled in --
 | |
|         unused fields are left as uninitialized memory and are therefore
 | |
|         noted by valgrind.  These instances are not errors and were not
 | |
|         repaired.
 | |
|     </para></listitem>
 | |
|     <listitem><para>
 | |
|         At each server generation, glxInitVisuals allocates memory that
 | |
|         is never freed.  The amount of memory lost each generation
 | |
|         approximately equal to 128 bytes for each back-end visual.
 | |
|         Because the code involved is automatically generated, this bug
 | |
|         has not been fixed and will be referred to SGI.
 | |
|     </para></listitem>
 | |
|     <listitem><para>
 | |
|         At each server generation, dmxRealizeFont calls XLoadQueryFont,
 | |
|         which allocates a font structure that is not freed.
 | |
|         dmxUnrealizeFont can free the font structure for the first
 | |
|         screen, but cannot free it for the other screens since they are
 | |
|         already closed by the time dmxUnrealizeFont could free them.
 | |
|         The amount of memory lost each generation is approximately equal
 | |
|         to 80 bytes per font per back-end.  When this bug is fixed in
 | |
|         the the X server's device-independent (dix) code, DMX will be
 | |
|         able to properly free the memory allocated by XLoadQueryFont.
 | |
|     </para></listitem>
 | |
| </orderedlist>
 | |
| </para>
 | |
| </sect3>
 | |
| 
 | |
| <sect3>
 | |
| <title>RATS</title>
 | |
| 
 | |
| <para>RATS (Rough Auditing Tool for Security) is an open-source (GPL)
 | |
| security analysis tool that scans source code for common
 | |
| security-related programming errors (e.g., buffer overflows and TOCTOU
 | |
| races).  RATS was used to audit all of the code in the hw/dmx directory
 | |
| and all "High" notations were checked manually.  The code was either
 | |
| re-written to eliminate the warning, or a comment containing "RATS" was
 | |
| inserted on the line to indicate that a human had checked the code.
 | |
| Unrepaired warnings are as follows:
 | |
| <orderedlist>
 | |
|     <listitem><para>
 | |
|         Fixed-size buffers are used in many areas, but code has been
 | |
|         added to protect against buffer overflows (e.g., snprintf).
 | |
|         The only instances that have not yet been fixed are in
 | |
|         config/xdmxconfig.c (which is not part of the Xdmx server) and
 | |
|         input/usb-common.c.
 | |
|     </para></listitem>
 | |
|     <listitem><para>
 | |
|         vprintf and vfprintf are used in the logging routines.  In
 | |
|         general, all uses of these functions (e.g., dmxLog) provide a
 | |
|         constant format string from a trusted source, so the use is
 | |
|         relatively benign.
 | |
|     </para></listitem>
 | |
|     <listitem><para>
 | |
|         glxProxy/glxscreens.c uses getenv and strcat.  The use of these
 | |
|         functions is safe and will remain safe as long as
 | |
|         ExtensionsString is longer then GLXServerExtensions (ensuring
 | |
|         this may not be ovious to the casual programmer, but this is in
 | |
|         automatically generated code, so we hope that the generator
 | |
|         enforces this constraint).
 | |
|     </para></listitem>
 | |
| </orderedlist>
 | |
| 
 | |
| </para>
 | |
| 
 | |
| </sect3>
 | |
| 
 | |
| </sect2>
 | |
| 
 | |
| </sect1>
 | |
| 
 | |
| </appendix>
 | |
| 
 | |
|   </article>
 | |
| 
 | |
|   <!-- Local Variables: -->
 | |
|   <!-- fill-column: 72  -->
 | |
|   <!-- End:             -->
 |