xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86cmap.c (36353B)


      1 /*
      2  * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Except as contained in this notice, the name of the copyright holder(s)
     23  * and author(s) shall not be used in advertising or otherwise to promote
     24  * the sale, use or other dealings in this Software without prior written
     25  * authorization from the copyright holder(s) and author(s).
     26  */
     27 
     28 #ifdef HAVE_XORG_CONFIG_H
     29 #include <xorg-config.h>
     30 #endif
     31 
     32 #if defined(_XOPEN_SOURCE) || defined(__sun) && defined(__SVR4)
     33 #include <math.h>
     34 #else
     35 #define _XOPEN_SOURCE           /* to get prototype for pow on some systems */
     36 #include <math.h>
     37 #undef _XOPEN_SOURCE
     38 #endif
     39 
     40 #include <X11/X.h>
     41 #include "misc.h"
     42 #include <X11/Xproto.h>
     43 #include "colormapst.h"
     44 #include "scrnintstr.h"
     45 
     46 #include "resource.h"
     47 
     48 #include "xf86.h"
     49 #include "xf86_OSproc.h"
     50 #include "xf86str.h"
     51 #include "micmap.h"
     52 #include "xf86RandR12.h"
     53 #include "xf86Crtc.h"
     54 
     55 #ifdef XFreeXDGA
     56 #include <X11/extensions/xf86dgaproto.h>
     57 #include "dgaproc.h"
     58 #endif
     59 
     60 #include "xf86cmap.h"
     61 
     62 #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
     63     ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field)
     64 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
     65     ((pScreen)->field = wrapper)
     66 
     67 #define LOAD_PALETTE(pmap) \
     68     ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \
     69      ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
     70       xf86ScreenToScrn(pmap->pScreen)->vtSema || pScreenPriv->isDGAmode))
     71 
     72 typedef struct _CMapLink {
     73     ColormapPtr cmap;
     74     struct _CMapLink *next;
     75 } CMapLink, *CMapLinkPtr;
     76 
     77 typedef struct {
     78     CloseScreenProcPtr CloseScreen;
     79     CreateColormapProcPtr CreateColormap;
     80     DestroyColormapProcPtr DestroyColormap;
     81     InstallColormapProcPtr InstallColormap;
     82     StoreColorsProcPtr StoreColors;
     83     Bool (*EnterVT) (ScrnInfoPtr);
     84     Bool (*SwitchMode) (ScrnInfoPtr, DisplayModePtr);
     85     int (*SetDGAMode) (ScrnInfoPtr, int, DGADevicePtr);
     86     xf86ChangeGammaProc *ChangeGamma;
     87     int maxColors;
     88     int sigRGBbits;
     89     int gammaElements;
     90     LOCO *gamma;
     91     int *PreAllocIndices;
     92     CMapLinkPtr maps;
     93     unsigned int flags;
     94     Bool isDGAmode;
     95 } CMapScreenRec, *CMapScreenPtr;
     96 
     97 typedef struct {
     98     int numColors;
     99     LOCO *colors;
    100     Bool recalculate;
    101     int overscan;
    102 } CMapColormapRec, *CMapColormapPtr;
    103 
    104 static DevPrivateKeyRec CMapScreenKeyRec;
    105 
    106 #define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec)
    107 #define CMapScreenKey (&CMapScreenKeyRec)
    108 static DevPrivateKeyRec CMapColormapKeyRec;
    109 
    110 #define CMapColormapKey (&CMapColormapKeyRec)
    111 
    112 static void CMapInstallColormap(ColormapPtr);
    113 static void CMapStoreColors(ColormapPtr, int, xColorItem *);
    114 static Bool CMapCloseScreen(ScreenPtr);
    115 static Bool CMapCreateColormap(ColormapPtr);
    116 static void CMapDestroyColormap(ColormapPtr);
    117 
    118 static Bool CMapEnterVT(ScrnInfoPtr);
    119 static Bool CMapSwitchMode(ScrnInfoPtr, DisplayModePtr);
    120 
    121 #ifdef XFreeXDGA
    122 static int CMapSetDGAMode(ScrnInfoPtr, int, DGADevicePtr);
    123 #endif
    124 static int CMapChangeGamma(ScrnInfoPtr, Gamma);
    125 
    126 static void ComputeGamma(ScrnInfoPtr, CMapScreenPtr);
    127 static Bool CMapAllocateColormapPrivate(ColormapPtr);
    128 static void CMapRefreshColors(ColormapPtr, int, int *);
    129 static void CMapSetOverscan(ColormapPtr, int, int *);
    130 static void CMapReinstallMap(ColormapPtr);
    131 static void CMapUnwrapScreen(ScreenPtr pScreen);
    132 
    133 Bool
    134 xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn)
    135 {
    136     if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0))
    137         return FALSE;
    138 
    139     if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0))
    140         return FALSE;
    141     return TRUE;
    142 }
    143 
    144 Bool
    145 xf86HandleColormaps(ScreenPtr pScreen,
    146                     int maxColors,
    147                     int sigRGBbits,
    148                     xf86LoadPaletteProc * loadPalette,
    149                     xf86SetOverscanProc * setOverscan, unsigned int flags)
    150 {
    151     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    152     ColormapPtr pDefMap = NULL;
    153     CMapScreenPtr pScreenPriv;
    154     LOCO *gamma;
    155     int *indices;
    156     int elements;
    157 
    158     if (!maxColors || !sigRGBbits ||
    159         (!loadPalette && !xf86_crtc_supports_gamma(pScrn)))
    160         return FALSE;
    161 
    162     elements = 1 << sigRGBbits;
    163 
    164     if (!(gamma = xallocarray(elements, sizeof(LOCO))))
    165         return FALSE;
    166 
    167     if (!(indices = xallocarray(maxColors, sizeof(int)))) {
    168         free(gamma);
    169         return FALSE;
    170     }
    171 
    172     if (!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) {
    173         free(gamma);
    174         free(indices);
    175         return FALSE;
    176     }
    177 
    178     dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv);
    179 
    180     pScreenPriv->CloseScreen = pScreen->CloseScreen;
    181     pScreenPriv->CreateColormap = pScreen->CreateColormap;
    182     pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
    183     pScreenPriv->InstallColormap = pScreen->InstallColormap;
    184     pScreenPriv->StoreColors = pScreen->StoreColors;
    185     pScreen->CloseScreen = CMapCloseScreen;
    186     pScreen->CreateColormap = CMapCreateColormap;
    187     pScreen->DestroyColormap = CMapDestroyColormap;
    188     pScreen->InstallColormap = CMapInstallColormap;
    189     pScreen->StoreColors = CMapStoreColors;
    190 
    191     pScrn->LoadPalette = loadPalette;
    192     pScrn->SetOverscan = setOverscan;
    193     pScreenPriv->maxColors = maxColors;
    194     pScreenPriv->sigRGBbits = sigRGBbits;
    195     pScreenPriv->gammaElements = elements;
    196     pScreenPriv->gamma = gamma;
    197     pScreenPriv->PreAllocIndices = indices;
    198     pScreenPriv->maps = NULL;
    199     pScreenPriv->flags = flags;
    200     pScreenPriv->isDGAmode = FALSE;
    201 
    202     pScreenPriv->EnterVT = pScrn->EnterVT;
    203     pScreenPriv->SwitchMode = pScrn->SwitchMode;
    204     pScreenPriv->SetDGAMode = pScrn->SetDGAMode;
    205     pScreenPriv->ChangeGamma = pScrn->ChangeGamma;
    206 
    207     if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) {
    208         pScrn->EnterVT = CMapEnterVT;
    209         if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode)
    210             pScrn->SwitchMode = CMapSwitchMode;
    211     }
    212 #ifdef XFreeXDGA
    213     pScrn->SetDGAMode = CMapSetDGAMode;
    214 #endif
    215     pScrn->ChangeGamma = CMapChangeGamma;
    216 
    217     ComputeGamma(pScrn, pScreenPriv);
    218 
    219     /* get the default map */
    220     dixLookupResourceByType((void **) &pDefMap, pScreen->defColormap,
    221                             RT_COLORMAP, serverClient, DixInstallAccess);
    222 
    223     if (!CMapAllocateColormapPrivate(pDefMap)) {
    224         CMapUnwrapScreen(pScreen);
    225         return FALSE;
    226     }
    227 
    228     if (xf86_crtc_supports_gamma(pScrn)) {
    229         pScrn->LoadPalette = xf86RandR12LoadPalette;
    230 
    231         if (!xf86RandR12InitGamma(pScrn, elements)) {
    232             CMapUnwrapScreen(pScreen);
    233             return FALSE;
    234         }
    235     }
    236 
    237     /* Force the initial map to be loaded */
    238     SetInstalledmiColormap(pScreen, NULL);
    239     CMapInstallColormap(pDefMap);
    240     return TRUE;
    241 }
    242 
    243 /**** Screen functions ****/
    244 
    245 static Bool
    246 CMapCloseScreen(ScreenPtr pScreen)
    247 {
    248     CMapUnwrapScreen(pScreen);
    249 
    250     return (*pScreen->CloseScreen) (pScreen);
    251 }
    252 
    253 static Bool
    254 CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv)
    255 {
    256     if (pVisual->nplanes > 16)
    257         return TRUE;
    258     return ((1 << pVisual->nplanes) > pScreenPriv->maxColors);
    259 }
    260 
    261 static Bool
    262 CMapAllocateColormapPrivate(ColormapPtr pmap)
    263 {
    264     CMapScreenPtr pScreenPriv =
    265         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
    266                                          CMapScreenKey);
    267     CMapColormapPtr pColPriv;
    268     CMapLinkPtr pLink;
    269     int numColors;
    270     LOCO *colors;
    271 
    272     if (CMapColormapUseMax(pmap->pVisual, pScreenPriv))
    273         numColors = pmap->pVisual->ColormapEntries;
    274     else
    275         numColors = 1 << pmap->pVisual->nplanes;
    276 
    277     if (!(colors = xallocarray(numColors, sizeof(LOCO))))
    278         return FALSE;
    279 
    280     if (!(pColPriv = malloc(sizeof(CMapColormapRec)))) {
    281         free(colors);
    282         return FALSE;
    283     }
    284 
    285     dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv);
    286 
    287     pColPriv->numColors = numColors;
    288     pColPriv->colors = colors;
    289     pColPriv->recalculate = TRUE;
    290     pColPriv->overscan = -1;
    291 
    292     /* add map to list */
    293     pLink = malloc(sizeof(CMapLink));
    294     if (pLink) {
    295         pLink->cmap = pmap;
    296         pLink->next = pScreenPriv->maps;
    297         pScreenPriv->maps = pLink;
    298     }
    299 
    300     return TRUE;
    301 }
    302 
    303 static Bool
    304 CMapCreateColormap(ColormapPtr pmap)
    305 {
    306     ScreenPtr pScreen = pmap->pScreen;
    307     CMapScreenPtr pScreenPriv =
    308         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    309     Bool ret = FALSE;
    310 
    311     pScreen->CreateColormap = pScreenPriv->CreateColormap;
    312     if ((*pScreen->CreateColormap) (pmap)) {
    313         if (CMapAllocateColormapPrivate(pmap))
    314             ret = TRUE;
    315     }
    316     pScreen->CreateColormap = CMapCreateColormap;
    317 
    318     return ret;
    319 }
    320 
    321 static void
    322 CMapDestroyColormap(ColormapPtr cmap)
    323 {
    324     ScreenPtr pScreen = cmap->pScreen;
    325     CMapScreenPtr pScreenPriv =
    326         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    327     CMapColormapPtr pColPriv =
    328         (CMapColormapPtr) dixLookupPrivate(&cmap->devPrivates, CMapColormapKey);
    329     CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps;
    330 
    331     if (pColPriv) {
    332         free(pColPriv->colors);
    333         free(pColPriv);
    334     }
    335 
    336     /* remove map from list */
    337     while (pLink) {
    338         if (pLink->cmap == cmap) {
    339             if (prevLink)
    340                 prevLink->next = pLink->next;
    341             else
    342                 pScreenPriv->maps = pLink->next;
    343             free(pLink);
    344             break;
    345         }
    346         prevLink = pLink;
    347         pLink = pLink->next;
    348     }
    349 
    350     if (pScreenPriv->DestroyColormap) {
    351         pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
    352         (*pScreen->DestroyColormap) (cmap);
    353         pScreen->DestroyColormap = CMapDestroyColormap;
    354     }
    355 }
    356 
    357 static void
    358 CMapStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs)
    359 {
    360     ScreenPtr pScreen = pmap->pScreen;
    361     VisualPtr pVisual = pmap->pVisual;
    362     CMapScreenPtr pScreenPriv =
    363         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    364     int *indices = pScreenPriv->PreAllocIndices;
    365     int num = ndef;
    366 
    367     /* At the moment this isn't necessary since there's nobody below us */
    368     pScreen->StoreColors = pScreenPriv->StoreColors;
    369     (*pScreen->StoreColors) (pmap, ndef, pdefs);
    370     pScreen->StoreColors = CMapStoreColors;
    371 
    372     /* should never get here for these */
    373     if ((pVisual->class == TrueColor) ||
    374         (pVisual->class == StaticColor) || (pVisual->class == StaticGray))
    375         return;
    376 
    377     if (pVisual->class == DirectColor) {
    378         CMapColormapPtr pColPriv =
    379             (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates,
    380                                                CMapColormapKey);
    381         int i;
    382 
    383         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
    384             int index;
    385 
    386             num = 0;
    387             while (ndef--) {
    388                 if (pdefs[ndef].flags & DoRed) {
    389                     index = (pdefs[ndef].pixel & pVisual->redMask) >>
    390                         pVisual->offsetRed;
    391                     i = num;
    392                     while (i--)
    393                         if (indices[i] == index)
    394                             break;
    395                     if (i == -1)
    396                         indices[num++] = index;
    397                 }
    398                 if (pdefs[ndef].flags & DoGreen) {
    399                     index = (pdefs[ndef].pixel & pVisual->greenMask) >>
    400                         pVisual->offsetGreen;
    401                     i = num;
    402                     while (i--)
    403                         if (indices[i] == index)
    404                             break;
    405                     if (i == -1)
    406                         indices[num++] = index;
    407                 }
    408                 if (pdefs[ndef].flags & DoBlue) {
    409                     index = (pdefs[ndef].pixel & pVisual->blueMask) >>
    410                         pVisual->offsetBlue;
    411                     i = num;
    412                     while (i--)
    413                         if (indices[i] == index)
    414                             break;
    415                     if (i == -1)
    416                         indices[num++] = index;
    417                 }
    418             }
    419 
    420         }
    421         else {
    422             /* not really as overkill as it seems */
    423             num = pColPriv->numColors;
    424             for (i = 0; i < pColPriv->numColors; i++)
    425                 indices[i] = i;
    426         }
    427     }
    428     else {
    429         while (ndef--)
    430             indices[ndef] = pdefs[ndef].pixel;
    431     }
    432 
    433     CMapRefreshColors(pmap, num, indices);
    434 }
    435 
    436 static void
    437 CMapInstallColormap(ColormapPtr pmap)
    438 {
    439     ScreenPtr pScreen = pmap->pScreen;
    440     CMapScreenPtr pScreenPriv =
    441         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    442 
    443     if (pmap == GetInstalledmiColormap(pmap->pScreen))
    444         return;
    445 
    446     pScreen->InstallColormap = pScreenPriv->InstallColormap;
    447     (*pScreen->InstallColormap) (pmap);
    448     pScreen->InstallColormap = CMapInstallColormap;
    449 
    450     /* Important. We let the lower layers, namely DGA,
    451        overwrite the choice of Colormap to install */
    452     if (GetInstalledmiColormap(pmap->pScreen))
    453         pmap = GetInstalledmiColormap(pmap->pScreen);
    454 
    455     if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
    456         (pmap->pVisual->class == TrueColor) &&
    457         CMapColormapUseMax(pmap->pVisual, pScreenPriv))
    458         return;
    459 
    460     if (LOAD_PALETTE(pmap))
    461         CMapReinstallMap(pmap);
    462 }
    463 
    464 /**** ScrnInfoRec functions ****/
    465 
    466 static Bool
    467 CMapEnterVT(ScrnInfoPtr pScrn)
    468 {
    469     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    470     Bool ret;
    471     CMapScreenPtr pScreenPriv =
    472         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    473 
    474     pScrn->EnterVT = pScreenPriv->EnterVT;
    475     ret = (*pScreenPriv->EnterVT) (pScrn);
    476     pScreenPriv->EnterVT = pScrn->EnterVT;
    477     pScrn->EnterVT = CMapEnterVT;
    478     if (ret) {
    479         if (GetInstalledmiColormap(pScreen))
    480             CMapReinstallMap(GetInstalledmiColormap(pScreen));
    481         return TRUE;
    482     }
    483     return FALSE;
    484 }
    485 
    486 static Bool
    487 CMapSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
    488 {
    489     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    490     CMapScreenPtr pScreenPriv =
    491         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    492 
    493     if ((*pScreenPriv->SwitchMode) (pScrn, mode)) {
    494         if (GetInstalledmiColormap(pScreen))
    495             CMapReinstallMap(GetInstalledmiColormap(pScreen));
    496         return TRUE;
    497     }
    498     return FALSE;
    499 }
    500 
    501 #ifdef XFreeXDGA
    502 static int
    503 CMapSetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr dev)
    504 {
    505     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    506     CMapScreenPtr pScreenPriv =
    507         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    508     int ret;
    509 
    510     ret = (*pScreenPriv->SetDGAMode) (pScrn, num, dev);
    511 
    512     pScreenPriv->isDGAmode = DGAActive(pScrn->scrnIndex);
    513 
    514     if (!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen)
    515         && xf86ScreenToScrn(pScreen)->vtSema)
    516         CMapReinstallMap(GetInstalledmiColormap(pScreen));
    517 
    518     return ret;
    519 }
    520 #endif
    521 
    522 /**** Utilities ****/
    523 
    524 static void
    525 CMapReinstallMap(ColormapPtr pmap)
    526 {
    527     CMapScreenPtr pScreenPriv =
    528         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
    529                                          CMapScreenKey);
    530     CMapColormapPtr cmapPriv =
    531         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
    532     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
    533     int i = cmapPriv->numColors;
    534     int *indices = pScreenPriv->PreAllocIndices;
    535 
    536     while (i--)
    537         indices[i] = i;
    538 
    539     if (cmapPriv->recalculate)
    540         CMapRefreshColors(pmap, cmapPriv->numColors, indices);
    541     else {
    542         (*pScrn->LoadPalette) (pScrn, cmapPriv->numColors,
    543                                indices, cmapPriv->colors, pmap->pVisual);
    544         if (pScrn->SetOverscan) {
    545 #ifdef DEBUGOVERSCAN
    546             ErrorF("SetOverscan() called from CMapReinstallMap\n");
    547 #endif
    548             pScrn->SetOverscan(pScrn, cmapPriv->overscan);
    549         }
    550     }
    551 
    552     cmapPriv->recalculate = FALSE;
    553 }
    554 
    555 static void
    556 CMapRefreshColors(ColormapPtr pmap, int defs, int *indices)
    557 {
    558     CMapScreenPtr pScreenPriv =
    559         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
    560                                          CMapScreenKey);
    561     CMapColormapPtr pColPriv =
    562         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
    563     VisualPtr pVisual = pmap->pVisual;
    564     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
    565     int numColors, i;
    566     LOCO *gamma, *colors;
    567     EntryPtr entry;
    568     int reds, greens, blues, maxValue, index, shift;
    569 
    570     numColors = pColPriv->numColors;
    571     shift = 16 - pScreenPriv->sigRGBbits;
    572     maxValue = (1 << pScreenPriv->sigRGBbits) - 1;
    573     gamma = pScreenPriv->gamma;
    574     colors = pColPriv->colors;
    575 
    576     reds = pVisual->redMask >> pVisual->offsetRed;
    577     greens = pVisual->greenMask >> pVisual->offsetGreen;
    578     blues = pVisual->blueMask >> pVisual->offsetBlue;
    579 
    580     switch (pVisual->class) {
    581     case StaticGray:
    582         for (i = 0; i < numColors; i++) {
    583             index = (i + 1) * maxValue / numColors;
    584             colors[i].red = gamma[index].red;
    585             colors[i].green = gamma[index].green;
    586             colors[i].blue = gamma[index].blue;
    587         }
    588         break;
    589     case TrueColor:
    590         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
    591             for (i = 0; i <= reds; i++)
    592                 colors[i].red = gamma[i * maxValue / reds].red;
    593             for (i = 0; i <= greens; i++)
    594                 colors[i].green = gamma[i * maxValue / greens].green;
    595             for (i = 0; i <= blues; i++)
    596                 colors[i].blue = gamma[i * maxValue / blues].blue;
    597             break;
    598         }
    599         for (i = 0; i < numColors; i++) {
    600             colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) *
    601                                   maxValue / reds].red;
    602             colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) *
    603                                     maxValue / greens].green;
    604             colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) *
    605                                    maxValue / blues].blue;
    606         }
    607         break;
    608     case StaticColor:
    609     case PseudoColor:
    610     case GrayScale:
    611         for (i = 0; i < defs; i++) {
    612             index = indices[i];
    613             entry = (EntryPtr) &pmap->red[index];
    614 
    615             if (entry->fShared) {
    616                 colors[index].red =
    617                     gamma[entry->co.shco.red->color >> shift].red;
    618                 colors[index].green =
    619                     gamma[entry->co.shco.green->color >> shift].green;
    620                 colors[index].blue =
    621                     gamma[entry->co.shco.blue->color >> shift].blue;
    622             }
    623             else {
    624                 colors[index].red = gamma[entry->co.local.red >> shift].red;
    625                 colors[index].green =
    626                     gamma[entry->co.local.green >> shift].green;
    627                 colors[index].blue = gamma[entry->co.local.blue >> shift].blue;
    628             }
    629         }
    630         break;
    631     case DirectColor:
    632         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
    633             for (i = 0; i < defs; i++) {
    634                 index = indices[i];
    635                 if (index <= reds)
    636                     colors[index].red =
    637                         gamma[pmap->red[index].co.local.red >> shift].red;
    638                 if (index <= greens)
    639                     colors[index].green =
    640                         gamma[pmap->green[index].co.local.green >> shift].green;
    641                 if (index <= blues)
    642                     colors[index].blue =
    643                         gamma[pmap->blue[index].co.local.blue >> shift].blue;
    644 
    645             }
    646             break;
    647         }
    648         for (i = 0; i < defs; i++) {
    649             index = indices[i];
    650 
    651             colors[index].red = gamma[pmap->red[(index >> pVisual->
    652                                                  offsetRed) & reds].co.local.
    653                                       red >> shift].red;
    654             colors[index].green =
    655                 gamma[pmap->green[(index >> pVisual->offsetGreen) & greens].co.
    656                       local.green >> shift].green;
    657             colors[index].blue =
    658                 gamma[pmap->blue[(index >> pVisual->offsetBlue) & blues].co.
    659                       local.blue >> shift].blue;
    660         }
    661         break;
    662     }
    663 
    664     if (LOAD_PALETTE(pmap))
    665         (*pScrn->LoadPalette) (pScrn, defs, indices, colors, pmap->pVisual);
    666 
    667     if (pScrn->SetOverscan)
    668         CMapSetOverscan(pmap, defs, indices);
    669 
    670 }
    671 
    672 static Bool
    673 CMapCompareColors(LOCO * color1, LOCO * color2)
    674 {
    675     /* return TRUE if the color1 is "closer" to black than color2 */
    676 #ifdef DEBUGOVERSCAN
    677     ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
    678            color1->red, color1->green, color1->blue,
    679            color2->red, color2->green, color2->blue,
    680            color1->red + color1->green + color1->blue,
    681            color2->red + color2->green + color2->blue);
    682 #endif
    683     return (color1->red + color1->green + color1->blue <
    684             color2->red + color2->green + color2->blue);
    685 }
    686 
    687 static void
    688 CMapSetOverscan(ColormapPtr pmap, int defs, int *indices)
    689 {
    690     CMapScreenPtr pScreenPriv =
    691         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
    692                                          CMapScreenKey);
    693     CMapColormapPtr pColPriv =
    694         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
    695     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
    696     VisualPtr pVisual = pmap->pVisual;
    697     int i;
    698     LOCO *colors;
    699     int index;
    700     Bool newOverscan = FALSE;
    701     int overscan, tmpOverscan;
    702 
    703     colors = pColPriv->colors;
    704     overscan = pColPriv->overscan;
    705 
    706     /*
    707      * Search for a new overscan index in the following cases:
    708      *
    709      *   - The index hasn't yet been initialised.  In this case search
    710      *     for an index that is black or a close match to black.
    711      *
    712      *   - The colour of the old index is changed.  In this case search
    713      *     all indices for a black or close match to black.
    714      *
    715      *   - The colour of the old index wasn't black.  In this case only
    716      *     search the indices that were changed for a better match to black.
    717      */
    718 
    719     switch (pVisual->class) {
    720     case StaticGray:
    721     case TrueColor:
    722         /* Should only come here once.  Initialise the overscan index to 0 */
    723         overscan = 0;
    724         newOverscan = TRUE;
    725         break;
    726     case StaticColor:
    727         /*
    728          * Only come here once, but search for the overscan in the same way
    729          * as for the other cases.
    730          */
    731     case DirectColor:
    732     case PseudoColor:
    733     case GrayScale:
    734         if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) {
    735             /* Uninitialised */
    736             newOverscan = TRUE;
    737         }
    738         else {
    739             /* Check if the overscan was changed */
    740             for (i = 0; i < defs; i++) {
    741                 index = indices[i];
    742                 if (index == overscan) {
    743                     newOverscan = TRUE;
    744                     break;
    745                 }
    746             }
    747         }
    748         if (newOverscan) {
    749             /* The overscan is either uninitialised or it has been changed */
    750 
    751             if (overscan < 0 || overscan > pScreenPriv->maxColors - 1)
    752                 tmpOverscan = pScreenPriv->maxColors - 1;
    753             else
    754                 tmpOverscan = overscan;
    755 
    756             /* search all entries for a close match to black */
    757             for (i = pScreenPriv->maxColors - 1; i >= 0; i--) {
    758                 if (colors[i].red == 0 && colors[i].green == 0 &&
    759                     colors[i].blue == 0) {
    760                     overscan = i;
    761 #ifdef DEBUGOVERSCAN
    762                     ErrorF("Black found at index 0x%02x\n", i);
    763 #endif
    764                     break;
    765                 }
    766                 else {
    767 #ifdef DEBUGOVERSCAN
    768                     ErrorF("0x%02x: ", i);
    769 #endif
    770                     if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) {
    771                         tmpOverscan = i;
    772 #ifdef DEBUGOVERSCAN
    773                         ErrorF("possible \"Black\" at index 0x%02x\n", i);
    774 #endif
    775                     }
    776                 }
    777             }
    778             if (i < 0)
    779                 overscan = tmpOverscan;
    780         }
    781         else {
    782             /* Check of the old overscan wasn't black */
    783             if (colors[overscan].red != 0 || colors[overscan].green != 0 ||
    784                 colors[overscan].blue != 0) {
    785                 int oldOverscan = tmpOverscan = overscan;
    786 
    787                 /* See of there is now a better match */
    788                 for (i = 0; i < defs; i++) {
    789                     index = indices[i];
    790                     if (colors[index].red == 0 && colors[index].green == 0 &&
    791                         colors[index].blue == 0) {
    792                         overscan = index;
    793 #ifdef DEBUGOVERSCAN
    794                         ErrorF("Black found at index 0x%02x\n", index);
    795 #endif
    796                         break;
    797                     }
    798                     else {
    799 #ifdef DEBUGOVERSCAN
    800                         ErrorF("0x%02x: ", index);
    801 #endif
    802                         if (CMapCompareColors(&colors[index],
    803                                               &colors[tmpOverscan])) {
    804                             tmpOverscan = index;
    805 #ifdef DEBUGOVERSCAN
    806                             ErrorF("possible \"Black\" at index 0x%02x\n",
    807                                    index);
    808 #endif
    809                         }
    810                     }
    811                 }
    812                 if (i == defs)
    813                     overscan = tmpOverscan;
    814                 if (overscan != oldOverscan)
    815                     newOverscan = TRUE;
    816             }
    817         }
    818         break;
    819     }
    820     if (newOverscan) {
    821         pColPriv->overscan = overscan;
    822         if (LOAD_PALETTE(pmap)) {
    823 #ifdef DEBUGOVERSCAN
    824             ErrorF("SetOverscan() called from CmapSetOverscan\n");
    825 #endif
    826             pScrn->SetOverscan(pScrn, overscan);
    827         }
    828     }
    829 }
    830 
    831 static void
    832 CMapUnwrapScreen(ScreenPtr pScreen)
    833 {
    834     CMapScreenPtr pScreenPriv =
    835         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
    836     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    837 
    838     pScreen->CloseScreen = pScreenPriv->CloseScreen;
    839     pScreen->CreateColormap = pScreenPriv->CreateColormap;
    840     pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
    841     pScreen->InstallColormap = pScreenPriv->InstallColormap;
    842     pScreen->StoreColors = pScreenPriv->StoreColors;
    843 
    844     pScrn->EnterVT = pScreenPriv->EnterVT;
    845     pScrn->SwitchMode = pScreenPriv->SwitchMode;
    846     pScrn->SetDGAMode = pScreenPriv->SetDGAMode;
    847     pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
    848 
    849     free(pScreenPriv->gamma);
    850     free(pScreenPriv->PreAllocIndices);
    851     free(pScreenPriv);
    852 }
    853 
    854 static void
    855 ComputeGamma(ScrnInfoPtr pScrn, CMapScreenPtr priv)
    856 {
    857     int elements = priv->gammaElements - 1;
    858     double RedGamma, GreenGamma, BlueGamma;
    859     int i;
    860 
    861 #ifndef DONT_CHECK_GAMMA
    862     /* This check is to catch drivers that are not initialising pScrn->gamma */
    863     if (pScrn->gamma.red < GAMMA_MIN || pScrn->gamma.red > GAMMA_MAX ||
    864         pScrn->gamma.green < GAMMA_MIN || pScrn->gamma.green > GAMMA_MAX ||
    865         pScrn->gamma.blue < GAMMA_MIN || pScrn->gamma.blue > GAMMA_MAX) {
    866 
    867         xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0,
    868                        "The %s driver didn't call xf86SetGamma() to initialise\n"
    869                        "\tthe gamma values.\n", pScrn->driverName);
    870         xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0,
    871                        "PLEASE FIX THE `%s' DRIVER!\n",
    872                        pScrn->driverName);
    873         pScrn->gamma.red = 1.0;
    874         pScrn->gamma.green = 1.0;
    875         pScrn->gamma.blue = 1.0;
    876     }
    877 #endif
    878 
    879     RedGamma = 1.0 / (double) pScrn->gamma.red;
    880     GreenGamma = 1.0 / (double) pScrn->gamma.green;
    881     BlueGamma = 1.0 / (double) pScrn->gamma.blue;
    882 
    883     for (i = 0; i <= elements; i++) {
    884         if (RedGamma == 1.0)
    885             priv->gamma[i].red = i;
    886         else
    887             priv->gamma[i].red = (CARD16) (pow((double) i / (double) elements,
    888                                                RedGamma) * (double) elements +
    889                                            0.5);
    890 
    891         if (GreenGamma == 1.0)
    892             priv->gamma[i].green = i;
    893         else
    894             priv->gamma[i].green = (CARD16) (pow((double) i / (double) elements,
    895                                                  GreenGamma) *
    896                                              (double) elements + 0.5);
    897 
    898         if (BlueGamma == 1.0)
    899             priv->gamma[i].blue = i;
    900         else
    901             priv->gamma[i].blue = (CARD16) (pow((double) i / (double) elements,
    902                                                 BlueGamma) * (double) elements +
    903                                             0.5);
    904     }
    905 }
    906 
    907 int
    908 CMapChangeGamma(ScrnInfoPtr pScrn, Gamma gamma)
    909 {
    910     int ret = Success;
    911     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    912     CMapColormapPtr pColPriv;
    913     CMapScreenPtr pScreenPriv;
    914     CMapLinkPtr pLink;
    915 
    916     /* Is this sufficient checking ? */
    917     if (!CMapScreenKeyRegistered)
    918         return BadImplementation;
    919 
    920     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
    921                                                    CMapScreenKey);
    922     if (!pScreenPriv)
    923         return BadImplementation;
    924 
    925     if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX ||
    926         gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX ||
    927         gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX)
    928         return BadValue;
    929 
    930     pScrn->gamma.red = gamma.red;
    931     pScrn->gamma.green = gamma.green;
    932     pScrn->gamma.blue = gamma.blue;
    933 
    934     ComputeGamma(pScrn, pScreenPriv);
    935 
    936     /* mark all colormaps on this screen */
    937     pLink = pScreenPriv->maps;
    938     while (pLink) {
    939         pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates,
    940                                                       CMapColormapKey);
    941         pColPriv->recalculate = TRUE;
    942         pLink = pLink->next;
    943     }
    944 
    945     if (GetInstalledmiColormap(pScreen) &&
    946         ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
    947          pScrn->vtSema || pScreenPriv->isDGAmode)) {
    948         ColormapPtr pMap = GetInstalledmiColormap(pScreen);
    949 
    950         if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
    951             (pMap->pVisual->class == TrueColor) &&
    952             CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
    953 
    954             /* if the current map doesn't have a palette look
    955                for another map to change the gamma on. */
    956 
    957             pLink = pScreenPriv->maps;
    958             while (pLink) {
    959                 if (pLink->cmap->pVisual->class == PseudoColor)
    960                     break;
    961                 pLink = pLink->next;
    962             }
    963 
    964             if (pLink) {
    965                 /* need to trick CMapRefreshColors() into thinking
    966                    this is the currently installed map */
    967                 SetInstalledmiColormap(pScreen, pLink->cmap);
    968                 CMapReinstallMap(pLink->cmap);
    969                 SetInstalledmiColormap(pScreen, pMap);
    970             }
    971         }
    972         else
    973             CMapReinstallMap(pMap);
    974     }
    975 
    976     pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
    977     if (pScrn->ChangeGamma)
    978         ret = pScrn->ChangeGamma(pScrn, gamma);
    979     pScrn->ChangeGamma = CMapChangeGamma;
    980 
    981     return ret;
    982 }
    983 
    984 static void
    985 ComputeGammaRamp(CMapScreenPtr priv,
    986                  unsigned short *red,
    987                  unsigned short *green, unsigned short *blue)
    988 {
    989     int elements = priv->gammaElements;
    990     LOCO *entry = priv->gamma;
    991     int shift = 16 - priv->sigRGBbits;
    992 
    993     while (elements--) {
    994         entry->red = *(red++) >> shift;
    995         entry->green = *(green++) >> shift;
    996         entry->blue = *(blue++) >> shift;
    997         entry++;
    998     }
    999 }
   1000 
   1001 int
   1002 xf86ChangeGammaRamp(ScreenPtr pScreen,
   1003                     int size,
   1004                     unsigned short *red,
   1005                     unsigned short *green, unsigned short *blue)
   1006 {
   1007     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1008     CMapColormapPtr pColPriv;
   1009     CMapScreenPtr pScreenPriv;
   1010     CMapLinkPtr pLink;
   1011 
   1012     if (!CMapScreenKeyRegistered)
   1013         return BadImplementation;
   1014 
   1015     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
   1016                                                    CMapScreenKey);
   1017     if (!pScreenPriv)
   1018         return BadImplementation;
   1019 
   1020     if (pScreenPriv->gammaElements != size)
   1021         return BadValue;
   1022 
   1023     ComputeGammaRamp(pScreenPriv, red, green, blue);
   1024 
   1025     /* mark all colormaps on this screen */
   1026     pLink = pScreenPriv->maps;
   1027     while (pLink) {
   1028         pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates,
   1029                                                       CMapColormapKey);
   1030         pColPriv->recalculate = TRUE;
   1031         pLink = pLink->next;
   1032     }
   1033 
   1034     if (GetInstalledmiColormap(pScreen) &&
   1035         ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
   1036          pScrn->vtSema || pScreenPriv->isDGAmode)) {
   1037         ColormapPtr pMap = GetInstalledmiColormap(pScreen);
   1038 
   1039         if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
   1040             (pMap->pVisual->class == TrueColor) &&
   1041             CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
   1042 
   1043             /* if the current map doesn't have a palette look
   1044                for another map to change the gamma on. */
   1045 
   1046             pLink = pScreenPriv->maps;
   1047             while (pLink) {
   1048                 if (pLink->cmap->pVisual->class == PseudoColor)
   1049                     break;
   1050                 pLink = pLink->next;
   1051             }
   1052 
   1053             if (pLink) {
   1054                 /* need to trick CMapRefreshColors() into thinking
   1055                    this is the currently installed map */
   1056                 SetInstalledmiColormap(pScreen, pLink->cmap);
   1057                 CMapReinstallMap(pLink->cmap);
   1058                 SetInstalledmiColormap(pScreen, pMap);
   1059             }
   1060         }
   1061         else
   1062             CMapReinstallMap(pMap);
   1063     }
   1064 
   1065     return Success;
   1066 }
   1067 
   1068 int
   1069 xf86GetGammaRampSize(ScreenPtr pScreen)
   1070 {
   1071     CMapScreenPtr pScreenPriv;
   1072 
   1073     if (!CMapScreenKeyRegistered)
   1074         return 0;
   1075 
   1076     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
   1077                                                    CMapScreenKey);
   1078     if (!pScreenPriv)
   1079         return 0;
   1080 
   1081     return pScreenPriv->gammaElements;
   1082 }
   1083 
   1084 int
   1085 xf86GetGammaRamp(ScreenPtr pScreen,
   1086                  int size,
   1087                  unsigned short *red,
   1088                  unsigned short *green, unsigned short *blue)
   1089 {
   1090     CMapScreenPtr pScreenPriv;
   1091     LOCO *entry;
   1092     int shift, sigbits;
   1093 
   1094     if (!CMapScreenKeyRegistered)
   1095         return BadImplementation;
   1096 
   1097     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
   1098                                                    CMapScreenKey);
   1099     if (!pScreenPriv)
   1100         return BadImplementation;
   1101 
   1102     if (size > pScreenPriv->gammaElements)
   1103         return BadValue;
   1104 
   1105     entry = pScreenPriv->gamma;
   1106     sigbits = pScreenPriv->sigRGBbits;
   1107 
   1108     while (size--) {
   1109         *red = entry->red << (16 - sigbits);
   1110         *green = entry->green << (16 - sigbits);
   1111         *blue = entry->blue << (16 - sigbits);
   1112         shift = sigbits;
   1113         while (shift < 16) {
   1114             *red |= *red >> shift;
   1115             *green |= *green >> shift;
   1116             *blue |= *blue >> shift;
   1117             shift += sigbits;
   1118         }
   1119         red++;
   1120         green++;
   1121         blue++;
   1122         entry++;
   1123     }
   1124 
   1125     return Success;
   1126 }
   1127 
   1128 int
   1129 xf86ChangeGamma(ScreenPtr pScreen, Gamma gamma)
   1130 {
   1131     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1132 
   1133     if (pScrn->ChangeGamma)
   1134         return (*pScrn->ChangeGamma) (pScrn, gamma);
   1135 
   1136     return BadImplementation;
   1137 }