Site hosted by Angelfire.com: Build your free website today!

Hands-on Projects for the Linux Graphics Subsystem

New book from Christos Karayiannis

Available in Amazon Kindle format at:

amazon.com   amazon.co.uk   amazon.de   amazon.es   amazon.fr   amazon.it

Other main() screen funcions

In this sections we examine some of the last routines called by main() related to the screen operations, called after InitOutput(). We actually continue from section 3.2.2.12, where CreateScreenResources(), the first of those routines, was covered.

I. CreateRootWindow()

	    if (!CreateRootWindow(pScreen))
		FatalError("failed to create root window");

CreateRootWindow() creates the initial window of the screen. It is implemented as:

/*****
 * CreateRootWindow
 *    Makes a window at initialization time for specified screen
 *****/

Bool
CreateRootWindow(ScreenPtr pScreen)
{
    WindowPtr	pWin;
    BoxRec	box;
    PixmapFormatRec *format;

    pWin = AllocateWindow(pScreen);
    if (!pWin)
	return FALSE;

    savedScreenInfo[pScreen->myNum].pWindow = NULL;
    savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
    savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
    screenIsSaved = SCREEN_SAVER_OFF;

    WindowTable[pScreen->myNum] = pWin;

    pWin->drawable.pScreen = pScreen;
    pWin->drawable.type = DRAWABLE_WINDOW;

    pWin->drawable.depth = pScreen->rootDepth;
    for (format = screenInfo.formats;
	 format->depth != pScreen->rootDepth;
	 format++)
	;
    pWin->drawable.bitsPerPixel = format->bitsPerPixel;

    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;

    pWin->parent = NullWindow;
    SetWindowToDefaults(pWin);

    pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec));
    if (!pWin->optional)
        return FALSE;

    pWin->optional->dontPropagateMask = 0;
    pWin->optional->otherEventMasks = 0;
    pWin->optional->otherClients = NULL;
    pWin->optional->passiveGrabs = NULL;
    pWin->optional->userProps = NULL;
    pWin->optional->backingBitPlanes = ~0L;
    pWin->optional->backingPixel = 0;
#ifdef SHAPE
    pWin->optional->boundingShape = NULL;
    pWin->optional->clipShape = NULL;
    pWin->optional->inputShape = NULL;
#endif
#ifdef XINPUT
    pWin->optional->inputMasks = NULL;
#endif
    pWin->optional->colormap = pScreen->defColormap;
    pWin->optional->visual = pScreen->rootVisual;

    pWin->nextSib = NullWindow;

    pWin->drawable.id = FakeClientID(0);

    pWin->origin.x = pWin->origin.y = 0;
    pWin->drawable.height = pScreen->height;
    pWin->drawable.width = pScreen->width;
    pWin->drawable.x = pWin->drawable.y = 0;

    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pScreen->width;
    box.y2 = pScreen->height;
    REGION_INIT(pScreen, &pWin->clipList, &box, 1);
    REGION_INIT(pScreen, &pWin->winSize, &box, 1);
    REGION_INIT(pScreen, &pWin->borderSize, &box, 1);
    REGION_INIT(pScreen, &pWin->borderClip, &box, 1);

    pWin->drawable.class = InputOutput;
    pWin->optional->visual = pScreen->rootVisual;

    pWin->backgroundState = BackgroundPixel;
    pWin->background.pixel = pScreen->whitePixel;

    pWin->borderIsPixel = TRUE;
    pWin->border.pixel = pScreen->blackPixel;
    pWin->borderWidth = 0;

    if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin))
	return FALSE;

    if (disableBackingStore)
	pScreen->backingStoreSupport = NotUseful;
    if (enableBackingStore)
	pScreen->backingStoreSupport = Always;

#ifdef DO_SAVE_UNDERS
    if ((pScreen->backingStoreSupport != NotUseful) &&
	(pScreen->saveUnderSupport == NotUseful))
    {
	/*
	 * If the screen has backing-store but no save-unders, let the
	 * clients know we can support save-unders using backing-store.
	 */
	pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS;
    }
#endif /* DO_SAVE_UNDERS */
		
    if (disableSaveUnders)
	pScreen->saveUnderSupport = NotUseful;

    return TRUE;
}

For DO_SAVE_UNDERS we read in this link:

"If save-under is True, the X server is advised that, when this window is mapped, saving the contents of windows it obscures would be beneficial".

II. InitRootWindow()

	for (i = 0; i < screenInfo.numScreens; i++)
	    InitRootWindow(WindowTable[i]);
	DefineInitialRootWindow(WindowTable[0]);

The Root window is initialised with InitRootWindow, which is implemented as:

void
InitRootWindow(WindowPtr pWin)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;

    if (!(*pScreen->CreateWindow)(pWin))
	return; /* XXX */
    (*pScreen->PositionWindow)(pWin, 0, 0);

    pWin->cursorIsNone = FALSE;
    pWin->optional->cursor = rootCursor;
    rootCursor->refcnt++;
    MakeRootTile(pWin);
    pWin->backingStore = defaultBackingStore;
    pWin->forcedBS = (defaultBackingStore != NotUseful);
    /* We SHOULD check for an error value here XXX */
    (*pScreen->ChangeWindowAttributes)(pWin,
		       CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore);

    MapWindow(pWin, serverClient);
}

