1138 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1138 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | ||
|  * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
 | ||
|  *
 | ||
|  * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
 | ||
|  *
 | ||
|  * Except as contained in this notice, the name of the copyright holder(s)
 | ||
|  * and author(s) shall not be used in advertising or otherwise to promote
 | ||
|  * the sale, use or other dealings in this Software without prior written
 | ||
|  * authorization from the copyright holder(s) and author(s).
 | ||
|  */
 | ||
| 
 | ||
| #ifdef HAVE_XORG_CONFIG_H
 | ||
| #include <xorg-config.h>
 | ||
| #endif
 | ||
| 
 | ||
| #if defined(_XOPEN_SOURCE) || defined(__sun) && defined(__SVR4)
 | ||
| #include <math.h>
 | ||
| #else
 | ||
| #define _XOPEN_SOURCE           /* to get prototype for pow on some systems */
 | ||
| #include <math.h>
 | ||
| #undef _XOPEN_SOURCE
 | ||
| #endif
 | ||
| 
 | ||
| #include <X11/X.h>
 | ||
| #include "misc.h"
 | ||
| #include <X11/Xproto.h>
 | ||
| #include "colormapst.h"
 | ||
| #include "scrnintstr.h"
 | ||
| 
 | ||
| #include "resource.h"
 | ||
| 
 | ||
| #include "xf86.h"
 | ||
| #include "xf86_OSproc.h"
 | ||
| #include "xf86str.h"
 | ||
| #include "micmap.h"
 | ||
| #include "xf86RandR12.h"
 | ||
| #include "xf86Crtc.h"
 | ||
| 
 | ||
| #ifdef XFreeXDGA
 | ||
| #include <X11/extensions/xf86dgaproto.h>
 | ||
| #include "dgaproc.h"
 | ||
| #endif
 | ||
| 
 | ||
| #include "xf86cmap.h"
 | ||
| 
 | ||
| #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
 | ||
|     ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field)
 | ||
| #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
 | ||
|     ((pScreen)->field = wrapper)
 | ||
| 
 | ||
| #define LOAD_PALETTE(pmap) \
 | ||
|     ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \
 | ||
|      ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
 | ||
|       xf86ScreenToScrn(pmap->pScreen)->vtSema || pScreenPriv->isDGAmode))
 | ||
| 
 | ||
| typedef struct _CMapLink {
 | ||
|     ColormapPtr cmap;
 | ||
|     struct _CMapLink *next;
 | ||
| } CMapLink, *CMapLinkPtr;
 | ||
| 
 | ||
| typedef struct {
 | ||
|     CloseScreenProcPtr CloseScreen;
 | ||
|     CreateColormapProcPtr CreateColormap;
 | ||
|     DestroyColormapProcPtr DestroyColormap;
 | ||
|     InstallColormapProcPtr InstallColormap;
 | ||
|     StoreColorsProcPtr StoreColors;
 | ||
|     Bool (*EnterVT) (ScrnInfoPtr);
 | ||
|     Bool (*SwitchMode) (ScrnInfoPtr, DisplayModePtr);
 | ||
|     int (*SetDGAMode) (ScrnInfoPtr, int, DGADevicePtr);
 | ||
|     xf86ChangeGammaProc *ChangeGamma;
 | ||
|     int maxColors;
 | ||
|     int sigRGBbits;
 | ||
|     int gammaElements;
 | ||
|     LOCO *gamma;
 | ||
|     int *PreAllocIndices;
 | ||
|     CMapLinkPtr maps;
 | ||
|     unsigned int flags;
 | ||
|     Bool isDGAmode;
 | ||
| } CMapScreenRec, *CMapScreenPtr;
 | ||
| 
 | ||
| typedef struct {
 | ||
|     int numColors;
 | ||
|     LOCO *colors;
 | ||
|     Bool recalculate;
 | ||
|     int overscan;
 | ||
| } CMapColormapRec, *CMapColormapPtr;
 | ||
| 
 | ||
| static DevPrivateKeyRec CMapScreenKeyRec;
 | ||
| 
 | ||
| #define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec)
 | ||
| #define CMapScreenKey (&CMapScreenKeyRec)
 | ||
| static DevPrivateKeyRec CMapColormapKeyRec;
 | ||
| 
 | ||
| #define CMapColormapKey (&CMapColormapKeyRec)
 | ||
| 
 | ||
| static void CMapInstallColormap(ColormapPtr);
 | ||
| static void CMapStoreColors(ColormapPtr, int, xColorItem *);
 | ||
| static Bool CMapCloseScreen(ScreenPtr);
 | ||
| static Bool CMapCreateColormap(ColormapPtr);
 | ||
| static void CMapDestroyColormap(ColormapPtr);
 | ||
| 
 | ||
| static Bool CMapEnterVT(ScrnInfoPtr);
 | ||
| static Bool CMapSwitchMode(ScrnInfoPtr, DisplayModePtr);
 | ||
| 
 | ||
| #ifdef XFreeXDGA
 | ||
| static int CMapSetDGAMode(ScrnInfoPtr, int, DGADevicePtr);
 | ||
| #endif
 | ||
| static int CMapChangeGamma(ScrnInfoPtr, Gamma);
 | ||
| 
 | ||
| static void ComputeGamma(ScrnInfoPtr, CMapScreenPtr);
 | ||
| static Bool CMapAllocateColormapPrivate(ColormapPtr);
 | ||
| static void CMapRefreshColors(ColormapPtr, int, int *);
 | ||
| static void CMapSetOverscan(ColormapPtr, int, int *);
 | ||
| static void CMapReinstallMap(ColormapPtr);
 | ||
| static void CMapUnwrapScreen(ScreenPtr pScreen);
 | ||
| 
 | ||
| Bool
 | ||
| xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn)
 | ||
| {
 | ||
|     if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0))
 | ||
|         return FALSE;
 | ||
| 
 | ||
