#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stddef.h>
#include <limits.h>
#include "rootlessCommon.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};
#define EXTENTCHECK(r1,r2) \
(!( ((r1)->x2 <= (r2)->x1) || \
((r1)->x1 >= (r2)->x2) || \
((r1)->y2 <= (r2)->y1) || \
((r1)->y1 >= (r2)->y2) ) )
WindowPtr
TopLevelParent(WindowPtr pWindow)
{
WindowPtr top;
if (IsRoot(pWindow))
return pWindow;
top = pWindow;
while (top && ! IsTopLevel(top))
top = top->parent;
return top;
}
Bool
IsFramedWindow(WindowPtr pWin)
{
WindowPtr top;
if (!pWin->realized)
return FALSE;
top = TopLevelParent(pWin);
return (top && WINREC(top));
}
void RootlessStartDrawing(WindowPtr pWindow)
{
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) {
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;
}
winRec->oldPixmap = pScreen->GetWindowPixmap(pWindow);
pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
}
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);
pScreen->SetWindowPixmap(pWindow, winRec->oldPixmap);
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);
}
}
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;
b1 = REGION_EXTENTS(pScreen, &pWindow->borderClip);
b2 = REGION_EXTENTS(pScreen, pRegion);
if (EXTENTCHECK(b1, b2)) {
if (REGION_NUM_RECTS(pRegion) == 1) {
int in;
in = RECT_IN_REGION(pScreen, &pWindow->borderClip,
REGION_RECTS (pRegion));
if (in == rgnIN) {
#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) {
goto out;
}
}
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;
}
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);
}
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);
}
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);
REGION_TRANSLATE(pScreen, &winRec->damage,
-winRec->x, -winRec->y);
SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage);
REGION_EMPTY(pScreen, &winRec->damage);
}
#else
RootlessStopDrawing(pWindow, TRUE);
#endif
}
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);
}
}
}
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);
}
}
}
}