Displays to an X11 server
Name
display-x : Displays to an X11 server
Synopsis
display-x: [ [-screen=<screenidx>] | [-inwin=<winid>|root] ] [-noinput] [-nocursor] [-keepcursor] [-physz==<sizex>,<sizey>[dpi]] [-nobuffer] [-noaccel] [-nomansync] [-noshm] [-nodga] [-novidmode] [-nodbe] [-noevi] [<display>]
Description
display-x displays a GGI application via an X11 server. The server may be local or remote, and options are provided to tune performance to various scenerios. In normal operation, a new X11 window is opened, solid fill primitives and copybox are accelerated by the server, and a backbuffer is kept client-side for content fills (e.g. ggiPut* functions) and to restore data when an application has been exposed after being concealed by another window.
'Ctrl-Alt-m' toggles mouse grabbing in the new window. It will try to emulate a relative mouse device, i.e. one that can be moved arbitrarily far in any direction without ever leaving the window. This is useful for game controls, where loosing focus is generally undesireable. Note that grabbing must be turned off in order to leave the window.
Options
- display
The X display to connect to, otherwise defaults to the display specified in DISPLAY.
- '-screen=<screenidx>'
The screen to run on. Normally the biggest/deepest screen compatible with the requested mode will be chosen; with this option only the screen specified by screenidx will be considered.
- '-inwin=<winid>|root'
Run in already-existing window with id winid. This can be used to embed a LibGGI application into an X11 application. The value should be an X11 window ID expressed as a "0x" prefixed hexadecimal number. The special string "root" will cause the application to run in the root window of the selected screen (or the default screen if no explicit selection has been made.) Note that in the root window, you may need to explictly select a LibGII input source using the GGI_INPUT environment variable as the window manager will absorb all events sent to the root window. Some features (currently frames and virtual areas) may not work in root windows. On the other hand, when using the root window other features like direct framebuffer access and video hardware mode selection may be available which are not available when the application is running in a normal window.
- '-noinput'
X events sent to the window are not captured and merged with any other LibGII input sources. This allows one to take input from raw devices without receiving duplicate events should X also be configured to use the device.
- '-nocursor', '-keepcursor'
Normal behavior of display-x is to create a small dot mouse cursor pixmap which is visible when the mouse is positioned over the window containing the visual. This goes away when using mouse grabbing as described above, but otherwise can get in the way of mouse cursors implemented by the application. With the former option, the X mouse cursor will be invisible when it is over the visual, with the latter, the cursor from the root window is used unaltered. If both options are supplied, the latter takes precedence.
- '-physz==<sizex>,<sizey>[dpi]'
This option will override the physical screen size reported by the X server, which affects applications which wish to remain resolution independent. sizex,:p:sizey are the x,y size of the entire screen (not just the X window containing the visual) in millimeters, unless the optional 'dpi' string is affixed, in which case, they represent resolution in dots-per-inch. Yes, there are two equals signs there, for reasons of compatibility with other targets.
- '-nobuffer'
No client-side backbuffer is kept. This may result in lost data when the LibGGI application is obscured by other windows. This data loss can be minimized by enabling backing store in the X11 server. Using this option will cause operations which must read back framebuffer data to be much slower, but on the other hand can result in a slight speed gain for certain graphics primitives. It is best used when resources are severely limited on the client side, and with applications that do not perform frequent ggiPut* operations.
- '-noaccel'
All rendering is performed in the client-side backbuffer, and then sent to to the server; no server-side accelerated graphics operations are used. This will signifigantly slow down certain graphics applications, but for applications that use directbuffer and asyncronous mode extensively the effect will not be noticeable. The only real reason to use this option, however, is to eliminate artifacts caused by incorrectly implemented X11 hardware drivers.
- '-nomansync'
Use of the mansync helper library to periodically flush backbuffer contents to the X11 server is disabled. This, of course, will result in incorrect behavior of applications that use syncronous mode.
- '-noshm'
Use of the MIT-SHM extension to speed data transfer between clients and servers which are running on the same machine is disabled. Normally it is not necessary to use this option, as use of the MIT-SHM extension is disabled automatically if it appears to be nonfunctional.
- '-nodga'
Use of the XFree86-DGA extension to provide direct framebuffer access is disabled. Some implementations of the XFree86-DGA extension may cause system lockups. Use this option to prevent such occurrances.
NoteCurrently XFree86-DGA support has not been integrated into the display-X target. To use DGA, see the older display-dga target.
- '-novidmode'
Use of the X11 Vidmode extension to change video timing in full-screen modes is disabled. Some implementations of the Vidmode extension may cause system lockups. Use this option to prevent such occurrances.
NoteCurrently Vidmode support has not been completed.
- '-nodbe'
Use of the X11 DBE extension to provide buffered frame support is disabled.
NoteCurrently DBE extension support has not been completed.
- '-noevi'
Use of the X11 Extended Visual Information extension to identify visuals which are exclusively used for overlay/underlay is disabled.
"Cliff notes" on new X target
The old X target rendered all primitives in a RAM backbuffer, and then copied the entire backbuffer periodically using the mansync helper to the X screen. This caused a lot of wasted bandwidth. However, since the bandwidth was being wasted anyway, LibGGIMISC splitline support was a simple hack that added nearly no complexity.
The old Xlib target had no RAM backbuffer and rendered all primitives using Xlib calls. This caused very slow performance when a lot of individual pixels were being drawn one at a time, and slow performance on operations which got pixel data back from the visual, since it had to be fetched back over the wire. Also, this precluded the use of the directbuffer on the xlib target.
The new X target in its default mode maintains both a RAM backbuffer on the client side, and uses Xlib primitives to draw on the server side. When a primitive, such as a drawbox, can use an Xlib function, the command is dispatched to the X server and the data in the RAM buffer is updated using a software renderer. For operations such as putbox, the RAM buffer is updated first, and the synced to the X server. Unlike the old target, the new target keeps track of a "dirty region" and only syncs the area affected since the last time a syncronization occured. This dirty-region tracking only keeps track of one rectangular dirty area. A helper library that keeps track of more than one rectangle could be implemented to improve performance of display-X and any other similarly designed display target. To be most flexible such a target should take weighted parameters representing the cost of transferring data (per byte) from the backbuffer, and the per-operation cost of initiating such a transfer, which would alter its strategy as to how many regions are maintained and how much they overlap.
The old X target's RAM buffer was implemented using the X target's drawops hooks -- that is, the RAM buffer was essentially a re-implementation of display-memory with the extra facilities to sync to the X server built in. The new target capitalizes on some improvements made in display-memory, and instead it opens and loads a child display-memory visual which takes care of finding software renderers for the RAM buffer. The main drawops of the new target dispatch the the X server commands and call the child's corresponsing software drawops to ensure consistant state of the RAM buffer vs the X window. This must be done such that any requests to get data from the RAM backbuffer are not processed until the RAM backbuffer is up to date, and any flushes from the backbuffer are not processed until the backbuffer is up to date. There's a lot of locking intracacy to ensure this level of consistancy.
The basic syncronization operation is accomplished by the flush function, which is the function loaded on the xpriv flush member hook. The flush hook function is called:
- When the mansync helper decides it is time to refresh the screen.
- After a primitive, if the visual is in syncronous rendering mode.
- When an expose or graphicsexpose event is sent from the server. This means the server has discarded data that was concealed by another window or by the edge of the screen, and the data must be resent from the client.
...in the last case the whole area that must be refreshed is sent again by the client. In the first two cases only the dirty area is sent, except when the application is holding the directbuffer writing resource, in which case the whole area must be synced because there is no way for the target to tell what the user has modified. Holding the directbuffer write resource open when the display is in syncronous mode or when also sending primitives will result in bad perfomance. There's no reason to do so on any target, so don't.
Unfortunately some XFree86 drivers are buggy, and when you render an accelerated primitive which overlaps an area which is not visible to the user, the driver fails to update the backing store (it only draws the clipped primitive using accelarated funtions and does not complete the job by calling the software renderer to update the backing store.) Most people will not be affected by this bug, however.
The new X target implements gammamap (DirectColor), unlike the old targets.
The new X target is best used with backing store turned on in the server. When backing store is not turned on, primitives which are clipped to the visual area but still in the virtual area may be slower then the old target, since data will be sent to the server hoping it will be stored in the backing store. Likewise when a full-screen flush occurrs the entire virtual area data is sent. The target could be optimized not to send this data when it detects that there is no backing store available in the server.
Either the RAM backbuffer or the X primitives can be disabled via target options, which will cause emulation of the old X ('-noaccel') and Xlib ('-nobuffer') targets, with a couple of notable exceptions:
The old X and Xlib targets opened a window and drew directly into it. The old Xlib target did not implement support for ggiSetOrigin. As noted above the old X target used a hack that didn't cost much when compared to the cost of syncing the backbuffer periodically. The new target implements ggiSetOrigin by creating a parent window, then creating a child window inside the parent window. Thus the child window can be moved around inside the parent window, and the parent window will clip the displayed data to the right size. This is much more efficient than the old way when the server is keeping a backing store (which it sometimes does "in secret" even when the backing store functionality in the server is turned off.)
Unfortunately many window managers seem to be buggy, and do not install the colormap of a child window when a mouse enters it. This causes palette and gammamap to be messed up. Since so many windowmanagers fail to implement the behavior described in the Xlib manpages, a workaround needs to be added which will not use the child window (this part is easy enough since the -inwin=root option already implements a child-less rendering) and either disables ggiSetOrigin support, or uses a better version of the old display-x target's creative blitting to emulate setorigin support.
LibGGIMISC's splitline support for the original X display was broken by the new child-window stuff as well. In order to implement splitline support, libggimisc must implement a new set of primitives for the new display X that uses two child windows to produce the splitline effect. This complicates a lot of the primitives, so the code is best isolated in LibGGIMISC so any bugs or performance issues in it do not affect vanilla LibGGI users who have no need for splitline. It would probably be best if the special renderers were only loaded on the first call to ggiSetSplitline, so that when LibGGIMISC implements support for the XSync extension, users who are not using splitline do not pay a performance penalty for using XSync.
The child window may also be to blame for the fact that a window which is focused, but not moused over, stops receiving keyboard events. Reworking the X input target to take it's keyboard events from the parent window instead of the child window (mouse and expose/graphicsexpose events must still come from the child window) would be the needed fix.
The new target tries to remove dl dependencies by creating a separate module file for any X extensions used. Because of some deficiencies in the X module system (there is no way to cleanly unload a module) some kludges have had to be made when a module is loaded but gleaned to be nonpresent, then unloaded. This won't effect most people.
However, a more common problem will be seen because X does not give us any way to determine if the XSHM extension will work -- it tells us whether the server has XSHM, but it does not tell us whether the client and server can share memory segments. Thus, when running a remote client, it may be necessary to manually disable XSHM support with the -noshm target option.
Anyway, I hope this is helpful to any intrepid soul which decides to fondle this code :-) (Brian S. Julin)
Features
- DirectBuffer always available.
- Accelerated
- Multiple frames except for root window
- Panning except for root window
- Support Gammamap