|     if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0))
 | ||
|         return FALSE;
 | ||
|     return TRUE;
 | ||
| }
 | ||
| 
 | ||
| Bool
 | ||
| xf86HandleColormaps(ScreenPtr pScreen,
 | ||
|                     int maxColors,
 | ||
|                     int sigRGBbits,
 | ||
|                     xf86LoadPaletteProc * loadPalette,
 | ||
|                     xf86SetOverscanProc * setOverscan, unsigned int flags)
 | ||
| {
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | ||
|     ColormapPtr pDefMap = NULL;
 | ||
|     CMapScreenPtr pScreenPriv;
 | ||
|     LOCO *gamma;
 | ||
|     int *indices;
 | ||
|     int elements;
 | ||
| 
 | ||
|     if (!maxColors || !sigRGBbits ||
 | ||
|         (!loadPalette && !xf86_crtc_supports_gamma(pScrn)))
 | ||
|         return FALSE;
 | ||
| 
 | ||
|     elements = 1 << sigRGBbits;
 | ||
| 
 | ||
|     if (!(gamma = xallocarray(elements, sizeof(LOCO))))
 | ||
|         return FALSE;
 | ||
| 
 | ||
|     if (!(indices = xallocarray(maxColors, sizeof(int)))) {
 | ||
|         free(gamma);
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     if (!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) {
 | ||
|         free(gamma);
 | ||
|         free(indices);
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv);
 | ||
| 
 | ||
|     pScreenPriv->CloseScreen = pScreen->CloseScreen;
 | ||
|     pScreenPriv->CreateColormap = pScreen->CreateColormap;
 | ||
|     pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
 | ||
|     pScreenPriv->InstallColormap = pScreen->InstallColormap;
 | ||
|     pScreenPriv->StoreColors = pScreen->StoreColors;
 | ||
|     pScreen->CloseScreen = CMapCloseScreen;
 | ||
|     pScreen->CreateColormap = CMapCreateColormap;
 | ||
|     pScreen->DestroyColormap = CMapDestroyColormap;
 | ||
|     pScreen->InstallColormap = CMapInstallColormap;
 | ||
|     pScreen->StoreColors = CMapStoreColors;
 | ||
| 
 | ||
|     pScrn->LoadPalette = loadPalette;
 | ||
|     pScrn->SetOverscan = setOverscan;
 | ||
|     pScreenPriv->maxColors = maxColors;
 | ||
|     pScreenPriv->sigRGBbits = sigRGBbits;
 | ||
|     pScreenPriv->gammaElements = elements;
 | ||
|     pScreenPriv->gamma = gamma;
 | ||
|     pScreenPriv->PreAllocIndices = indices;
 | ||
|     pScreenPriv->maps = NULL;
 | ||
|     pScreenPriv->flags = flags;
 | ||
|     pScreenPriv->isDGAmode = FALSE;
 | ||
| 
 | ||
|     pScreenPriv->EnterVT = pScrn->EnterVT;
 | ||
|     pScreenPriv->SwitchMode = pScrn->SwitchMode;
 | ||
|     pScreenPriv->SetDGAMode = pScrn->SetDGAMode;
 | ||
|     pScreenPriv->ChangeGamma = pScrn->ChangeGamma;
 | ||
| 
 | ||
|     if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) {
 | ||
|         pScrn->EnterVT = CMapEnterVT;
 | ||
|         if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode)
 | ||
|             pScrn->SwitchMode = CMapSwitchMode;
 | ||
|     }
 | ||
| #ifdef XFreeXDGA
 | ||
|     pScrn->SetDGAMode = CMapSetDGAMode;
 | ||
| #endif
 | ||
|     pScrn->ChangeGamma = CMapChangeGamma;
 | ||
| 
 | ||
|     ComputeGamma(pScrn, pScreenPriv);
 | ||
| 
 | ||
|     /* get the default map */
 | ||
|     dixLookupResourceByType((void **) &pDefMap, pScreen->defColormap,
 | ||
|                             RT_COLORMAP, serverClient, DixInstallAccess);
 | ||
| 
 | ||
|     if (!CMapAllocateColormapPrivate(pDefMap)) {
 | ||
|         CMapUnwrapScreen(pScreen);
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     if (xf86_crtc_supports_gamma(pScrn)) {
 | ||
|         pScrn->LoadPalette = xf86RandR12LoadPalette;
 | ||
| 
 | ||
|         if (!xf86RandR12InitGamma(pScrn, elements)) {
 | ||
|             CMapUnwrapScreen(pScreen);
 | ||
|             return FALSE;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /* Force the initial map to be loaded */
 | ||
|     SetInstalledmiColormap(pScreen, NULL);
 | ||
|     CMapInstallColormap(pDefMap);
 | ||
|     return TRUE;
 | ||
| }
 | ||
| 
 | ||
| /**** Screen functions ****/
 | ||
| 
 | ||
| static Bool
 | ||
| CMapCloseScreen(ScreenPtr pScreen)
 | ||
| {
 | ||
|     CMapUnwrapScreen(pScreen);
 | ||
| 
 | ||
|     return (*pScreen->CloseScreen) (pScreen);
 | ||
| }
 | ||
| 
 | ||
| static Bool
 | ||
| CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv)
 | ||
| {
 | ||
|     if (pVisual->nplanes > 16)
 | ||
|         return TRUE;
 | ||
|     return ((1 << pVisual->nplanes) > pScreenPriv->maxColors);
 | ||
| }
 | ||
| 
 | ||
| static Bool
 | ||
| CMapAllocateColormapPrivate(ColormapPtr pmap)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
 | ||
|                                          CMapScreenKey);
 | ||
|     CMapColormapPtr pColPriv;
 | ||
|     CMapLinkPtr pLink;
 | ||
|     int numColors;
 | ||
|     LOCO *colors;
 | ||
| 
 | ||