As we saw in section 3.2.2.12 as pScreen->PositionWindow is assigned fbCreateWindow(), implemented as:

Bool
fbCreateWindow(WindowPtr pWin)
{
#ifndef FB_NO_WINDOW_PIXMAPS
    pWin->devPrivates[fbWinPrivateIndex].ptr = 
	(pointer) fbGetScreenPixmap(pWin->drawable.pScreen);
#endif
#ifdef FB_SCREEN_PRIVATE
    if (pWin->drawable.bitsPerPixel == 32)
	pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
#endif
    return TRUE;
}

Macro fbGetScreenPixmap is defined as:

#define fbGetScreenPixmap(s)	((PixmapPtr) (s)->devPrivate)

The devPrivate value was set at miCreateScreenResources() as seen in section 3.2.2.12. As this comment explains the value:
((PixmapPtr) (s)->devPrivate)
is either the pointer pbits or pPixmap, according to the existence of a 'stride'.
This value fills pWin->devPrivates[fbWinPrivateIndex].ptr.
Notice the similarity in the names of two different fileds from two different structs: devPrivate and devPrivates.

The ChangeWindowAttributes implementation is fbChangeWindowAttributes(). Some of the flags that are passed as the argument are defined in X.h. The attributes assigned by those flags are explained in numerous sites, for instance this wiki, this man page and the Xlib - C Language X Interface.

Next MapWindow() is called, implemented as:

/*****
 * MapWindow
 *    If some other client has selected SubStructureReDirect on the parent
 *    and override-redirect is xFalse, then a MapRequest event is generated,
 *    but the window remains unmapped.	Otherwise, the window is mapped and a
 *    MapNotify event is generated.
 *****/

int
MapWindow(register WindowPtr pWin, ClientPtr client)
{
    register ScreenPtr pScreen;

    register WindowPtr pParent;
#ifdef DO_SAVE_UNDERS
    Bool	dosave = FALSE;
#endif
    WindowPtr  pLayerWin;

    if (pWin->mapped)
	return(Success);

#ifdef XCSECURITY
    /*  don't let an untrusted client map a child-of-trusted-window, InputOnly
     *  window; too easy to steal device input
     */
    if ( (client->trustLevel != XSecurityClientTrusted) &&
	 (pWin->drawable.class == InputOnly) &&
	 (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) )
	 return Success;
#endif	

    pScreen = pWin->drawable.pScreen;
    if ( (pParent = pWin->parent) )
    {
	xEvent event;
	Bool anyMarked;
#ifdef XAPPGROUP
	ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)];
	ClientPtr ag_leader = XagLeader (win_owner);
#endif

	if ((!pWin->overrideRedirect) && 
	    (RedirectSend(pParent)
#ifdef XAPPGROUP
	    || (win_owner->appgroup && ag_leader &&
		XagIsControlledRoot (client, pParent))
#endif
	))
	{
	    event.u.u.type = MapRequest;
	    event.u.mapRequest.window = pWin->drawable.id;
#ifdef XAPPGROUP
	    /* make sure if the ag_leader maps the window it goes to the wm */
	    if (ag_leader && ag_leader != client &&
		XagIsControlledRoot (client, pParent)) {
		event.u.mapRequest.parent = XagId (win_owner);
		(void) TryClientEvents (ag_leader, &event, 1,
					NoEventMask, NoEventMask, NullGrab);
		return Success;
	    }
#endif
	    event.u.mapRequest.parent = pParent->drawable.id;

	    if (MaybeDeliverEventsToClient(pParent, &event, 1,
		SubstructureRedirectMask, client) == 1)
		return(Success);
	}

	pWin->mapped = TRUE;
	if (SubStrSend(pWin, pParent))
	{
	    event.u.u.type = MapNotify;
	    event.u.mapNotify.window = pWin->drawable.id;
	    event.u.mapNotify.override = pWin->overrideRedirect;
	    DeliverEvents(pWin, &event, 1, NullWindow);
	}

	if (!pParent->realized)
	    return(Success);
	RealizeTree(pWin);
	if (pWin->viewable)
	{
	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
							  &pLayerWin);
#ifdef DO_SAVE_UNDERS
	    if (DO_SAVE_UNDERS(pWin))
	    {
		dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib);
	    }
#endif /* DO_SAVE_UNDERS */
	    if (anyMarked)
	    {
		(*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
		(*pScreen->HandleExposures)(pLayerWin->parent);
	    }
#ifdef DO_SAVE_UNDERS
	    if (dosave)
		(*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
#endif /* DO_SAVE_UNDERS */
	if (anyMarked && pScreen->PostValidateTree)
	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
	}
	WindowsRestructured ();
    }
    else
    {
	RegionRec   temp;

	pWin->mapped = TRUE;
	pWin->realized = TRUE;	   /* for roots */
	pWin->viewable = pWin->drawable.class == InputOutput;
	/* We SHOULD check for an error value here XXX */
	(*pScreen->RealizeWindow)(pWin);
	if (pScreen->ClipNotify)
	    (*pScreen->ClipNotify) (pWin, 0, 0);
	if (pScreen->PostValidateTree)
	    (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
	REGION_NULL(pScreen, &temp);
	REGION_COPY(pScreen, &temp, &pWin->clipList);
	(*pScreen->WindowExposures) (pWin, &temp, NullRegion);
	REGION_UNINIT(pScreen, &temp);
    }

    return(Success);
}

