105b261ecSmrg Generic Rootless Layer 205b261ecSmrg Version 1.0 305b261ecSmrg July 13, 2004 405b261ecSmrg 505b261ecSmrg Torrey T. Lyons 605b261ecSmrg torrey@xfree86.org 705b261ecSmrg 805b261ecSmrg 905b261ecSmrgIntroduction 1005b261ecSmrg 1105b261ecSmrg The generic rootless layer allows an X server to be implemented 1205b261ecSmrgon top of another window server in a cooperative manner. This allows the 1305b261ecSmrgX11 windows and native windows of the underlying window server to 1405b261ecSmrgcoexist on the same screen. The layer is called "rootless" because the root 1505b261ecSmrgwindow of the X server is generally not drawn. Instead, each top-level 1605b261ecSmrgchild of the root window is represented as a separate on-screen window by 1705b261ecSmrgthe underlying window server. The layer is referred to as "generic" 1805b261ecSmrgbecause it abstracts away the details of the underlying window system and 1905b261ecSmrgcontains code that is useful for any rootless X server. The code for the 2005b261ecSmrggeneric rootless layer is located in xc/programs/Xserver/miext/rootless. To 2105b261ecSmrgbuild a complete rootless X server requires a specific rootless 2205b261ecSmrgimplementation, which provides functions that allow the generic rootless 2305b261ecSmrglayer to interact with the underlying window system. 2405b261ecSmrg 2505b261ecSmrg 2605b261ecSmrgConcepts 2705b261ecSmrg 2805b261ecSmrg In the context of a rootless X server the term window is used to 2905b261ecSmrgmean many fundamentally different things. For X11 a window is a DDX 3005b261ecSmrgresource that describes a visible, or potentially visible, rectangle on the 3105b261ecSmrgscreen. A top-level window is a direct child of the root window. To avoid 3205b261ecSmrgconfusion, an on-screen native window of the underlying window system 3305b261ecSmrgis referred to as a "frame". The generic rootless layer associates each 3405b261ecSmrgmapped top-level X11 window with a frame. An X11 window may be said 3505b261ecSmrgto be "framed" if it or its top-level parent is represented by a frame. 3605b261ecSmrg 3705b261ecSmrg The generic rootless layer models each frame as being backed at 3805b261ecSmrgall times by a backing buffer, which is periodically flushed to the screen. 3905b261ecSmrgIf the underlying window system does not provide a backing buffer for 4005b261ecSmrgframes, this must be done by the rootless implementation. The generic 4105b261ecSmrgrootless layer model does not assume it always has access to the frames' 4205b261ecSmrgbacking buffers. Any drawing to the buffer will be proceeded by a call to 4305b261ecSmrgthe rootless implementation's StartDrawing() function and StopDrawing() 4405b261ecSmrgwill be called when the drawing is concluded. The address of the frame's 4505b261ecSmrgbacking buffer is returned by the StartDrawing() function and it can 4605b261ecSmrgchange between successive calls. 4705b261ecSmrg 4805b261ecSmrg Because each frame is assumed to have a backing buffer, the 4905b261ecSmrggeneric rootless layer will stop Expose events being generated when the 5005b261ecSmrgregions of visibility of a frame change on screen. This is similar to backing 5105b261ecSmrgstore, but backing buffers are different in that they always store a copy of 5205b261ecSmrgthe entire window contents, not just the obscured portions. The price paid 5305b261ecSmrgin increased memory consumption is made up by the greatly decreased 5405b261ecSmrgcomplexity in not having to track and record regions as they are obscured. 5505b261ecSmrg 5605b261ecSmrg 5705b261ecSmrgRootless Implementation 5805b261ecSmrg 5905b261ecSmrg The specifics of the underlying window system are provided to the 6005b261ecSmrggeneric rootless layer through rootless implementation functions, compile- 6105b261ecSmrgtime options, and runtime parameters. The rootless implementation 6205b261ecSmrgfunctions are a list of functions that allow the generic rootless layer to 6305b261ecSmrgperform operations such as creating, destroying, moving, and resizing 6405b261ecSmrgframes. Some of the implementation functions are optional. A detailed 6505b261ecSmrgdescription of the rootless implementation functions is provided in 6605b261ecSmrgAppendix A. 6705b261ecSmrg 6805b261ecSmrg By design, a rootless implementation should only have to include 6905b261ecSmrgthe rootless.h header file. The rootlessCommon.h file contains definitions 7005b261ecSmrginternal to the generic rootless layer. (If you find you need to use 7105b261ecSmrgrootlessCommon.h in your implementation, let the generic rootless layer 7205b261ecSmrgmaintainers know. This could be an area where the generic rootless layer 7305b261ecSmrgshould be generalized.) A rootless implementation should also modify 7405b261ecSmrgrootlessConfig.h to specify compile time options for its platform. 7505b261ecSmrg 7605b261ecSmrg The following compile-time options are defined in 7705b261ecSmrgrootlessConfig.h: 7805b261ecSmrg 7905b261ecSmrg o ROOTLESS_PROTECT_ALPHA: By default for a color bit depth of 24 and 8005b261ecSmrg 32 bits per pixel, fb will overwrite the "unused" 8 bits to optimize 8105b261ecSmrg drawing speed. If this is true, the alpha channel of frames is 8205b261ecSmrg protected and is not modified when drawing to them. The bits 8305b261ecSmrg containing the alpha channel are defined by the macro 8405b261ecSmrg RootlessAlphaMask(bpp), which should return a bit mask for 8505b261ecSmrg various bits per pixel. 8605b261ecSmrg 8705b261ecSmrg o ROOTLESS_REDISPLAY_DELAY: Time in milliseconds between updates to 8805b261ecSmrg the underlying window server. Most operations will be buffered until 8905b261ecSmrg this time has expired. 9005b261ecSmrg 9105b261ecSmrg o ROOTLESS_RESIZE_GRAVITY: If the underlying window system supports it, 9205b261ecSmrg some frame resizes can be optimized by relying on the frame contents 9305b261ecSmrg maintaining a particular gravity during the resize. In this way less 9405b261ecSmrg of the frame contents need to be preserved by the generic rootless 9505b261ecSmrg layer. If true, the generic rootless layer will pass gravity hints 9605b261ecSmrg during resizing and rely on the frame contents being preserved 9705b261ecSmrg accordingly. 9805b261ecSmrg 9905b261ecSmrg The following runtime options are defined in rootless.h: 10005b261ecSmrg 1019ace9065Smrg o rootlessGlobalOffsetX, rootlessGlobalOffsetY: These specify the global 10205b261ecSmrg offset that is applied to all screens when converting from 10305b261ecSmrg screen-local to global coordinates. 10405b261ecSmrg 1059ace9065Smrg o rootless_CopyBytes_threshold, rootless_CopyWindow_threshold: 10605b261ecSmrg The minimum number of bytes or pixels for which to use the rootless 10705b261ecSmrg implementation's respective acceleration function. The rootless 10805b261ecSmrg acceleration functions are all optional so these will only be used 10905b261ecSmrg if the respective acceleration function pointer is not NULL. 11005b261ecSmrg 11105b261ecSmrg 11205b261ecSmrgAccelerated Drawing 11305b261ecSmrg 11405b261ecSmrg The rootless implementation typically does not have direct access 11505b261ecSmrgto the hardware. Its access to the graphics hardware is generally through 11605b261ecSmrgthe API of the underlying window system. This underlying API may not 11705b261ecSmrgoverlap well with the X11 drawing primitives. The generic rootless layer 11805b261ecSmrgfalls back to using fb for all its 2-D drawing. Providing optional rootless 11905b261ecSmrgimplementation acceleration functions can accelerate some graphics 12005b261ecSmrgprimitives and some window functions. Typically calling through to the 12105b261ecSmrgunderlying window systems API will not speed up these operations for 12205b261ecSmrgsmall enough areas. The rootless_*_threshold runtime options allow the 12305b261ecSmrgrootless implementation to provide hints for when the acceleration 12405b261ecSmrgfunctions should be used instead of fb. 12505b261ecSmrg 12605b261ecSmrg 12705b261ecSmrgAlpha Channel Protection 12805b261ecSmrg 12905b261ecSmrg If the bits per pixel is greater then the color bit depth, the contents 13005b261ecSmrgof the extra bits are undefined by the X11 protocol. Some window systems 13105b261ecSmrgwill use these extra bits as an alpha channel. The generic rootless layer can 13205b261ecSmrgbe configured to protect these bits and make sure they are not modified by 13305b261ecSmrgother parts of the X server. To protect the alpha channel 13405b261ecSmrgROOTLESS_PROTECT_ALPHA and RootlessAlphaMask(bpp) must be 13505b261ecSmrgset appropriately as described under the compile time options. This 13605b261ecSmrgensures that the X11 graphics primitives do not overwrite the alpha 13705b261ecSmrgchannel in an attempt to optimize drawing. In addition, the window 13805b261ecSmrgfunctions PaintWindow() and Composite() must be replaced by alpha 13905b261ecSmrgchannel safe variants. These are provided in rootless/safeAlpha. 14005b261ecSmrg 14105b261ecSmrg 14205b261ecSmrgCredits 14305b261ecSmrg 14405b261ecSmrg The generic rootless layer was originally conceived and developed 14505b261ecSmrgby Greg Parker as part of the XDarwin X server on Mac OS X. John 14605b261ecSmrgHarper made later optimizations to this code but removed its generic 14705b261ecSmrgindependence of the underlying window system. Torrey T. Lyons 14805b261ecSmrgreintroduced the generic abstractions and made the rootless code suitable 14905b261ecSmrgfor use by other X servers. 15005b261ecSmrg 15105b261ecSmrg 15205b261ecSmrgAppendix A: Rootless Implementation Functions 15305b261ecSmrg 15405b261ecSmrg The rootless implementation functions are defined in rootless.h. It 15505b261ecSmrgis intended that rootless.h contains the complete interface that is needed by 15605b261ecSmrgrootless implementations. The definitions contained in rootlessCommon.h 15705b261ecSmrgare intended for internal use by the generic rootless layer and are more 15805b261ecSmrglikely to change. 15905b261ecSmrg 16005b261ecSmrg Most of these functions take a RootlessFrameID as a parameter. 16105b261ecSmrgThe RootlessFrameID is an opaque object that is returned by the 16205b261ecSmrgimplementation's CreateFrame() function. The generic rootless layer does 16305b261ecSmrgnot use this frame id other than to pass it back to the rootless 16405b261ecSmrgimplementation to indicate the frame to operate on. 16505b261ecSmrg 16605b261ecSmrg/* 16705b261ecSmrg * Create a new frame. 16805b261ecSmrg * The frame is created unmapped. 16905b261ecSmrg * 17005b261ecSmrg * pFrame RootlessWindowPtr for this frame should be completely 17105b261ecSmrg * initialized before calling except for pFrame->wid, which 17205b261ecSmrg * is set by this function. 17305b261ecSmrg * pScreen Screen on which to place the new frame 1749ace9065Smrg * newX, newY Position of the frame. 17505b261ecSmrg * pNewShape Shape for the frame (in frame-local coordinates). NULL for 17605b261ecSmrg * unshaped frames. 17705b261ecSmrg */ 17805b261ecSmrgtypedef Bool (*RootlessCreateFrameProc) 17905b261ecSmrg (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY, 18005b261ecSmrg RegionPtr pNewShape); 18105b261ecSmrg 18205b261ecSmrg/* 18305b261ecSmrg * Destroy a frame. 18405b261ecSmrg * Drawing is stopped and all updates are flushed before this is called. 18505b261ecSmrg * 18605b261ecSmrg * wid Frame id 18705b261ecSmrg */ 18805b261ecSmrgtypedef void (*RootlessDestroyFrameProc) 18905b261ecSmrg (RootlessFrameID wid); 19005b261ecSmrg 19105b261ecSmrg/* 19205b261ecSmrg * Move a frame on screen. 19305b261ecSmrg * Drawing is stopped and all updates are flushed before this is called. 19405b261ecSmrg * 19505b261ecSmrg * wid Frame id 19605b261ecSmrg * pScreen Screen to move the new frame to 19705b261ecSmrg * newX, newY New position of the frame 19805b261ecSmrg */ 19905b261ecSmrgtypedef void (*RootlessMoveFrameProc) 20005b261ecSmrg (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); 20105b261ecSmrg 20205b261ecSmrg/* 20305b261ecSmrg * Resize and move a frame. 20405b261ecSmrg * Drawing is stopped and all updates are flushed before this is called. 20505b261ecSmrg * 20605b261ecSmrg * wid Frame id 20705b261ecSmrg * pScreen Screen to move the new frame to 20805b261ecSmrg * newX, newY New position of the frame 20905b261ecSmrg * newW, newH New size of the frame 21005b261ecSmrg * gravity Gravity for window contents (rl_gravity_enum). This is always 21105b261ecSmrg * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set. 21205b261ecSmrg */ 21305b261ecSmrgtypedef void (*RootlessResizeFrameProc) 21405b261ecSmrg (RootlessFrameID wid, ScreenPtr pScreen, 21505b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 21605b261ecSmrg unsigned int gravity); 21705b261ecSmrg 21805b261ecSmrg/* 21905b261ecSmrg * Change frame ordering (AKA stacking, layering). 22005b261ecSmrg * Drawing is stopped before this is called. Unmapped frames are mapped by 22105b261ecSmrg * setting their ordering. 22205b261ecSmrg * 22305b261ecSmrg * wid Frame id 22405b261ecSmrg * nextWid Frame id of frame that is now above this one or NULL if this 22505b261ecSmrg * frame is at the top. 22605b261ecSmrg */ 22705b261ecSmrgtypedef void (*RootlessRestackFrameProc) 22805b261ecSmrg (RootlessFrameID wid, RootlessFrameID nextWid); 22905b261ecSmrg 23005b261ecSmrg/* 23105b261ecSmrg * Change frame's shape. 23205b261ecSmrg * Drawing is stopped before this is called. 23305b261ecSmrg * 23405b261ecSmrg * wid Frame id 23505b261ecSmrg * pNewShape New shape for the frame (in frame-local coordinates) 23605b261ecSmrg * or NULL if now unshaped. 23705b261ecSmrg */ 23805b261ecSmrgtypedef void (*RootlessReshapeFrameProc) 23905b261ecSmrg (RootlessFrameID wid, RegionPtr pNewShape); 24005b261ecSmrg 24105b261ecSmrg/* 24205b261ecSmrg * Unmap a frame. 24305b261ecSmrg * 24405b261ecSmrg * wid Frame id 24505b261ecSmrg */ 24605b261ecSmrgtypedef void (*RootlessUnmapFrameProc) 24705b261ecSmrg (RootlessFrameID wid); 24805b261ecSmrg 24905b261ecSmrg/* 25005b261ecSmrg * Start drawing to a frame. 25105b261ecSmrg * Prepare a frame for direct access to its backing buffer. 25205b261ecSmrg * 25305b261ecSmrg * wid Frame id 25405b261ecSmrg * pixelData Address of the backing buffer (returned) 25505b261ecSmrg * bytesPerRow Width in bytes of the backing buffer (returned) 25605b261ecSmrg */ 25705b261ecSmrgtypedef void (*RootlessStartDrawingProc) 25805b261ecSmrg (RootlessFrameID wid, char **pixelData, int *bytesPerRow); 25905b261ecSmrg 26005b261ecSmrg/* 26105b261ecSmrg * Stop drawing to a frame. 26205b261ecSmrg * No drawing to the frame's backing buffer will occur until drawing 26305b261ecSmrg * is started again. 26405b261ecSmrg * 26505b261ecSmrg * wid Frame id 2669ace9065Smrg * flush Flush drawing updates for this frame to the screen. 26705b261ecSmrg */ 26805b261ecSmrgtypedef void (*RootlessStopDrawingProc) 26905b261ecSmrg (RootlessFrameID wid, Bool flush); 27005b261ecSmrg 27105b261ecSmrg/* 27205b261ecSmrg * Flush drawing updates to the screen. 27305b261ecSmrg * Drawing is stopped before this is called. 27405b261ecSmrg * 27505b261ecSmrg * wid Frame id 27605b261ecSmrg * pDamage Region containing all the changed pixels in frame-local 2779ace9065Smrg * coordinates. This is clipped to the window's clip. 27805b261ecSmrg */ 27905b261ecSmrgtypedef void (*RootlessUpdateRegionProc) 28005b261ecSmrg (RootlessFrameID wid, RegionPtr pDamage); 28105b261ecSmrg 28205b261ecSmrg/* 28305b261ecSmrg * Mark damaged rectangles as requiring redisplay to screen. 28405b261ecSmrg * 28505b261ecSmrg * wid Frame id 28605b261ecSmrg * nrects Number of damaged rectangles 28705b261ecSmrg * rects Array of damaged rectangles in frame-local coordinates 28805b261ecSmrg * shift_x, Vector to shift rectangles by 28905b261ecSmrg * shift_y 29005b261ecSmrg */ 29105b261ecSmrgtypedef void (*RootlessDamageRectsProc) 29205b261ecSmrg (RootlessFrameID wid, int nrects, const BoxRec *rects, 29305b261ecSmrg int shift_x, int shift_y); 29405b261ecSmrg 29505b261ecSmrg/* 29605b261ecSmrg * Switch the window associated with a frame. (Optional) 29705b261ecSmrg * When a framed window is reparented, the frame is resized and set to 29805b261ecSmrg * use the new top-level parent. If defined this function will be called 29905b261ecSmrg * afterwards for implementation specific bookkeeping. 30005b261ecSmrg * 30105b261ecSmrg * pFrame Frame whose window has switched 30205b261ecSmrg * oldWin Previous window wrapped by this frame 30305b261ecSmrg */ 30405b261ecSmrgtypedef void (*RootlessSwitchWindowProc) 30505b261ecSmrg (RootlessWindowPtr pFrame, WindowPtr oldWin); 30605b261ecSmrg 30705b261ecSmrg/* 30805b261ecSmrg * Copy bytes. (Optional) 30905b261ecSmrg * Source and destinate may overlap and the right thing should happen. 31005b261ecSmrg * 31105b261ecSmrg * width Bytes to copy per row 31205b261ecSmrg * height Number of rows 31305b261ecSmrg * src Source data 31405b261ecSmrg * srcRowBytes Width of source in bytes 31505b261ecSmrg * dst Destination data 31605b261ecSmrg * dstRowBytes Width of destination in bytes 31705b261ecSmrg */ 31805b261ecSmrgtypedef void (*RootlessCopyBytesProc) 31905b261ecSmrg (unsigned int width, unsigned int height, 32005b261ecSmrg const void *src, unsigned int srcRowBytes, 32105b261ecSmrg void *dst, unsigned int dstRowBytes); 32205b261ecSmrg 32305b261ecSmrg/* 32405b261ecSmrg * Copy area in frame to another part of frame. (Optional) 32505b261ecSmrg * 32605b261ecSmrg * wid Frame id 32705b261ecSmrg * dstNrects Number of rectangles to copy 32805b261ecSmrg * dstRects Array of rectangles to copy 32905b261ecSmrg * dx, dy Number of pixels away to copy area 33005b261ecSmrg */ 33105b261ecSmrgtypedef void (*RootlessCopyWindowProc) 33205b261ecSmrg (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, 33305b261ecSmrg int dx, int dy); 33405b261ecSmrg 335