|     if (CMapColormapUseMax(pmap->pVisual, pScreenPriv))
 | ||
|         numColors = pmap->pVisual->ColormapEntries;
 | ||
|     else
 | ||
|         numColors = 1 << pmap->pVisual->nplanes;
 | ||
| 
 | ||
|     if (!(colors = xallocarray(numColors, sizeof(LOCO))))
 | ||
|         return FALSE;
 | ||
| 
 | ||
|     if (!(pColPriv = malloc(sizeof(CMapColormapRec)))) {
 | ||
|         free(colors);
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv);
 | ||
| 
 | ||
|     pColPriv->numColors = numColors;
 | ||
|     pColPriv->colors = colors;
 | ||
|     pColPriv->recalculate = TRUE;
 | ||
|     pColPriv->overscan = -1;
 | ||
| 
 | ||
|     /* add map to list */
 | ||
|     pLink = malloc(sizeof(CMapLink));
 | ||
|     if (pLink) {
 | ||
|         pLink->cmap = pmap;
 | ||
|         pLink->next = pScreenPriv->maps;
 | ||
|         pScreenPriv->maps = pLink;
 | ||
|     }
 | ||
| 
 | ||
|     return TRUE;
 | ||
| }
 | ||
| 
 | ||
| static Bool
 | ||
| CMapCreateColormap(ColormapPtr pmap)
 | ||