MapWindow() mainly examines two cases, according to the condition:

    if ( (pParent = pWin->parent) )

This is an if condition with the assignment operation ('=') instead the equality testing ('=='). The condition holds true when the first part is not NULL after the assignment. On this see this wiki. Recall also that previously in CreateRootWindow() as parent of the Root window (pWin->parent) was assigned the NullWindow. Therefore the 'else' part of the condition holds true.

The macros we meet here are defined in regionstr.h. REGION_COPY is defined as:

#define REGION_COPY(_pScreen, dst, src) \
    (*(REG_pScreen)->RegionCopy)(dst, src)

where REG_pScreen is defined as:

#define REG_pScreen	screenInfo.screens[0]

As RegionCopy miRegionCopy() was assigned by miScreenInit() in section 3.2.2.12. miRegionCopy() is implemented as:

Bool
miRegionCopy(dst, src)
    register RegionPtr dst;
    register RegionPtr src;
{
    good(dst);
    good(src);
    if (dst == src)
	return TRUE;
    dst->extents = src->extents;
    if (!src->data || !src->data->size)
    {
	xfreeData(dst);
	dst->data = src->data;
	return TRUE;
    }
    if (!dst->data || (dst->data->size < src->data->numRects))
    {
	xfreeData(dst);
	dst->data = xallocData(src->data->numRects);
	if (!dst->data)
	    return miRegionBreak (dst);
	dst->data->size = src->data->numRects;
    }
    dst->data->numRects = src->data->numRects;
    memmove((char *)REGION_BOXPTR(dst),(char *)REGION_BOXPTR(src), 
	  dst->data->numRects * sizeof(BoxRec));
    return TRUE;
}

As we read from the memmove() man page:

     void *
     memmove(void *s1, const void *s2, size_t n);

     The memmove() function copies n bytes from string s2 to string s1.  The
     two strings may overlap; the copy is always done in a non-destructive
     manner.

Struct BoxRec is defined as:

typedef struct _Box {
    short x1, y1, x2, y2;
} BoxRec;

BoxPtr is defined as:

typedef struct _Box *BoxPtr;

As dst and src the &temp and &pWin->clipList values were previously passed to REGION_COPY. Both are of type RegionRec, which is defined as:

typedef struct _Region RegionRec, *RegionPtr;
. . .
typedef struct _RegData {
    long	size;
    long 	numRects;
/*  BoxRec	rects[size];   in memory but not explicitly declared */
} RegDataRec, *RegDataPtr;

struct _Region {
    BoxRec 	extents;
    RegDataPtr	data;
};

Since rects of type BoxRec are not explicitly declared, however there are in memory REGION_BOXPTR makes a hack by accessing the next pointer ((reg)->data + 1)) at the end of the struct (RegDataRec). However the point the struct ends starts the 'hidden' third field of the struct, rects[].

REGION_BOXPTR is defined as:

#define REGION_BOXPTR(reg) ((BoxPtr)((reg)->data + 1))

pWin is of type WindowPtr, which is defined as:

typedef struct _Window *WindowPtr;

where _Window is defined as:

typedef struct _Window {
    DrawableRec		drawable;
    WindowPtr		parent;		/* ancestor chain */
    WindowPtr		nextSib;	/* next lower sibling */
    WindowPtr		prevSib;	/* next higher sibling */
    WindowPtr		firstChild;	/* top-most child */
    WindowPtr		lastChild;	/* bottom-most child */
    RegionRec		clipList;	/* clipping rectangle for output */
    RegionRec		borderClip;	/* NotClippedByChildren + border */
    union _Validate	*valdata;
    RegionRec		winSize;
    RegionRec		borderSize;
    DDXPointRec		origin;		/* position relative to parent */
    unsigned short	borderWidth;
    unsigned short	deliverableEvents;
    Mask		eventMask;
    PixUnion		background;
    PixUnion		border;
    pointer		backStorage;	/* null when BS disabled */
    WindowOptPtr	optional;
    unsigned		backgroundState:2; /* None, Relative, Pixel, Pixmap */
    unsigned		borderIsPixel:1;
    unsigned		cursorIsNone:1;	/* else real cursor (might inherit) */
    unsigned		backingStore:2;
    unsigned		saveUnder:1;
    unsigned		DIXsaveUnder:1;
    unsigned		bitGravity:4;
    unsigned		winGravity:4;
    unsigned		overrideRedirect:1;
    unsigned		visibility:2;
    unsigned		mapped:1;
    unsigned		realized:1;	/* ancestors are all mapped */
    unsigned		viewable:1;	/* realized && InputOutput */
    unsigned		dontPropagate:3;/* index into DontPropagateMasks */
    unsigned		forcedBS:1;	/* system-supplied backingStore */
#ifdef NEED_DBE_BUF_BITS
#define DBE_FRONT_BUFFER 1
#define DBE_BACK_BUFFER  0
    unsigned		dstBuffer:1;	/* destination buffer for rendering */
    unsigned		srcBuffer:1;	/* source buffer for rendering */
#endif
#ifdef COMPOSITE
    unsigned		redirectDraw:1;	/* rendering is redirected from here */
#endif
    DevUnion		*devPrivates;
} WindowRec;

