Edit

IABSD.fr/xenocara/xserver/mi/micmap.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2021-11-11 09:03:02
    Hash : e086cf5a
    Message : Update to xserver 21.1.0

  • xserver/mi/micmap.c
  • /*
     * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved.
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     * DEALINGS IN THE SOFTWARE.
     */
    
    /*
     * This is based on cfbcmap.c.  The functions here are useful independently
     * of cfb, which is the reason for including them here.  How "mi" these
     * are may be debatable.
     */
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include <X11/X.h>
    #include <X11/Xproto.h>
    #include "scrnintstr.h"
    #include "colormapst.h"
    #include "resource.h"
    #include "globals.h"
    #include "micmap.h"
    
    DevPrivateKeyRec micmapScrPrivateKeyRec;
    
    int
    miListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps)
    {
        if (GetInstalledmiColormap(pScreen)) {
            *pmaps = GetInstalledmiColormap(pScreen)->mid;
            return 1;
        }
        return 0;
    }
    
    void
    miInstallColormap(ColormapPtr pmap)
    {
        ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
    
        if (pmap != oldpmap) {
            /* Uninstall pInstalledMap. No hardware changes required, just
             * notify all interested parties. */
            if (oldpmap != (ColormapPtr) None)
                WalkTree(pmap->pScreen, TellLostMap, (char *) &oldpmap->mid);
            /* Install pmap */
            SetInstalledmiColormap(pmap->pScreen, pmap);
            WalkTree(pmap->pScreen, TellGainedMap, (char *) &pmap->mid);
    
        }
    }
    
    void
    miUninstallColormap(ColormapPtr pmap)
    {
        ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen);
    
        if (pmap == curpmap) {
            if (pmap->mid != pmap->pScreen->defColormap) {
                dixLookupResourceByType((void **) &curpmap,
                                        pmap->pScreen->defColormap,
                                        RT_COLORMAP, serverClient, DixUseAccess);
                (*pmap->pScreen->InstallColormap) (curpmap);
            }
        }
    }
    
    void
    miResolveColor(unsigned short *pred, unsigned short *pgreen,
                   unsigned short *pblue, VisualPtr pVisual)
    {
        int shift = 16 - pVisual->bitsPerRGBValue;
        unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
    
        if ((pVisual->class | DynamicClass) == GrayScale) {
            /* rescale to gray then rgb bits */
            *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
            *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
        }
        else {
            /* rescale to rgb bits */
            *pred = ((*pred >> shift) * 65535) / lim;
            *pgreen = ((*pgreen >> shift) * 65535) / lim;
            *pblue = ((*pblue >> shift) * 65535) / lim;
        }
    }
    
    Bool
    miInitializeColormap(ColormapPtr pmap)
    {
        unsigned i;
        VisualPtr pVisual;
        unsigned lim, maxent, shift;
    
        pVisual = pmap->pVisual;
        lim = (1 << pVisual->bitsPerRGBValue) - 1;
        shift = 16 - pVisual->bitsPerRGBValue;
        maxent = pVisual->ColormapEntries - 1;
        if (pVisual->class == TrueColor) {
            unsigned limr, limg, limb;
    
            limr = pVisual->redMask >> pVisual->offsetRed;
            limg = pVisual->greenMask >> pVisual->offsetGreen;
            limb = pVisual->blueMask >> pVisual->offsetBlue;
            for (i = 0; i <= maxent; i++) {
                /* rescale to [0..65535] then rgb bits */
                pmap->red[i].co.local.red =
                    ((((i * 65535) / limr) >> shift) * 65535) / lim;
                pmap->green[i].co.local.green =
                    ((((i * 65535) / limg) >> shift) * 65535) / lim;
                pmap->blue[i].co.local.blue =
                    ((((i * 65535) / limb) >> shift) * 65535) / lim;
            }
        }
        else if (pVisual->class == StaticColor) {
            unsigned limr, limg, limb;
    
            limr = pVisual->redMask >> pVisual->offsetRed;
            limg = pVisual->greenMask >> pVisual->offsetGreen;
            limb = pVisual->blueMask >> pVisual->offsetBlue;
            for (i = 0; i <= maxent; i++) {
                /* rescale to [0..65535] then rgb bits */
                pmap->red[i].co.local.red =
                    ((((((i & pVisual->redMask) >> pVisual->offsetRed)
                        * 65535) / limr) >> shift) * 65535) / lim;
                pmap->red[i].co.local.green =
                    ((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
                        * 65535) / limg) >> shift) * 65535) / lim;
                pmap->red[i].co.local.blue =
                    ((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
                        * 65535) / limb) >> shift) * 65535) / lim;
            }
        }
        else if (pVisual->class == StaticGray) {
            for (i = 0; i <= maxent; i++) {
                /* rescale to [0..65535] then rgb bits */
                pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
                                             * 65535) / lim;
                pmap->red[i].co.local.green = pmap->red[i].co.local.red;
                pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
            }
        }
        return TRUE;
    }
    
    /* When simulating DirectColor on PseudoColor hardware, multiple
       entries of the colormap must be updated
     */
    
    #define AddElement(mask) { \
        pixel = red | green | blue; \
        for (i = 0; i < nresult; i++) \
      	if (outdefs[i].pixel == pixel) \
        	    break; \
        if (i == nresult) \
        { \
       	nresult++; \
    	outdefs[i].pixel = pixel; \
    	outdefs[i].flags = 0; \
        } \
        outdefs[i].flags |= (mask); \
        outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
        outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
        outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
    }
    
    int
    miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem * indefs,
                         xColorItem * outdefs)
    {
        int red, green, blue;
        int maxred, maxgreen, maxblue;
        int stepred, stepgreen, stepblue;
        VisualPtr pVisual;
        int pixel;
        int nresult;
        int i;
    
        pVisual = pmap->pVisual;
    
        stepred = 1 << pVisual->offsetRed;
        stepgreen = 1 << pVisual->offsetGreen;
        stepblue = 1 << pVisual->offsetBlue;
        maxred = pVisual->redMask;
        maxgreen = pVisual->greenMask;
        maxblue = pVisual->blueMask;
        nresult = 0;
        for (; ndef--; indefs++) {
            if (indefs->flags & DoRed) {
                red = indefs->pixel & pVisual->redMask;
                for (green = 0; green <= maxgreen; green += stepgreen) {
                    for (blue = 0; blue <= maxblue; blue += stepblue) {
                        AddElement(DoRed)
                    }
                }
            }
            if (indefs->flags & DoGreen) {
                green = indefs->pixel & pVisual->greenMask;
                for (red = 0; red <= maxred; red += stepred) {
                    for (blue = 0; blue <= maxblue; blue += stepblue) {
                        AddElement(DoGreen)
                    }
                }
            }
            if (indefs->flags & DoBlue) {
                blue = indefs->pixel & pVisual->blueMask;
                for (red = 0; red <= maxred; red += stepred) {
                    for (green = 0; green <= maxgreen; green += stepgreen) {
                        AddElement(DoBlue)
                    }
                }
            }
        }
        return nresult;
    }
    
    Bool
    miCreateDefColormap(ScreenPtr pScreen)
    {
        unsigned short zero = 0, ones = 0xFFFF;
        Pixel wp, bp;
        VisualPtr pVisual;
        ColormapPtr cmap;
        int alloctype;
    
        if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
            return FALSE;
    
        for (pVisual = pScreen->visuals;
             pVisual->vid != pScreen->rootVisual; pVisual++);
    
        if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
            alloctype = AllocNone;
        else
            alloctype = AllocAll;
    
        if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
                           alloctype, 0) != Success)
            return FALSE;
    
        if (pScreen->rootDepth > 1) {
            wp = pScreen->whitePixel;
            bp = pScreen->blackPixel;
            if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
                 Success) ||
                (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != Success))
                return FALSE;
            pScreen->whitePixel = wp;
            pScreen->blackPixel = bp;
        }
    
        (*pScreen->InstallColormap) (cmap);
        return TRUE;
    }
    
    /*
     * Default true color bitmasks, should be overridden by
     * driver
     */
    
    #define _RZ(d) ((d + 2) / 3)
    #define _RS(d) 0
    #define _RM(d) ((1U << _RZ(d)) - 1)
    #define _GZ(d) ((d - _RZ(d) + 1) / 2)
    #define _GS(d) _RZ(d)
    #define _GM(d) (((1U << _GZ(d)) - 1) << _GS(d))
    #define _BZ(d) (d - _RZ(d) - _GZ(d))
    #define _BS(d) (_RZ(d) + _GZ(d))
    #define _BM(d) (((1U << _BZ(d)) - 1) << _BS(d))
    #define _CE(d) (1U << _RZ(d))
    
    typedef struct _miVisuals {
        struct _miVisuals *next;
        int depth;
        int bitsPerRGB;
        int visuals;
        int count;
        int preferredCVC;
        Pixel redMask, greenMask, blueMask;
    } miVisualsRec, *miVisualsPtr;
    
    static int miVisualPriority[] = {
        PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
    };
    
    #define NUM_PRIORITY	6
    
    static miVisualsPtr miVisuals;
    
    void
    miClearVisualTypes(void)
    {
        miVisualsPtr v;
    
        while ((v = miVisuals)) {
            miVisuals = v->next;
            free(v);
        }
    }
    
    Bool
    miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
                             int preferredCVC,
                             Pixel redMask, Pixel greenMask, Pixel blueMask)
    {
        miVisualsPtr new, *prev, v;
        int count;
    
        new = malloc(sizeof *new);
        if (!new)
            return FALSE;
        if (!redMask || !greenMask || !blueMask) {
            redMask = _RM(depth);
            greenMask = _GM(depth);
            blueMask = _BM(depth);
        }
        new->next = 0;
        new->depth = depth;
        new->visuals = visuals;
        new->bitsPerRGB = bitsPerRGB;
        new->preferredCVC = preferredCVC;
        new->redMask = redMask;
        new->greenMask = greenMask;
        new->blueMask = blueMask;
        count = (visuals >> 1) & 033333333333;
        count = visuals - count - ((count >> 1) & 033333333333);
        count = (((count + (count >> 3)) & 030707070707) % 077);    /* HAKMEM 169 */
        new->count = count;
        for (prev = &miVisuals; (v = *prev); prev = &v->next);
        *prev = new;
        return TRUE;
    }
    
    Bool
    miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
    {
        return miSetVisualTypesAndMasks(depth, visuals, bitsPerRGB,
                                        preferredCVC, 0, 0, 0);
    }
    
    int
    miGetDefaultVisualMask(int depth)
    {
        if (depth > MAX_PSEUDO_DEPTH)
            return LARGE_VISUALS;
        else if (depth >= MIN_TRUE_DEPTH)
            return ALL_VISUALS;
        else if (depth == 1)
            return StaticGrayMask;
        else
            return SMALL_VISUALS;
    }
    
    static Bool
    miVisualTypesSet(int depth)
    {
        miVisualsPtr visuals;
    
        for (visuals = miVisuals; visuals; visuals = visuals->next)
            if (visuals->depth == depth)
                return TRUE;
        return FALSE;
    }
    
    Bool
    miSetPixmapDepths(void)
    {
        int d, f;
    
        /* Add any unlisted depths from the pixmap formats */
        for (f = 0; f < screenInfo.numPixmapFormats; f++) {
            d = screenInfo.formats[f].depth;
            if (!miVisualTypesSet(d)) {
                if (!miSetVisualTypes(d, 0, 0, -1))
                    return FALSE;
            }
        }
        return TRUE;
    }
    
    /*
     * Distance to least significant one bit
     */
    static int
    maskShift(Pixel p)
    {
        int s;
    
        if (!p)
            return 0;
        s = 0;
        while (!(p & 1)) {
            s++;
            p >>= 1;
        }
        return s;
    }
    
    /*
     * Given a list of formats for a screen, create a list
     * of visuals and depths for the screen which correspond to
     * the set which can be used with this version of cfb.
     */
    
    Bool
    miInitVisuals(VisualPtr * visualp, DepthPtr * depthp, int *nvisualp,
                  int *ndepthp, int *rootDepthp, VisualID * defaultVisp,
                  unsigned long sizes, int bitsPerRGB, int preferredVis)
    {
        int i, j = 0, k;
        VisualPtr visual;
        DepthPtr depth;
        VisualID *vid;
        int d, b;
        int f;
        int ndepth, nvisual;
        int nvtype;
        int vtype;
        miVisualsPtr visuals, nextVisuals;
        int *preferredCVCs, *prefp;
        int first_depth;
    
        /* none specified, we'll guess from pixmap formats */
        if (!miVisuals) {
            for (f = 0; f < screenInfo.numPixmapFormats; f++) {
                d = screenInfo.formats[f].depth;
                b = screenInfo.formats[f].bitsPerPixel;
                if (sizes & (1 << (b - 1)))
                    vtype = miGetDefaultVisualMask(d);
                else
                    vtype = 0;
                if (!miSetVisualTypes(d, vtype, bitsPerRGB, -1))
                    return FALSE;
            }
        }
        nvisual = 0;
        ndepth = 0;
        for (visuals = miVisuals; visuals; visuals = nextVisuals) {
            nextVisuals = visuals->next;
            ndepth++;
            nvisual += visuals->count;
        }
        depth = xallocarray(ndepth, sizeof(DepthRec));
        visual = xallocarray(nvisual, sizeof(VisualRec));
        preferredCVCs = xallocarray(ndepth, sizeof(int));
        if (!depth || !visual || !preferredCVCs) {
            free(depth);
            free(visual);
            free(preferredCVCs);
            return FALSE;
        }
        *depthp = depth;
        *visualp = visual;
        *ndepthp = ndepth;
        *nvisualp = nvisual;
        prefp = preferredCVCs;
        for (visuals = miVisuals; visuals; visuals = nextVisuals) {
            nextVisuals = visuals->next;
            d = visuals->depth;
            vtype = visuals->visuals;
            nvtype = visuals->count;
            *prefp = visuals->preferredCVC;
            prefp++;
            vid = NULL;
            if (nvtype) {
                vid = xallocarray(nvtype, sizeof(VisualID));
                if (!vid) {
                    free(depth);
                    free(visual);
                    free(preferredCVCs);
                    return FALSE;
                }
            }
            depth->depth = d;
            depth->numVids = nvtype;
            depth->vids = vid;
            depth++;
            for (i = 0; i < NUM_PRIORITY; i++) {
                if (!(vtype & (1 << miVisualPriority[i])))
                    continue;
                visual->class = miVisualPriority[i];
                visual->bitsPerRGBValue = visuals->bitsPerRGB;
                visual->ColormapEntries = 1 << d;
                visual->nplanes = d;
                visual->vid = *vid = FakeClientID(0);
                switch (visual->class) {
                case PseudoColor:
                case GrayScale:
                case StaticGray:
                    visual->redMask = 0;
                    visual->greenMask = 0;
                    visual->blueMask = 0;
                    visual->offsetRed = 0;
                    visual->offsetGreen = 0;
                    visual->offsetBlue = 0;
                    break;
                case DirectColor:
                case TrueColor:
                    visual->ColormapEntries = _CE(d);
                    /* fall through */
                case StaticColor:
                    visual->redMask = visuals->redMask;
                    visual->greenMask = visuals->greenMask;
                    visual->blueMask = visuals->blueMask;
                    visual->offsetRed = maskShift(visuals->redMask);
                    visual->offsetGreen = maskShift(visuals->greenMask);
                    visual->offsetBlue = maskShift(visuals->blueMask);
                }
                vid++;
                visual++;
            }
            free(visuals);
        }
        miVisuals = NULL;
        visual = *visualp;
        depth = *depthp;
    
        /*
         * if we did not supplyied by a preferred visual class
         * check if there is a preferred class in one of the depth
         * structures - if there is, we want to start looking for the
         * default visual/depth from that depth.
         */
        first_depth = 0;
        if (preferredVis < 0 && defaultColorVisualClass < 0) {
            for (i = 0; i < ndepth; i++) {
                if (preferredCVCs[i] >= 0) {
                    first_depth = i;
                    break;
                }
            }
        }
    
        for (i = first_depth; i < ndepth; i++) {
            int prefColorVisualClass = -1;
    
            if (defaultColorVisualClass >= 0)
                prefColorVisualClass = defaultColorVisualClass;
            else if (preferredVis >= 0)
                prefColorVisualClass = preferredVis;
            else if (preferredCVCs[i] >= 0)
                prefColorVisualClass = preferredCVCs[i];
    
            if (*rootDepthp && *rootDepthp != depth[i].depth)
                continue;
    
            for (j = 0; j < depth[i].numVids; j++) {
                for (k = 0; k < nvisual; k++)
                    if (visual[k].vid == depth[i].vids[j])
                        break;
                if (k == nvisual)
                    continue;
                if (prefColorVisualClass < 0 ||
                    visual[k].class == prefColorVisualClass)
                    break;
            }
            if (j != depth[i].numVids)
                break;
        }
        if (i == ndepth) {
            i = 0;
            j = 0;
        }
        *rootDepthp = depth[i].depth;
        *defaultVisp = depth[i].vids[j];
        free(preferredCVCs);
    
        return TRUE;
    }