| {
 | ||
|     ScreenPtr pScreen = pmap->pScreen;
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
|     Bool ret = FALSE;
 | ||
| 
 | ||
|     pScreen->CreateColormap = pScreenPriv->CreateColormap;
 | ||
|     if ((*pScreen->CreateColormap) (pmap)) {
 | ||
|         if (CMapAllocateColormapPrivate(pmap))
 | ||
|             ret = TRUE;
 | ||
|     }
 | ||
|     pScreen->CreateColormap = CMapCreateColormap;
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapDestroyColormap(ColormapPtr cmap)
 | ||
| {
 | ||
|     ScreenPtr pScreen = cmap->pScreen;
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
|     CMapColormapPtr pColPriv =
 | ||
|         (CMapColormapPtr) dixLookupPrivate(&cmap->devPrivates, CMapColormapKey);
 | ||
|     CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps;
 | ||
| 
 | ||
|     if (pColPriv) {
 | ||
|         free(pColPriv->colors);
 | ||
|         free(pColPriv);
 | ||
|     }
 | ||
| 
 | ||
|     /* remove map from list */
 | ||
|     while (pLink) {
 | ||
|         if (pLink->cmap == cmap) {
 | ||
|             if (prevLink)
 | ||
|                 prevLink->next = pLink->next;
 | ||
|             else
 | ||
|                 pScreenPriv->maps = pLink->next;
 | ||
|             free(pLink);
 | ||
|             break;
 | ||
|         }
 | ||
|         prevLink = pLink;
 | ||
|         pLink = pLink->next;
 | ||
|     }
 | ||
| 
 | ||
|     if (pScreenPriv->DestroyColormap) {
 | ||
|         pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
 | ||
|         (*pScreen->DestroyColormap) (cmap);
 | ||
|         pScreen->DestroyColormap = CMapDestroyColormap;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs)
 | ||
| {
 | ||
|     ScreenPtr pScreen = pmap->pScreen;
 | ||
|     VisualPtr pVisual = pmap->pVisual;
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
|     int *indices = pScreenPriv->PreAllocIndices;
 | ||
|     int num = ndef;
 | ||
| 
 | ||
|     /* At the moment this isn't necessary since there's nobody below us */
 | ||
|     pScreen->StoreColors = pScreenPriv->StoreColors;
 | ||
|     (*pScreen->StoreColors) (pmap, ndef, pdefs);
 | ||
|     pScreen->StoreColors = CMapStoreColors;
 | ||
| 
 | ||
|     /* should never get here for these */
 | ||
|     if ((pVisual->class == TrueColor) ||
 | ||
|         (pVisual->class == StaticColor) || (pVisual->class == StaticGray))
 | ||
|         return;
 | ||
| 
 | ||
|     if (pVisual->class == DirectColor) {
 | ||
|         CMapColormapPtr pColPriv =
 | ||
|             (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates,
 | ||
|                                                CMapColormapKey);
 | ||
|         int i;
 | ||
| 
 | ||
|         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
 | ||
|             int index;
 | ||
| 
 | ||
|             num = 0;
 | ||
|             while (ndef--) {
 | ||
|                 if (pdefs[ndef].flags & DoRed) {
 | ||
|                     index = (pdefs[ndef].pixel & pVisual->redMask) >>
 | ||
|                         pVisual->offsetRed;
 | ||
|                     i = num;
 | ||
|                     while (i--)
 | ||
|                         if (indices[i] == index)
 | ||
|                             break;
 | ||
|                     if (i == -1)
 | ||
|                         indices[num++] = index;
 | ||
|                 }
 | ||
|                 if (pdefs[ndef].flags & DoGreen) {
 | ||
|                     index = (pdefs[ndef].pixel & pVisual->greenMask) >>
 | ||
|                         pVisual->offsetGreen;
 | ||
|                     i = num;
 | ||
|                     while (i--)
 | ||
|                         if (indices[i] == index)
 | ||
|                             break;
 | ||
|                     if (i == -1)
 | ||
|                         indices[num++] = index;
 | ||
|                 }
 | ||
|                 if (pdefs[ndef].flags & DoBlue) {
 | ||
|                     index = (pdefs[ndef].pixel & pVisual->blueMask) >>
 | ||
|                         pVisual->offsetBlue;
 | ||
|                     i = num;
 | ||
|                     while (i--)
 | ||
|                         if (indices[i] == index)
 | ||
|                             break;
 | ||
|                     if (i == -1)
 | ||
|                         indices[num++] = index;
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|         }
 | ||
|         else {
 | ||
|             /* not really as overkill as it seems */
 | ||
|             num = pColPriv->numColors;
 | ||
|             for (i = 0; i < pColPriv->numColors; i++)
 | ||
|                 indices[i] = i;
 | ||
|         }
 | ||
|     }
 | ||
|     else {
 | ||
|         while (ndef--)
 | ||
|             indices[ndef] = pdefs[ndef].pixel;
 | ||
|     }
 | ||
| 
 | ||
|     CMapRefreshColors(pmap, num, indices);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapInstallColormap(ColormapPtr pmap)
 | ||
| {
 | ||
|     ScreenPtr pScreen = pmap->pScreen;
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
| 
 | ||
|     if (pmap == GetInstalledmiColormap(pmap->pScreen))
 | ||
|         return;
 | ||
| 
 | ||
|     pScreen->InstallColormap = pScreenPriv->InstallColormap;
 | ||
|     (*pScreen->InstallColormap) (pmap);
 | ||
|     pScreen->InstallColormap = CMapInstallColormap;
 | ||
| 
 | ||
|     /* Important. We let the lower layers, namely DGA,
 | ||
|        overwrite the choice of Colormap to install */
 | ||
|     if (GetInstalledmiColormap(pmap->pScreen))
 | ||
|         pmap = GetInstalledmiColormap(pmap->pScreen);
 | ||
| 
 | ||
|     if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
 | ||
|         (pmap->pVisual->class == TrueColor) &&
 | ||
|         CMapColormapUseMax(pmap->pVisual, pScreenPriv))
 | ||
|         return;
 | ||
| 
 | ||
|     if (LOAD_PALETTE(pmap))
 | ||
|         CMapReinstallMap(pmap);
 | ||
| }
 | ||
| 
 | ||
| /**** ScrnInfoRec functions ****/
 | ||
| 
 | ||
| static Bool
 | ||
| CMapEnterVT(ScrnInfoPtr pScrn)
 | ||
| {
 | ||
|     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 | ||
|     Bool ret;
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
| 
 | ||
|     pScrn->EnterVT = pScreenPriv->EnterVT;
 | ||
|     ret = (*pScreenPriv->EnterVT) (pScrn);
 | ||
|     pScreenPriv->EnterVT = pScrn->EnterVT;
 | ||
|     pScrn->EnterVT = CMapEnterVT;
 | ||
|     if (ret) {
 | ||
|         if (GetInstalledmiColormap(pScreen))
 | ||
|             CMapReinstallMap(GetInstalledmiColormap(pScreen));
 | ||
|         return TRUE;
 | ||
|     }
 | ||
|     return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static Bool
 | ||
| CMapSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
 | ||
| {
 | ||
|     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
| 
 | ||
|     if ((*pScreenPriv->SwitchMode) (pScrn, mode)) {
 | ||
|         if (GetInstalledmiColormap(pScreen))
 | ||
|             CMapReinstallMap(GetInstalledmiColormap(pScreen));
 | ||
|         return TRUE;
 | ||
|     }
 | ||
|     return FALSE;
 | ||
| }
 | ||
| 
 | ||
| #ifdef XFreeXDGA
 | ||
| static int
 | ||
| CMapSetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr dev)
 | ||
| {
 | ||
|     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
|     int ret;
 | ||
| 
 | ||
|     ret = (*pScreenPriv->SetDGAMode) (pScrn, num, dev);
 | ||
| 
 | ||
|     pScreenPriv->isDGAmode = DGAActive(pScrn->scrnIndex);
 | ||
| 
 | ||
|     if (!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen)
 | ||
|         && xf86ScreenToScrn(pScreen)->vtSema)
 | ||
|         CMapReinstallMap(GetInstalledmiColormap(pScreen));
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| #endif
 | ||
| 
 | ||
| /**** Utilities ****/
 | ||
| 
 | ||
| static void
 | ||
| CMapReinstallMap(ColormapPtr pmap)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
 | ||
|                                          CMapScreenKey);
 | ||
|     CMapColormapPtr cmapPriv =
 | ||
|         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
 | ||
|     int i = cmapPriv->numColors;
 | ||
|     int *indices = pScreenPriv->PreAllocIndices;
 | ||
| 
 | ||
|     while (i--)
 | ||
|         indices[i] = i;
 | ||
| 
 | ||
|     if (cmapPriv->recalculate)
 | ||
|         CMapRefreshColors(pmap, cmapPriv->numColors, indices);
 | ||
|     else {
 | ||
|         (*pScrn->LoadPalette) (pScrn, cmapPriv->numColors,
 | ||
|                                indices, cmapPriv->colors, pmap->pVisual);
 | ||
|         if (pScrn->SetOverscan) {
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|             ErrorF("SetOverscan() called from CMapReinstallMap\n");
 | ||
| #endif
 | ||
|             pScrn->SetOverscan(pScrn, cmapPriv->overscan);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     cmapPriv->recalculate = FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapRefreshColors(ColormapPtr pmap, int defs, int *indices)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
 | ||
|                                          CMapScreenKey);
 | ||
|     CMapColormapPtr pColPriv =
 | ||
|         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
 | ||
|     VisualPtr pVisual = pmap->pVisual;
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
 | ||
|     int numColors, i;
 | ||
|     LOCO *gamma, *colors;
 | ||
|     EntryPtr entry;
 | ||
|     int reds, greens, blues, maxValue, index, shift;
 | ||
| 
 | ||
|     numColors = pColPriv->numColors;
 | ||
|     shift = 16 - pScreenPriv->sigRGBbits;
 | ||
|     maxValue = (1 << pScreenPriv->sigRGBbits) - 1;
 | ||
|     gamma = pScreenPriv->gamma;
 | ||
|     colors = pColPriv->colors;
 | ||
| 
 | ||
|     reds = pVisual->redMask >> pVisual->offsetRed;
 | ||
|     greens = pVisual->greenMask >> pVisual->offsetGreen;
 | ||
|     blues = pVisual->blueMask >> pVisual->offsetBlue;
 | ||
| 
 | ||
|     switch (pVisual->class) {
 | ||
|     case StaticGray:
 | ||
|         for (i = 0; i < numColors; i++) {
 | ||
|             index = (i + 1) * maxValue / numColors;
 | ||
|             colors[i].red = gamma[index].red;
 | ||
|             colors[i].green = gamma[index].green;
 | ||
|             colors[i].blue = gamma[index].blue;
 | ||
|         }
 | ||
|         break;
 | ||
|     case TrueColor:
 | ||
|         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
 | ||
|             for (i = 0; i <= reds; i++)
 | ||
|                 colors[i].red = gamma[i * maxValue / reds].red;
 | ||
|             for (i = 0; i <= greens; i++)
 | ||
|                 colors[i].green = gamma[i * maxValue / greens].green;
 | ||
|             for (i = 0; i <= blues; i++)
 | ||
|                 colors[i].blue = gamma[i * maxValue / blues].blue;
 | ||
|             break;
 | ||
|         }
 | ||
|         for (i = 0; i < numColors; i++) {
 | ||
|             colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) *
 | ||
|                                   maxValue / reds].red;
 | ||
|             colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) *
 | ||
|                                     maxValue / greens].green;
 | ||
