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