16747b715Smrg/*
29ace9065Smrg * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved.
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
226747b715Smrg */
2305b261ecSmrg
2405b261ecSmrg/*
2505b261ecSmrg * This is based on cfbcmap.c.  The functions here are useful independently
2605b261ecSmrg * of cfb, which is the reason for including them here.  How "mi" these
2705b261ecSmrg * are may be debatable.
2805b261ecSmrg */
2905b261ecSmrg
3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3105b261ecSmrg#include <dix-config.h>
3205b261ecSmrg#endif
3305b261ecSmrg
3405b261ecSmrg#include <X11/X.h>
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include "scrnintstr.h"
3705b261ecSmrg#include "colormapst.h"
3805b261ecSmrg#include "resource.h"
3905b261ecSmrg#include "globals.h"
4005b261ecSmrg#include "micmap.h"
4105b261ecSmrg
426747b715SmrgDevPrivateKeyRec micmapScrPrivateKeyRec;
4305b261ecSmrg
446747b715Smrgint
4535c4bbdfSmrgmiListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps)
4605b261ecSmrg{
476747b715Smrg    if (GetInstalledmiColormap(pScreen)) {
4835c4bbdfSmrg        *pmaps = GetInstalledmiColormap(pScreen)->mid;
4935c4bbdfSmrg        return 1;
5005b261ecSmrg    }
5105b261ecSmrg    return 0;
5205b261ecSmrg}
5305b261ecSmrg
546747b715Smrgvoid
5505b261ecSmrgmiInstallColormap(ColormapPtr pmap)
5605b261ecSmrg{
576747b715Smrg    ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
5805b261ecSmrg
5935c4bbdfSmrg    if (pmap != oldpmap) {
6035c4bbdfSmrg        /* Uninstall pInstalledMap. No hardware changes required, just
6135c4bbdfSmrg         * notify all interested parties. */
6235c4bbdfSmrg        if (oldpmap != (ColormapPtr) None)
6335c4bbdfSmrg            WalkTree(pmap->pScreen, TellLostMap, (char *) &oldpmap->mid);
6435c4bbdfSmrg        /* Install pmap */
6535c4bbdfSmrg        SetInstalledmiColormap(pmap->pScreen, pmap);
6635c4bbdfSmrg        WalkTree(pmap->pScreen, TellGainedMap, (char *) &pmap->mid);
6705b261ecSmrg
6805b261ecSmrg    }
6905b261ecSmrg}
7005b261ecSmrg
716747b715Smrgvoid
7205b261ecSmrgmiUninstallColormap(ColormapPtr pmap)
7305b261ecSmrg{
746747b715Smrg    ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen);
7505b261ecSmrg
7635c4bbdfSmrg    if (pmap == curpmap) {
7735c4bbdfSmrg        if (pmap->mid != pmap->pScreen->defColormap) {
7835c4bbdfSmrg            dixLookupResourceByType((void **) &curpmap,
7935c4bbdfSmrg                                    pmap->pScreen->defColormap,
8035c4bbdfSmrg                                    RT_COLORMAP, serverClient, DixUseAccess);
8135c4bbdfSmrg            (*pmap->pScreen->InstallColormap) (curpmap);
8235c4bbdfSmrg        }
8305b261ecSmrg    }
8405b261ecSmrg}
8505b261ecSmrg
866747b715Smrgvoid
8705b261ecSmrgmiResolveColor(unsigned short *pred, unsigned short *pgreen,
8835c4bbdfSmrg               unsigned short *pblue, VisualPtr pVisual)
8905b261ecSmrg{
9005b261ecSmrg    int shift = 16 - pVisual->bitsPerRGBValue;
9105b261ecSmrg    unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
9205b261ecSmrg
9335c4bbdfSmrg    if ((pVisual->class | DynamicClass) == GrayScale) {
9435c4bbdfSmrg        /* rescale to gray then rgb bits */
9535c4bbdfSmrg        *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
9635c4bbdfSmrg        *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
9705b261ecSmrg    }
9835c4bbdfSmrg    else {
9935c4bbdfSmrg        /* rescale to rgb bits */
10035c4bbdfSmrg        *pred = ((*pred >> shift) * 65535) / lim;
10135c4bbdfSmrg        *pgreen = ((*pgreen >> shift) * 65535) / lim;
10235c4bbdfSmrg        *pblue = ((*pblue >> shift) * 65535) / lim;
10305b261ecSmrg    }
10405b261ecSmrg}
10505b261ecSmrg
1066747b715SmrgBool
10705b261ecSmrgmiInitializeColormap(ColormapPtr pmap)
10805b261ecSmrg{
10905b261ecSmrg    unsigned i;
11005b261ecSmrg    VisualPtr pVisual;
11105b261ecSmrg    unsigned lim, maxent, shift;
11205b261ecSmrg
11305b261ecSmrg    pVisual = pmap->pVisual;
11405b261ecSmrg    lim = (1 << pVisual->bitsPerRGBValue) - 1;
11505b261ecSmrg    shift = 16 - pVisual->bitsPerRGBValue;
11605b261ecSmrg    maxent = pVisual->ColormapEntries - 1;
11735c4bbdfSmrg    if (pVisual->class == TrueColor) {
11835c4bbdfSmrg        unsigned limr, limg, limb;
11935c4bbdfSmrg
12035c4bbdfSmrg        limr = pVisual->redMask >> pVisual->offsetRed;
12135c4bbdfSmrg        limg = pVisual->greenMask >> pVisual->offsetGreen;
12235c4bbdfSmrg        limb = pVisual->blueMask >> pVisual->offsetBlue;
12335c4bbdfSmrg        for (i = 0; i <= maxent; i++) {
12435c4bbdfSmrg            /* rescale to [0..65535] then rgb bits */
12535c4bbdfSmrg            pmap->red[i].co.local.red =
12635c4bbdfSmrg                ((((i * 65535) / limr) >> shift) * 65535) / lim;
12735c4bbdfSmrg            pmap->green[i].co.local.green =
12835c4bbdfSmrg                ((((i * 65535) / limg) >> shift) * 65535) / lim;
12935c4bbdfSmrg            pmap->blue[i].co.local.blue =
13035c4bbdfSmrg                ((((i * 65535) / limb) >> shift) * 65535) / lim;
13135c4bbdfSmrg        }
13205b261ecSmrg    }
13335c4bbdfSmrg    else if (pVisual->class == StaticColor) {
13435c4bbdfSmrg        unsigned limr, limg, limb;
13535c4bbdfSmrg
13635c4bbdfSmrg        limr = pVisual->redMask >> pVisual->offsetRed;
13735c4bbdfSmrg        limg = pVisual->greenMask >> pVisual->offsetGreen;
13835c4bbdfSmrg        limb = pVisual->blueMask >> pVisual->offsetBlue;
13935c4bbdfSmrg        for (i = 0; i <= maxent; i++) {
14035c4bbdfSmrg            /* rescale to [0..65535] then rgb bits */
14135c4bbdfSmrg            pmap->red[i].co.local.red =
14235c4bbdfSmrg                ((((((i & pVisual->redMask) >> pVisual->offsetRed)
14335c4bbdfSmrg                    * 65535) / limr) >> shift) * 65535) / lim;
14435c4bbdfSmrg            pmap->red[i].co.local.green =
14535c4bbdfSmrg                ((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
14635c4bbdfSmrg                    * 65535) / limg) >> shift) * 65535) / lim;
14735c4bbdfSmrg            pmap->red[i].co.local.blue =
14835c4bbdfSmrg                ((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
14935c4bbdfSmrg                    * 65535) / limb) >> shift) * 65535) / lim;
15035c4bbdfSmrg        }
15105b261ecSmrg    }
15235c4bbdfSmrg    else if (pVisual->class == StaticGray) {
15335c4bbdfSmrg        for (i = 0; i <= maxent; i++) {
15435c4bbdfSmrg            /* rescale to [0..65535] then rgb bits */
15535c4bbdfSmrg            pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
15635c4bbdfSmrg                                         * 65535) / lim;
15735c4bbdfSmrg            pmap->red[i].co.local.green = pmap->red[i].co.local.red;
15835c4bbdfSmrg            pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
15935c4bbdfSmrg        }
16005b261ecSmrg    }
16105b261ecSmrg    return TRUE;
16205b261ecSmrg}
16305b261ecSmrg
16405b261ecSmrg/* When simulating DirectColor on PseudoColor hardware, multiple
16505b261ecSmrg   entries of the colormap must be updated
16605b261ecSmrg */
16705b261ecSmrg
16805b261ecSmrg#define AddElement(mask) { \
16905b261ecSmrg    pixel = red | green | blue; \
17005b261ecSmrg    for (i = 0; i < nresult; i++) \
17105b261ecSmrg  	if (outdefs[i].pixel == pixel) \
17205b261ecSmrg    	    break; \
17305b261ecSmrg    if (i == nresult) \
17405b261ecSmrg    { \
17505b261ecSmrg   	nresult++; \
17605b261ecSmrg	outdefs[i].pixel = pixel; \
17705b261ecSmrg	outdefs[i].flags = 0; \
17805b261ecSmrg    } \
17905b261ecSmrg    outdefs[i].flags |= (mask); \
18005b261ecSmrg    outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
18105b261ecSmrg    outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
18205b261ecSmrg    outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
18305b261ecSmrg}
18405b261ecSmrg
1856747b715Smrgint
18635c4bbdfSmrgmiExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem * indefs,
18735c4bbdfSmrg                     xColorItem * outdefs)
18805b261ecSmrg{
18935c4bbdfSmrg    int red, green, blue;
19035c4bbdfSmrg    int maxred, maxgreen, maxblue;
19135c4bbdfSmrg    int stepred, stepgreen, stepblue;
19235c4bbdfSmrg    VisualPtr pVisual;
19335c4bbdfSmrg    int pixel;
19435c4bbdfSmrg    int nresult;
19535c4bbdfSmrg    int i;
19605b261ecSmrg
19705b261ecSmrg    pVisual = pmap->pVisual;
19805b261ecSmrg
19905b261ecSmrg    stepred = 1 << pVisual->offsetRed;
20005b261ecSmrg    stepgreen = 1 << pVisual->offsetGreen;
20105b261ecSmrg    stepblue = 1 << pVisual->offsetBlue;
20205b261ecSmrg    maxred = pVisual->redMask;
20305b261ecSmrg    maxgreen = pVisual->greenMask;
20405b261ecSmrg    maxblue = pVisual->blueMask;
20505b261ecSmrg    nresult = 0;
20635c4bbdfSmrg    for (; ndef--; indefs++) {
20735c4bbdfSmrg        if (indefs->flags & DoRed) {
20835c4bbdfSmrg            red = indefs->pixel & pVisual->redMask;
20935c4bbdfSmrg            for (green = 0; green <= maxgreen; green += stepgreen) {
21035c4bbdfSmrg                for (blue = 0; blue <= maxblue; blue += stepblue) {
21135c4bbdfSmrg                    AddElement(DoRed)
21235c4bbdfSmrg                }
21335c4bbdfSmrg            }
21435c4bbdfSmrg        }
21535c4bbdfSmrg        if (indefs->flags & DoGreen) {
21635c4bbdfSmrg            green = indefs->pixel & pVisual->greenMask;
21735c4bbdfSmrg            for (red = 0; red <= maxred; red += stepred) {
21835c4bbdfSmrg                for (blue = 0; blue <= maxblue; blue += stepblue) {
21935c4bbdfSmrg                    AddElement(DoGreen)
22035c4bbdfSmrg                }
22135c4bbdfSmrg            }
22235c4bbdfSmrg        }
22335c4bbdfSmrg        if (indefs->flags & DoBlue) {
22435c4bbdfSmrg            blue = indefs->pixel & pVisual->blueMask;
22535c4bbdfSmrg            for (red = 0; red <= maxred; red += stepred) {
22635c4bbdfSmrg                for (green = 0; green <= maxgreen; green += stepgreen) {
22735c4bbdfSmrg                    AddElement(DoBlue)
22835c4bbdfSmrg                }
22935c4bbdfSmrg            }
23035c4bbdfSmrg        }
23105b261ecSmrg    }
23205b261ecSmrg    return nresult;
23305b261ecSmrg}
23405b261ecSmrg
2356747b715SmrgBool
23605b261ecSmrgmiCreateDefColormap(ScreenPtr pScreen)
23705b261ecSmrg{
23835c4bbdfSmrg    unsigned short zero = 0, ones = 0xFFFF;
23905b261ecSmrg    Pixel wp, bp;
24035c4bbdfSmrg    VisualPtr pVisual;
24135c4bbdfSmrg    ColormapPtr cmap;
24205b261ecSmrg    int alloctype;
24335c4bbdfSmrg
2446747b715Smrg    if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
24535c4bbdfSmrg        return FALSE;
2466747b715Smrg
24705b261ecSmrg    for (pVisual = pScreen->visuals;
24835c4bbdfSmrg         pVisual->vid != pScreen->rootVisual; pVisual++);
24905b261ecSmrg
25005b261ecSmrg    if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
25135c4bbdfSmrg        alloctype = AllocNone;
25205b261ecSmrg    else
25335c4bbdfSmrg        alloctype = AllocAll;
25405b261ecSmrg
25505b261ecSmrg    if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
25635c4bbdfSmrg                       alloctype, 0) != Success)
25735c4bbdfSmrg        return FALSE;
25805b261ecSmrg
25905b261ecSmrg    if (pScreen->rootDepth > 1) {
26035c4bbdfSmrg        wp = pScreen->whitePixel;
26135c4bbdfSmrg        bp = pScreen->blackPixel;
26235c4bbdfSmrg        if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
26335c4bbdfSmrg             Success) ||
26435c4bbdfSmrg            (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != Success))
26535c4bbdfSmrg            return FALSE;
26635c4bbdfSmrg        pScreen->whitePixel = wp;
26735c4bbdfSmrg        pScreen->blackPixel = bp;
26805b261ecSmrg    }
26905b261ecSmrg
27035c4bbdfSmrg    (*pScreen->InstallColormap) (cmap);
27105b261ecSmrg    return TRUE;
27205b261ecSmrg}
27305b261ecSmrg
27405b261ecSmrg/*
27505b261ecSmrg * Default true color bitmasks, should be overridden by
27605b261ecSmrg * driver
27705b261ecSmrg */
27805b261ecSmrg
27905b261ecSmrg#define _RZ(d) ((d + 2) / 3)
28005b261ecSmrg#define _RS(d) 0
281ed6184dfSmrg#define _RM(d) ((1U << _RZ(d)) - 1)
28205b261ecSmrg#define _GZ(d) ((d - _RZ(d) + 1) / 2)
28305b261ecSmrg#define _GS(d) _RZ(d)
284ed6184dfSmrg#define _GM(d) (((1U << _GZ(d)) - 1) << _GS(d))
28505b261ecSmrg#define _BZ(d) (d - _RZ(d) - _GZ(d))
28605b261ecSmrg#define _BS(d) (_RZ(d) + _GZ(d))
287ed6184dfSmrg#define _BM(d) (((1U << _BZ(d)) - 1) << _BS(d))
288ed6184dfSmrg#define _CE(d) (1U << _RZ(d))
28905b261ecSmrg
29005b261ecSmrgtypedef struct _miVisuals {
29135c4bbdfSmrg    struct _miVisuals *next;
29235c4bbdfSmrg    int depth;
29335c4bbdfSmrg    int bitsPerRGB;
29435c4bbdfSmrg    int visuals;
29535c4bbdfSmrg    int count;
29635c4bbdfSmrg    int preferredCVC;
29735c4bbdfSmrg    Pixel redMask, greenMask, blueMask;
29805b261ecSmrg} miVisualsRec, *miVisualsPtr;
29905b261ecSmrg
30035c4bbdfSmrgstatic int miVisualPriority[] = {
30105b261ecSmrg    PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
30205b261ecSmrg};
30305b261ecSmrg
30405b261ecSmrg#define NUM_PRIORITY	6
30505b261ecSmrg
30635c4bbdfSmrgstatic miVisualsPtr miVisuals;
30705b261ecSmrg
3086747b715Smrgvoid
30905b261ecSmrgmiClearVisualTypes(void)
31005b261ecSmrg{
31105b261ecSmrg    miVisualsPtr v;
31205b261ecSmrg
31305b261ecSmrg    while ((v = miVisuals)) {
31435c4bbdfSmrg        miVisuals = v->next;
31535c4bbdfSmrg        free(v);
31605b261ecSmrg    }
31705b261ecSmrg}
31805b261ecSmrg
3196747b715SmrgBool
32035c4bbdfSmrgmiSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
32135c4bbdfSmrg                         int preferredCVC,
32235c4bbdfSmrg                         Pixel redMask, Pixel greenMask, Pixel blueMask)
32305b261ecSmrg{
32435c4bbdfSmrg    miVisualsPtr new, *prev, v;
32535c4bbdfSmrg    int count;
32605b261ecSmrg
3276747b715Smrg    new = malloc(sizeof *new);
32805b261ecSmrg    if (!new)
32935c4bbdfSmrg        return FALSE;
33035c4bbdfSmrg    if (!redMask || !greenMask || !blueMask) {
33135c4bbdfSmrg        redMask = _RM(depth);
33235c4bbdfSmrg        greenMask = _GM(depth);
33335c4bbdfSmrg        blueMask = _BM(depth);
33405b261ecSmrg    }
33505b261ecSmrg    new->next = 0;
33605b261ecSmrg    new->depth = depth;
33705b261ecSmrg    new->visuals = visuals;
33805b261ecSmrg    new->bitsPerRGB = bitsPerRGB;
33905b261ecSmrg    new->preferredCVC = preferredCVC;
34005b261ecSmrg    new->redMask = redMask;
34105b261ecSmrg    new->greenMask = greenMask;
34205b261ecSmrg    new->blueMask = blueMask;
34305b261ecSmrg    count = (visuals >> 1) & 033333333333;
34405b261ecSmrg    count = visuals - count - ((count >> 1) & 033333333333);
34535c4bbdfSmrg    count = (((count + (count >> 3)) & 030707070707) % 077);    /* HAKMEM 169 */
34605b261ecSmrg    new->count = count;
34705b261ecSmrg    for (prev = &miVisuals; (v = *prev); prev = &v->next);
34805b261ecSmrg    *prev = new;
34905b261ecSmrg    return TRUE;
35005b261ecSmrg}
35105b261ecSmrg
3526747b715SmrgBool
35305b261ecSmrgmiSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
35405b261ecSmrg{
35535c4bbdfSmrg    return miSetVisualTypesAndMasks(depth, visuals, bitsPerRGB,
35635c4bbdfSmrg                                    preferredCVC, 0, 0, 0);
35705b261ecSmrg}
35805b261ecSmrg
3596747b715Smrgint
36005b261ecSmrgmiGetDefaultVisualMask(int depth)
36105b261ecSmrg{
36205b261ecSmrg    if (depth > MAX_PSEUDO_DEPTH)
36335c4bbdfSmrg        return LARGE_VISUALS;
36405b261ecSmrg    else if (depth >= MIN_TRUE_DEPTH)
36535c4bbdfSmrg        return ALL_VISUALS;
36605b261ecSmrg    else if (depth == 1)
36735c4bbdfSmrg        return StaticGrayMask;
36805b261ecSmrg    else
36935c4bbdfSmrg        return SMALL_VISUALS;
37005b261ecSmrg}
37105b261ecSmrg
37205b261ecSmrgstatic Bool
37335c4bbdfSmrgmiVisualTypesSet(int depth)
37405b261ecSmrg{
37535c4bbdfSmrg    miVisualsPtr visuals;
37605b261ecSmrg
37705b261ecSmrg    for (visuals = miVisuals; visuals; visuals = visuals->next)
37835c4bbdfSmrg        if (visuals->depth == depth)
37935c4bbdfSmrg            return TRUE;
38005b261ecSmrg    return FALSE;
38105b261ecSmrg}
38205b261ecSmrg
3836747b715SmrgBool
38435c4bbdfSmrgmiSetPixmapDepths(void)
38505b261ecSmrg{
38635c4bbdfSmrg    int d, f;
38735c4bbdfSmrg
38805b261ecSmrg    /* Add any unlisted depths from the pixmap formats */
38935c4bbdfSmrg    for (f = 0; f < screenInfo.numPixmapFormats; f++) {
39035c4bbdfSmrg        d = screenInfo.formats[f].depth;
39135c4bbdfSmrg        if (!miVisualTypesSet(d)) {
39235c4bbdfSmrg            if (!miSetVisualTypes(d, 0, 0, -1))
39335c4bbdfSmrg                return FALSE;
39435c4bbdfSmrg        }
39505b261ecSmrg    }
39605b261ecSmrg    return TRUE;
39705b261ecSmrg}
39805b261ecSmrg
39905b261ecSmrg/*
40005b261ecSmrg * Distance to least significant one bit
40105b261ecSmrg */
40205b261ecSmrgstatic int
40335c4bbdfSmrgmaskShift(Pixel p)
40405b261ecSmrg{
40535c4bbdfSmrg    int s;
40605b261ecSmrg
40735c4bbdfSmrg    if (!p)
40835c4bbdfSmrg        return 0;
40905b261ecSmrg    s = 0;
41035c4bbdfSmrg    while (!(p & 1)) {
41135c4bbdfSmrg        s++;
41235c4bbdfSmrg        p >>= 1;
41305b261ecSmrg    }
41405b261ecSmrg    return s;
41505b261ecSmrg}
41605b261ecSmrg
41705b261ecSmrg/*
41805b261ecSmrg * Given a list of formats for a screen, create a list
419ed6184dfSmrg * of visuals and depths for the screen which correspond to
42005b261ecSmrg * the set which can be used with this version of cfb.
42105b261ecSmrg */
42205b261ecSmrg
4236747b715SmrgBool
42435c4bbdfSmrgmiInitVisuals(VisualPtr * visualp, DepthPtr * depthp, int *nvisualp,
42535c4bbdfSmrg              int *ndepthp, int *rootDepthp, VisualID * defaultVisp,
42635c4bbdfSmrg              unsigned long sizes, int bitsPerRGB, int preferredVis)
42705b261ecSmrg{
42835c4bbdfSmrg    int i, j = 0, k;
42935c4bbdfSmrg    VisualPtr visual;
43035c4bbdfSmrg    DepthPtr depth;
43135c4bbdfSmrg    VisualID *vid;
43235c4bbdfSmrg    int d, b;
43335c4bbdfSmrg    int f;
43435c4bbdfSmrg    int ndepth, nvisual;
43535c4bbdfSmrg    int nvtype;
43635c4bbdfSmrg    int vtype;
43735c4bbdfSmrg    miVisualsPtr visuals, nextVisuals;
43835c4bbdfSmrg    int *preferredCVCs, *prefp;
43935c4bbdfSmrg    int first_depth;
44005b261ecSmrg
44105b261ecSmrg    /* none specified, we'll guess from pixmap formats */
44235c4bbdfSmrg    if (!miVisuals) {
44335c4bbdfSmrg        for (f = 0; f < screenInfo.numPixmapFormats; f++) {
44435c4bbdfSmrg            d = screenInfo.formats[f].depth;
44535c4bbdfSmrg            b = screenInfo.formats[f].bitsPerPixel;
44635c4bbdfSmrg            if (sizes & (1 << (b - 1)))
44735c4bbdfSmrg                vtype = miGetDefaultVisualMask(d);
44835c4bbdfSmrg            else
44935c4bbdfSmrg                vtype = 0;
45035c4bbdfSmrg            if (!miSetVisualTypes(d, vtype, bitsPerRGB, -1))
45135c4bbdfSmrg                return FALSE;
45235c4bbdfSmrg        }
45305b261ecSmrg    }
45405b261ecSmrg    nvisual = 0;
45505b261ecSmrg    ndepth = 0;
45635c4bbdfSmrg    for (visuals = miVisuals; visuals; visuals = nextVisuals) {
45735c4bbdfSmrg        nextVisuals = visuals->next;
45835c4bbdfSmrg        ndepth++;
45935c4bbdfSmrg        nvisual += visuals->count;
46005b261ecSmrg    }
46135c4bbdfSmrg    depth = xallocarray(ndepth, sizeof(DepthRec));
46235c4bbdfSmrg    visual = xallocarray(nvisual, sizeof(VisualRec));
46335c4bbdfSmrg    preferredCVCs = xallocarray(ndepth, sizeof(int));
46435c4bbdfSmrg    if (!depth || !visual || !preferredCVCs) {
46535c4bbdfSmrg        free(depth);
46635c4bbdfSmrg        free(visual);
46735c4bbdfSmrg        free(preferredCVCs);
46835c4bbdfSmrg        return FALSE;
46905b261ecSmrg    }
47005b261ecSmrg    *depthp = depth;
47105b261ecSmrg    *visualp = visual;
47205b261ecSmrg    *ndepthp = ndepth;
47305b261ecSmrg    *nvisualp = nvisual;
47405b261ecSmrg    prefp = preferredCVCs;
47535c4bbdfSmrg    for (visuals = miVisuals; visuals; visuals = nextVisuals) {
47635c4bbdfSmrg        nextVisuals = visuals->next;
47735c4bbdfSmrg        d = visuals->depth;
47835c4bbdfSmrg        vtype = visuals->visuals;
47935c4bbdfSmrg        nvtype = visuals->count;
48035c4bbdfSmrg        *prefp = visuals->preferredCVC;
48135c4bbdfSmrg        prefp++;
48235c4bbdfSmrg        vid = NULL;
48335c4bbdfSmrg        if (nvtype) {
48435c4bbdfSmrg            vid = xallocarray(nvtype, sizeof(VisualID));
48535c4bbdfSmrg            if (!vid) {
48635c4bbdfSmrg                free(depth);
48735c4bbdfSmrg                free(visual);
48835c4bbdfSmrg                free(preferredCVCs);
48935c4bbdfSmrg                return FALSE;
49035c4bbdfSmrg            }
49135c4bbdfSmrg        }
49235c4bbdfSmrg        depth->depth = d;
49335c4bbdfSmrg        depth->numVids = nvtype;
49435c4bbdfSmrg        depth->vids = vid;
49535c4bbdfSmrg        depth++;
49635c4bbdfSmrg        for (i = 0; i < NUM_PRIORITY; i++) {
49735c4bbdfSmrg            if (!(vtype & (1 << miVisualPriority[i])))
49835c4bbdfSmrg                continue;
49935c4bbdfSmrg            visual->class = miVisualPriority[i];
50035c4bbdfSmrg            visual->bitsPerRGBValue = visuals->bitsPerRGB;
50135c4bbdfSmrg            visual->ColormapEntries = 1 << d;
50235c4bbdfSmrg            visual->nplanes = d;
50335c4bbdfSmrg            visual->vid = *vid = FakeClientID(0);
50435c4bbdfSmrg            switch (visual->class) {
50535c4bbdfSmrg            case PseudoColor:
50635c4bbdfSmrg            case GrayScale:
50735c4bbdfSmrg            case StaticGray:
50835c4bbdfSmrg                visual->redMask = 0;
50935c4bbdfSmrg                visual->greenMask = 0;
51035c4bbdfSmrg                visual->blueMask = 0;
51135c4bbdfSmrg                visual->offsetRed = 0;
51235c4bbdfSmrg                visual->offsetGreen = 0;
51335c4bbdfSmrg                visual->offsetBlue = 0;
51435c4bbdfSmrg                break;
51535c4bbdfSmrg            case DirectColor:
51635c4bbdfSmrg            case TrueColor:
51735c4bbdfSmrg                visual->ColormapEntries = _CE(d);
51835c4bbdfSmrg                /* fall through */
51935c4bbdfSmrg            case StaticColor:
52035c4bbdfSmrg                visual->redMask = visuals->redMask;
52135c4bbdfSmrg                visual->greenMask = visuals->greenMask;
52235c4bbdfSmrg                visual->blueMask = visuals->blueMask;
52335c4bbdfSmrg                visual->offsetRed = maskShift(visuals->redMask);
52435c4bbdfSmrg                visual->offsetGreen = maskShift(visuals->greenMask);
52535c4bbdfSmrg                visual->offsetBlue = maskShift(visuals->blueMask);
52635c4bbdfSmrg            }
52735c4bbdfSmrg            vid++;
52835c4bbdfSmrg            visual++;
52935c4bbdfSmrg        }
53035c4bbdfSmrg        free(visuals);
53105b261ecSmrg    }
53205b261ecSmrg    miVisuals = NULL;
53305b261ecSmrg    visual = *visualp;
53405b261ecSmrg    depth = *depthp;
53505b261ecSmrg
53605b261ecSmrg    /*
53705b261ecSmrg     * if we did not supplyied by a preferred visual class
53805b261ecSmrg     * check if there is a preferred class in one of the depth
53905b261ecSmrg     * structures - if there is, we want to start looking for the
54005b261ecSmrg     * default visual/depth from that depth.
54105b261ecSmrg     */
54205b261ecSmrg    first_depth = 0;
54335c4bbdfSmrg    if (preferredVis < 0 && defaultColorVisualClass < 0) {
54435c4bbdfSmrg        for (i = 0; i < ndepth; i++) {
54535c4bbdfSmrg            if (preferredCVCs[i] >= 0) {
54635c4bbdfSmrg                first_depth = i;
54735c4bbdfSmrg                break;
54835c4bbdfSmrg            }
54935c4bbdfSmrg        }
55005b261ecSmrg    }
55105b261ecSmrg
55235c4bbdfSmrg    for (i = first_depth; i < ndepth; i++) {
55335c4bbdfSmrg        int prefColorVisualClass = -1;
55435c4bbdfSmrg
55535c4bbdfSmrg        if (defaultColorVisualClass >= 0)
55635c4bbdfSmrg            prefColorVisualClass = defaultColorVisualClass;
55735c4bbdfSmrg        else if (preferredVis >= 0)
55835c4bbdfSmrg            prefColorVisualClass = preferredVis;
55935c4bbdfSmrg        else if (preferredCVCs[i] >= 0)
56035c4bbdfSmrg            prefColorVisualClass = preferredCVCs[i];
56135c4bbdfSmrg
56235c4bbdfSmrg        if (*rootDepthp && *rootDepthp != depth[i].depth)
56335c4bbdfSmrg            continue;
56435c4bbdfSmrg
56535c4bbdfSmrg        for (j = 0; j < depth[i].numVids; j++) {
56635c4bbdfSmrg            for (k = 0; k < nvisual; k++)
56735c4bbdfSmrg                if (visual[k].vid == depth[i].vids[j])
56835c4bbdfSmrg                    break;
56935c4bbdfSmrg            if (k == nvisual)
57035c4bbdfSmrg                continue;
57135c4bbdfSmrg            if (prefColorVisualClass < 0 ||
57235c4bbdfSmrg                visual[k].class == prefColorVisualClass)
57335c4bbdfSmrg                break;
57435c4bbdfSmrg        }
57535c4bbdfSmrg        if (j != depth[i].numVids)
57635c4bbdfSmrg            break;
57705b261ecSmrg    }
57805b261ecSmrg    if (i == ndepth) {
57935c4bbdfSmrg        i = 0;
58035c4bbdfSmrg        j = 0;
58105b261ecSmrg    }
58205b261ecSmrg    *rootDepthp = depth[i].depth;
58305b261ecSmrg    *defaultVisp = depth[i].vids[j];
5846747b715Smrg    free(preferredCVCs);
58505b261ecSmrg
58605b261ecSmrg    return TRUE;
58705b261ecSmrg}
588