|             colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) *
 | ||
|                                    maxValue / blues].blue;
 | ||
|         }
 | ||
|         break;
 | ||
|     case StaticColor:
 | ||
|     case PseudoColor:
 | ||
|     case GrayScale:
 | ||
|         for (i = 0; i < defs; i++) {
 | ||
|             index = indices[i];
 | ||
|             entry = (EntryPtr) &pmap->red[index];
 | ||
| 
 | ||
|             if (entry->fShared) {
 | ||
|                 colors[index].red =
 | ||
|                     gamma[entry->co.shco.red->color >> shift].red;
 | ||
|                 colors[index].green =
 | ||
|                     gamma[entry->co.shco.green->color >> shift].green;
 | ||
|                 colors[index].blue =
 | ||
|                     gamma[entry->co.shco.blue->color >> shift].blue;
 | ||
|             }
 | ||
|             else {
 | ||
|                 colors[index].red = gamma[entry->co.local.red >> shift].red;
 | ||
|                 colors[index].green =
 | ||
|                     gamma[entry->co.local.green >> shift].green;
 | ||
|                 colors[index].blue = gamma[entry->co.local.blue >> shift].blue;
 | ||
|             }
 | ||
|         }
 | ||
|         break;
 | ||
|     case DirectColor:
 | ||
|         if (CMapColormapUseMax(pVisual, pScreenPriv)) {
 | ||
|             for (i = 0; i < defs; i++) {
 | ||
|                 index = indices[i];
 | ||
|                 if (index <= reds)
 | ||
|                     colors[index].red =
 | ||
|                         gamma[pmap->red[index].co.local.red >> shift].red;
 | ||
|                 if (index <= greens)
 | ||
|                     colors[index].green =
 | ||
|                         gamma[pmap->green[index].co.local.green >> shift].green;
 | ||
|                 if (index <= blues)
 | ||
|                     colors[index].blue =
 | ||
|                         gamma[pmap->blue[index].co.local.blue >> shift].blue;
 | ||
| 
 | ||
|             }
 | ||
|             break;
 | ||
|         }
 | ||
|         for (i = 0; i < defs; i++) {
 | ||
|             index = indices[i];
 | ||
| 
 | ||
|             colors[index].red = gamma[pmap->red[(index >> pVisual->
 | ||
|                                                  offsetRed) & reds].co.local.
 | ||
|                                       red >> shift].red;
 | ||
|             colors[index].green =
 | ||
|                 gamma[pmap->green[(index >> pVisual->offsetGreen) & greens].co.
 | ||
|                       local.green >> shift].green;
 | ||
|             colors[index].blue =
 | ||
|                 gamma[pmap->blue[(index >> pVisual->offsetBlue) & blues].co.
 | ||
|                       local.blue >> shift].blue;
 | ||
|         }
 | ||
|         break;
 | ||
|     }
 | ||
| 
 | ||
|     if (LOAD_PALETTE(pmap))
 | ||
|         (*pScrn->LoadPalette) (pScrn, defs, indices, colors, pmap->pVisual);
 | ||
| 
 | ||
|     if (pScrn->SetOverscan)
 | ||
|         CMapSetOverscan(pmap, defs, indices);
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| static Bool
 | ||
| CMapCompareColors(LOCO * color1, LOCO * color2)
 | ||
| {
 | ||
|     /* return TRUE if the color1 is "closer" to black than color2 */
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|     ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
 | ||
|            color1->red, color1->green, color1->blue,
 | ||
|            color2->red, color2->green, color2->blue,
 | ||
|            color1->red + color1->green + color1->blue,
 | ||
|            color2->red + color2->green + color2->blue);
 | ||
| #endif
 | ||
|     return (color1->red + color1->green + color1->blue <
 | ||
|             color2->red + color2->green + color2->blue);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapSetOverscan(ColormapPtr pmap, int defs, int *indices)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates,
 | ||
|                                          CMapScreenKey);
 | ||
|     CMapColormapPtr pColPriv =
 | ||
|         (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey);
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen);
 | ||
|     VisualPtr pVisual = pmap->pVisual;
 | ||
|     int i;
 | ||
|     LOCO *colors;
 | ||
|     int index;
 | ||
|     Bool newOverscan = FALSE;
 | ||
|     int overscan, tmpOverscan;
 | ||
| 
 | ||
|     colors = pColPriv->colors;
 | ||
|     overscan = pColPriv->overscan;
 | ||
| 
 | ||
