Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | Generic Rootless Layer |
2 | Version 1.0 | |
3 | July 13, 2004 | |
4 | ||
5 | Torrey T. Lyons | |
6 | torrey@xfree86.org | |
7 | ||
8 | ||
9 | Introduction | |
10 | ||
11 | The generic rootless layer allows an X server to be implemented | |
12 | on top of another window server in a cooperative manner. This allows the | |
13 | X11 windows and native windows of the underlying window server to | |
14 | coexist on the same screen. The layer is called "rootless" because the root | |
15 | window of the X server is generally not drawn. Instead, each top-level | |
16 | child of the root window is represented as a separate on-screen window by | |
17 | the underlying window server. The layer is referred to as "generic" | |
18 | because it abstracts away the details of the underlying window system and | |
19 | contains code that is useful for any rootless X server. The code for the | |
20 | generic rootless layer is located in xc/programs/Xserver/miext/rootless. To | |
21 | build a complete rootless X server requires a specific rootless | |
22 | implementation, which provides functions that allow the generic rootless | |
23 | layer to interact with the underlying window system. | |
24 | ||
25 | ||
26 | Concepts | |
27 | ||
28 | In the context of a rootless X server the term window is used to | |
29 | mean many fundamentally different things. For X11 a window is a DDX | |
30 | resource that describes a visible, or potentially visible, rectangle on the | |
31 | screen. A top-level window is a direct child of the root window. To avoid | |
32 | confusion, an on-screen native window of the underlying window system | |
33 | is referred to as a "frame". The generic rootless layer associates each | |
34 | mapped top-level X11 window with a frame. An X11 window may be said | |
35 | to 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 | |
38 | all times by a backing buffer, which is periodically flushed to the screen. | |
39 | If the underlying window system does not provide a backing buffer for | |
40 | frames, this must be done by the rootless implementation. The generic | |
41 | rootless layer model does not assume it always has access to the frames' | |
42 | backing buffers. Any drawing to the buffer will be proceeded by a call to | |
43 | the rootless implementation's StartDrawing() function and StopDrawing() | |
44 | will be called when the drawing is concluded. The address of the frame's | |
45 | backing buffer is returned by the StartDrawing() function and it can | |
46 | change between successive calls. | |
47 | ||
48 | Because each frame is assumed to have a backing buffer, the | |
49 | generic rootless layer will stop Expose events being generated when the | |
50 | regions of visibility of a frame change on screen. This is similar to backing | |
51 | store, but backing buffers are different in that they always store a copy of | |
52 | the entire window contents, not just the obscured portions. The price paid | |
53 | in increased memory consumption is made up by the greatly decreased | |
54 | complexity in not having to track and record regions as they are obscured. | |
55 | ||
56 | ||
57 | Rootless Implementation | |
58 | ||
59 | The specifics of the underlying window system are provided to the | |
60 | generic rootless layer through rootless implementation functions, compile- | |
61 | time options, and runtime parameters. The rootless implementation | |
62 | functions are a list of functions that allow the generic rootless layer to | |
63 | perform operations such as creating, destroying, moving, and resizing | |
64 | frames. Some of the implementation functions are optional. A detailed | |
65 | description of the rootless implementation functions is provided in | |
66 | Appendix A. | |
67 | ||
68 | By design, a rootless implementation should only have to include | |
69 | the rootless.h header file. The rootlessCommon.h file contains definitions | |
70 | internal to the generic rootless layer. (If you find you need to use | |
71 | rootlessCommon.h in your implementation, let the generic rootless layer | |
72 | maintainers know. This could be an area where the generic rootless layer | |
73 | should be generalized.) A rootless implementation should also modify | |
74 | rootlessConfig.h to specify compile time options for its platform. | |
75 | ||
76 | The following compile-time options are defined in | |
77 | rootlessConfig.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 | ||
112 | Accelerated Drawing | |
113 | ||
114 | The rootless implementation typically does not have direct access | |
115 | to the hardware. Its access to the graphics hardware is generally through | |
116 | the API of the underlying window system. This underlying API may not | |
117 | overlap well with the X11 drawing primitives. The generic rootless layer | |
118 | falls back to using fb for all its 2-D drawing. Providing optional rootless | |
119 | implementation acceleration functions can accelerate some graphics | |
120 | primitives and some window functions. Typically calling through to the | |
121 | underlying window systems API will not speed up these operations for | |
122 | small enough areas. The rootless_*_threshold runtime options allow the | |
123 | rootless implementation to provide hints for when the acceleration | |
124 | functions should be used instead of fb. | |
125 | ||
126 | ||
127 | Alpha Channel Protection | |
128 | ||
129 | If the bits per pixel is greater then the color bit depth, the contents | |
130 | of the extra bits are undefined by the X11 protocol. Some window systems | |
131 | will use these extra bits as an alpha channel. The generic rootless layer can | |
132 | be configured to protect these bits and make sure they are not modified by | |
133 | other parts of the X server. To protect the alpha channel | |
134 | ROOTLESS_PROTECT_ALPHA and RootlessAlphaMask(bpp) must be | |
135 | set appropriately as described under the compile time options. This | |
136 | ensures that the X11 graphics primitives do not overwrite the alpha | |
137 | channel in an attempt to optimize drawing. In addition, the window | |
138 | functions PaintWindow() and Composite() must be replaced by alpha | |
139 | channel safe variants. These are provided in rootless/safeAlpha. | |
140 | ||
141 | ||
142 | Credits | |
143 | ||
144 | The generic rootless layer was originally conceived and developed | |
145 | by Greg Parker as part of the XDarwin X server on Mac OS X. John | |
146 | Harper made later optimizations to this code but removed its generic | |
147 | independence of the underlying window system. Torrey T. Lyons | |
148 | reintroduced the generic abstractions and made the rootless code suitable | |
149 | for use by other X servers. | |
150 | ||
151 | ||
152 | Appendix A: Rootless Implementation Functions | |
153 | ||
154 | The rootless implementation functions are defined in rootless.h. It | |
155 | is intended that rootless.h contains the complete interface that is needed by | |
156 | rootless implementations. The definitions contained in rootlessCommon.h | |
157 | are intended for internal use by the generic rootless layer and are more | |
158 | likely to change. | |
159 | ||
160 | Most of these functions take a RootlessFrameID as a parameter. | |
161 | The RootlessFrameID is an opaque object that is returned by the | |
162 | implementation's CreateFrame() function. The generic rootless layer does | |
163 | not use this frame id other than to pass it back to the rootless | |
164 | implementation 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 | */ | |
178 | typedef 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 | */ | |
188 | typedef 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 | */ | |
199 | typedef 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 | */ | |
213 | typedef 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 | */ | |
227 | typedef 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 | */ | |
238 | typedef void (*RootlessReshapeFrameProc) | |
239 | (RootlessFrameID wid, RegionPtr pNewShape); | |
240 | ||
241 | /* | |
242 | * Unmap a frame. | |
243 | * | |
244 | * wid Frame id | |
245 | */ | |
246 | typedef 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 | */ | |
257 | typedef 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 | */ | |
268 | typedef 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 | */ | |
279 | typedef 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 | */ | |
291 | typedef 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 | */ | |
304 | typedef 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 | */ | |
318 | typedef 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 | */ | |
331 | typedef void (*RootlessCopyWindowProc) | |
332 | (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, | |
333 | int dx, int dy); | |
334 |