#include "rootless-common.h"
#include "dri-surface.h"
#include "fb.h"
#include "colormapst.h"
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) ) )
#define SUBSUMES(r1,r2) \
( ((r1)->x1 <= (r2)->x1) && \
((r1)->x2 >= (r2)->x2) && \
((r1)->y1 <= (r2)->y1) && \
((r1)->y2 >= (r2)->y2) )
int rootlessNoDRIDrawing = 0;
WindowPtr
TopLevelParent (WindowPtr pWindow)
{
WindowPtr top;
if (IsRoot (pWindow))
return pWindow;
top = pWindow;
while (top != NULL && !IsTopLevel (top))
top = top->parent;
return top;
}
Bool
IsFramedWindow (WindowPtr pWin)
{
WindowPtr top;
if (!pWin->realized)
return FALSE;
top = TopLevelParent (pWin);
return top != NULL && WINREC (top) != NULL;
}
void
TranslatePixmapBase (PixmapPtr pPix, int dx, int dy)
{
unsigned diff;
pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr +
((dx + pPix->drawable.x)
* pPix->drawable.bitsPerPixel / 8 +
dy * pPix->devKind));
if (pPix->drawable.bitsPerPixel != FB_UNIT)
{
diff = ((unsigned) pPix->devPrivate.ptr) & (FB_UNIT / CHAR_BIT - 1);
pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr) - diff;
if (pPix->drawable.bitsPerPixel == 16)
pPix->drawable.x = diff / (16 / CHAR_BIT);
else if (pPix->drawable.bitsPerPixel == 8)
pPix->drawable.x = diff / (8 / CHAR_BIT);
else
pPix->drawable.x = diff / (pPix->drawable.bitsPerPixel / CHAR_BIT);
}
}
void
RootlessDisableUpdate (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
if (winRec != NULL
&& !winRec->is_offscreen
&& !winRec->is_reorder_pending
&& !winRec->is_update_disabled)
{
xp_disable_update ();
winRec->is_update_disabled = TRUE;
}
}
void
RootlessReenableUpdate (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
if (winRec != NULL && winRec->is_update_disabled)
{
xp_reenable_update ();
winRec->is_update_disabled = FALSE;
}
}
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;
}
void
RootlessStartDrawing (WindowPtr pWindow)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
WindowPtr top = TopLevelParent (pWindow);
RootlessWindowRec *winRec;
if (!rootlessNoDRIDrawing && DRIStartDrawing (&pWindow->drawable))
{
return;
}
if (top == NULL || WINREC (top) == NULL)
return;
winRec = WINREC(top);
if (!winRec->is_drawing)
{
void *data[2];
unsigned int rowbytes[2];
xp_error err;
int bw = wBorderWidth (top);
err = xp_lock_window (winRec->wid, NULL, NULL, data, rowbytes, NULL);
if (err != Success)
abort ();
winRec->data = data[0];
winRec->rowbytes = rowbytes[0];
winRec->pixmap =
GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
winRec->win->drawable.depth,
winRec->win->drawable.bitsPerPixel,
winRec->rowbytes, winRec->data);
TranslatePixmapBase (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
RootlessFinishedDrawing (WindowPtr pWindow)
{
DRIStopDrawing (&pWindow->drawable, FALSE);
RootlessMayRedisplay (pWindow->drawable.pScreen);
}
void
RootlessStopDrawing (WindowPtr pWindow, Bool flush)
{
WindowPtr top = TopLevelParent (pWindow);
RootlessWindowRec *winRec;
if (top == NULL || WINREC (top) == NULL)
return;
winRec = WINREC(top);
DRIStopDrawing (&pWindow->drawable, flush);
if (winRec->is_drawing)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
xp_unlock_window (winRec->wid, flush);
FreeScratchPixmapHeader (winRec->pixmap);
pScreen->SetWindowPixmap (pWindow, winRec->oldPixmap);
winRec->pixmap = NULL;
winRec->is_drawing = FALSE;
}
else if (flush)
{
xp_flush_window (winRec->wid);
}
if (flush && winRec->is_reorder_pending)
{
winRec->is_reorder_pending = FALSE;
RootlessReorderWindow (pWindow);
}
if (flush && winRec->is_update_disabled)
{
RootlessReenableUpdate (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;
if (DRIDamageRegion (&pWindow->drawable, pRegion))
{
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)
{
xp_mark_window (winRec->wid, REGION_NUM_RECTS (pRegion),
REGION_RECTS (pRegion),
-winRec->x, -winRec->y);
RootlessQueueRedisplay (pTop->drawable.pScreen);
goto out;
}
else if (in == rgnOUT)
{
goto out;
}
}
REGION_NULL (pScreen, &clipped);
REGION_INTERSECT (pScreen, &clipped, &pWindow->borderClip, pRegion);
xp_mark_window (winRec->wid, REGION_NUM_RECTS (&clipped),
REGION_RECTS (&clipped), -winRec->x, -winRec->y);
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)
{
DRISynchronizeDrawable (&pWindow->drawable, TRUE);
RootlessStopDrawing(pWindow, TRUE);
}
void
RootlessRedisplayScreen (ScreenPtr pScreen)
{
RootlessScreenRec *screenRec = SCREENREC (pScreen);
WindowPtr root = WindowTable[pScreen->myNum];
WindowPtr win;
if (root != NULL)
{
RootlessRedisplay(root);
for (win = root->firstChild; win; win = win->nextSib)
{
if (WINREC (win) != NULL)
RootlessRedisplay (win);
}
}
screenRec->last_redisplay = GetTimeInMillis ();
}
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
RootlessFlushScreenColormaps (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)
RootlessFlushWindowColormap (win);
}
}
}