|     /*
 | ||
|      * Search for a new overscan index in the following cases:
 | ||
|      *
 | ||
|      *   - The index hasn't yet been initialised.  In this case search
 | ||
|      *     for an index that is black or a close match to black.
 | ||
|      *
 | ||
|      *   - The colour of the old index is changed.  In this case search
 | ||
|      *     all indices for a black or close match to black.
 | ||
|      *
 | ||
|      *   - The colour of the old index wasn't black.  In this case only
 | ||
|      *     search the indices that were changed for a better match to black.
 | ||
|      */
 | ||
| 
 | ||
|     switch (pVisual->class) {
 | ||
|     case StaticGray:
 | ||
|     case TrueColor:
 | ||
|         /* Should only come here once.  Initialise the overscan index to 0 */
 | ||
|         overscan = 0;
 | ||
|         newOverscan = TRUE;
 | ||
|         break;
 | ||
|     case StaticColor:
 | ||
|         /*
 | ||
|          * Only come here once, but search for the overscan in the same way
 | ||
|          * as for the other cases.
 | ||
|          */
 | ||
|     case DirectColor:
 | ||
|     case PseudoColor:
 | ||
|     case GrayScale:
 | ||
|         if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) {
 | ||
|             /* Uninitialised */
 | ||
|             newOverscan = TRUE;
 | ||
|         }
 | ||