The previous show that REGION_COPY called as:

REGION_COPY(pScreen, &temp, &pWin->clipList);
resolves to a miRegionCopy() call. We also show the types of the dst and src arguments, the &temp and &pWin->clipList respectivelly. The source, clipList, was initialised in CreateRootWindow() as:

    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pScreen->width;
    box.y2 = pScreen->height;
    REGION_INIT(pScreen, &pWin->clipList, &box, 1);

REGION_INIT is an encapsulation of pScreen->RegionInit, which is miRegionInit(). This function initialises the region with the box of the third argument. This box starts at coordination (0,0) and spans the whole screen.

A second empty region called temp is initialised with REGION_NULL in MapWindow() as:

REGION_NULL(pScreen, &temp);

Then the REGION_COPY copies the contents of the clipList to temp.

temp is passed then as an argument to (*pScreen->WindowExposures), which is actually miWindowExposures().

(*pScreen->WindowExposures) (pWin, &temp, NullRegion);

As the second argument of miWindowExposures(), prgn, is passed the value temp, a copy of clipList, which as seen previously represents the whole screen region.

miWindowExposures() is implemented as:

void 
miWindowExposures(pWin, prgn, other_exposed)
    WindowPtr pWin;
    register RegionPtr prgn, other_exposed;
{
    RegionPtr   exposures = prgn;
    if (pWin->backStorage && prgn)
	/*
	 * in some cases, backing store will cause a different
	 * region to be exposed than needs to be repainted
	 * (like when a window is mapped).  RestoreAreas is
	 * allowed to return a region other than prgn,
	 * in which case this routine will free the resultant
	 * region.  If exposures is null, then no events will
	 * be sent to the client; if prgn is empty
	 * no areas will be repainted.
	 */
	exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
    if ((prgn && !REGION_NIL(prgn)) || 
	(exposures && !REGION_NIL(exposures)) || other_exposed)
    {
	RegionRec   expRec;
	int	    clientInterested;

	/*
	 * Restore from backing-store FIRST.
	 */
	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
	if (other_exposed)
	{
	    if (exposures)
	    {
		REGION_UNION(pWin->drawable.pScreen, other_exposed,
						  exposures,
					          other_exposed);
		if (exposures != prgn)
		    REGION_DESTROY(pWin->drawable.pScreen, exposures);
	    }
	    exposures = other_exposed;
	}
	if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
	{
	    /*
	     * If we have LOTS of rectangles, we decide to take the extents
	     * and force an exposure on that.  This should require much less
	     * work overall, on both client and server.  This is cheating, but
	     * isn't prohibited by the protocol ("spontaneous combustion" :-).
	     */
	    BoxRec box;

	    box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
	    if (exposures == prgn) {
		exposures = &expRec;
		REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
		REGION_RESET( pWin->drawable.pScreen, prgn, &box);
	    } else {
		REGION_RESET( pWin->drawable.pScreen, exposures, &box);
		REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
	    }
	    /* PaintWindowBackground doesn't clip, so we have to */
	    REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
	    /* need to clear out new areas of backing store, too */
	    if (pWin->backStorage)
		(void) (* pWin->drawable.pScreen->ClearBackingStore)(
					     pWin,
					     box.x1 - pWin->drawable.x,
					     box.y1 - pWin->drawable.y,
					     box.x2 - box.x1,
					     box.y2 - box.y1,
					     FALSE);
	}
	if (prgn && !REGION_NIL(prgn))
	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
	if (clientInterested && exposures && !REGION_NIL(exposures))
	    miSendExposures(pWin, exposures,
			    pWin->drawable.x, pWin->drawable.y);
	if (exposures == &expRec)
	{
	    REGION_UNINIT( pWin->drawable.pScreen, exposures);
	}
	else if (exposures && exposures != prgn && exposures != other_exposed)
	    REGION_DESTROY( pWin->drawable.pScreen, exposures);
	if (prgn)
	    REGION_EMPTY( pWin->drawable.pScreen, prgn);
    }
    else if (exposures && exposures != prgn)
	REGION_DESTROY( pWin->drawable.pScreen, exposures);
}

InitRootWindow() set backingStore to defaultBackingStore as:

pWin->backingStore = defaultBackingStore;

defaultBackingStore is defined in window.c as:

int	defaultBackingStore = NotUseful;

For BackingStore read this text.

NotUseful is defined in X.h as:

#define NotUseful               0

Since pWin->backStorage is zero miWindowExposures() executes the following instruction:

	if (prgn && !REGION_NIL(prgn))
	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);

PW_BACKGROUND is defined in pixmap.h as:

/* flags to PaintWindow() */
#define PW_BACKGROUND 0

The current PaintWindowBackground implementation as seen in section 3.2.2.12 is fbPaintWindow(), implemented as:

void
fbPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
{
    WindowPtr	pBgWin;
    
    switch (what) {
    case PW_BACKGROUND:
	switch (pWin->backgroundState) {
	case None:
	    break;
	case ParentRelative:
	    do {
		pWin = pWin->parent;
	    } while (pWin->backgroundState == ParentRelative);
	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
							     what);
	    break;
	case BackgroundPixmap:
	    fbFillRegionTiled (&pWin->drawable,
			       pRegion,
			       pWin->background.pixmap);
	    break;
	case BackgroundPixel:
	    fbFillRegionSolid (&pWin->drawable,
			       pRegion,
			       0,
			       fbReplicatePixel (pWin->background.pixel,
						 pWin->drawable.bitsPerPixel));
	    break;
    	}
    	break;
    case PW_BORDER:
	if (pWin->borderIsPixel)
	{
	    fbFillRegionSolid (&pWin->drawable,
			       pRegion,
			       0,
			       fbReplicatePixel (pWin->border.pixel,
						 pWin->drawable.bitsPerPixel));
	}
	else
	{
	    for (pBgWin = pWin;
		 pBgWin->backgroundState == ParentRelative;
		 pBgWin = pBgWin->parent);

	    fbFillRegionTiled (&pBgWin->drawable,
			       pRegion,
			       pWin->border.pixmap);
	}
	break;
    }
    fbValidateDrawable (&pWin->drawable);
}

CreateRootWindow() set backgroundState previously as:

    pWin->backgroundState = BackgroundPixel;

Therefore the following lines execute:

	case BackgroundPixel:
	    fbFillRegionSolid (&pWin->drawable,
			       pRegion,
			       0,
			       fbReplicatePixel (pWin->background.pixel,
						 pWin->drawable.bitsPerPixel));
	    break;

background.pixel was previously set by CreateRootWindow() as:

   pWin->background.pixel = pScreen->whitePixel;

pScreen->whitePixel was set fbSetupScreen(), in section 3.2.2.12 as:

    pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0;

fbReplicatePixel is implemented as:

FbBits
fbReplicatePixel (Pixel p, int bpp)
{
    FbBits  b = p;
    
    b &= FbFullMask (bpp);
    while (bpp < FB_UNIT)
    {
	b |= b << bpp;
	bpp <<= 1;
    }
    return b;
}

Macro FbFullMask is defined in fb.h as:

#define FbFullMask(n)   ((n) == FB_UNIT ? FB_ALLONES : ((((FbBits) 1) << n) - 1))

Macro FbFullMask masks off the number of bits determined by bpp, for instance 8 or 24. In the case of 8 it masks 1111111, that is 8 ones, or in the case of 24 it masks 24 bits. In the case of 32-bits it macro FB_ALLONES is used which does the same for 32 bits, it just uses -1, which is binary 11111111111111111111111111111111. This is 32 ones. Considering that we see that fbReplicatePixel() actually replicates a byte 4 times or a word 2 times (to a the 32-bit region of FbBits). Using a 32-bit quantity it improves the performance of the 'xor', 'and' operations.

Pixel is defined in colormap.h as:

typedef CARD32 Pixel;

fbFillRegionSolid() is implemented as:

void
fbFillRegionSolid (DrawablePtr	pDrawable,
		   RegionPtr	pRegion,
		   FbBits	and,
		   FbBits	xor)
{
    FbBits	*dst;
    FbStride	dstStride;
    int		dstBpp;
    int		dstXoff, dstYoff;
    int		n = REGION_NUM_RECTS(pRegion);
    BoxPtr	pbox = REGION_RECTS(pRegion);

    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
    
    while (n--)
    {
	fbSolid (dst + (pbox->y1 + dstYoff) * dstStride,
		 dstStride,
		 (pbox->x1 + dstXoff) * dstBpp,
		 dstBpp,
		 (pbox->x2 - pbox->x1) * dstBpp,
		 pbox->y2 - pbox->y1,
		 and, xor);
	fbValidateDrawable (pDrawable);
	pbox++;
    }
}

fbSolid fills dst with the pRegion contents.

pRegion is actually the argument prgn, passed to PaintWindowBackground. Previously prgn was substituted by temp, the &pWin->clipList which represents the whole screen region, the one the Root window that we currently build occupies:

    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pScreen->width;
    box.y2 = pScreen->height;
    REGION_INIT(pScreen, &pWin->clipList, &box, 1);
dst is obtained from macro fbGetDrawable and it is the pPixmap->devPrivate.ptr, which was set in section 3.2.2.12 to point at the pixmap data. This is the pixmap that represends the screen memory. Recall the commnet of miCreateScreenResources() at section 3.2.2.12 "create a pixmap with no data, then redirect it to point to the screen".

At this comment (*pScreen->CreatePixmap), the fbCreatePixmap(), created the empty pixmap and
(*pScreen->ModifyPixmapHeader), which is actually miModifyPixmapHeader() set the address of the pixmap to the screen memory address.

See also this comment.

Macros REGION_NUM_RECTS and REGION_RECTS are defined in regionstr.h as:

#define REGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)

#define REGION_RECTS(reg) ((reg)->data ? (BoxPtr)((reg)->data + 1) \
			               : &(reg)->extents)

Macro fbGetDrawable is defined as:

#define fbGetDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \
    PixmapPtr   _pPix; \
    if ((pDrawable)->type != DRAWABLE_PIXMAP) { \
	_pPix = fbGetWindowPixmap(pDrawable); \
	(xoff) = __fbPixOffXWin(_pPix); \
	(yoff) = __fbPixOffYWin(_pPix); \
    } else { \
	_pPix = (PixmapPtr) (pDrawable); \
	(xoff) = __fbPixOffXPix(_pPix); \
	(yoff) = __fbPixOffYPix(_pPix); \
    } \
    (pointer) = (FbBits *) _pPix->devPrivate.ptr; \
    (stride) = ((int) _pPix->devKind) / sizeof (FbBits); (void)(stride); \
    (bpp) = _pPix->drawable.bitsPerPixel;  (void)(bpp); \
}

