2 * Common rootless definitions and code
4 * Greg Parker gparker@cs.stanford.edu
7 /* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation files
11 (the "Software"), to deal in the Software without restriction,
12 including without limitation the rights to use, copy, modify, merge,
13 publish, distribute, sublicense, and/or sell copies of the Software,
14 and to permit persons to whom the Software is furnished to do so,
15 subject to the following conditions:
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
24 HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
29 Except as contained in this notice, the name(s) of the above
30 copyright holders shall not be used in advertising or otherwise to
31 promote the sale, use or other dealings in this Software without
32 prior written authorization. */
34 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c,v 1.6 2002/07/15 19:58:31 torrey Exp $ */
36 #include "rootless-common.h"
37 #include "dri-surface.h"
39 #include "colormapst.h"
41 RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
43 /* Following two macros from miregion.c */
45 /* true iff two Boxes overlap */
46 #define EXTENTCHECK(r1,r2) \
47 (!( ((r1)->x2 <= (r2)->x1) || \
48 ((r1)->x1 >= (r2)->x2) || \
49 ((r1)->y2 <= (r2)->y1) || \
50 ((r1)->y1 >= (r2)->y2) ) )
52 /* true iff Box r1 contains Box r2 */
53 #define SUBSUMES(r1,r2) \
54 ( ((r1)->x1 <= (r2)->x1) && \
55 ((r1)->x2 >= (r2)->x2) && \
56 ((r1)->y1 <= (r2)->y1) && \
57 ((r1)->y2 >= (r2)->y2) )
59 int rootlessNoDRIDrawing = 0;
61 /* Returns the top-level parent of pWindow. The root is the top-level
62 parent of itself, even though the root is not otherwise considered
63 to be a top-level window. */
65 TopLevelParent (WindowPtr pWindow)
73 while (top != NULL && !IsTopLevel (top))
79 /* Returns TRUE if this window is visible inside a frame (e.g. it is
80 visible and has a top-level parent) */
82 IsFramedWindow (WindowPtr pWin)
89 top = TopLevelParent (pWin);
91 return top != NULL && WINREC (top) != NULL;
95 TranslatePixmapBase (PixmapPtr pPix, int dx, int dy)
99 pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr +
100 ((dx + pPix->drawable.x)
101 * pPix->drawable.bitsPerPixel / 8 +
102 dy * pPix->devKind));
104 if (pPix->drawable.bitsPerPixel != FB_UNIT)
106 diff = ((unsigned) pPix->devPrivate.ptr) & (FB_UNIT / CHAR_BIT - 1);
107 pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr) - diff;
109 if (pPix->drawable.bitsPerPixel == 16)
110 pPix->drawable.x = diff / (16 / CHAR_BIT);
111 else if (pPix->drawable.bitsPerPixel == 8)
112 pPix->drawable.x = diff / (8 / CHAR_BIT);
114 pPix->drawable.x = diff / (pPix->drawable.bitsPerPixel / CHAR_BIT);
119 RootlessDisableUpdate (WindowPtr pWin)
121 RootlessWindowRec *winRec = WINREC (pWin);
124 && !winRec->is_offscreen
125 && !winRec->is_reorder_pending
126 && !winRec->is_update_disabled)
128 xp_disable_update ();
129 winRec->is_update_disabled = TRUE;
134 RootlessReenableUpdate (WindowPtr pWin)
136 RootlessWindowRec *winRec = WINREC (pWin);
138 if (winRec != NULL && winRec->is_update_disabled)
140 xp_reenable_update ();
141 winRec->is_update_disabled = FALSE;
146 RootlessResolveColormap (ScreenPtr pScreen, int first_color,
147 int n_colors, uint32_t *colors)
152 map = RootlessGetColormap (pScreen);
153 if (map == NULL || map->class != PseudoColor)
156 last = MIN (map->pVisual->ColormapEntries, first_color + n_colors);
157 for (i = MAX (0, first_color); i < last; i++)
159 Entry *ent = map->red + i;
160 uint16_t red, green, blue;
166 red = ent->co.shco.red->color;
167 green = ent->co.shco.green->color;
168 blue = ent->co.shco.blue->color;
172 red = ent->co.local.red;
173 green = ent->co.local.green;
174 blue = ent->co.local.blue;
177 colors[i - first_color] = (0xFF000000UL
178 | ((uint32_t) red & 0xff00) << 8
186 /* Prepare a window for direct access to its backing buffer. Each
187 top-level parent has a Pixmap representing its backing store, which
188 all of its children inherit. */
190 RootlessStartDrawing (WindowPtr pWindow)
192 ScreenPtr pScreen = pWindow->drawable.pScreen;
193 WindowPtr top = TopLevelParent (pWindow);
194 RootlessWindowRec *winRec;
196 if (!rootlessNoDRIDrawing && DRIStartDrawing (&pWindow->drawable))
201 /* At the top of the stack now. */
203 if (top == NULL || WINREC (top) == NULL)
206 winRec = WINREC(top);
208 /* Make sure the window's top-level parent is prepared for drawing. */
210 if (!winRec->is_drawing)
213 unsigned int rowbytes[2];
216 int bw = wBorderWidth (top);
218 err = xp_lock_window (winRec->wid, NULL, NULL, data, rowbytes, NULL);
220 abort (); /* FIXME: */
222 winRec->data = data[0];
223 winRec->rowbytes = rowbytes[0];
226 GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
227 winRec->win->drawable.depth,
228 winRec->win->drawable.bitsPerPixel,
229 winRec->rowbytes, winRec->data);
230 TranslatePixmapBase (winRec->pixmap,
231 - (top->drawable.x - bw),
232 - (top->drawable.y - bw));
234 winRec->is_drawing = TRUE;
237 winRec->oldPixmap = pScreen->GetWindowPixmap (pWindow);
238 pScreen->SetWindowPixmap (pWindow, winRec->pixmap);
242 RootlessFinishedDrawing (WindowPtr pWindow)
244 /* Called after each drawing primitive, lets us unlock surfaces
245 as often as possible (which is a Good Thing to do.) */
247 DRIStopDrawing (&pWindow->drawable, FALSE);
249 /* Also, see if we're due a flush. */
251 RootlessMayRedisplay (pWindow->drawable.pScreen);
255 RootlessStopDrawing (WindowPtr pWindow, Bool flush)
257 WindowPtr top = TopLevelParent (pWindow);
258 RootlessWindowRec *winRec;
260 if (top == NULL || WINREC (top) == NULL)
263 winRec = WINREC(top);
265 DRIStopDrawing (&pWindow->drawable, flush);
267 if (winRec->is_drawing)
269 ScreenPtr pScreen = pWindow->drawable.pScreen;
271 xp_unlock_window (winRec->wid, flush);
273 FreeScratchPixmapHeader (winRec->pixmap);
274 pScreen->SetWindowPixmap (pWindow, winRec->oldPixmap);
275 winRec->pixmap = NULL;
277 winRec->is_drawing = FALSE;
281 xp_flush_window (winRec->wid);
284 /* FIXME: instead of just checking if we tried to flush (which
285 happens everytime we block for I/O), I used to check if
286 anything was actually marked in the window. But that often
287 caused problems with some window managers, and it didn't really
288 make any noticeable difference, so... */
290 if (flush && winRec->is_reorder_pending)
292 winRec->is_reorder_pending = FALSE;
293 RootlessReorderWindow (pWindow);
296 if (flush && winRec->is_update_disabled)
298 RootlessReenableUpdate (pWindow);
302 /* pRegion is GLOBAL */
304 RootlessDamageRegion (WindowPtr pWindow, RegionPtr pRegion)
306 RootlessWindowRec *winRec;
311 RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
313 pTop = TopLevelParent (pWindow);
317 winRec = WINREC (pTop);
321 if (DRIDamageRegion (&pWindow->drawable, pRegion))
326 /* We need to intersect the drawn region with the clip of the window
327 to avoid marking places we didn't actually draw (which can cause
328 problems when the window has an extra client-side backing store)
330 But this is a costly operation and since we'll normally just be
331 drawing inside the clip, go to some lengths to avoid the general
332 case intersection. */
334 b1 = REGION_EXTENTS (pScreen, &pWindow->borderClip);
335 b2 = REGION_EXTENTS (pScreen, pRegion);
337 if (EXTENTCHECK (b1, b2))
339 /* Regions may overlap. */
341 if (REGION_NUM_RECTS (pRegion) == 1)
345 /* Damaged region only has a single rect, so we can
346 just compare that against the region */
348 in = RECT_IN_REGION (pScreen, &pWindow->borderClip,
349 REGION_RECTS (pRegion));
352 /* clip totally contains pRegion */
354 xp_mark_window (winRec->wid, REGION_NUM_RECTS (pRegion),
355 REGION_RECTS (pRegion),
356 -winRec->x, -winRec->y);
358 RootlessQueueRedisplay (pTop->drawable.pScreen);
361 else if (in == rgnOUT)
363 /* clip doesn't contain pRegion */
369 /* clip overlaps pRegion, need to intersect */
371 REGION_INIT (pScreen, &clipped, NullBox, 0);
372 REGION_INTERSECT (pScreen, &clipped, &pWindow->borderClip, pRegion);
374 xp_mark_window (winRec->wid, REGION_NUM_RECTS (&clipped),
375 REGION_RECTS (&clipped), -winRec->x, -winRec->y);
377 REGION_UNINIT (pScreen, &clipped);
379 RootlessQueueRedisplay (pTop->drawable.pScreen);
385 BoxRec *box = REGION_RECTS(pRegion), *end;
386 int numBox = REGION_NUM_RECTS(pRegion);
388 for (end = box+numBox; box < end; box++) {
389 RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
390 box->x1, box->x2, box->y1, box->y2);
399 RootlessDamageBox (WindowPtr pWindow, BoxPtr pBox)
403 REGION_INIT (pWindow->drawable.pScreen, ®ion, pBox, 1);
405 RootlessDamageRegion (pWindow, ®ion);
407 REGION_UNINIT (pWindow->drawable.pScreen, ®ion); /* no-op */
411 /* (x, y, w, h) is in window-local coordinates. */
413 RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
418 x += pWindow->drawable.x;
419 y += pWindow->drawable.y;
426 REGION_INIT (pWindow->drawable.pScreen, ®ion, &box, 1);
428 RootlessDamageRegion (pWindow, ®ion);
430 REGION_UNINIT (pWindow->drawable.pScreen, ®ion); /* no-op */
433 /* Stop drawing and redisplay the damaged region of a window. */
435 RootlessRedisplay (WindowPtr pWindow)
437 DRISynchronizeDrawable (&pWindow->drawable, TRUE);
438 RootlessStopDrawing(pWindow, TRUE);
441 /* Walk every window on a screen and redisplay the damaged regions. */
443 RootlessRedisplayScreen (ScreenPtr pScreen)
445 RootlessScreenRec *screenRec = SCREENREC (pScreen);
446 WindowPtr root = WindowTable[pScreen->myNum];
451 RootlessRedisplay(root);
453 for (win = root->firstChild; win; win = win->nextSib)
455 if (WINREC (win) != NULL)
456 RootlessRedisplay (win);
460 screenRec->last_redisplay = GetTimeInMillis ();
464 RootlessRepositionWindows (ScreenPtr pScreen)
466 WindowPtr root = WindowTable[pScreen->myNum];
471 RootlessRepositionWindow (root);
473 for (win = root->firstChild; win; win = win->nextSib)
475 if (WINREC (win) != NULL)
476 RootlessRepositionWindow (win);
482 RootlessFlushScreenColormaps (ScreenPtr pScreen)
484 WindowPtr root = WindowTable[pScreen->myNum];
489 RootlessRepositionWindow (root);
491 for (win = root->firstChild; win; win = win->nextSib)
493 if (WINREC (win) != NULL)
494 RootlessFlushWindowColormap (win);