|         else {
 | ||
|             /* Check if the overscan was changed */
 | ||
|             for (i = 0; i < defs; i++) {
 | ||
|                 index = indices[i];
 | ||
|                 if (index == overscan) {
 | ||
|                     newOverscan = TRUE;
 | ||
|                     break;
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         if (newOverscan) {
 | ||
|             /* The overscan is either uninitialised or it has been changed */
 | ||
| 
 | ||
|             if (overscan < 0 || overscan > pScreenPriv->maxColors - 1)
 | ||
|                 tmpOverscan = pScreenPriv->maxColors - 1;
 | ||
|             else
 | ||
|                 tmpOverscan = overscan;
 | ||
| 
 | ||
|             /* search all entries for a close match to black */
 | ||
|             for (i = pScreenPriv->maxColors - 1; i >= 0; i--) {
 | ||
|                 if (colors[i].red == 0 && colors[i].green == 0 &&
 | ||
|                     colors[i].blue == 0) {
 | ||
|                     overscan = i;
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                     ErrorF("Black found at index 0x%02x\n", i);
 | ||
| #endif
 | ||
|                     break;
 | ||
|                 }
 | ||
|                 else {
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                     ErrorF("0x%02x: ", i);
 | ||
| #endif
 | ||
|                     if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) {
 | ||
|                         tmpOverscan = i;
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                         ErrorF("possible \"Black\" at index 0x%02x\n", i);
 | ||
| #endif
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|             if (i < 0)
 | ||
|                 overscan = tmpOverscan;
 | ||
|         }
 | ||
|         else {
 | ||
|             /* Check of the old overscan wasn't black */
 | ||
|             if (colors[overscan].red != 0 || colors[overscan].green != 0 ||
 | ||
|                 colors[overscan].blue != 0) {
 | ||
|                 int oldOverscan = tmpOverscan = overscan;
 | ||
| 
 | ||
|                 /* See of there is now a better match */
 | ||
|                 for (i = 0; i < defs; i++) {
 | ||
|                     index = indices[i];
 | ||
|                     if (colors[index].red == 0 && colors[index].green == 0 &&
 | ||
|                         colors[index].blue == 0) {
 | ||
|                         overscan = index;
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                         ErrorF("Black found at index 0x%02x\n", index);
 | ||
| #endif
 | ||
|                         break;
 | ||
|                     }
 | ||
|                     else {
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                         ErrorF("0x%02x: ", index);
 | ||
| #endif
 | ||
|                         if (CMapCompareColors(&colors[index],
 | ||
|                                               &colors[tmpOverscan])) {
 | ||
|                             tmpOverscan = index;
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|                             ErrorF("possible \"Black\" at index 0x%02x\n",
 | ||
|                                    index);
 | ||
| #endif
 | ||
|                         }
 | ||
|                     }
 | ||
|                 }
 | ||
|                 if (i == defs)
 | ||
|                     overscan = tmpOverscan;
 | ||
|                 if (overscan != oldOverscan)
 | ||
|                     newOverscan = TRUE;
 | ||
|             }
 | ||
|         }
 | ||
|         break;
 | ||
|     }
 | ||
|     if (newOverscan) {
 | ||
|         pColPriv->overscan = overscan;
 | ||
|         if (LOAD_PALETTE(pmap)) {
 | ||
| #ifdef DEBUGOVERSCAN
 | ||
|             ErrorF("SetOverscan() called from CmapSetOverscan\n");
 | ||
| #endif
 | ||
|             pScrn->SetOverscan(pScrn, overscan);
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| CMapUnwrapScreen(ScreenPtr pScreen)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv =
 | ||
|         (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey);
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | ||
| 
 | ||
|     pScreen->CloseScreen = pScreenPriv->CloseScreen;
 | ||
|     pScreen->CreateColormap = pScreenPriv->CreateColormap;
 | ||
|     pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
 | ||
|     pScreen->InstallColormap = pScreenPriv->InstallColormap;
 | ||
|     pScreen->StoreColors = pScreenPriv->StoreColors;
 | ||
| 
 | ||
|     pScrn->EnterVT = pScreenPriv->EnterVT;
 | ||
|     pScrn->SwitchMode = pScreenPriv->SwitchMode;
 | ||
|     pScrn->SetDGAMode = pScreenPriv->SetDGAMode;
 | ||
|     pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
 | ||
| 
 | ||
|     free(pScreenPriv->gamma);
 | ||
|     free(pScreenPriv->PreAllocIndices);
 | ||
|     free(pScreenPriv);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| ComputeGamma(ScrnInfoPtr pScrn, CMapScreenPtr priv)
 | ||
| {
 | ||
|     int elements = priv->gammaElements - 1;
 | ||
|     double RedGamma, GreenGamma, BlueGamma;
 | ||
|     int i;
 | ||
| 
 | ||
| #ifndef DONT_CHECK_GAMMA
 | ||
|     /* This check is to catch drivers that are not initialising pScrn->gamma */
 | ||
|     if (pScrn->gamma.red < GAMMA_MIN || pScrn->gamma.red > GAMMA_MAX ||
 | ||
|         pScrn->gamma.green < GAMMA_MIN || pScrn->gamma.green > GAMMA_MAX ||
 | ||
|         pScrn->gamma.blue < GAMMA_MIN || pScrn->gamma.blue > GAMMA_MAX) {
 | ||
| 
 | ||
|         xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0,
 | ||
|                        "The %s driver didn't call xf86SetGamma() to initialise\n"
 | ||
|                        "\tthe gamma values.\n", pScrn->driverName);
 | ||
|         xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0,
 | ||
|                        "PLEASE FIX THE `%s' DRIVER!\n",
 | ||
|                        pScrn->driverName);
 | ||
|         pScrn->gamma.red = 1.0;
 | ||
|         pScrn->gamma.green = 1.0;
 | ||
|         pScrn->gamma.blue = 1.0;
 | ||
|     }
 | ||
| #endif
 | ||
| 
 | ||
|     RedGamma = 1.0 / (double) pScrn->gamma.red;
 | ||
|     GreenGamma = 1.0 / (double) pScrn->gamma.green;
 | ||
|     BlueGamma = 1.0 / (double) pScrn->gamma.blue;
 | ||
| 
 | ||
|     for (i = 0; i <= elements; i++) {
 | ||
|         if (RedGamma == 1.0)
 | ||
|             priv->gamma[i].red = i;
 | ||
|         else
 | ||
|             priv->gamma[i].red = (CARD16) (pow((double) i / (double) elements,
 | ||
|                                                RedGamma) * (double) elements +
 | ||
|                                            0.5);
 | ||
| 
 | ||
|         if (GreenGamma == 1.0)
 | ||
|             priv->gamma[i].green = i;
 | ||
|         else
 | ||
|             priv->gamma[i].green = (CARD16) (pow((double) i / (double) elements,
 | ||
|                                                  GreenGamma) *
 | ||
|                                              (double) elements + 0.5);
 | ||
| 
 | ||
|         if (BlueGamma == 1.0)
 | ||
|             priv->gamma[i].blue = i;
 | ||
|         else
 | ||
|             priv->gamma[i].blue = (CARD16) (pow((double) i / (double) elements,
 | ||
|                                                 BlueGamma) * (double) elements +
 | ||
|                                             0.5);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| int
 | ||
| CMapChangeGamma(ScrnInfoPtr pScrn, Gamma gamma)
 | ||
| {
 | ||
|     int ret = Success;
 | ||
|     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
 | ||
|     CMapColormapPtr pColPriv;
 | ||
|     CMapScreenPtr pScreenPriv;
 | ||
|     CMapLinkPtr pLink;
 | ||
| 
 | ||
|     /* Is this sufficient checking ? */
 | ||
|     if (!CMapScreenKeyRegistered)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
 | ||
|                                                    CMapScreenKey);
 | ||
|     if (!pScreenPriv)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX ||
 | ||
|         gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX ||
 | ||
|         gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX)
 | ||
|         return BadValue;
 | ||
| 
 | ||
|     pScrn->gamma.red = gamma.red;
 | ||
|     pScrn->gamma.green = gamma.green;
 | ||
|     pScrn->gamma.blue = gamma.blue;
 | ||
| 
 | ||
|     ComputeGamma(pScrn, pScreenPriv);
 | ||
| 
 | ||
|     /* mark all colormaps on this screen */
 | ||
|     pLink = pScreenPriv->maps;
 | ||
|     while (pLink) {
 | ||
|         pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates,
 | ||
|                                                       CMapColormapKey);
 | ||
|         pColPriv->recalculate = TRUE;
 | ||
|         pLink = pLink->next;
 | ||
|     }
 | ||
| 
 | ||
|     if (GetInstalledmiColormap(pScreen) &&
 | ||
|         ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
 | ||
|          pScrn->vtSema || pScreenPriv->isDGAmode)) {
 | ||
|         ColormapPtr pMap = GetInstalledmiColormap(pScreen);
 | ||
| 
 | ||
|         if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
 | ||
|             (pMap->pVisual->class == TrueColor) &&
 | ||
|             CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
 | ||
| 
 | ||
|             /* if the current map doesn't have a palette look
 | ||
|                for another map to change the gamma on. */
 | ||
| 
 | ||
|             pLink = pScreenPriv->maps;
 | ||
|             while (pLink) {
 | ||
|                 if (pLink->cmap->pVisual->class == PseudoColor)
 | ||
|                     break;
 | ||
|                 pLink = pLink->next;
 | ||
|             }
 | ||
| 
 | ||
|             if (pLink) {
 | ||
|                 /* need to trick CMapRefreshColors() into thinking
 | ||
|                    this is the currently installed map */
 | ||
|                 SetInstalledmiColormap(pScreen, pLink->cmap);
 | ||
|                 CMapReinstallMap(pLink->cmap);
 | ||
|                 SetInstalledmiColormap(pScreen, pMap);
 | ||
|             }
 | ||
|         }
 | ||
|         else
 | ||
|             CMapReinstallMap(pMap);
 | ||
|     }
 | ||
| 
 | ||
|     pScrn->ChangeGamma = pScreenPriv->ChangeGamma;
 | ||
|     if (pScrn->ChangeGamma)
 | ||
|         ret = pScrn->ChangeGamma(pScrn, gamma);
 | ||
|     pScrn->ChangeGamma = CMapChangeGamma;
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| ComputeGammaRamp(CMapScreenPtr priv,
 | ||
|                  unsigned short *red,
 | ||
|                  unsigned short *green, unsigned short *blue)
 | ||
| {
 | ||
|     int elements = priv->gammaElements;
 | ||
|     LOCO *entry = priv->gamma;
 | ||
|     int shift = 16 - priv->sigRGBbits;
 | ||
| 
 | ||
|     while (elements--) {
 | ||
|         entry->red = *(red++) >> shift;
 | ||
|         entry->green = *(green++) >> shift;
 | ||
|         entry->blue = *(blue++) >> shift;
 | ||
|         entry++;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| int
 | ||
| xf86ChangeGammaRamp(ScreenPtr pScreen,
 | ||
|                     int size,
 | ||
|                     unsigned short *red,
 | ||
|                     unsigned short *green, unsigned short *blue)
 | ||
| {
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | ||
|     CMapColormapPtr pColPriv;
 | ||
|     CMapScreenPtr pScreenPriv;
 | ||
|     CMapLinkPtr pLink;
 | ||
| 
 | ||
|     if (!CMapScreenKeyRegistered)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
 | ||
|                                                    CMapScreenKey);
 | ||
|     if (!pScreenPriv)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     if (pScreenPriv->gammaElements != size)
 | ||
|         return BadValue;
 | ||
| 
 | ||
|     ComputeGammaRamp(pScreenPriv, red, green, blue);
 | ||
| 
 | ||
|     /* mark all colormaps on this screen */
 | ||
|     pLink = pScreenPriv->maps;
 | ||
|     while (pLink) {
 | ||
|         pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates,
 | ||
|                                                       CMapColormapKey);
 | ||
|         pColPriv->recalculate = TRUE;
 | ||
|         pLink = pLink->next;
 | ||
|     }
 | ||
| 
 | ||
|     if (GetInstalledmiColormap(pScreen) &&
 | ||
|         ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) ||
 | ||
|          pScrn->vtSema || pScreenPriv->isDGAmode)) {
 | ||
|         ColormapPtr pMap = GetInstalledmiColormap(pScreen);
 | ||
| 
 | ||
|         if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) &&
 | ||
|             (pMap->pVisual->class == TrueColor) &&
 | ||
|             CMapColormapUseMax(pMap->pVisual, pScreenPriv)) {
 | ||
| 
 | ||
|             /* if the current map doesn't have a palette look
 | ||
|                for another map to change the gamma on. */
 | ||
| 
 | ||
|             pLink = pScreenPriv->maps;
 | ||
|             while (pLink) {
 | ||
|                 if (pLink->cmap->pVisual->class == PseudoColor)
 | ||
|                     break;
 | ||
|                 pLink = pLink->next;
 | ||
|             }
 | ||
| 
 | ||
|             if (pLink) {
 | ||
|                 /* need to trick CMapRefreshColors() into thinking
 | ||
|                    this is the currently installed map */
 | ||
|                 SetInstalledmiColormap(pScreen, pLink->cmap);
 | ||
|                 CMapReinstallMap(pLink->cmap);
 | ||
|                 SetInstalledmiColormap(pScreen, pMap);
 | ||
|             }
 | ||
|         }
 | ||