Since fbCreatePixmapBpp () set at section 3.2.2.12 pPixmap->drawable.type to DRAWABLE_PIXMAP the following lines execute:

	_pPix = (PixmapPtr) (pDrawable); \
	(xoff) = __fbPixOffXPix(_pPix); \
	(yoff) = __fbPixOffYPix(_pPix); \

stride is calculated in fbGetDrawable as:

    (stride) = ((int) _pPix->devKind) / sizeof (FbBits); 
pPixmap->devKind is filled in fbCreatePixmapBpp() at section 3.2.2.12 as:
pPixmap->devKind = paddedWidth;
where paddedWidth is filled in fbCreatePixmapBpp() as:
   paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
This pads width to a multiple of 32. The simplified rule for stride is width * bpp.

The definitions for FB_MASK, FB_SHIFT and FbBits follow bellow.

The following macros are defined in fb.h as:

#define __fbPixOffXPix(pPix)	(__fbPixDrawableX(pPix))
#define __fbPixOffYPix(pPix)	(__fbPixDrawableY(pPix))
. . .
#define __fbPixDrawableX(pPix)	0
#define __fbPixDrawableY(pPix)	0

fbSolid() is implemented as:

void
fbSolid (FbBits	    *dst,
	 FbStride   dstStride,
	 int	    dstX,
	 int	    bpp,

	 int	    width,
	 int	    height,

	 FbBits	    and,
	 FbBits	    xor)
{
    FbBits  startmask, endmask;
    int	    n, nmiddle;
    int	    startbyte, endbyte;

#ifdef FB_24BIT
    if (bpp == 24 && (!FbCheck24Pix(and) || !FbCheck24Pix(xor)))
    {
	fbSolid24 (dst, dstStride, dstX, width, height, and, xor);
	return;
    }
#endif
    dst += dstX >> FB_SHIFT;
    dstX &= FB_MASK;
    FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte, 
		    nmiddle, endmask, endbyte);
    if (startmask)
	dstStride--;
    dstStride -= nmiddle;
    while (height--)
    {
	if (startmask)
	{
	    FbDoLeftMaskByteRRop(dst,startbyte,startmask,and,xor);
	    dst++;
	}
	n = nmiddle;
	if (!and)
	    while (n--)
		*dst++ = xor;
	else
	    while (n--)
	    {
		*dst = FbDoRRop (*dst, and, xor);
		dst++;
	    }
	if (endmask)
	    FbDoRightMaskByteRRop(dst,endbyte,endmask,and,xor);
	dst += dstStride;
    }
}

fbsolid() is called from fbFillRegionSolid() to fill the specified number or ranges (in our case, where the initial screen window, the Root window is created there is one range that fills the whole screen range). It copies the box that represents the screen dimensions at the memory location dst, which as we previously saw is the starting memory location of the video memory. It is called as:


	fbSolid (dst + (pbox->y1 + dstYoff) * dstStride,
		 dstStride,
		 (pbox->x1 + dstXoff) * dstBpp,
		 dstBpp,
		 (pbox->x2 - pbox->x1) * dstBpp,
		 pbox->y2 - pbox->y1,
		 and, xor);
The first argument represents the whole screen bits, starting from location dst. It multiplies the y dimension with the stride of the x axis. Stride is the number of bits per pixel, therefore the product is the whole screen bits.

The second argument is the stride of the screen

The third argument is the number of bits in the x dimension

The fourth argument is the screen Bpp (bits per pixel)

The fifth argument is the width of the box

The sixth argument is the height of the box

The last two arguments are the FbBits pattern that will be used in the 'and' and 'xor' raster operations. Both were set to zero when fbFillRegionSolid() was called.


The blue arrow point at dst, the start of the video memory.

The green arrow point at the actual dst as this is formed at the first argument. The first argument is
dst + (pbox->y1 + dstYoff) * dstStride, where dstYoff is zero. With this formula we proceed at point (0,Y), where as Y is the y axis coordination of the upper-left corner.

The red arrow point at the upper-left corner of the box and we proceed there with the instruction

dst += dstX >> FB_SHIFT;

The next instruction masks dst:
dstX &= FB_MASK;
and then fbSolid() calls macro FbMaskBitsBytes, which is described in detail next. The masking, which occurs also inside FbMaskBitsBytes, tries to find the left and right areas of the boxed region that occupy areas, which are not inside a 32-bit border. Those areas are handled a little bit different, because the clear 32-bit parts are painted with algorithms that have a better performance.

FbMaskBitsBytes finds the left and right mask than need to apply left and right in order to determnine those areas.

Then the while() loop starting from the top and processing each line paints the left, right parts (if exist) and the main part.

Recall that each line is actually a stride, consists therefore from the number of pixels multiplied by the bits a pixel needs for its color.

The painting consists of the 'and' and 'xor' logical operations.


      

