diff options
Diffstat (limited to 'xorg-server/miext/rootless/rootlessCommon.c')
-rw-r--r-- | xorg-server/miext/rootless/rootlessCommon.c | 967 |
1 files changed, 484 insertions, 483 deletions
diff --git a/xorg-server/miext/rootless/rootlessCommon.c b/xorg-server/miext/rootless/rootlessCommon.c index 39a3eed0f..e97a53725 100644 --- a/xorg-server/miext/rootless/rootlessCommon.c +++ b/xorg-server/miext/rootless/rootlessCommon.c @@ -1,483 +1,484 @@ -/* - * Common rootless definitions and code - */ -/* - * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stddef.h> /* For NULL */ -#include <limits.h> /* For CHAR_BIT */ - -#include "rootlessCommon.h" -#include "colormapst.h" - -unsigned int rootless_CopyBytes_threshold = 0; -unsigned int rootless_FillBytes_threshold = 0; -unsigned int rootless_CompositePixels_threshold = 0; -unsigned int rootless_CopyWindow_threshold = 0; -#ifdef ROOTLESS_GLOBAL_COORDS -int rootlessGlobalOffsetX = 0; -int rootlessGlobalOffsetY = 0; -#endif - -RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL}; - -/* Following macro from miregion.c */ - -/* true iff two Boxes overlap */ -#define EXTENTCHECK(r1,r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) - - -/* - * TopLevelParent - * Returns the top-level parent of pWindow. - * The root is the top-level parent of itself, even though the root is - * not otherwise considered to be a top-level window. - */ -WindowPtr -TopLevelParent(WindowPtr pWindow) -{ - WindowPtr top; - - if (IsRoot(pWindow)) - return pWindow; - - top = pWindow; - while (top && ! IsTopLevel(top)) - top = top->parent; - - return top; -} - - -/* - * IsFramedWindow - * Returns TRUE if this window is visible inside a frame - * (e.g. it is visible and has a top-level or root parent) - */ -Bool -IsFramedWindow(WindowPtr pWin) -{ - WindowPtr top; - - if (!pWin->realized) - return FALSE; - top = TopLevelParent(pWin); - - return (top && WINREC(top)); -} - -Bool -RootlessResolveColormap (ScreenPtr pScreen, int first_color, - int n_colors, uint32_t *colors) -{ - int last, i; - ColormapPtr map; - - map = RootlessGetColormap (pScreen); - if (map == NULL || map->class != PseudoColor) return FALSE; - - last = min (map->pVisual->ColormapEntries, first_color + n_colors); - for (i = max (0, first_color); i < last; i++) { - Entry *ent = map->red + i; - uint16_t red, green, blue; - - if (!ent->refcnt) continue; - if (ent->fShared) { - red = ent->co.shco.red->color; - green = ent->co.shco.green->color; - blue = ent->co.shco.blue->color; - } else { - red = ent->co.local.red; - green = ent->co.local.green; - blue = ent->co.local.blue; - } - - colors[i - first_color] = (0xFF000000UL - | ((uint32_t) red & 0xff00) << 8 - | (green & 0xff00) - | (blue >> 8)); - } - - return TRUE; -} - - -/* - * RootlessStartDrawing - * Prepare a window for direct access to its backing buffer. - * Each top-level parent has a Pixmap representing its backing buffer, - * which all of its children inherit. - */ -void RootlessStartDrawing(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - WindowPtr top = TopLevelParent(pWindow); - RootlessWindowRec *winRec; - PixmapPtr curPixmap; - - if (top == NULL) - return; - winRec = WINREC(top); - if (winRec == NULL) - return; - - // Make sure the window's top-level parent is prepared for drawing. - if (!winRec->is_drawing) { - int bw = wBorderWidth(top); - - SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData, - &winRec->bytesPerRow); - - winRec->pixmap = - GetScratchPixmapHeader(pScreen, winRec->width, winRec->height, - top->drawable.depth, - top->drawable.bitsPerPixel, - winRec->bytesPerRow, - winRec->pixelData); - SetPixmapBaseToScreen(winRec->pixmap, - top->drawable.x - bw, top->drawable.y - bw); - - winRec->is_drawing = TRUE; - } - - curPixmap = pScreen->GetWindowPixmap(pWindow); - if (curPixmap == winRec->pixmap) - { - RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", pWindow, winRec->pixmap); - } - else - { - PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey); - if (oldPixmap != NULL) - { - if (oldPixmap == curPixmap) - RL_DEBUG_MSG("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", pWindow, curPixmap); - else - RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", pWindow, oldPixmap); - } - dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, curPixmap); - pScreen->SetWindowPixmap(pWindow, winRec->pixmap); - } -} - - -/* - * RootlessStopDrawing - * Stop drawing to a window's backing buffer. If flush is true, - * damaged regions are flushed to the screen. - */ -static int RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data) -{ - RootlessWindowRec *winRec = (RootlessWindowRec*)data; - ScreenPtr pScreen = pWindow->drawable.pScreen; - PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow); - PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey); - if (oldPixmap == NULL) - { - if (exPixmap == winRec->pixmap) - RL_DEBUG_MSG("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", pWindow, exPixmap); - } - else - { - if (exPixmap != winRec->pixmap) - RL_DEBUG_MSG("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", pWindow, oldPixmap, exPixmap, winRec->pixmap); - if (oldPixmap == winRec->pixmap) - RL_DEBUG_MSG("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", pWindow, oldPixmap); - pScreen->SetWindowPixmap(pWindow, oldPixmap); - dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); - } - return WT_WALKCHILDREN; -} - -void RootlessStopDrawing(WindowPtr pWindow, Bool flush) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - WindowPtr top = TopLevelParent(pWindow); - RootlessWindowRec *winRec; - - if (top == NULL) - return; - winRec = WINREC(top); - if (winRec == NULL) - return; - - if (winRec->is_drawing) { - SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush); - - FreeScratchPixmapHeader(winRec->pixmap); - TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer)winRec); - winRec->pixmap = NULL; - - winRec->is_drawing = FALSE; - } - else if (flush) { - SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL); - } - - if (flush && winRec->is_reorder_pending) { - winRec->is_reorder_pending = FALSE; - RootlessReorderWindow(pWindow); - } -} - - -/* - * RootlessDamageRegion - * Mark a damaged region as requiring redisplay to screen. - * pRegion is in GLOBAL coordinates. - */ -void -RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - RootlessWindowRec *winRec; - RegionRec clipped; - WindowPtr pTop; - BoxPtr b1, b2; - - RL_DEBUG_MSG("Damaged win 0x%x ", pWindow); - - pTop = TopLevelParent(pWindow); - if (pTop == NULL) - return; - - winRec = WINREC(pTop); - if (winRec == NULL) - return; - - /* We need to intersect the drawn region with the clip of the window - to avoid marking places we didn't actually draw (which can cause - problems when the window has an extra client-side backing store) - - But this is a costly operation and since we'll normally just be - drawing inside the clip, go to some lengths to avoid the general - case intersection. */ - - b1 = REGION_EXTENTS(pScreen, &pWindow->borderClip); - b2 = REGION_EXTENTS(pScreen, pRegion); - - if (EXTENTCHECK(b1, b2)) { - /* Regions may overlap. */ - - if (REGION_NUM_RECTS(pRegion) == 1) { - int in; - - /* Damaged region only has a single rect, so we can - just compare that against the region */ - - in = RECT_IN_REGION(pScreen, &pWindow->borderClip, - REGION_RECTS (pRegion)); - if (in == rgnIN) { - /* clip totally contains pRegion */ - -#ifdef ROOTLESS_TRACK_DAMAGE - REGION_UNION(pScreen, &winRec->damage, - &winRec->damage, (pRegion)); -#else - SCREENREC(pScreen)->imp->DamageRects(winRec->wid, - REGION_NUM_RECTS(pRegion), - REGION_RECTS(pRegion), - -winRec->x, -winRec->y); -#endif - - RootlessQueueRedisplay(pTop->drawable.pScreen); - goto out; - } - else if (in == rgnOUT) { - /* clip doesn't contain pRegion */ - - goto out; - } - } - - /* clip overlaps pRegion, need to intersect */ - - REGION_NULL(pScreen, &clipped); - REGION_INTERSECT(pScreen, &clipped, &pWindow->borderClip, pRegion); - -#ifdef ROOTLESS_TRACK_DAMAGE - REGION_UNION(pScreen, &winRec->damage, - &winRec->damage, (pRegion)); -#else - SCREENREC(pScreen)->imp->DamageRects(winRec->wid, - REGION_NUM_RECTS(&clipped), - REGION_RECTS(&clipped), - -winRec->x, -winRec->y); -#endif - - REGION_UNINIT(pScreen, &clipped); - - RootlessQueueRedisplay(pTop->drawable.pScreen); - } - -out: -#ifdef ROOTLESSDEBUG - { - BoxRec *box = REGION_RECTS(pRegion), *end; - int numBox = REGION_NUM_RECTS(pRegion); - - for (end = box+numBox; box < end; box++) { - RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n", - box->x1, box->x2, box->y1, box->y2); - } - } -#endif - return; -} - - -/* - * RootlessDamageBox - * Mark a damaged box as requiring redisplay to screen. - * pRegion is in GLOBAL coordinates. - */ -void -RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox) -{ - RegionRec region; - - REGION_INIT(pWindow->drawable.pScreen, ®ion, pBox, 1); - - RootlessDamageRegion(pWindow, ®ion); - - REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ -} - - -/* - * RootlessDamageRect - * Mark a damaged rectangle as requiring redisplay to screen. - * (x, y, w, h) is in window-local coordinates. - */ -void -RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h) -{ - BoxRec box; - RegionRec region; - - x += pWindow->drawable.x; - y += pWindow->drawable.y; - - box.x1 = x; - box.x2 = x + w; - box.y1 = y; - box.y2 = y + h; - - REGION_INIT(pWindow->drawable.pScreen, ®ion, &box, 1); - - RootlessDamageRegion(pWindow, ®ion); - - REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ -} - - -/* - * RootlessRedisplay - * Stop drawing and redisplay the damaged region of a window. - */ -void -RootlessRedisplay(WindowPtr pWindow) -{ -#ifdef ROOTLESS_TRACK_DAMAGE - - RootlessWindowRec *winRec = WINREC(pWindow); - ScreenPtr pScreen = pWindow->drawable.pScreen; - - RootlessStopDrawing(pWindow, FALSE); - - if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { - RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n", - pWindow, winRec->width, winRec->height, - winRec->x, winRec->y); - - // move region to window local coords - REGION_TRANSLATE(pScreen, &winRec->damage, - -winRec->x, -winRec->y); - - SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage); - - REGION_EMPTY(pScreen, &winRec->damage); - } - -#else /* !ROOTLESS_TRACK_DAMAGE */ - - RootlessStopDrawing(pWindow, TRUE); - -#endif -} - - -/* - * RootlessRepositionWindows - * Reposition all windows on a screen to their correct positions. - */ -void -RootlessRepositionWindows(ScreenPtr pScreen) -{ - WindowPtr root = WindowTable[pScreen->myNum]; - WindowPtr win; - - if (root != NULL) { - RootlessRepositionWindow(root); - - for (win = root->firstChild; win; win = win->nextSib) { - if (WINREC(win) != NULL) - RootlessRepositionWindow(win); - } - } -} - - -/* - * RootlessRedisplayScreen - * Walk every window on a screen and redisplay the damaged regions. - */ -void -RootlessRedisplayScreen(ScreenPtr pScreen) -{ - WindowPtr root = WindowTable[pScreen->myNum]; - - if (root != NULL) { - WindowPtr win; - - RootlessRedisplay(root); - for (win = root->firstChild; win; win = win->nextSib) { - if (WINREC(win) != NULL) { - RootlessRedisplay(win); - } - } - } -} +/*
+ * Common rootless definitions and code
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stddef.h> /* For NULL */
+#include <limits.h> /* For CHAR_BIT */
+
+#include "rootlessCommon.h"
+#include "colormapst.h"
+
+unsigned int rootless_CopyBytes_threshold = 0;
+unsigned int rootless_FillBytes_threshold = 0;
+unsigned int rootless_CompositePixels_threshold = 0;
+unsigned int rootless_CopyWindow_threshold = 0;
+#ifdef ROOTLESS_GLOBAL_COORDS
+int rootlessGlobalOffsetX = 0;
+int rootlessGlobalOffsetY = 0;
+#endif
+
+RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
+
+/* Following macro from miregion.c */
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+
+/*
+ * TopLevelParent
+ * Returns the top-level parent of pWindow.
+ * The root is the top-level parent of itself, even though the root is
+ * not otherwise considered to be a top-level window.
+ */
+WindowPtr
+TopLevelParent(WindowPtr pWindow)
+{
+ WindowPtr top;
+
+ if (IsRoot(pWindow))
+ return pWindow;
+
+ top = pWindow;
+ while (top && ! IsTopLevel(top))
+ top = top->parent;
+
+ return top;
+}
+
+
+/*
+ * IsFramedWindow
+ * Returns TRUE if this window is visible inside a frame
+ * (e.g. it is visible and has a top-level or root parent)
+ */
+Bool
+IsFramedWindow(WindowPtr pWin)
+{
+ WindowPtr top;
+
+ if (!pWin->realized)
+ return FALSE;
+ top = TopLevelParent(pWin);
+
+ return (top && WINREC(top));
+}
+
+Bool
+RootlessResolveColormap (ScreenPtr pScreen, int first_color,
+ int n_colors, uint32_t *colors)
+{
+ int last, i;
+ ColormapPtr map;
+
+ map = RootlessGetColormap (pScreen);
+ if (map == NULL || map->class != PseudoColor) return FALSE;
+
+ last = min (map->pVisual->ColormapEntries, first_color + n_colors);
+ for (i = max (0, first_color); i < last; i++) {
+ Entry *ent = map->red + i;
+ uint16_t red, green, blue;
+
+ if (!ent->refcnt) continue;
+ if (ent->fShared) {
+ red = ent->co.shco.red->color;
+ green = ent->co.shco.green->color;
+ blue = ent->co.shco.blue->color;
+ } else {
+ red = ent->co.local.red;
+ green = ent->co.local.green;
+ blue = ent->co.local.blue;
+ }
+
+ colors[i - first_color] = (0xFF000000UL
+ | ((uint32_t) red & 0xff00) << 8
+ | (green & 0xff00)
+ | (blue >> 8));
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * RootlessStartDrawing
+ * Prepare a window for direct access to its backing buffer.
+ * Each top-level parent has a Pixmap representing its backing buffer,
+ * which all of its children inherit.
+ */
+void RootlessStartDrawing(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+ PixmapPtr curPixmap;
+
+ if (top == NULL)
+ return;
+ winRec = WINREC(top);
+ if (winRec == NULL)
+ return;
+
+ // Make sure the window's top-level parent is prepared for drawing.
+ if (!winRec->is_drawing) {
+ int bw = wBorderWidth(top);
+
+ SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData,
+ &winRec->bytesPerRow);
+
+ winRec->pixmap =
+ GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
+ top->drawable.depth,
+ top->drawable.bitsPerPixel,
+ winRec->bytesPerRow,
+ winRec->pixelData);
+ SetPixmapBaseToScreen(winRec->pixmap,
+ top->drawable.x - bw, top->drawable.y - bw);
+
+ winRec->is_drawing = TRUE;
+ }
+
+ curPixmap = pScreen->GetWindowPixmap(pWindow);
+ if (curPixmap == winRec->pixmap)
+ {
+ RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", pWindow, winRec->pixmap);
+ }
+ else
+ {
+ PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
+ if (oldPixmap != NULL)
+ {
+ if (oldPixmap == curPixmap)
+ RL_DEBUG_MSG("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", pWindow, curPixmap);
+ else
+ RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", pWindow, oldPixmap);
+ }
+ dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, curPixmap);
+ pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
+ }
+}
+
+
+/*
+ * RootlessStopDrawing
+ * Stop drawing to a window's backing buffer. If flush is true,
+ * damaged regions are flushed to the screen.
+ */
+static int RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data)
+{
+ RootlessWindowRec *winRec = (RootlessWindowRec*)data;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow);
+ PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
+ if (oldPixmap == NULL)
+ {
+ if (exPixmap == winRec->pixmap)
+ RL_DEBUG_MSG("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", pWindow, exPixmap);
+ }
+ else
+ {
+ if (exPixmap != winRec->pixmap)
+ RL_DEBUG_MSG("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", pWindow, oldPixmap, exPixmap, winRec->pixmap);
+ if (oldPixmap == winRec->pixmap)
+ RL_DEBUG_MSG("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", pWindow, oldPixmap);
+ pScreen->SetWindowPixmap(pWindow, oldPixmap);
+ dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
+ }
+ return WT_WALKCHILDREN;
+}
+
+void RootlessStopDrawing(WindowPtr pWindow, Bool flush)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+
+ if (top == NULL)
+ return;
+ winRec = WINREC(top);
+ if (winRec == NULL)
+ return;
+
+ if (winRec->is_drawing) {
+ SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush);
+
+ FreeScratchPixmapHeader(winRec->pixmap);
+ TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer)winRec);
+ winRec->pixmap = NULL;
+
+ winRec->is_drawing = FALSE;
+ }
+ else if (flush) {
+ SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL);
+ }
+
+ if (flush && winRec->is_reorder_pending) {
+ winRec->is_reorder_pending = FALSE;
+ RootlessReorderWindow(pWindow);
+ }
+}
+
+
+/*
+ * RootlessDamageRegion
+ * Mark a damaged region as requiring redisplay to screen.
+ * pRegion is in GLOBAL coordinates.
+ */
+void
+RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
+{
+ RootlessWindowRec *winRec;
+ RegionRec clipped;
+ WindowPtr pTop;
+ BoxPtr b1, b2;
+
+ RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
+
+ pTop = TopLevelParent(pWindow);
+ if (pTop == NULL)
+ return;
+
+ winRec = WINREC(pTop);
+ if (winRec == NULL)
+ return;
+
+ /* We need to intersect the drawn region with the clip of the window
+ to avoid marking places we didn't actually draw (which can cause
+ problems when the window has an extra client-side backing store)
+
+ But this is a costly operation and since we'll normally just be
+ drawing inside the clip, go to some lengths to avoid the general
+ case intersection. */
+
+ b1 = RegionExtents(&pWindow->borderClip);
+ b2 = RegionExtents(pRegion);
+
+ if (EXTENTCHECK(b1, b2)) {
+ /* Regions may overlap. */
+
+ if (RegionNumRects(pRegion) == 1) {
+ int in;
+
+ /* Damaged region only has a single rect, so we can
+ just compare that against the region */
+
+ in = RegionContainsRect(&pWindow->borderClip,
+ RegionRects (pRegion));
+ if (in == rgnIN) {
+ /* clip totally contains pRegion */
+
+#ifdef ROOTLESS_TRACK_DAMAGE
+ RegionUnion(&winRec->damage,
+ &winRec->damage, (pRegion));
+#else
+ SCREENREC(pWindow->drawable.pScreen)->imp->
+ DamageRects(winRec->wid,
+ RegionNumRects(pRegion),
+ RegionRects(pRegion),
+ -winRec->x, -winRec->y);
+#endif
+
+ RootlessQueueRedisplay(pTop->drawable.pScreen);
+ goto out;
+ }
+ else if (in == rgnOUT) {
+ /* clip doesn't contain pRegion */
+
+ goto out;
+ }
+ }
+
+ /* clip overlaps pRegion, need to intersect */
+
+ RegionNull(&clipped);
+ RegionIntersect(&clipped, &pWindow->borderClip, pRegion);
+
+#ifdef ROOTLESS_TRACK_DAMAGE
+ RegionUnion(&winRec->damage,
+ &winRec->damage, (pRegion));
+#else
+ SCREENREC(pWindow->drawable.pScreen)->imp->
+ DamageRects(winRec->wid,
+ RegionNumRects(&clipped),
+ RegionRects(&clipped),
+ -winRec->x, -winRec->y);
+#endif
+
+ RegionUninit(&clipped);
+
+ RootlessQueueRedisplay(pTop->drawable.pScreen);
+ }
+
+out:
+#ifdef ROOTLESSDEBUG
+ {
+ BoxRec *box = RegionRects(pRegion), *end;
+ int numBox = RegionNumRects(pRegion);
+
+ for (end = box+numBox; box < end; box++) {
+ RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
+ box->x1, box->x2, box->y1, box->y2);
+ }
+ }
+#endif
+ return;
+}
+
+
+/*
+ * RootlessDamageBox
+ * Mark a damaged box as requiring redisplay to screen.
+ * pRegion is in GLOBAL coordinates.
+ */
+void
+RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
+{
+ RegionRec region;
+
+ RegionInit(®ion, pBox, 1);
+
+ RootlessDamageRegion(pWindow, ®ion);
+
+ RegionUninit(®ion); /* no-op */
+}
+
+
+/*
+ * RootlessDamageRect
+ * Mark a damaged rectangle as requiring redisplay to screen.
+ * (x, y, w, h) is in window-local coordinates.
+ */
+void
+RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
+{
+ BoxRec box;
+ RegionRec region;
+
+ x += pWindow->drawable.x;
+ y += pWindow->drawable.y;
+
+ box.x1 = x;
+ box.x2 = x + w;
+ box.y1 = y;
+ box.y2 = y + h;
+
+ RegionInit(®ion, &box, 1);
+
+ RootlessDamageRegion(pWindow, ®ion);
+
+ RegionUninit(®ion); /* no-op */
+}
+
+
+/*
+ * RootlessRedisplay
+ * Stop drawing and redisplay the damaged region of a window.
+ */
+void
+RootlessRedisplay(WindowPtr pWindow)
+{
+#ifdef ROOTLESS_TRACK_DAMAGE
+
+ RootlessWindowRec *winRec = WINREC(pWindow);
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+ RootlessStopDrawing(pWindow, FALSE);
+
+ if (RegionNotEmpty(&winRec->damage)) {
+ RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n",
+ pWindow, winRec->width, winRec->height,
+ winRec->x, winRec->y);
+
+ // move region to window local coords
+ RegionTranslate(&winRec->damage,
+ -winRec->x, -winRec->y);
+
+ SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage);
+
+ RegionEmpty(&winRec->damage);
+ }
+
+#else /* !ROOTLESS_TRACK_DAMAGE */
+
+ RootlessStopDrawing(pWindow, TRUE);
+
+#endif
+}
+
+
+/*
+ * RootlessRepositionWindows
+ * Reposition all windows on a screen to their correct positions.
+ */
+void
+RootlessRepositionWindows(ScreenPtr pScreen)
+{
+ WindowPtr root = pScreen->root;
+ WindowPtr win;
+
+ if (root != NULL) {
+ RootlessRepositionWindow(root);
+
+ for (win = root->firstChild; win; win = win->nextSib) {
+ if (WINREC(win) != NULL)
+ RootlessRepositionWindow(win);
+ }
+ }
+}
+
+
+/*
+ * RootlessRedisplayScreen
+ * Walk every window on a screen and redisplay the damaged regions.
+ */
+void
+RootlessRedisplayScreen(ScreenPtr pScreen)
+{
+ WindowPtr root = pScreen->root;
+
+ if (root != NULL) {
+ WindowPtr win;
+
+ RootlessRedisplay(root);
+ for (win = root->firstChild; win; win = win->nextSib) {
+ if (WINREC(win) != NULL) {
+ RootlessRedisplay(win);
+ }
+ }
+ }
+}
|