|         else
 | ||
|             CMapReinstallMap(pMap);
 | ||
|     }
 | ||
| 
 | ||
|     return Success;
 | ||
| }
 | ||
| 
 | ||
| int
 | ||
| xf86GetGammaRampSize(ScreenPtr pScreen)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv;
 | ||
| 
 | ||
|     if (!CMapScreenKeyRegistered)
 | ||
|         return 0;
 | ||
| 
 | ||
|     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
 | ||
|                                                    CMapScreenKey);
 | ||
|     if (!pScreenPriv)
 | ||
|         return 0;
 | ||
| 
 | ||
|     return pScreenPriv->gammaElements;
 | ||
| }
 | ||
| 
 | ||
| int
 | ||
| xf86GetGammaRamp(ScreenPtr pScreen,
 | ||
|                  int size,
 | ||
|                  unsigned short *red,
 | ||
|                  unsigned short *green, unsigned short *blue)
 | ||
| {
 | ||
|     CMapScreenPtr pScreenPriv;
 | ||
|     LOCO *entry;
 | ||
|     int shift, sigbits;
 | ||
| 
 | ||
|     if (!CMapScreenKeyRegistered)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
 | ||
|                                                    CMapScreenKey);
 | ||
|     if (!pScreenPriv)
 | ||
|         return BadImplementation;
 | ||
| 
 | ||
|     if (size > pScreenPriv->gammaElements)
 | ||
|         return BadValue;
 | ||
| 
 | ||
|     entry = pScreenPriv->gamma;
 | ||
|     sigbits = pScreenPriv->sigRGBbits;
 | ||
| 
 | ||
|     while (size--) {
 | ||
|         *red = entry->red << (16 - sigbits);
 | ||
|         *green = entry->green << (16 - sigbits);
 | ||
|         *blue = entry->blue << (16 - sigbits);
 | ||
|         shift = sigbits;
 | ||
|         while (shift < 16) {
 | ||
|             *red |= *red >> shift;
 | ||
|             *green |= *green >> shift;
 | ||
|             *blue |= *blue >> shift;
 | ||
|             shift += sigbits;
 | ||
|         }
 | ||
|         red++;
 | ||
|         green++;
 | ||
|         blue++;
 | ||
|         entry++;
 | ||
|     }
 | ||
| 
 | ||
|     return Success;
 | ||
| }
 | ||
| 
 | ||
| int
 | ||
| xf86ChangeGamma(ScreenPtr pScreen, Gamma gamma)
 | ||
| {
 | ||
|     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | ||
| 
 | ||
|     if (pScrn->ChangeGamma)
 | ||
|         return (*pScrn->ChangeGamma) (pScrn, gamma);
 | ||
| 
 | ||
|     return BadImplementation;
 | ||
| }
 |