micmap.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
305b261ecSmrg
405b261ecSmrg                    All Rights Reserved
505b261ecSmrg
605b261ecSmrgPermission  to  use,  copy,  modify,  and  distribute   this
705b261ecSmrgsoftware  and  its documentation for any purpose and without
805b261ecSmrgfee is hereby granted, provided that the above copyright no-
905b261ecSmrgtice  appear  in all copies and that both that copyright no-
1005b261ecSmrgtice and this permission notice appear in  supporting  docu-
1105b261ecSmrgmentation,  and  that the names of Sun or X Consortium
1205b261ecSmrgnot be used in advertising or publicity pertaining to
1305b261ecSmrgdistribution  of  the software  without specific prior
1405b261ecSmrgwritten permission. Sun and X Consortium make no
1505b261ecSmrgrepresentations about the suitability of this software for
1605b261ecSmrgany purpose. It is provided "as is" without any express or
1705b261ecSmrgimplied warranty.
1805b261ecSmrg
1905b261ecSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
2005b261ecSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
2105b261ecSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
2205b261ecSmrgABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2305b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
2405b261ecSmrgPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
2505b261ecSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2605b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2705b261ecSmrg
2805b261ecSmrg********************************************************/
2905b261ecSmrg
3005b261ecSmrg/*
3105b261ecSmrg * This is based on cfbcmap.c.  The functions here are useful independently
3205b261ecSmrg * of cfb, which is the reason for including them here.  How "mi" these
3305b261ecSmrg * are may be debatable.
3405b261ecSmrg */
3505b261ecSmrg
3605b261ecSmrg
3705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3805b261ecSmrg#include <dix-config.h>
3905b261ecSmrg#endif
4005b261ecSmrg
4105b261ecSmrg#include <X11/X.h>
4205b261ecSmrg#include <X11/Xproto.h>
4305b261ecSmrg#include "scrnintstr.h"
4405b261ecSmrg#include "colormapst.h"
4505b261ecSmrg#include "resource.h"
4605b261ecSmrg#include "globals.h"
4705b261ecSmrg#include "micmap.h"
4805b261ecSmrg
4905b261ecSmrg_X_EXPORT ColormapPtr miInstalledMaps[MAXSCREENS];
5005b261ecSmrg
5105b261ecSmrgstatic Bool miDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
5205b261ecSmrg		int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
5305b261ecSmrg		unsigned long sizes, int bitsPerRGB, int preferredVis);
5405b261ecSmrg
5505b261ecSmrg_X_EXPORT miInitVisualsProcPtr miInitVisualsProc = miDoInitVisuals;
5605b261ecSmrg
5705b261ecSmrg_X_EXPORT int
5805b261ecSmrgmiListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
5905b261ecSmrg{
6005b261ecSmrg    if (miInstalledMaps[pScreen->myNum]) {
6105b261ecSmrg	*pmaps = miInstalledMaps[pScreen->myNum]->mid;
6205b261ecSmrg	return (1);
6305b261ecSmrg    }
6405b261ecSmrg    return 0;
6505b261ecSmrg}
6605b261ecSmrg
6705b261ecSmrg_X_EXPORT void
6805b261ecSmrgmiInstallColormap(ColormapPtr pmap)
6905b261ecSmrg{
7005b261ecSmrg    int index = pmap->pScreen->myNum;
7105b261ecSmrg    ColormapPtr oldpmap = miInstalledMaps[index];
7205b261ecSmrg
7305b261ecSmrg    if(pmap != oldpmap)
7405b261ecSmrg    {
7505b261ecSmrg	/* Uninstall pInstalledMap. No hardware changes required, just
7605b261ecSmrg	 * notify all interested parties. */
7705b261ecSmrg	if(oldpmap != (ColormapPtr)None)
7805b261ecSmrg	    WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
7905b261ecSmrg	/* Install pmap */
8005b261ecSmrg	miInstalledMaps[index] = pmap;
8105b261ecSmrg	WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
8205b261ecSmrg
8305b261ecSmrg    }
8405b261ecSmrg}
8505b261ecSmrg
8605b261ecSmrg_X_EXPORT void
8705b261ecSmrgmiUninstallColormap(ColormapPtr pmap)
8805b261ecSmrg{
8905b261ecSmrg    int index = pmap->pScreen->myNum;
9005b261ecSmrg    ColormapPtr curpmap = miInstalledMaps[index];
9105b261ecSmrg
9205b261ecSmrg    if(pmap == curpmap)
9305b261ecSmrg    {
9405b261ecSmrg	if (pmap->mid != pmap->pScreen->defColormap)
9505b261ecSmrg	{
9605b261ecSmrg	    curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
9705b261ecSmrg						   RT_COLORMAP);
9805b261ecSmrg	    (*pmap->pScreen->InstallColormap)(curpmap);
9905b261ecSmrg	}
10005b261ecSmrg    }
10105b261ecSmrg}
10205b261ecSmrg
10305b261ecSmrg_X_EXPORT void
10405b261ecSmrgmiResolveColor(unsigned short *pred, unsigned short *pgreen,
10505b261ecSmrg		unsigned short *pblue, VisualPtr pVisual)
10605b261ecSmrg{
10705b261ecSmrg    int shift = 16 - pVisual->bitsPerRGBValue;
10805b261ecSmrg    unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
10905b261ecSmrg
11005b261ecSmrg    if ((pVisual->class | DynamicClass) == GrayScale)
11105b261ecSmrg    {
11205b261ecSmrg	/* rescale to gray then rgb bits */
11305b261ecSmrg	*pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
11405b261ecSmrg	*pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
11505b261ecSmrg    }
11605b261ecSmrg    else
11705b261ecSmrg    {
11805b261ecSmrg	/* rescale to rgb bits */
11905b261ecSmrg	*pred = ((*pred >> shift) * 65535) / lim;
12005b261ecSmrg	*pgreen = ((*pgreen >> shift) * 65535) / lim;
12105b261ecSmrg	*pblue = ((*pblue >> shift) * 65535) / lim;
12205b261ecSmrg    }
12305b261ecSmrg}
12405b261ecSmrg
12505b261ecSmrg_X_EXPORT Bool
12605b261ecSmrgmiInitializeColormap(ColormapPtr pmap)
12705b261ecSmrg{
12805b261ecSmrg    unsigned i;
12905b261ecSmrg    VisualPtr pVisual;
13005b261ecSmrg    unsigned lim, maxent, shift;
13105b261ecSmrg
13205b261ecSmrg    pVisual = pmap->pVisual;
13305b261ecSmrg    lim = (1 << pVisual->bitsPerRGBValue) - 1;
13405b261ecSmrg    shift = 16 - pVisual->bitsPerRGBValue;
13505b261ecSmrg    maxent = pVisual->ColormapEntries - 1;
13605b261ecSmrg    if (pVisual->class == TrueColor)
13705b261ecSmrg    {
13805b261ecSmrg	unsigned limr, limg, limb;
13905b261ecSmrg
14005b261ecSmrg	limr = pVisual->redMask >> pVisual->offsetRed;
14105b261ecSmrg	limg = pVisual->greenMask >> pVisual->offsetGreen;
14205b261ecSmrg	limb = pVisual->blueMask >> pVisual->offsetBlue;
14305b261ecSmrg	for(i = 0; i <= maxent; i++)
14405b261ecSmrg	{
14505b261ecSmrg	    /* rescale to [0..65535] then rgb bits */
14605b261ecSmrg	    pmap->red[i].co.local.red =
14705b261ecSmrg		((((i * 65535) / limr) >> shift) * 65535) / lim;
14805b261ecSmrg	    pmap->green[i].co.local.green =
14905b261ecSmrg		((((i * 65535) / limg) >> shift) * 65535) / lim;
15005b261ecSmrg	    pmap->blue[i].co.local.blue =
15105b261ecSmrg		((((i * 65535) / limb) >> shift) * 65535) / lim;
15205b261ecSmrg	}
15305b261ecSmrg    }
15405b261ecSmrg    else if (pVisual->class == StaticColor)
15505b261ecSmrg    {
15605b261ecSmrg	unsigned limr, limg, limb;
15705b261ecSmrg
15805b261ecSmrg	limr = pVisual->redMask >> pVisual->offsetRed;
15905b261ecSmrg	limg = pVisual->greenMask >> pVisual->offsetGreen;
16005b261ecSmrg	limb = pVisual->blueMask >> pVisual->offsetBlue;
16105b261ecSmrg	for(i = 0; i <= maxent; i++)
16205b261ecSmrg	{
16305b261ecSmrg	    /* rescale to [0..65535] then rgb bits */
16405b261ecSmrg	    pmap->red[i].co.local.red =
16505b261ecSmrg		((((((i & pVisual->redMask) >> pVisual->offsetRed)
16605b261ecSmrg		    * 65535) / limr) >> shift) * 65535) / lim;
16705b261ecSmrg	    pmap->red[i].co.local.green =
16805b261ecSmrg		((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
16905b261ecSmrg		    * 65535) / limg) >> shift) * 65535) / lim;
17005b261ecSmrg	    pmap->red[i].co.local.blue =
17105b261ecSmrg		((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
17205b261ecSmrg		    * 65535) / limb) >> shift) * 65535) / lim;
17305b261ecSmrg	}
17405b261ecSmrg    }
17505b261ecSmrg    else if (pVisual->class == StaticGray)
17605b261ecSmrg    {
17705b261ecSmrg	for(i = 0; i <= maxent; i++)
17805b261ecSmrg	{
17905b261ecSmrg	    /* rescale to [0..65535] then rgb bits */
18005b261ecSmrg	    pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
18105b261ecSmrg					 * 65535) / lim;
18205b261ecSmrg	    pmap->red[i].co.local.green = pmap->red[i].co.local.red;
18305b261ecSmrg	    pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
18405b261ecSmrg	}
18505b261ecSmrg    }
18605b261ecSmrg    return TRUE;
18705b261ecSmrg}
18805b261ecSmrg
18905b261ecSmrg/* When simulating DirectColor on PseudoColor hardware, multiple
19005b261ecSmrg   entries of the colormap must be updated
19105b261ecSmrg */
19205b261ecSmrg
19305b261ecSmrg#define AddElement(mask) { \
19405b261ecSmrg    pixel = red | green | blue; \
19505b261ecSmrg    for (i = 0; i < nresult; i++) \
19605b261ecSmrg  	if (outdefs[i].pixel == pixel) \
19705b261ecSmrg    	    break; \
19805b261ecSmrg    if (i == nresult) \
19905b261ecSmrg    { \
20005b261ecSmrg   	nresult++; \
20105b261ecSmrg	outdefs[i].pixel = pixel; \
20205b261ecSmrg	outdefs[i].flags = 0; \
20305b261ecSmrg    } \
20405b261ecSmrg    outdefs[i].flags |= (mask); \
20505b261ecSmrg    outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
20605b261ecSmrg    outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
20705b261ecSmrg    outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrg_X_EXPORT int
21105b261ecSmrgmiExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs,
21205b261ecSmrg			xColorItem *outdefs)
21305b261ecSmrg{
21405b261ecSmrg    int	        red, green, blue;
21505b261ecSmrg    int	        maxred, maxgreen, maxblue;
21605b261ecSmrg    int	        stepred, stepgreen, stepblue;
21705b261ecSmrg    VisualPtr   pVisual;
21805b261ecSmrg    int         pixel;
21905b261ecSmrg    int         nresult;
22005b261ecSmrg    int         i;
22105b261ecSmrg
22205b261ecSmrg    pVisual = pmap->pVisual;
22305b261ecSmrg
22405b261ecSmrg    stepred = 1 << pVisual->offsetRed;
22505b261ecSmrg    stepgreen = 1 << pVisual->offsetGreen;
22605b261ecSmrg    stepblue = 1 << pVisual->offsetBlue;
22705b261ecSmrg    maxred = pVisual->redMask;
22805b261ecSmrg    maxgreen = pVisual->greenMask;
22905b261ecSmrg    maxblue = pVisual->blueMask;
23005b261ecSmrg    nresult = 0;
23105b261ecSmrg    for (;ndef--; indefs++)
23205b261ecSmrg    {
23305b261ecSmrg	if (indefs->flags & DoRed)
23405b261ecSmrg	{
23505b261ecSmrg	    red = indefs->pixel & pVisual->redMask;
23605b261ecSmrg    	    for (green = 0; green <= maxgreen; green += stepgreen)
23705b261ecSmrg    	    {
23805b261ecSmrg	    	for (blue = 0; blue <= maxblue; blue += stepblue)
23905b261ecSmrg	    	{
24005b261ecSmrg		    AddElement (DoRed)
24105b261ecSmrg	    	}
24205b261ecSmrg    	    }
24305b261ecSmrg	}
24405b261ecSmrg	if (indefs->flags & DoGreen)
24505b261ecSmrg	{
24605b261ecSmrg	    green = indefs->pixel & pVisual->greenMask;
24705b261ecSmrg    	    for (red = 0; red <= maxred; red += stepred)
24805b261ecSmrg    	    {
24905b261ecSmrg	    	for (blue = 0; blue <= maxblue; blue += stepblue)
25005b261ecSmrg	    	{
25105b261ecSmrg		    AddElement (DoGreen)
25205b261ecSmrg	    	}
25305b261ecSmrg    	    }
25405b261ecSmrg	}
25505b261ecSmrg	if (indefs->flags & DoBlue)
25605b261ecSmrg	{
25705b261ecSmrg	    blue = indefs->pixel & pVisual->blueMask;
25805b261ecSmrg    	    for (red = 0; red <= maxred; red += stepred)
25905b261ecSmrg    	    {
26005b261ecSmrg	    	for (green = 0; green <= maxgreen; green += stepgreen)
26105b261ecSmrg	    	{
26205b261ecSmrg		    AddElement (DoBlue)
26305b261ecSmrg	    	}
26405b261ecSmrg    	    }
26505b261ecSmrg	}
26605b261ecSmrg    }
26705b261ecSmrg    return nresult;
26805b261ecSmrg}
26905b261ecSmrg
27005b261ecSmrg_X_EXPORT Bool
27105b261ecSmrgmiCreateDefColormap(ScreenPtr pScreen)
27205b261ecSmrg{
27305b261ecSmrg/*
27405b261ecSmrg * In the following sources PC X server vendors may want to delete
27505b261ecSmrg * "_not_tog" from "#ifdef WIN32_not_tog"
27605b261ecSmrg */
27705b261ecSmrg#ifdef WIN32_not_tog
27805b261ecSmrg    /*
27905b261ecSmrg     * these are the MS-Windows desktop colors, adjusted for X's 16-bit
28005b261ecSmrg     * color specifications.
28105b261ecSmrg     */
28205b261ecSmrg    static xColorItem citems[] = {
28305b261ecSmrg	{   0,      0,      0,      0, 0, 0 },
28405b261ecSmrg	{   1, 0x8000,      0,      0, 0, 0 },
28505b261ecSmrg	{   2,      0, 0x8000,      0, 0, 0 },
28605b261ecSmrg	{   3, 0x8000, 0x8000,      0, 0, 0 },
28705b261ecSmrg	{   4,      0,      0, 0x8000, 0, 0 },
28805b261ecSmrg	{   5, 0x8000,      0, 0x8000, 0, 0 },
28905b261ecSmrg	{   6,      0, 0x8000, 0x8000, 0, 0 },
29005b261ecSmrg	{   7, 0xc000, 0xc000, 0xc000, 0, 0 },
29105b261ecSmrg	{   8, 0xc000, 0xdc00, 0xc000, 0, 0 },
29205b261ecSmrg	{   9, 0xa600, 0xca00, 0xf000, 0, 0 },
29305b261ecSmrg	{ 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
29405b261ecSmrg	{ 247, 0xa000, 0xa000, 0xa400, 0, 0 },
29505b261ecSmrg	{ 248, 0x8000, 0x8000, 0x8000, 0, 0 },
29605b261ecSmrg	{ 249, 0xff00,      0,      0, 0, 0 },
29705b261ecSmrg	{ 250,      0, 0xff00,      0, 0, 0 },
29805b261ecSmrg	{ 251, 0xff00, 0xff00,      0, 0, 0 },
29905b261ecSmrg	{ 252,      0,      0, 0xff00, 0, 0 },
30005b261ecSmrg	{ 253, 0xff00,      0, 0xff00, 0, 0 },
30105b261ecSmrg	{ 254,      0, 0xff00, 0xff00, 0, 0 },
30205b261ecSmrg	{ 255, 0xff00, 0xff00, 0xff00, 0, 0 }
30305b261ecSmrg    };
30405b261ecSmrg#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
30505b261ecSmrg    int i;
30605b261ecSmrg#else
30705b261ecSmrg    unsigned short	zero = 0, ones = 0xFFFF;
30805b261ecSmrg#endif
30905b261ecSmrg    Pixel wp, bp;
31005b261ecSmrg    VisualPtr	pVisual;
31105b261ecSmrg    ColormapPtr	cmap;
31205b261ecSmrg    int alloctype;
31305b261ecSmrg
31405b261ecSmrg    for (pVisual = pScreen->visuals;
31505b261ecSmrg	 pVisual->vid != pScreen->rootVisual;
31605b261ecSmrg	 pVisual++)
31705b261ecSmrg	;
31805b261ecSmrg
31905b261ecSmrg    if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
32005b261ecSmrg	alloctype = AllocNone;
32105b261ecSmrg    else
32205b261ecSmrg	alloctype = AllocAll;
32305b261ecSmrg
32405b261ecSmrg    if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
32505b261ecSmrg		       alloctype, 0) != Success)
32605b261ecSmrg	return FALSE;
32705b261ecSmrg
32805b261ecSmrg    if (pScreen->rootDepth > 1) {
32905b261ecSmrg	wp = pScreen->whitePixel;
33005b261ecSmrg	bp = pScreen->blackPixel;
33105b261ecSmrg#ifdef WIN32_not_tog
33205b261ecSmrg	for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
33305b261ecSmrg	    if (AllocColor (cmap,
33405b261ecSmrg			    &citems[i].red, &citems[i].green, &citems[i].blue,
33505b261ecSmrg			    &citems[i].pixel, 0) != Success)
33605b261ecSmrg		return FALSE;
33705b261ecSmrg	}
33805b261ecSmrg#else
33905b261ecSmrg	if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
34005b261ecSmrg       	       Success) ||
34105b261ecSmrg	    (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) !=
34205b261ecSmrg       	       Success))
34305b261ecSmrg    	    return FALSE;
34405b261ecSmrg	pScreen->whitePixel = wp;
34505b261ecSmrg	pScreen->blackPixel = bp;
34605b261ecSmrg#endif
34705b261ecSmrg    }
34805b261ecSmrg
34905b261ecSmrg    (*pScreen->InstallColormap)(cmap);
35005b261ecSmrg    return TRUE;
35105b261ecSmrg}
35205b261ecSmrg
35305b261ecSmrg/*
35405b261ecSmrg * Default true color bitmasks, should be overridden by
35505b261ecSmrg * driver
35605b261ecSmrg */
35705b261ecSmrg
35805b261ecSmrg#define _RZ(d) ((d + 2) / 3)
35905b261ecSmrg#define _RS(d) 0
36005b261ecSmrg#define _RM(d) ((1 << _RZ(d)) - 1)
36105b261ecSmrg#define _GZ(d) ((d - _RZ(d) + 1) / 2)
36205b261ecSmrg#define _GS(d) _RZ(d)
36305b261ecSmrg#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
36405b261ecSmrg#define _BZ(d) (d - _RZ(d) - _GZ(d))
36505b261ecSmrg#define _BS(d) (_RZ(d) + _GZ(d))
36605b261ecSmrg#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
36705b261ecSmrg#define _CE(d) (1 << _RZ(d))
36805b261ecSmrg
36905b261ecSmrgtypedef struct _miVisuals {
37005b261ecSmrg    struct _miVisuals	*next;
37105b261ecSmrg    int			depth;
37205b261ecSmrg    int			bitsPerRGB;
37305b261ecSmrg    int			visuals;
37405b261ecSmrg    int			count;
37505b261ecSmrg    int			preferredCVC;
37605b261ecSmrg    Pixel		redMask, greenMask, blueMask;
37705b261ecSmrg} miVisualsRec, *miVisualsPtr;
37805b261ecSmrg
37905b261ecSmrgstatic int  miVisualPriority[] = {
38005b261ecSmrg    PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
38105b261ecSmrg};
38205b261ecSmrg
38305b261ecSmrg#define NUM_PRIORITY	6
38405b261ecSmrg
38505b261ecSmrgstatic miVisualsPtr	miVisuals;
38605b261ecSmrg
38705b261ecSmrg_X_EXPORT void
38805b261ecSmrgmiClearVisualTypes(void)
38905b261ecSmrg{
39005b261ecSmrg    miVisualsPtr v;
39105b261ecSmrg
39205b261ecSmrg    while ((v = miVisuals)) {
39305b261ecSmrg	miVisuals = v->next;
39405b261ecSmrg	xfree(v);
39505b261ecSmrg    }
39605b261ecSmrg}
39705b261ecSmrg
39805b261ecSmrg
39905b261ecSmrg_X_EXPORT Bool
40005b261ecSmrgmiSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
40105b261ecSmrg			 int preferredCVC,
40205b261ecSmrg			 Pixel redMask, Pixel greenMask, Pixel blueMask)
40305b261ecSmrg{
40405b261ecSmrg    miVisualsPtr   new, *prev, v;
40505b261ecSmrg    int		    count;
40605b261ecSmrg
40705b261ecSmrg    new = (miVisualsPtr) xalloc (sizeof *new);
40805b261ecSmrg    if (!new)
40905b261ecSmrg	return FALSE;
41005b261ecSmrg    if (!redMask || !greenMask || !blueMask)
41105b261ecSmrg    {
41205b261ecSmrg	redMask = _RM(depth);
41305b261ecSmrg	greenMask = _GM(depth);
41405b261ecSmrg	blueMask = _BM(depth);
41505b261ecSmrg    }
41605b261ecSmrg    new->next = 0;
41705b261ecSmrg    new->depth = depth;
41805b261ecSmrg    new->visuals = visuals;
41905b261ecSmrg    new->bitsPerRGB = bitsPerRGB;
42005b261ecSmrg    new->preferredCVC = preferredCVC;
42105b261ecSmrg    new->redMask = redMask;
42205b261ecSmrg    new->greenMask = greenMask;
42305b261ecSmrg    new->blueMask = blueMask;
42405b261ecSmrg    count = (visuals >> 1) & 033333333333;
42505b261ecSmrg    count = visuals - count - ((count >> 1) & 033333333333);
42605b261ecSmrg    count = (((count + (count >> 3)) & 030707070707) % 077);	/* HAKMEM 169 */
42705b261ecSmrg    new->count = count;
42805b261ecSmrg    for (prev = &miVisuals; (v = *prev); prev = &v->next);
42905b261ecSmrg    *prev = new;
43005b261ecSmrg    return TRUE;
43105b261ecSmrg}
43205b261ecSmrg
43305b261ecSmrg_X_EXPORT Bool
43405b261ecSmrgmiSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
43505b261ecSmrg{
43605b261ecSmrg    return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB,
43705b261ecSmrg				     preferredCVC, 0, 0, 0);
43805b261ecSmrg}
43905b261ecSmrg
44005b261ecSmrg_X_EXPORT int
44105b261ecSmrgmiGetDefaultVisualMask(int depth)
44205b261ecSmrg{
44305b261ecSmrg    if (depth > MAX_PSEUDO_DEPTH)
44405b261ecSmrg	return LARGE_VISUALS;
44505b261ecSmrg    else if (depth >= MIN_TRUE_DEPTH)
44605b261ecSmrg	return ALL_VISUALS;
44705b261ecSmrg    else if (depth == 1)
44805b261ecSmrg	return StaticGrayMask;
44905b261ecSmrg    else
45005b261ecSmrg	return SMALL_VISUALS;
45105b261ecSmrg}
45205b261ecSmrg
45305b261ecSmrgstatic Bool
45405b261ecSmrgmiVisualTypesSet (int depth)
45505b261ecSmrg{
45605b261ecSmrg    miVisualsPtr    visuals;
45705b261ecSmrg
45805b261ecSmrg    for (visuals = miVisuals; visuals; visuals = visuals->next)
45905b261ecSmrg	if (visuals->depth == depth)
46005b261ecSmrg	    return TRUE;
46105b261ecSmrg    return FALSE;
46205b261ecSmrg}
46305b261ecSmrg
46405b261ecSmrg_X_EXPORT Bool
46505b261ecSmrgmiSetPixmapDepths (void)
46605b261ecSmrg{
46705b261ecSmrg    int	d, f;
46805b261ecSmrg
46905b261ecSmrg    /* Add any unlisted depths from the pixmap formats */
47005b261ecSmrg    for (f = 0; f < screenInfo.numPixmapFormats; f++)
47105b261ecSmrg    {
47205b261ecSmrg	d = screenInfo.formats[f].depth;
47305b261ecSmrg	if (!miVisualTypesSet (d))
47405b261ecSmrg	{
47505b261ecSmrg	    if (!miSetVisualTypes (d, 0, 0, -1))
47605b261ecSmrg		return FALSE;
47705b261ecSmrg	}
47805b261ecSmrg    }
47905b261ecSmrg    return TRUE;
48005b261ecSmrg}
48105b261ecSmrg
48205b261ecSmrg_X_EXPORT Bool
48305b261ecSmrgmiInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
48405b261ecSmrg		int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
48505b261ecSmrg		unsigned long sizes, int bitsPerRGB, int preferredVis)
48605b261ecSmrg
48705b261ecSmrg{
48805b261ecSmrg    if (miInitVisualsProc)
48905b261ecSmrg	return miInitVisualsProc(visualp, depthp, nvisualp, ndepthp,
49005b261ecSmrg				 rootDepthp, defaultVisp, sizes, bitsPerRGB,
49105b261ecSmrg				 preferredVis);
49205b261ecSmrg    else
49305b261ecSmrg	return FALSE;
49405b261ecSmrg}
49505b261ecSmrg
49605b261ecSmrg/*
49705b261ecSmrg * Distance to least significant one bit
49805b261ecSmrg */
49905b261ecSmrgstatic int
50005b261ecSmrgmaskShift (Pixel p)
50105b261ecSmrg{
50205b261ecSmrg    int	s;
50305b261ecSmrg
50405b261ecSmrg    if (!p) return 0;
50505b261ecSmrg    s = 0;
50605b261ecSmrg    while (!(p & 1))
50705b261ecSmrg    {
50805b261ecSmrg	s++;
50905b261ecSmrg	p >>= 1;
51005b261ecSmrg    }
51105b261ecSmrg    return s;
51205b261ecSmrg}
51305b261ecSmrg
51405b261ecSmrg/*
51505b261ecSmrg * Given a list of formats for a screen, create a list
51605b261ecSmrg * of visuals and depths for the screen which corespond to
51705b261ecSmrg * the set which can be used with this version of cfb.
51805b261ecSmrg */
51905b261ecSmrg
52005b261ecSmrgstatic Bool
52105b261ecSmrgmiDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
52205b261ecSmrg		int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
52305b261ecSmrg		unsigned long sizes, int bitsPerRGB, int preferredVis)
52405b261ecSmrg{
52505b261ecSmrg    int		i, j = 0, k;
52605b261ecSmrg    VisualPtr	visual;
52705b261ecSmrg    DepthPtr	depth;
52805b261ecSmrg    VisualID	*vid;
52905b261ecSmrg    int		d, b;
53005b261ecSmrg    int		f;
53105b261ecSmrg    int		ndepth, nvisual;
53205b261ecSmrg    int		nvtype;
53305b261ecSmrg    int		vtype;
53405b261ecSmrg    miVisualsPtr   visuals, nextVisuals;
53505b261ecSmrg    int		*preferredCVCs, *prefp;
53605b261ecSmrg    int		first_depth;
53705b261ecSmrg
53805b261ecSmrg    /* none specified, we'll guess from pixmap formats */
53905b261ecSmrg    if (!miVisuals)
54005b261ecSmrg    {
54105b261ecSmrg    	for (f = 0; f < screenInfo.numPixmapFormats; f++)
54205b261ecSmrg    	{
54305b261ecSmrg	    d = screenInfo.formats[f].depth;
54405b261ecSmrg	    b = screenInfo.formats[f].bitsPerPixel;
54505b261ecSmrg	    if (sizes & (1 << (b - 1)))
54605b261ecSmrg		vtype = miGetDefaultVisualMask(d);
54705b261ecSmrg	    else
54805b261ecSmrg		vtype = 0;
54905b261ecSmrg	    if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1))
55005b261ecSmrg		return FALSE;
55105b261ecSmrg    	}
55205b261ecSmrg    }
55305b261ecSmrg    nvisual = 0;
55405b261ecSmrg    ndepth = 0;
55505b261ecSmrg    for (visuals = miVisuals; visuals; visuals = nextVisuals)
55605b261ecSmrg    {
55705b261ecSmrg	nextVisuals = visuals->next;
55805b261ecSmrg	ndepth++;
55905b261ecSmrg	nvisual += visuals->count;
56005b261ecSmrg    }
56105b261ecSmrg    depth = (DepthPtr) xalloc (ndepth * sizeof (DepthRec));
56205b261ecSmrg    visual = (VisualPtr) xalloc (nvisual * sizeof (VisualRec));
56305b261ecSmrg    preferredCVCs = (int *)xalloc(ndepth * sizeof(int));
56405b261ecSmrg    if (!depth || !visual || !preferredCVCs)
56505b261ecSmrg    {
56605b261ecSmrg	xfree (depth);
56705b261ecSmrg	xfree (visual);
56805b261ecSmrg	xfree (preferredCVCs);
56905b261ecSmrg	return FALSE;
57005b261ecSmrg    }
57105b261ecSmrg    *depthp = depth;
57205b261ecSmrg    *visualp = visual;
57305b261ecSmrg    *ndepthp = ndepth;
57405b261ecSmrg    *nvisualp = nvisual;
57505b261ecSmrg    prefp = preferredCVCs;
57605b261ecSmrg    for (visuals = miVisuals; visuals; visuals = nextVisuals)
57705b261ecSmrg    {
57805b261ecSmrg	nextVisuals = visuals->next;
57905b261ecSmrg	d = visuals->depth;
58005b261ecSmrg	vtype = visuals->visuals;
58105b261ecSmrg	nvtype = visuals->count;
58205b261ecSmrg	*prefp = visuals->preferredCVC;
58305b261ecSmrg	prefp++;
58405b261ecSmrg	vid = NULL;
58505b261ecSmrg	if (nvtype)
58605b261ecSmrg	{
58705b261ecSmrg	    vid = (VisualID *) xalloc (nvtype * sizeof (VisualID));
58805b261ecSmrg	    if (!vid) {
58905b261ecSmrg		xfree(preferredCVCs);
59005b261ecSmrg		return FALSE;
59105b261ecSmrg	    }
59205b261ecSmrg	}
59305b261ecSmrg	depth->depth = d;
59405b261ecSmrg	depth->numVids = nvtype;
59505b261ecSmrg	depth->vids = vid;
59605b261ecSmrg	depth++;
59705b261ecSmrg	for (i = 0; i < NUM_PRIORITY; i++) {
59805b261ecSmrg	    if (! (vtype & (1 << miVisualPriority[i])))
59905b261ecSmrg		continue;
60005b261ecSmrg	    visual->class = miVisualPriority[i];
60105b261ecSmrg	    visual->bitsPerRGBValue = visuals->bitsPerRGB;
60205b261ecSmrg	    visual->ColormapEntries = 1 << d;
60305b261ecSmrg	    visual->nplanes = d;
60405b261ecSmrg	    visual->vid = *vid = FakeClientID (0);
60505b261ecSmrg	    switch (visual->class) {
60605b261ecSmrg	    case PseudoColor:
60705b261ecSmrg	    case GrayScale:
60805b261ecSmrg	    case StaticGray:
60905b261ecSmrg		visual->redMask = 0;
61005b261ecSmrg		visual->greenMask =  0;
61105b261ecSmrg		visual->blueMask =  0;
61205b261ecSmrg		visual->offsetRed  =  0;
61305b261ecSmrg		visual->offsetGreen = 0;
61405b261ecSmrg		visual->offsetBlue =  0;
61505b261ecSmrg		break;
61605b261ecSmrg	    case DirectColor:
61705b261ecSmrg	    case TrueColor:
61805b261ecSmrg		visual->ColormapEntries = _CE(d);
61905b261ecSmrg		/* fall through */
62005b261ecSmrg	    case StaticColor:
62105b261ecSmrg		visual->redMask =  visuals->redMask;
62205b261ecSmrg		visual->greenMask =  visuals->greenMask;
62305b261ecSmrg		visual->blueMask =  visuals->blueMask;
62405b261ecSmrg		visual->offsetRed  =  maskShift (visuals->redMask);
62505b261ecSmrg		visual->offsetGreen = maskShift (visuals->greenMask);
62605b261ecSmrg		visual->offsetBlue =  maskShift (visuals->blueMask);
62705b261ecSmrg	    }
62805b261ecSmrg	    vid++;
62905b261ecSmrg	    visual++;
63005b261ecSmrg	}
63105b261ecSmrg	xfree (visuals);
63205b261ecSmrg    }
63305b261ecSmrg    miVisuals = NULL;
63405b261ecSmrg    visual = *visualp;
63505b261ecSmrg    depth = *depthp;
63605b261ecSmrg
63705b261ecSmrg    /*
63805b261ecSmrg     * if we did not supplyied by a preferred visual class
63905b261ecSmrg     * check if there is a preferred class in one of the depth
64005b261ecSmrg     * structures - if there is, we want to start looking for the
64105b261ecSmrg     * default visual/depth from that depth.
64205b261ecSmrg     */
64305b261ecSmrg    first_depth = 0;
64405b261ecSmrg    if (preferredVis < 0 && defaultColorVisualClass < 0 ) {
64505b261ecSmrg       for (i = 0; i < ndepth; i++) {
64605b261ecSmrg	  if (preferredCVCs[i] >= 0) {
64705b261ecSmrg	     first_depth = i;
64805b261ecSmrg	     break;
64905b261ecSmrg	  }
65005b261ecSmrg       }
65105b261ecSmrg    }
65205b261ecSmrg
65305b261ecSmrg    for (i = first_depth; i < ndepth; i++)
65405b261ecSmrg    {
65505b261ecSmrg	int prefColorVisualClass = -1;
65605b261ecSmrg
65705b261ecSmrg	if (defaultColorVisualClass >= 0)
65805b261ecSmrg	    prefColorVisualClass = defaultColorVisualClass;
65905b261ecSmrg	else if (preferredVis >= 0)
66005b261ecSmrg	    prefColorVisualClass = preferredVis;
66105b261ecSmrg	else if (preferredCVCs[i] >= 0)
66205b261ecSmrg	    prefColorVisualClass = preferredCVCs[i];
66305b261ecSmrg
66405b261ecSmrg	if (*rootDepthp && *rootDepthp != depth[i].depth)
66505b261ecSmrg	    continue;
66605b261ecSmrg
66705b261ecSmrg	for (j = 0; j < depth[i].numVids; j++)
66805b261ecSmrg	{
66905b261ecSmrg	    for (k = 0; k < nvisual; k++)
67005b261ecSmrg		if (visual[k].vid == depth[i].vids[j])
67105b261ecSmrg		    break;
67205b261ecSmrg	    if (k == nvisual)
67305b261ecSmrg		continue;
67405b261ecSmrg	    if (prefColorVisualClass < 0 ||
67505b261ecSmrg		visual[k].class == prefColorVisualClass)
67605b261ecSmrg		break;
67705b261ecSmrg	}
67805b261ecSmrg	if (j != depth[i].numVids)
67905b261ecSmrg	    break;
68005b261ecSmrg    }
68105b261ecSmrg    if (i == ndepth) {
68205b261ecSmrg	i = 0;
68305b261ecSmrg	j = 0;
68405b261ecSmrg    }
68505b261ecSmrg    *rootDepthp = depth[i].depth;
68605b261ecSmrg    *defaultVisp = depth[i].vids[j];
68705b261ecSmrg    xfree(preferredCVCs);
68805b261ecSmrg
68905b261ecSmrg    return TRUE;
69005b261ecSmrg}
69105b261ecSmrg
69205b261ecSmrgvoid
69305b261ecSmrgmiResetInitVisuals(void)
69405b261ecSmrg{
69505b261ecSmrg    miInitVisualsProc = miDoInitVisuals;
69605b261ecSmrg}
69705b261ecSmrg
698