The previous figure examines a case where the left side starts from a non 32-bit boundary and has to be masked. The red line indicates the masked area after the fbSolid() instruction:
dstX &= FB_MASK;
and the green line indicates the masked area after dstX is passed as x (the formal argument there is x) to FbMaskBitsBytes. This masked area, given as green in the figure, painted by FbDoLeftMaskByteRRop (FbDoMaskRRop eventually) while the rest is painted directly as:
*dst++ = xor;
or by FbDoRRop in some other cases.

NOTE: We end this section with fbsolid(). The text that follows describe macros and functions that are called from fbsolid().

Macros FB_SHIFT and FB_MASK are defined in fb.h as:

/*
 * This single define controls the basic size of data manipulated
 * by this software; it must be log2(sizeof (FbBits) * 8)
 */

#ifndef FB_SHIFT
#define FB_SHIFT    LOG2_BITMAP_PAD
#endif

#define FB_UNIT	    (1 << FB_SHIFT)
#define FB_HALFUNIT (1 << (FB_SHIFT-1))
#define FB_MASK	    (FB_UNIT - 1)
#define FB_ALLONES  ((FbBits) -1)

where LOG2_BITMAP_PAD is defined as:

#define LOG2_BITMAP_PAD		5

Macro FbMaskBitsBytes is defined as:

#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) { \
    n = (w); \
    lb = 0; \
    rb = 0; \
    r = FbRightMask((x)+n); \
    if (r) { \
	/* compute right byte length */ \
	if ((copy) && (((x) + n) & 7) == 0) { \
	    rb = (((x) + n) & FB_MASK) >> 3; \
	} else { \
	    rb = FbByteMaskInvalid; \
	} \
    } \
    l = FbLeftMask(x); \
    if (l) { \
	/* compute left byte length */ \
	if ((copy) && ((x) & 7) == 0) { \
	    lb = ((x) & FB_MASK) >> 3; \
	} else { \
	    lb = FbByteMaskInvalid; \
	} \
	/* subtract out the portion painted by leftMask */ \
	n -= FB_UNIT - ((x) & FB_MASK); \
	if (n < 0) { \
	    if (lb != FbByteMaskInvalid) { \
		if (rb == FbByteMaskInvalid) { \
		    lb = FbByteMaskInvalid; \
		} else if (rb) { \
		    lb |= (rb - lb) << (FB_SHIFT - 3); \
		    rb = 0; \
		} \
	    } \
	    n = 0; \
	    l &= r; \
	    r = 0; \
	}\
    } \
    n >>= FB_SHIFT; \
}

FbMaskBitsBytes

FbMaskBitsBytes() finds for the range the left mask (l) and the right mask (r) and then computes the left (lb) and the right (rb) byte length, of the distance from a 32-bit boundary. Seeing the range as 4-byte quantities improves the performance when painting the range:


    l = FbLeftMask(x); 
FbLeftMask is defined as:
#define FbLeftMask(x)	    ( ((x) & FB_MASK) ? \
			     FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0)
and FB_ALLONES is 32 "all ones" bits, 11111111111111111111111111111111. It is defined as:
#define FB_ALLONES  ((FbBits) -1)

                          +-------------------------+
                          |                         |
                          |          ---            |
                          |<--170-->|   |           |
                          |         |   |           |
                          |          ---            |        
                          +-------------------------+
If we consider the case of a non 32-bit multiple, for instance x = 170 (10101010 binary), FB_MASK used by FbLeftMask results to 1010 (10 decimal) and then FbLeftMask results to left-shifting 11111111111111111111111111111111 by 10. The left mask, is therefore
11111111111111111111110000000000.

                     x
 * - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - *
160=                170           +22 to the next boundary      192= 
5x32                                                            6x32
                     1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
The left mask marks the area (170-191) that will use FbDoLeftMaskByteRRop (enentually FbDoMaskRRop) to paint the region while the other part (except the right mask's) will use FbDoRRop.

For the left side of the region, FbLeftMask is used to mask the bytes and then the following instruction is used to find the distance, in bytes, from a 32-bit boundary:


	/* compute left byte length */ \
	if ((copy) && ((x) & 7) == 0) { \
	    lb = ((x) & FB_MASK) >> 3; \
	} else { \
	    lb = FbByteMaskInvalid; \
	} \
In the current example x is not a multiple of 8 (a byte) and the lb takes the FbByteMaskInvalid value.

Similarly for the right side of the region FbRightMask is used to mask the bytes and this time as argument x+n is used, where x is distance of the region from the left side of the screen and n the region's width, so that we proceed to the region's right side:


    r = FbRightMask((x)+n); 
and the distance, in bytes, from a 32-bit boundary is also:

	/* compute right byte length */ \
	if ((copy) && (((x) + n) & 7) == 0) { \
	    rb = (((x) + n) & FB_MASK) >> 3; \
	} else { \
	    rb = FbByteMaskInvalid; \
	} \
where also the FbByteMaskInvalid value is used for rb.

Finally the width is turned to 32-bit quantities:

    n >>= FB_SHIFT; 

FbByteMaskInvalid is defined as:

#define FbByteMaskInvalid   0x10

Also the following are defined in fb.h:

#define FbLeftMask(x)	    ( ((x) & FB_MASK) ? \
			     FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0)
