1 Generic Rootless Layer 2 Version 1.0 3 July 13, 2004 4 5 Torrey T. Lyons 6 torrey@xfree86.org 7 8 9Introduction 10 11 The generic rootless layer allows an X server to be implemented 12on top of another window server in a cooperative manner. This allows the 13X11 windows and native windows of the underlying window server to 14coexist on the same screen. The layer is called "rootless" because the root 15window of the X server is generally not drawn. Instead, each top-level 16child of the root window is represented as a separate on-screen window by 17the underlying window server. The layer is referred to as "generic" 18because it abstracts away the details of the underlying window system and 19contains code that is useful for any rootless X server. The code for the 20generic rootless layer is located in xc/programs/Xserver/miext/rootless. To 21build a complete rootless X server requires a specific rootless 22implementation, which provides functions that allow the generic rootless 23layer to interact with the underlying window system. 24 25 26Concepts 27 28 In the context of a rootless X server the term window is used to 29mean many fundamentally different things. For X11 a window is a DDX 30resource that describes a visible, or potentially visible, rectangle on the 31screen. A top-level window is a direct child of the root window. To avoid 32confusion, an on-screen native window of the underlying window system 33is referred to as a "frame". The generic rootless layer associates each 34mapped top-level X11 window with a frame. An X11 window may be said 35to be "framed" if it or its top-level parent is represented by a frame. 36 37 The generic rootless layer models each frame as being backed at 38all times by a backing buffer, which is periodically flushed to the screen. 39If the underlying window system does not provide a backing buffer for 40frames, this must be done by the rootless implementation. The generic 41rootless layer model does not assume it always has access to the frames' 42backing buffers. Any drawing to the buffer will be proceeded by a call to 43the rootless implementation's StartDrawing() function and StopDrawing() 44will be called when the drawing is concluded. The address of the frame's 45backing buffer is returned by the StartDrawing() function and it can 46change between successive calls. 47 48 Because each frame is assumed to have a backing buffer, the 49generic rootless layer will stop Expose events being generated when the 50regions of visibility of a frame change on screen. This is similar to backing 51store, but backing buffers are different in that they always store a copy of 52the entire window contents, not just the obscured portions. The price paid 53in increased memory consumption is made up by the greatly decreased 54complexity in not having to track and record regions as they are obscured. 55 56 57Rootless Implementation 58 59 The specifics of the underlying window system are provided to the 60generic rootless layer through rootless implementation functions, compile- 61time options, and runtime parameters. The rootless implementation 62functions are a list of functions that allow the generic rootless layer to 63perform operations such as creating, destroying, moving, and resizing 64frames. Some of the implementation functions are optional. A detailed 65description of the rootless implementation functions is provided in 66Appendix A. 67 68 By design, a rootless implementation should only have to include 69the rootless.h header file. The rootlessCommon.h file contains definitions 70internal to the generic rootless layer. (If you find you need to use 71rootlessCommon.h in your implementation, let the generic rootless layer 72maintainers know. This could be an area where the generic rootless layer 73should be generalized.) A rootless implementation should also modify 74rootlessConfig.h to specify compile time options for its platform. 75 76 The following compile-time options are defined in 77rootlessConfig.h: 78 79 o ROOTLESS_PROTECT_ALPHA: By default for a color bit depth of 24 and 80 32 bits per pixel, fb will overwrite the "unused" 8 bits to optimize 81 drawing speed. If this is true, the alpha channel of frames is 82 protected and is not modified when drawing to them. The bits 83 containing the alpha channel are defined by the macro 84 RootlessAlphaMask(bpp), which should return a bit mask for 85 various bits per pixel. 86 87 o ROOTLESS_REDISPLAY_DELAY: Time in milliseconds between updates to 88 the underlying window server. Most operations will be buffered until 89 this time has expired. 90 91 o ROOTLESS_RESIZE_GRAVITY: If the underlying window system supports it, 92 some frame resizes can be optimized by relying on the frame contents 93 maintaining a particular gravity during the resize. In this way less 94 of the frame contents need to be preserved by the generic rootless 95 layer. If true, the generic rootless layer will pass gravity hints 96 during resizing and rely on the frame contents being preserved 97 accordingly. 98 99 The following runtime options are defined in rootless.h: 100 101 o rootlessGlobalOffsetX, rootlessGlobalOffsetY: These specify the global 102 offset that is applied to all screens when converting from 103 screen-local to global coordinates. 104 105 o rootless_CopyBytes_threshold, rootless_CopyWindow_threshold: 106 The minimum number of bytes or pixels for which to use the rootless 107 implementation's respective acceleration function. The rootless 108 acceleration functions are all optional so these will only be used 109 if the respective acceleration function pointer is not NULL. 110 111 112Accelerated Drawing 113 114 The rootless implementation typically does not have direct access 115to the hardware. Its access to the graphics hardware is generally through 116the API of the underlying window system. This underlying API may not 117overlap well with the X11 drawing primitives. The generic rootless layer 118falls back to using fb for all its 2-D drawing. Providing optional rootless 119implementation acceleration functions can accelerate some graphics 120primitives and some window functions. Typically calling through to the 121underlying window systems API will not speed up these operations for 122small enough areas. The rootless_*_threshold runtime options allow the 123rootless implementation to provide hints for when the acceleration 124functions should be used instead of fb. 125 126 127Alpha Channel Protection 128 129 If the bits per pixel is greater then the color bit depth, the contents 130of the extra bits are undefined by the X11 protocol. Some window systems 131will use these extra bits as an alpha channel. The generic rootless layer can 132be configured to protect these bits and make sure they are not modified by 133other parts of the X server. To protect the alpha channel 134ROOTLESS_PROTECT_ALPHA and RootlessAlphaMask(bpp) must be 135set appropriately as described under the compile time options. This 136ensures that the X11 graphics primitives do not overwrite the alpha 137channel in an attempt to optimize drawing. In addition, the window 138functions PaintWindow() and Composite() must be replaced by alpha 139channel safe variants. These are provided in rootless/safeAlpha. 140 141 142Credits 143 144 The generic rootless layer was originally conceived and developed 145by Greg Parker as part of the XDarwin X server on Mac OS X. John 146Harper made later optimizations to this code but removed its generic 147independence of the underlying window system. Torrey T. Lyons 148reintroduced the generic abstractions and made the rootless code suitable 149for use by other X servers. 150 151 152Appendix A: Rootless Implementation Functions 153 154 The rootless implementation functions are defined in rootless.h. It 155is intended that rootless.h contains the complete interface that is needed by 156rootless implementations. The definitions contained in rootlessCommon.h 157are intended for internal use by the generic rootless layer and are more 158likely to change. 159 160 Most of these functions take a RootlessFrameID as a parameter. 161The RootlessFrameID is an opaque object that is returned by the 162implementation's CreateFrame() function. The generic rootless layer does 163not use this frame id other than to pass it back to the rootless 164implementation to indicate the frame to operate on. 165 166/* 167 * Create a new frame. 168 * The frame is created unmapped. 169 * 170 * pFrame RootlessWindowPtr for this frame should be completely 171 * initialized before calling except for pFrame->wid, which 172 * is set by this function. 173 * pScreen Screen on which to place the new frame 174 * newX, newY Position of the frame. 175 * pNewShape Shape for the frame (in frame-local coordinates). NULL for 176 * unshaped frames. 177 */ 178typedef Bool (*RootlessCreateFrameProc) 179 (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY, 180 RegionPtr pNewShape); 181 182/* 183 * Destroy a frame. 184 * Drawing is stopped and all updates are flushed before this is called. 185 * 186 * wid Frame id 187 */ 188typedef void (*RootlessDestroyFrameProc) 189 (RootlessFrameID wid); 190 191/* 192 * Move a frame on screen. 193 * Drawing is stopped and all updates are flushed before this is called. 194 * 195 * wid Frame id 196 * pScreen Screen to move the new frame to 197 * newX, newY New position of the frame 198 */ 199typedef void (*RootlessMoveFrameProc) 200 (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); 201 202/* 203 * Resize and move a frame. 204 * Drawing is stopped and all updates are flushed before this is called. 205 * 206 * wid Frame id 207 * pScreen Screen to move the new frame to 208 * newX, newY New position of the frame 209 * newW, newH New size of the frame 210 * gravity Gravity for window contents (rl_gravity_enum). This is always 211 * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set. 212 */ 213typedef void (*RootlessResizeFrameProc) 214 (RootlessFrameID wid, ScreenPtr pScreen, 215 int newX, int newY, unsigned int newW, unsigned int newH, 216 unsigned int gravity); 217 218/* 219 * Change frame ordering (AKA stacking, layering). 220 * Drawing is stopped before this is called. Unmapped frames are mapped by 221 * setting their ordering. 222 * 223 * wid Frame id 224 * nextWid Frame id of frame that is now above this one or NULL if this 225 * frame is at the top. 226 */ 227typedef void (*RootlessRestackFrameProc) 228 (RootlessFrameID wid, RootlessFrameID nextWid); 229 230/* 231 * Change frame's shape. 232 * Drawing is stopped before this is called. 233 * 234 * wid Frame id 235 * pNewShape New shape for the frame (in frame-local coordinates) 236 * or NULL if now unshaped. 237 */ 238typedef void (*RootlessReshapeFrameProc) 239 (RootlessFrameID wid, RegionPtr pNewShape); 240 241/* 242 * Unmap a frame. 243 * 244 * wid Frame id 245 */ 246typedef void (*RootlessUnmapFrameProc) 247 (RootlessFrameID wid); 248 249/* 250 * Start drawing to a frame. 251 * Prepare a frame for direct access to its backing buffer. 252 * 253 * wid Frame id 254 * pixelData Address of the backing buffer (returned) 255 * bytesPerRow Width in bytes of the backing buffer (returned) 256 */ 257typedef void (*RootlessStartDrawingProc) 258 (RootlessFrameID wid, char **pixelData, int *bytesPerRow); 259 260/* 261 * Stop drawing to a frame. 262 * No drawing to the frame's backing buffer will occur until drawing 263 * is started again. 264 * 265 * wid Frame id 266 * flush Flush drawing updates for this frame to the screen. 267 */ 268typedef void (*RootlessStopDrawingProc) 269 (RootlessFrameID wid, Bool flush); 270 271/* 272 * Flush drawing updates to the screen. 273 * Drawing is stopped before this is called. 274 * 275 * wid Frame id 276 * pDamage Region containing all the changed pixels in frame-local 277 * coordinates. This is clipped to the window's clip. 278 */ 279typedef void (*RootlessUpdateRegionProc) 280 (RootlessFrameID wid, RegionPtr pDamage); 281 282/* 283 * Mark damaged rectangles as requiring redisplay to screen. 284 * 285 * wid Frame id 286 * nrects Number of damaged rectangles 287 * rects Array of damaged rectangles in frame-local coordinates 288 * shift_x, Vector to shift rectangles by 289 * shift_y 290 */ 291typedef void (*RootlessDamageRectsProc) 292 (RootlessFrameID wid, int nrects, const BoxRec *rects, 293 int shift_x, int shift_y); 294 295/* 296 * Switch the window associated with a frame. (Optional) 297 * When a framed window is reparented, the frame is resized and set to 298 * use the new top-level parent. If defined this function will be called 299 * afterwards for implementation specific bookkeeping. 300 * 301 * pFrame Frame whose window has switched 302 * oldWin Previous window wrapped by this frame 303 */ 304typedef void (*RootlessSwitchWindowProc) 305 (RootlessWindowPtr pFrame, WindowPtr oldWin); 306 307/* 308 * Copy bytes. (Optional) 309 * Source and destinate may overlap and the right thing should happen. 310 * 311 * width Bytes to copy per row 312 * height Number of rows 313 * src Source data 314 * srcRowBytes Width of source in bytes 315 * dst Destination data 316 * dstRowBytes Width of destination in bytes 317 */ 318typedef void (*RootlessCopyBytesProc) 319 (unsigned int width, unsigned int height, 320 const void *src, unsigned int srcRowBytes, 321 void *dst, unsigned int dstRowBytes); 322 323/* 324 * Copy area in frame to another part of frame. (Optional) 325 * 326 * wid Frame id 327 * dstNrects Number of rectangles to copy 328 * dstRects Array of rectangles to copy 329 * dx, dy Number of pixels away to copy area 330 */ 331typedef void (*RootlessCopyWindowProc) 332 (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, 333 int dx, int dy); 334 335