2 * Common rootless definitions and code
5 * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6 * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
7 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the sale,
29 * use or other dealings in this Software without prior written authorization.
32 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
36 #include <stddef.h> /* For NULL */
37 #include <limits.h> /* For CHAR_BIT */
39 #include "rootlessCommon.h"
40 #include "colormapst.h"
42 unsigned int rootless_CopyBytes_threshold
= 0;
43 unsigned int rootless_CopyWindow_threshold
= 0;
44 int rootlessGlobalOffsetX
= 0;
45 int rootlessGlobalOffsetY
= 0;
47 RegionRec rootlessHugeRoot
= { {-32767, -32767, 32767, 32767}, NULL
};
49 /* Following macro from miregion.c */
51 /* true iff two Boxes overlap */
52 #define EXTENTCHECK(r1,r2) \
53 (!( ((r1)->x2 <= (r2)->x1) || \
54 ((r1)->x1 >= (r2)->x2) || \
55 ((r1)->y2 <= (r2)->y1) || \
56 ((r1)->y1 >= (r2)->y2) ) )
60 * Returns the top-level parent of pWindow.
61 * The root is the top-level parent of itself, even though the root is
62 * not otherwise considered to be a top-level window.
65 TopLevelParent(WindowPtr pWindow
)
73 while (top
&& !IsTopLevel(top
))
81 * Returns TRUE if this window is visible inside a frame
82 * (e.g. it is visible and has a top-level or root parent)
85 IsFramedWindow(WindowPtr pWin
)
89 if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec
))
94 top
= TopLevelParent(pWin
);
96 return (top
&& WINREC(top
));
100 RootlessResolveColormap(ScreenPtr pScreen
, int first_color
,
101 int n_colors
, uint32_t * colors
)
106 map
= RootlessGetColormap(pScreen
);
107 if (map
== NULL
|| map
->class != PseudoColor
)
110 last
= min(map
->pVisual
->ColormapEntries
, first_color
+ n_colors
);
111 for (i
= max(0, first_color
); i
< last
; i
++) {
112 Entry
*ent
= map
->red
+ i
;
113 uint16_t red
, green
, blue
;
118 red
= ent
->co
.shco
.red
->color
;
119 green
= ent
->co
.shco
.green
->color
;
120 blue
= ent
->co
.shco
.blue
->color
;
123 red
= ent
->co
.local
.red
;
124 green
= ent
->co
.local
.green
;
125 blue
= ent
->co
.local
.blue
;
128 colors
[i
- first_color
] = (0xFF000000UL
129 | ((uint32_t) red
& 0xff00) << 8
138 * RootlessStartDrawing
139 * Prepare a window for direct access to its backing buffer.
140 * Each top-level parent has a Pixmap representing its backing buffer,
141 * which all of its children inherit.
144 RootlessStartDrawing(WindowPtr pWindow
)
146 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
147 WindowPtr top
= TopLevelParent(pWindow
);
148 RootlessWindowRec
*winRec
;
153 winRec
= WINREC(top
);
157 // Make sure the window's top-level parent is prepared for drawing.
158 if (!winRec
->is_drawing
) {
159 int bw
= wBorderWidth(top
);
161 SCREENREC(pScreen
)->imp
->StartDrawing(winRec
->wid
, &winRec
->pixelData
,
162 &winRec
->bytesPerRow
);
165 GetScratchPixmapHeader(pScreen
, winRec
->width
, winRec
->height
,
167 top
->drawable
.bitsPerPixel
,
168 winRec
->bytesPerRow
, winRec
->pixelData
);
169 SetPixmapBaseToScreen(winRec
->pixmap
,
170 top
->drawable
.x
- bw
, top
->drawable
.y
- bw
);
172 winRec
->is_drawing
= TRUE
;
175 curPixmap
= pScreen
->GetWindowPixmap(pWindow
);
176 if (curPixmap
== winRec
->pixmap
) {
177 RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n",
178 pWindow
, winRec
->pixmap
);
181 PixmapPtr oldPixmap
=
182 dixLookupPrivate(&pWindow
->devPrivates
,
183 rootlessWindowOldPixmapPrivateKey
);
184 if (oldPixmap
!= NULL
) {
185 if (oldPixmap
== curPixmap
)
187 ("Window %p's curPixmap %p is the same as its oldPixmap; strange\n",
190 RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n",
193 dixSetPrivate(&pWindow
->devPrivates
, rootlessWindowOldPixmapPrivateKey
,
195 pScreen
->SetWindowPixmap(pWindow
, winRec
->pixmap
);
200 * RootlessStopDrawing
201 * Stop drawing to a window's backing buffer. If flush is true,
202 * damaged regions are flushed to the screen.
205 RestorePreDrawingPixmapVisitor(WindowPtr pWindow
, pointer data
)
207 RootlessWindowRec
*winRec
= (RootlessWindowRec
*) data
;
208 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
209 PixmapPtr exPixmap
= pScreen
->GetWindowPixmap(pWindow
);
210 PixmapPtr oldPixmap
=
211 dixLookupPrivate(&pWindow
->devPrivates
,
212 rootlessWindowOldPixmapPrivateKey
);
213 if (oldPixmap
== NULL
) {
214 if (exPixmap
== winRec
->pixmap
)
216 ("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n",
220 if (exPixmap
!= winRec
->pixmap
)
222 ("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n",
223 pWindow
, oldPixmap
, exPixmap
, winRec
->pixmap
);
224 if (oldPixmap
== winRec
->pixmap
)
226 ("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n",
228 pScreen
->SetWindowPixmap(pWindow
, oldPixmap
);
229 dixSetPrivate(&pWindow
->devPrivates
, rootlessWindowOldPixmapPrivateKey
,
232 return WT_WALKCHILDREN
;
236 RootlessStopDrawing(WindowPtr pWindow
, Bool flush
)
238 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
239 WindowPtr top
= TopLevelParent(pWindow
);
240 RootlessWindowRec
*winRec
;
244 winRec
= WINREC(top
);
248 if (winRec
->is_drawing
) {
249 SCREENREC(pScreen
)->imp
->StopDrawing(winRec
->wid
, flush
);
251 FreeScratchPixmapHeader(winRec
->pixmap
);
252 TraverseTree(top
, RestorePreDrawingPixmapVisitor
, (pointer
) winRec
);
253 winRec
->pixmap
= NULL
;
255 winRec
->is_drawing
= FALSE
;
258 SCREENREC(pScreen
)->imp
->UpdateRegion(winRec
->wid
, NULL
);
261 if (flush
&& winRec
->is_reorder_pending
) {
262 winRec
->is_reorder_pending
= FALSE
;
263 RootlessReorderWindow(pWindow
);
268 * RootlessDamageRegion
269 * Mark a damaged region as requiring redisplay to screen.
270 * pRegion is in GLOBAL coordinates.
273 RootlessDamageRegion(WindowPtr pWindow
, RegionPtr pRegion
)
275 RootlessWindowRec
*winRec
;
280 RL_DEBUG_MSG("Damaged win 0x%x ", pWindow
);
282 pTop
= TopLevelParent(pWindow
);
286 winRec
= WINREC(pTop
);
290 /* We need to intersect the drawn region with the clip of the window
291 to avoid marking places we didn't actually draw (which can cause
292 problems when the window has an extra client-side backing store)
294 But this is a costly operation and since we'll normally just be
295 drawing inside the clip, go to some lengths to avoid the general
296 case intersection. */
298 b1
= RegionExtents(&pWindow
->borderClip
);
299 b2
= RegionExtents(pRegion
);
301 if (EXTENTCHECK(b1
, b2
)) {
302 /* Regions may overlap. */
304 if (RegionNumRects(pRegion
) == 1) {
307 /* Damaged region only has a single rect, so we can
308 just compare that against the region */
310 in
= RegionContainsRect(&pWindow
->borderClip
, RegionRects(pRegion
));
312 /* clip totally contains pRegion */
314 SCREENREC(pWindow
->drawable
.pScreen
)->imp
->DamageRects(winRec
->
325 RootlessQueueRedisplay(pTop
->drawable
.pScreen
);
328 else if (in
== rgnOUT
) {
329 /* clip doesn't contain pRegion */
335 /* clip overlaps pRegion, need to intersect */
337 RegionNull(&clipped
);
338 RegionIntersect(&clipped
, &pWindow
->borderClip
, pRegion
);
340 SCREENREC(pWindow
->drawable
.pScreen
)->imp
->DamageRects(winRec
->wid
,
348 RegionUninit(&clipped
);
350 RootlessQueueRedisplay(pTop
->drawable
.pScreen
);
356 BoxRec
*box
= RegionRects(pRegion
), *end
;
357 int numBox
= RegionNumRects(pRegion
);
359 for (end
= box
+ numBox
; box
< end
; box
++) {
360 RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
361 box
->x1
, box
->x2
, box
->y1
, box
->y2
);
370 * Mark a damaged box as requiring redisplay to screen.
371 * pRegion is in GLOBAL coordinates.
374 RootlessDamageBox(WindowPtr pWindow
, BoxPtr pBox
)
378 RegionInit(®ion
, pBox
, 1);
380 RootlessDamageRegion(pWindow
, ®ion
);
382 RegionUninit(®ion
); /* no-op */
387 * Mark a damaged rectangle as requiring redisplay to screen.
388 * (x, y, w, h) is in window-local coordinates.
391 RootlessDamageRect(WindowPtr pWindow
, int x
, int y
, int w
, int h
)
396 x
+= pWindow
->drawable
.x
;
397 y
+= pWindow
->drawable
.y
;
404 RegionInit(®ion
, &box
, 1);
406 RootlessDamageRegion(pWindow
, ®ion
);
408 RegionUninit(®ion
); /* no-op */
413 * Stop drawing and redisplay the damaged region of a window.
416 RootlessRedisplay(WindowPtr pWindow
)
418 RootlessStopDrawing(pWindow
, TRUE
);
422 * RootlessRepositionWindows
423 * Reposition all windows on a screen to their correct positions.
426 RootlessRepositionWindows(ScreenPtr pScreen
)
428 WindowPtr root
= pScreen
->root
;
432 RootlessRepositionWindow(root
);
434 for (win
= root
->firstChild
; win
; win
= win
->nextSib
) {
435 if (WINREC(win
) != NULL
)
436 RootlessRepositionWindow(win
);
442 * RootlessRedisplayScreen
443 * Walk every window on a screen and redisplay the damaged regions.
446 RootlessRedisplayScreen(ScreenPtr pScreen
)
448 WindowPtr root
= pScreen
->root
;
453 RootlessRedisplay(root
);
454 for (win
= root
->firstChild
; win
; win
= win
->nextSib
) {
455 if (WINREC(win
) != NULL
) {
456 RootlessRedisplay(win
);