#define FbRightMask(x)	    ( ((FB_UNIT - (x)) & FB_MASK) ? \
			     FbScrLeft(FB_ALLONES,(FB_UNIT - (x)) & FB_MASK) : 0)

and

#if BITMAP_BIT_ORDER == LSBFirst
#define FbScrLeft(x,n)	((x) >> (n))
#define FbScrRight(x,n)	((x) << (n))
. . .
#else
#define FbScrLeft(x,n)	((x) << (n))
#define FbScrRight(x,n)	((x) >> (n))

BITMAP_BIT_ORDER is defined in servermd.h for various computer architectures. For instance for i386 it is defined as:

 
#ifdef i386
# define IMAGE_BYTE_ORDER	LSBFirst	/* Value for PS/2 only */

FbBits is defined in fb.h as:

 
#if FB_SHIFT == 5
typedef CARD32		    FbBits;
#endif

FbDoRRop is defined as:

 
#define FbDoRRop(dst, and, xor)	(((dst) & (and)) ^ (xor))

Rop in FbDoRRop() and at the end of some other routine names stand for Raster Operation. From How Video Cards Work we read:

The 2D engine (often called a blitter) basically moves data around in video ram. There are generally 4 operations done by the 2D engine: blits (copying data from one place to another), fills (draw a solid color), lines (draws lines), and color expansion (convert mono data to color data; e.g. convert monochrome font glyphs to the depth of your screen: usually 16 or 24 bit color). Logical operations (rops -- raster operations) can also be performed on the data.

Macros FbDoLeftMaskByteRRop and FbDoRightMaskByteRRop are defined in fb.h as:

 
#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \
    switch (lb) { \
    FbDoLeftMaskByteRRop6Cases(dst,xor) \
    case (sizeof (FbBits) - 3) | (1 << (FB_SHIFT - 3)): \
	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
	break; \
    case (sizeof (FbBits) - 3) | (2 << (FB_SHIFT - 3)): \
	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
	FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
	break; \
    case (sizeof (FbBits) - 2) | (1 << (FB_SHIFT - 3)): \
	FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \
	break; \
    case sizeof (FbBits) - 3: \
	FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \
    case sizeof (FbBits) - 2: \
	FbStorePart(dst,sizeof (FbBits) - 2,CARD16,xor); \
	break; \
    case sizeof (FbBits) - 1: \
	FbStorePart(dst,sizeof (FbBits) - 1,CARD8,xor); \
	break; \
    default: \
	*dst = FbDoMaskRRop(*dst, and, xor, l); \
	break; \
    } \
}

#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \
    switch (rb) { \
    case 1: \
	FbStorePart(dst,0,CARD8,xor); \
	break; \
    case 2: \
	FbStorePart(dst,0,CARD16,xor); \
	break; \
    case 3: \
	FbStorePart(dst,0,CARD16,xor); \
	FbStorePart(dst,2,CARD8,xor); \
	break; \
    FbDoRightMaskByteRRop6Cases(dst,xor) \
    default: \
	*dst = FbDoMaskRRop (*dst, and, xor, r); \
    } \
}

Because lb and rb were set to FbByteMaskInvalid previously in FbMaskBitsBytes the default cases apply in both bDoLeftMaskByteRRop and FbDoRightMaskByteRRop.

The following macros are empty:

 
#define FbDoLeftMaskByteRRop6Cases(dst,xor)
#define FbDoRightMaskByteRRop6Cases(dst,xor)

Macro FbStorePart is defined with other relevant macros in fb.h as:

 
#define FbSelectPatternPart(xor,o,t)	((xor) >> (FbPatternOffset (o,t) << 3))
#define FbStorePart(dst,off,t,xor)	(*FbPtrOffset(dst,off,t) = \
					 FbSelectPart(xor,off,t))
#ifndef FbSelectPart
#define FbSelectPart(x,o,t) FbSelectPatternPart(x,o,t)
#endif

FbDoMaskRRop is defined as:

 
#define FbDoMaskRRop(dst, and, xor, mask) \
    (((dst) & ((and) | ~(mask))) ^ (xor & mask))

FbDoMaskRRop is similar to FbDoRRop, which applies the 'and' and 'xor' operations to dst, however this time the masked area is only painted. The 'and' operator applies first and then 'xor'. At the first case the mask is negated and ORed:
((and) | ~(mask))
and at the second the normal mask is used:
(xor & mask)
If we use the previously example we see that in order to apply 'and and 'xor' to the area 170 to 191 the area from 192 and up should be preserved untouched until the next FbDoRRop. With the mask negation the green zeroes as appear bellow are turned to ones. The formula
((and) | ~(mask))
also produce ones at the 'green' area and and as a result only the first 'blue' part is logically added to dst. The 'xor' part that follows:
^ (xor & mask)
does not alter the 192 and up area, since the 0 at the one side of an XOR operation preserves the other operant (see this wiki).

                     x
 * - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - *
160=                170           +22 to the next boundary      192= 
5x32                                                            6x32
                     1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0

FbDoRRop and FbDoMaskRRop are the macros that fbSolid() actually uses since FbDoLeftMaskByteRRop and FbDoRightMaskByteRRop are replaced by FbDoMaskRRop. Actually FbDoRRop is not used at all in the current case since the following condition in fbsolid() do not apply:
if (!and)

REFERENCES:

Wiki about Blit
How Video Cards Work