1706f2543Smrg Generic Rootless Layer 2706f2543Smrg Version 1.0 3706f2543Smrg July 13, 2004 4706f2543Smrg 5706f2543Smrg Torrey T. Lyons 6706f2543Smrg torrey@xfree86.org 7706f2543Smrg 8706f2543Smrg 9706f2543SmrgIntroduction 10706f2543Smrg 11706f2543Smrg The generic rootless layer allows an X server to be implemented 12706f2543Smrgon top of another window server in a cooperative manner. This allows the 13706f2543SmrgX11 windows and native windows of the underlying window server to 14706f2543Smrgcoexist on the same screen. The layer is called "rootless" because the root 15706f2543Smrgwindow of the X server is generally not drawn. Instead, each top-level 16706f2543Smrgchild of the root window is represented as a separate on-screen window by 17706f2543Smrgthe underlying window server. The layer is referred to as "generic" 18706f2543Smrgbecause it abstracts away the details of the underlying window system and 19706f2543Smrgcontains code that is useful for any rootless X server. The code for the 20706f2543Smrggeneric rootless layer is located in xc/programs/Xserver/miext/rootless. To 21706f2543Smrgbuild a complete rootless X server requires a specific rootless 22706f2543Smrgimplementation, which provides functions that allow the generic rootless 23706f2543Smrglayer to interact with the underlying window system. 24706f2543Smrg 25706f2543Smrg 26706f2543SmrgConcepts 27706f2543Smrg 28706f2543Smrg In the context of a rootless X server the term window is used to 29706f2543Smrgmean many fundamentally different things. For X11 a window is a DDX 30706f2543Smrgresource that describes a visible, or potentially visible, rectangle on the 31706f2543Smrgscreen. A top-level window is a direct child of the root window. To avoid 32706f2543Smrgconfusion, an on-screen native window of the underlying window system 33706f2543Smrgis referred to as a "frame". The generic rootless layer associates each 34706f2543Smrgmapped top-level X11 window with a frame. An X11 window may be said 35706f2543Smrgto be "framed" if it or its top-level parent is represented by a frame. 36706f2543Smrg 37706f2543Smrg The generic rootless layer models each frame as being backed at 38706f2543Smrgall times by a backing buffer, which is periodically flushed to the screen. 39706f2543SmrgIf the underlying window system does not provide a backing buffer for 40706f2543Smrgframes, this must be done by the rootless implementation. The generic 41706f2543Smrgrootless layer model does not assume it always has access to the frames' 42706f2543Smrgbacking buffers. Any drawing to the buffer will be proceeded by a call to 43706f2543Smrgthe rootless implementation's StartDrawing() function and StopDrawing() 44706f2543Smrgwill be called when the drawing is concluded. The address of the frame's 45706f2543Smrgbacking buffer is returned by the StartDrawing() function and it can 46706f2543Smrgchange between successive calls. 47706f2543Smrg 48706f2543Smrg Because each frame is assumed to have a backing buffer, the 49706f2543Smrggeneric rootless layer will stop Expose events being generated when the 50706f2543Smrgregions of visibility of a frame change on screen. This is similar to backing 51706f2543Smrgstore, but backing buffers are different in that they always store a copy of 52706f2543Smrgthe entire window contents, not just the obscured portions. The price paid 53706f2543Smrgin increased memory consumption is made up by the greatly decreased 54706f2543Smrgcomplexity in not having to track and record regions as they are obscured. 55706f2543Smrg 56706f2543Smrg 57706f2543SmrgRootless Implementation 58706f2543Smrg 59706f2543Smrg The specifics of the underlying window system are provided to the 60706f2543Smrggeneric rootless layer through rootless implementation functions, compile- 61706f2543Smrgtime options, and runtime parameters. The rootless implementation 62706f2543Smrgfunctions are a list of functions that allow the generic rootless layer to 63706f2543Smrgperform operations such as creating, destroying, moving, and resizing 64706f2543Smrgframes. Some of the implementation functions are optional. A detailed 65706f2543Smrgdescription of the rootless implementation functions is provided in 66706f2543SmrgAppendix A. 67706f2543Smrg 68706f2543Smrg By design, a rootless implementation should only have to include 69706f2543Smrgthe rootless.h header file. The rootlessCommon.h file contains definitions 70706f2543Smrginternal to the generic rootless layer. (If you find you need to use 71706f2543SmrgrootlessCommon.h in your implementation, let the generic rootless layer 72706f2543Smrgmaintainers know. This could be an area where the generic rootless layer 73706f2543Smrgshould be generalized.) A rootless implementation should also modify 74706f2543SmrgrootlessConfig.h to specify compile time options for its platform. 75706f2543Smrg 76706f2543Smrg The following compile-time options are defined in 77706f2543SmrgrootlessConfig.h: 78706f2543Smrg 79706f2543Smrg o ROOTLESS_PROTECT_ALPHA: By default for a color bit depth of 24 and 80706f2543Smrg 32 bits per pixel, fb will overwrite the "unused" 8 bits to optimize 81706f2543Smrg drawing speed. If this is true, the alpha channel of frames is 82706f2543Smrg protected and is not modified when drawing to them. The bits 83706f2543Smrg containing the alpha channel are defined by the macro 84706f2543Smrg RootlessAlphaMask(bpp), which should return a bit mask for 85706f2543Smrg various bits per pixel. 86706f2543Smrg 87706f2543Smrg o ROOTLESS_REDISPLAY_DELAY: Time in milliseconds between updates to 88706f2543Smrg the underlying window server. Most operations will be buffered until 89706f2543Smrg this time has expired. 90706f2543Smrg 91706f2543Smrg o ROOTLESS_RESIZE_GRAVITY: If the underlying window system supports it, 92706f2543Smrg some frame resizes can be optimized by relying on the frame contents 93706f2543Smrg maintaining a particular gravity during the resize. In this way less 94706f2543Smrg of the frame contents need to be preserved by the generic rootless 95706f2543Smrg layer. If true, the generic rootless layer will pass gravity hints 96706f2543Smrg during resizing and rely on the frame contents being preserved 97706f2543Smrg accordingly. 98706f2543Smrg 99706f2543Smrg The following runtime options are defined in rootless.h: 100706f2543Smrg 101706f2543Smrg o rootlessGlobalOffsetX, rootlessGlobalOffsetY: These specify the global 102706f2543Smrg offset that is applied to all screens when converting from 103706f2543Smrg screen-local to global coordinates. 104706f2543Smrg 105706f2543Smrg o rootless_CopyBytes_threshold, rootless_CopyWindow_threshold: 106706f2543Smrg The minimum number of bytes or pixels for which to use the rootless 107706f2543Smrg implementation's respective acceleration function. The rootless 108706f2543Smrg acceleration functions are all optional so these will only be used 109706f2543Smrg if the respective acceleration function pointer is not NULL. 110706f2543Smrg 111706f2543Smrg 112706f2543SmrgAccelerated Drawing 113706f2543Smrg 114706f2543Smrg The rootless implementation typically does not have direct access 115706f2543Smrgto the hardware. Its access to the graphics hardware is generally through 116706f2543Smrgthe API of the underlying window system. This underlying API may not 117706f2543Smrgoverlap well with the X11 drawing primitives. The generic rootless layer 118706f2543Smrgfalls back to using fb for all its 2-D drawing. Providing optional rootless 119706f2543Smrgimplementation acceleration functions can accelerate some graphics 120706f2543Smrgprimitives and some window functions. Typically calling through to the 121706f2543Smrgunderlying window systems API will not speed up these operations for 122706f2543Smrgsmall enough areas. The rootless_*_threshold runtime options allow the 123706f2543Smrgrootless implementation to provide hints for when the acceleration 124706f2543Smrgfunctions should be used instead of fb. 125706f2543Smrg 126706f2543Smrg 127706f2543SmrgAlpha Channel Protection 128706f2543Smrg 129706f2543Smrg If the bits per pixel is greater then the color bit depth, the contents 130706f2543Smrgof the extra bits are undefined by the X11 protocol. Some window systems 131706f2543Smrgwill use these extra bits as an alpha channel. The generic rootless layer can 132706f2543Smrgbe configured to protect these bits and make sure they are not modified by 133706f2543Smrgother parts of the X server. To protect the alpha channel 134706f2543SmrgROOTLESS_PROTECT_ALPHA and RootlessAlphaMask(bpp) must be 135706f2543Smrgset appropriately as described under the compile time options. This 136706f2543Smrgensures that the X11 graphics primitives do not overwrite the alpha 137706f2543Smrgchannel in an attempt to optimize drawing. In addition, the window 138706f2543Smrgfunctions PaintWindow() and Composite() must be replaced by alpha 139706f2543Smrgchannel safe variants. These are provided in rootless/safeAlpha. 140706f2543Smrg 141706f2543Smrg 142706f2543SmrgCredits 143706f2543Smrg 144706f2543Smrg The generic rootless layer was originally conceived and developed 145706f2543Smrgby Greg Parker as part of the XDarwin X server on Mac OS X. John 146706f2543SmrgHarper made later optimizations to this code but removed its generic 147706f2543Smrgindependence of the underlying window system. Torrey T. Lyons 148706f2543Smrgreintroduced the generic abstractions and made the rootless code suitable 149706f2543Smrgfor use by other X servers. 150706f2543Smrg 151706f2543Smrg 152706f2543SmrgAppendix A: Rootless Implementation Functions 153706f2543Smrg 154706f2543Smrg The rootless implementation functions are defined in rootless.h. It 155706f2543Smrgis intended that rootless.h contains the complete interface that is needed by 156706f2543Smrgrootless implementations. The definitions contained in rootlessCommon.h 157706f2543Smrgare intended for internal use by the generic rootless layer and are more 158706f2543Smrglikely to change. 159706f2543Smrg 160706f2543Smrg Most of these functions take a RootlessFrameID as a parameter. 161706f2543SmrgThe RootlessFrameID is an opaque object that is returned by the 162706f2543Smrgimplementation's CreateFrame() function. The generic rootless layer does 163706f2543Smrgnot use this frame id other than to pass it back to the rootless 164706f2543Smrgimplementation to indicate the frame to operate on. 165706f2543Smrg 166706f2543Smrg/* 167706f2543Smrg * Create a new frame. 168706f2543Smrg * The frame is created unmapped. 169706f2543Smrg * 170706f2543Smrg * pFrame RootlessWindowPtr for this frame should be completely 171706f2543Smrg * initialized before calling except for pFrame->wid, which 172706f2543Smrg * is set by this function. 173706f2543Smrg * pScreen Screen on which to place the new frame 174706f2543Smrg * newX, newY Position of the frame. 175706f2543Smrg * pNewShape Shape for the frame (in frame-local coordinates). NULL for 176706f2543Smrg * unshaped frames. 177706f2543Smrg */ 178706f2543Smrgtypedef Bool (*RootlessCreateFrameProc) 179706f2543Smrg (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY, 180706f2543Smrg RegionPtr pNewShape); 181706f2543Smrg 182706f2543Smrg/* 183706f2543Smrg * Destroy a frame. 184706f2543Smrg * Drawing is stopped and all updates are flushed before this is called. 185706f2543Smrg * 186706f2543Smrg * wid Frame id 187706f2543Smrg */ 188706f2543Smrgtypedef void (*RootlessDestroyFrameProc) 189706f2543Smrg (RootlessFrameID wid); 190706f2543Smrg 191706f2543Smrg/* 192706f2543Smrg * Move a frame on screen. 193706f2543Smrg * Drawing is stopped and all updates are flushed before this is called. 194706f2543Smrg * 195706f2543Smrg * wid Frame id 196706f2543Smrg * pScreen Screen to move the new frame to 197706f2543Smrg * newX, newY New position of the frame 198706f2543Smrg */ 199706f2543Smrgtypedef void (*RootlessMoveFrameProc) 200706f2543Smrg (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); 201706f2543Smrg 202706f2543Smrg/* 203706f2543Smrg * Resize and move a frame. 204706f2543Smrg * Drawing is stopped and all updates are flushed before this is called. 205706f2543Smrg * 206706f2543Smrg * wid Frame id 207706f2543Smrg * pScreen Screen to move the new frame to 208706f2543Smrg * newX, newY New position of the frame 209706f2543Smrg * newW, newH New size of the frame 210706f2543Smrg * gravity Gravity for window contents (rl_gravity_enum). This is always 211706f2543Smrg * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set. 212706f2543Smrg */ 213706f2543Smrgtypedef void (*RootlessResizeFrameProc) 214706f2543Smrg (RootlessFrameID wid, ScreenPtr pScreen, 215706f2543Smrg int newX, int newY, unsigned int newW, unsigned int newH, 216706f2543Smrg unsigned int gravity); 217706f2543Smrg 218706f2543Smrg/* 219706f2543Smrg * Change frame ordering (AKA stacking, layering). 220706f2543Smrg * Drawing is stopped before this is called. Unmapped frames are mapped by 221706f2543Smrg * setting their ordering. 222706f2543Smrg * 223706f2543Smrg * wid Frame id 224706f2543Smrg * nextWid Frame id of frame that is now above this one or NULL if this 225706f2543Smrg * frame is at the top. 226706f2543Smrg */ 227706f2543Smrgtypedef void (*RootlessRestackFrameProc) 228706f2543Smrg (RootlessFrameID wid, RootlessFrameID nextWid); 229706f2543Smrg 230706f2543Smrg/* 231706f2543Smrg * Change frame's shape. 232706f2543Smrg * Drawing is stopped before this is called. 233706f2543Smrg * 234706f2543Smrg * wid Frame id 235706f2543Smrg * pNewShape New shape for the frame (in frame-local coordinates) 236706f2543Smrg * or NULL if now unshaped. 237706f2543Smrg */ 238706f2543Smrgtypedef void (*RootlessReshapeFrameProc) 239706f2543Smrg (RootlessFrameID wid, RegionPtr pNewShape); 240706f2543Smrg 241706f2543Smrg/* 242706f2543Smrg * Unmap a frame. 243706f2543Smrg * 244706f2543Smrg * wid Frame id 245706f2543Smrg */ 246706f2543Smrgtypedef void (*RootlessUnmapFrameProc) 247706f2543Smrg (RootlessFrameID wid); 248706f2543Smrg 249706f2543Smrg/* 250706f2543Smrg * Start drawing to a frame. 251706f2543Smrg * Prepare a frame for direct access to its backing buffer. 252706f2543Smrg * 253706f2543Smrg * wid Frame id 254706f2543Smrg * pixelData Address of the backing buffer (returned) 255706f2543Smrg * bytesPerRow Width in bytes of the backing buffer (returned) 256706f2543Smrg */ 257706f2543Smrgtypedef void (*RootlessStartDrawingProc) 258706f2543Smrg (RootlessFrameID wid, char **pixelData, int *bytesPerRow); 259706f2543Smrg 260706f2543Smrg/* 261706f2543Smrg * Stop drawing to a frame. 262706f2543Smrg * No drawing to the frame's backing buffer will occur until drawing 263706f2543Smrg * is started again. 264706f2543Smrg * 265706f2543Smrg * wid Frame id 266706f2543Smrg * flush Flush drawing updates for this frame to the screen. 267706f2543Smrg */ 268706f2543Smrgtypedef void (*RootlessStopDrawingProc) 269706f2543Smrg (RootlessFrameID wid, Bool flush); 270706f2543Smrg 271706f2543Smrg/* 272706f2543Smrg * Flush drawing updates to the screen. 273706f2543Smrg * Drawing is stopped before this is called. 274706f2543Smrg * 275706f2543Smrg * wid Frame id 276706f2543Smrg * pDamage Region containing all the changed pixels in frame-local 277706f2543Smrg * coordinates. This is clipped to the window's clip. 278706f2543Smrg */ 279706f2543Smrgtypedef void (*RootlessUpdateRegionProc) 280706f2543Smrg (RootlessFrameID wid, RegionPtr pDamage); 281706f2543Smrg 282706f2543Smrg/* 283706f2543Smrg * Mark damaged rectangles as requiring redisplay to screen. 284706f2543Smrg * 285706f2543Smrg * wid Frame id 286706f2543Smrg * nrects Number of damaged rectangles 287706f2543Smrg * rects Array of damaged rectangles in frame-local coordinates 288706f2543Smrg * shift_x, Vector to shift rectangles by 289706f2543Smrg * shift_y 290706f2543Smrg */ 291706f2543Smrgtypedef void (*RootlessDamageRectsProc) 292706f2543Smrg (RootlessFrameID wid, int nrects, const BoxRec *rects, 293706f2543Smrg int shift_x, int shift_y); 294706f2543Smrg 295706f2543Smrg/* 296706f2543Smrg * Switch the window associated with a frame. (Optional) 297706f2543Smrg * When a framed window is reparented, the frame is resized and set to 298706f2543Smrg * use the new top-level parent. If defined this function will be called 299706f2543Smrg * afterwards for implementation specific bookkeeping. 300706f2543Smrg * 301706f2543Smrg * pFrame Frame whose window has switched 302706f2543Smrg * oldWin Previous window wrapped by this frame 303706f2543Smrg */ 304706f2543Smrgtypedef void (*RootlessSwitchWindowProc) 305706f2543Smrg (RootlessWindowPtr pFrame, WindowPtr oldWin); 306706f2543Smrg 307706f2543Smrg/* 308706f2543Smrg * Copy bytes. (Optional) 309706f2543Smrg * Source and destinate may overlap and the right thing should happen. 310706f2543Smrg * 311706f2543Smrg * width Bytes to copy per row 312706f2543Smrg * height Number of rows 313706f2543Smrg * src Source data 314706f2543Smrg * srcRowBytes Width of source in bytes 315706f2543Smrg * dst Destination data 316706f2543Smrg * dstRowBytes Width of destination in bytes 317706f2543Smrg */ 318706f2543Smrgtypedef void (*RootlessCopyBytesProc) 319706f2543Smrg (unsigned int width, unsigned int height, 320706f2543Smrg const void *src, unsigned int srcRowBytes, 321706f2543Smrg void *dst, unsigned int dstRowBytes); 322706f2543Smrg 323706f2543Smrg/* 324706f2543Smrg * Copy area in frame to another part of frame. (Optional) 325706f2543Smrg * 326706f2543Smrg * wid Frame id 327706f2543Smrg * dstNrects Number of rectangles to copy 328706f2543Smrg * dstRects Array of rectangles to copy 329706f2543Smrg * dx, dy Number of pixels away to copy area 330706f2543Smrg */ 331706f2543Smrgtypedef void (*RootlessCopyWindowProc) 332706f2543Smrg (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, 333706f2543Smrg int dx, int dy); 334706f2543Smrg 335