From 348130c450be8b5c4abcb03272b326434e3f5022 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 22 Mar 2010 09:17:19 +0000 Subject: Updated to xorg-server-1.7.99.902 --- xorg-server/hw/xfree86/common/xf86cmap.c | 2337 +++++++++++++++--------------- 1 file changed, 1167 insertions(+), 1170 deletions(-) (limited to 'xorg-server/hw/xfree86/common/xf86cmap.c') diff --git a/xorg-server/hw/xfree86/common/xf86cmap.c b/xorg-server/hw/xfree86/common/xf86cmap.c index 4cab8b3eb..f60d96e7d 100644 --- a/xorg-server/hw/xfree86/common/xf86cmap.c +++ b/xorg-server/hw/xfree86/common/xf86cmap.c @@ -1,1170 +1,1167 @@ -/* - * 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 -#endif - -#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) -#include -#else -#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ -#include -#undef _XOPEN_SOURCE -#endif - -#include -#include "misc.h" -#include -#include "colormapst.h" -#include "scrnintstr.h" - -#include "resource.h" - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86str.h" -#include "micmap.h" -#include "xf86Crtc.h" - -#ifdef XFreeXDGA -#include -#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, index) \ - ((pmap == miInstalledMaps[index]) && \ - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ - xf86Screens[index]->vtSema || pScreenPriv->isDGAmode)) - - -typedef struct _CMapLink { - ColormapPtr cmap; - struct _CMapLink *next; -} CMapLink, *CMapLinkPtr; - -typedef struct { - ScrnInfoPtr pScrn; - CloseScreenProcPtr CloseScreen; - CreateColormapProcPtr CreateColormap; - DestroyColormapProcPtr DestroyColormap; - InstallColormapProcPtr InstallColormap; - StoreColorsProcPtr StoreColors; - Bool (*EnterVT)(int, int); - Bool (*SwitchMode)(int, DisplayModePtr, int); - int (*SetDGAMode)(int, 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 int CMapScreenKeyIndex; -static DevPrivateKey CMapScreenKey; -static int CMapColormapKeyIndex; -static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex; - -static void CMapInstallColormap(ColormapPtr); -static void CMapStoreColors(ColormapPtr, int, xColorItem *); -static Bool CMapCloseScreen (int, ScreenPtr); -static Bool CMapCreateColormap (ColormapPtr); -static void CMapDestroyColormap (ColormapPtr); - -static Bool CMapEnterVT(int, int); -static Bool CMapSwitchMode(int, DisplayModePtr, int); -#ifdef XFreeXDGA -static int CMapSetDGAMode(int, int, DGADevicePtr); -#endif -static int CMapChangeGamma(int, Gamma); - -static void ComputeGamma(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 xf86HandleColormaps( - ScreenPtr pScreen, - int maxColors, - int sigRGBbits, - xf86LoadPaletteProc *loadPalette, - xf86SetOverscanProc *setOverscan, - unsigned int flags -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ColormapPtr pDefMap = NULL; - CMapScreenPtr pScreenPriv; - LOCO *gamma; - int *indices; - int elements; - - /* If we support a better colormap system, then pretend we succeeded. */ - if (xf86_crtc_supports_gamma(pScrn)) - return TRUE; - - if(!maxColors || !sigRGBbits || !loadPalette) - return FALSE; - - CMapScreenKey = &CMapScreenKeyIndex; - - elements = 1 << sigRGBbits; - - if(!(gamma = xalloc(elements * sizeof(LOCO)))) - return FALSE; - - if(!(indices = xalloc(maxColors * sizeof(int)))) { - xfree(gamma); - return FALSE; - } - - if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) { - xfree(gamma); - xfree(indices); - return FALSE; - } - - dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, 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; - - pScreenPriv->pScrn = pScrn; - 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(pScreenPriv); - - /* get the default map */ - dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, - RT_COLORMAP, serverClient, DixInstallAccess); - - if(!CMapAllocateColormapPrivate(pDefMap)) { - CMapUnwrapScreen(pScreen); - return FALSE; - } - - /* Force the initial map to be loaded */ - miInstalledMaps[pScreen->myNum] = NULL; - CMapInstallColormap(pDefMap); - return TRUE; -} - - -/**** Screen functions ****/ - - -static Bool -CMapCloseScreen (int i, ScreenPtr pScreen) -{ - CMapUnwrapScreen(pScreen); - - return (*pScreen->CloseScreen) (i, 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 = xalloc(numColors * sizeof(LOCO)))) - return FALSE; - - if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) { - xfree(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 = xalloc(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) { - if(pColPriv->colors) xfree(pColPriv->colors); - xfree(pColPriv); - } - - /* remove map from list */ - while(pLink) { - if(pLink->cmap == cmap) { - if(prevLink) - prevLink->next = pLink->next; - else - pScreenPriv->maps = pLink->next; - xfree(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; - int index = pScreen->myNum; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if (pmap == miInstalledMaps[index]) - 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 (miInstalledMaps[index]) - pmap = miInstalledMaps[index]; - - if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && - (pmap->pVisual->class == TrueColor) && - CMapColormapUseMax(pmap->pVisual, pScreenPriv)) - return; - - if(LOAD_PALETTE(pmap, index)) - CMapReinstallMap(pmap); -} - - -/**** ScrnInfoRec functions ****/ - -static Bool -CMapEnterVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if((*pScreenPriv->EnterVT)(index, flags)) { - if(miInstalledMaps[index]) - CMapReinstallMap(miInstalledMaps[index]); - return TRUE; - } - return FALSE; -} - - -static Bool -CMapSwitchMode(int index, DisplayModePtr mode, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if((*pScreenPriv->SwitchMode)(index, mode, flags)) { - if(miInstalledMaps[index]) - CMapReinstallMap(miInstalledMaps[index]); - return TRUE; - } - return FALSE; -} - -#ifdef XFreeXDGA -static int -CMapSetDGAMode(int index, int num, DGADevicePtr dev) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - int ret; - - ret = (*pScreenPriv->SetDGAMode)(index, num, dev); - - pScreenPriv->isDGAmode = DGAActive(index); - - if(!pScreenPriv->isDGAmode && miInstalledMaps[index] - && xf86Screens[pScreen->myNum]->vtSema) - CMapReinstallMap(miInstalledMaps[index]); - - 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 = xf86Screens[pmap->pScreen->myNum]; - 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 = xf86Screens[pmap->pScreen->myNum]; - 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, pmap->pScreen->myNum)) - (*pScrn->LoadPalette)(pScreenPriv->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 = xf86Screens[pmap->pScreen->myNum]; - 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, pmap->pScreen->myNum)) { -#ifdef DEBUGOVERSCAN - ErrorF("SetOverscan() called from CmapSetOverscan\n"); -#endif - pScrn->SetOverscan(pScreenPriv->pScrn, overscan); - } - } -} - -static void -CMapUnwrapScreen(ScreenPtr pScreen) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - 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; - - xfree(pScreenPriv->gamma); - xfree(pScreenPriv->PreAllocIndices); - xfree(pScreenPriv); -} - - -static void -ComputeGamma(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 (priv->pScrn->gamma.red < GAMMA_MIN || - priv->pScrn->gamma.red > GAMMA_MAX || - priv->pScrn->gamma.green < GAMMA_MIN || - priv->pScrn->gamma.green > GAMMA_MAX || - priv->pScrn->gamma.blue < GAMMA_MIN || - priv->pScrn->gamma.blue > GAMMA_MAX) { - - xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, - "The %s driver didn't call xf86SetGamma() to initialise\n" - "\tthe gamma values.\n", priv->pScrn->driverName); - xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, - "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); - priv->pScrn->gamma.red = 1.0; - priv->pScrn->gamma.green = 1.0; - priv->pScrn->gamma.blue = 1.0; - } -#endif - - RedGamma = 1.0 / (double)priv->pScrn->gamma.red; - GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; - BlueGamma = 1.0 / (double)priv->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( - int index, - Gamma gamma -){ - int ret = Success; - ScrnInfoPtr pScrn = xf86Screens[index]; - ScreenPtr pScreen = pScrn->pScreen; - CMapColormapPtr pColPriv; - CMapScreenPtr pScreenPriv; - CMapLinkPtr pLink; - - /* Is this sufficient checking ? */ - if(CMapScreenKey == NULL) - 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(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(miInstalledMaps[pScreen->myNum] && - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || - pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; - - 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 */ - miInstalledMaps[pScreen->myNum] = pLink->cmap; - CMapReinstallMap(pLink->cmap); - miInstalledMaps[pScreen->myNum] = pMap; - } - } else - CMapReinstallMap(pMap); - } - - pScrn->ChangeGamma = pScreenPriv->ChangeGamma; - if (pScrn->ChangeGamma) - ret = pScrn->ChangeGamma(index, 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 = xf86Screens[pScreen->myNum]; - CMapColormapPtr pColPriv; - CMapScreenPtr pScreenPriv; - CMapLinkPtr pLink; - - if (xf86_crtc_supports_gamma(pScrn)) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc; - - if (crtc) { - if (crtc->gammaSize != size) - return BadValue; - - RRCrtcGammaSet(crtc, red, green, blue); - - return Success; - } - } - - if(CMapScreenKey == NULL) - 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(miInstalledMaps[pScreen->myNum] && - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || - pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; - - 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 */ - miInstalledMaps[pScreen->myNum] = pLink->cmap; - CMapReinstallMap(pLink->cmap); - miInstalledMaps[pScreen->myNum] = pMap; - } - } else - CMapReinstallMap(pMap); - } - - return Success; -} - -int -xf86GetGammaRampSize(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - CMapScreenPtr pScreenPriv; - - if (xf86_crtc_supports_gamma(pScrn)) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc; - - if (crtc) - return crtc->gammaSize; - } - - if(CMapScreenKey == NULL) 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 -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - CMapScreenPtr pScreenPriv; - LOCO *entry; - int shift, sigbits; - - if (xf86_crtc_supports_gamma(pScrn)) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RRCrtcPtr crtc = config->output[config->compat_output]->crtc->randr_crtc; - - if (crtc) { - if (crtc->gammaSize < size) - return BadValue; - - if (!RRCrtcGammaGet(crtc)) - return BadImplementation; - - memcpy(red, crtc->gammaRed, size * sizeof(*red)); - memcpy(green, crtc->gammaGreen, size * sizeof(*green)); - memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); - - return Success; - } - } - - if(CMapScreenKey == NULL) - 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 = xf86Screens[pScreen->myNum]; - - if(pScrn->ChangeGamma) - return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); - - return BadImplementation; -} +/* + * 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 +#endif + +#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) +#include +#else +#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ +#include +#undef _XOPEN_SOURCE +#endif + +#include +#include "misc.h" +#include +#include "colormapst.h" +#include "scrnintstr.h" + +#include "resource.h" + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86str.h" +#include "micmap.h" +#include "xf86Crtc.h" + +#ifdef XFreeXDGA +#include +#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, index) \ + ((pmap == miInstalledMaps[index]) && \ + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ + xf86Screens[index]->vtSema || pScreenPriv->isDGAmode)) + + +typedef struct _CMapLink { + ColormapPtr cmap; + struct _CMapLink *next; +} CMapLink, *CMapLinkPtr; + +typedef struct { + ScrnInfoPtr pScrn; + CloseScreenProcPtr CloseScreen; + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + Bool (*EnterVT)(int, int); + Bool (*SwitchMode)(int, DisplayModePtr, int); + int (*SetDGAMode)(int, 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 int CMapScreenKeyIndex; +static DevPrivateKey CMapScreenKey; +static int CMapColormapKeyIndex; +static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex; + +static void CMapInstallColormap(ColormapPtr); +static void CMapStoreColors(ColormapPtr, int, xColorItem *); +static Bool CMapCloseScreen (int, ScreenPtr); +static Bool CMapCreateColormap (ColormapPtr); +static void CMapDestroyColormap (ColormapPtr); + +static Bool CMapEnterVT(int, int); +static Bool CMapSwitchMode(int, DisplayModePtr, int); +#ifdef XFreeXDGA +static int CMapSetDGAMode(int, int, DGADevicePtr); +#endif +static int CMapChangeGamma(int, Gamma); + +static void ComputeGamma(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 xf86HandleColormaps( + ScreenPtr pScreen, + int maxColors, + int sigRGBbits, + xf86LoadPaletteProc *loadPalette, + xf86SetOverscanProc *setOverscan, + unsigned int flags +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ColormapPtr pDefMap = NULL; + CMapScreenPtr pScreenPriv; + LOCO *gamma; + int *indices; + int elements; + + /* If we support a better colormap system, then pretend we succeeded. */ + if (xf86_crtc_supports_gamma(pScrn)) + return TRUE; + + if(!maxColors || !sigRGBbits || !loadPalette) + return FALSE; + + CMapScreenKey = &CMapScreenKeyIndex; + + elements = 1 << sigRGBbits; + + if(!(gamma = xalloc(elements * sizeof(LOCO)))) + return FALSE; + + if(!(indices = xalloc(maxColors * sizeof(int)))) { + xfree(gamma); + return FALSE; + } + + if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) { + xfree(gamma); + xfree(indices); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, 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; + + pScreenPriv->pScrn = pScrn; + 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(pScreenPriv); + + /* get the default map */ + dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, + RT_COLORMAP, serverClient, DixInstallAccess); + + if(!CMapAllocateColormapPrivate(pDefMap)) { + CMapUnwrapScreen(pScreen); + return FALSE; + } + + /* Force the initial map to be loaded */ + miInstalledMaps[pScreen->myNum] = NULL; + CMapInstallColormap(pDefMap); + return TRUE; +} + + +/**** Screen functions ****/ + + +static Bool +CMapCloseScreen (int i, ScreenPtr pScreen) +{ + CMapUnwrapScreen(pScreen); + + return (*pScreen->CloseScreen) (i, 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 = xalloc(numColors * sizeof(LOCO)))) + return FALSE; + + if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) { + xfree(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 = xalloc(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) { + if(pColPriv->colors) xfree(pColPriv->colors); + xfree(pColPriv); + } + + /* remove map from list */ + while(pLink) { + if(pLink->cmap == cmap) { + if(prevLink) + prevLink->next = pLink->next; + else + pScreenPriv->maps = pLink->next; + xfree(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; + int index = pScreen->myNum; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if (pmap == miInstalledMaps[index]) + 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 (miInstalledMaps[index]) + pmap = miInstalledMaps[index]; + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pmap->pVisual->class == TrueColor) && + CMapColormapUseMax(pmap->pVisual, pScreenPriv)) + return; + + if(LOAD_PALETTE(pmap, index)) + CMapReinstallMap(pmap); +} + + +/**** ScrnInfoRec functions ****/ + +static Bool +CMapEnterVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if((*pScreenPriv->EnterVT)(index, flags)) { + if(miInstalledMaps[index]) + CMapReinstallMap(miInstalledMaps[index]); + return TRUE; + } + return FALSE; +} + + +static Bool +CMapSwitchMode(int index, DisplayModePtr mode, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if((*pScreenPriv->SwitchMode)(index, mode, flags)) { + if(miInstalledMaps[index]) + CMapReinstallMap(miInstalledMaps[index]); + return TRUE; + } + return FALSE; +} + +#ifdef XFreeXDGA +static int +CMapSetDGAMode(int index, int num, DGADevicePtr dev) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + int ret; + + ret = (*pScreenPriv->SetDGAMode)(index, num, dev); + + pScreenPriv->isDGAmode = DGAActive(index); + + if(!pScreenPriv->isDGAmode && miInstalledMaps[index] + && xf86Screens[pScreen->myNum]->vtSema) + CMapReinstallMap(miInstalledMaps[index]); + + 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 = xf86Screens[pmap->pScreen->myNum]; + 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 = xf86Screens[pmap->pScreen->myNum]; + 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, pmap->pScreen->myNum)) + (*pScrn->LoadPalette)(pScreenPriv->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 = xf86Screens[pmap->pScreen->myNum]; + 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, pmap->pScreen->myNum)) { +#ifdef DEBUGOVERSCAN + ErrorF("SetOverscan() called from CmapSetOverscan\n"); +#endif + pScrn->SetOverscan(pScreenPriv->pScrn, overscan); + } + } +} + +static void +CMapUnwrapScreen(ScreenPtr pScreen) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + 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; + + xfree(pScreenPriv->gamma); + xfree(pScreenPriv->PreAllocIndices); + xfree(pScreenPriv); +} + + +static void +ComputeGamma(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 (priv->pScrn->gamma.red < GAMMA_MIN || + priv->pScrn->gamma.red > GAMMA_MAX || + priv->pScrn->gamma.green < GAMMA_MIN || + priv->pScrn->gamma.green > GAMMA_MAX || + priv->pScrn->gamma.blue < GAMMA_MIN || + priv->pScrn->gamma.blue > GAMMA_MAX) { + + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "The %s driver didn't call xf86SetGamma() to initialise\n" + "\tthe gamma values.\n", priv->pScrn->driverName); + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); + priv->pScrn->gamma.red = 1.0; + priv->pScrn->gamma.green = 1.0; + priv->pScrn->gamma.blue = 1.0; + } +#endif + + RedGamma = 1.0 / (double)priv->pScrn->gamma.red; + GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; + BlueGamma = 1.0 / (double)priv->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( + int index, + Gamma gamma +){ + int ret = Success; + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + /* Is this sufficient checking ? */ + if(CMapScreenKey == NULL) + 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(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(miInstalledMaps[pScreen->myNum] && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; + + 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 */ + miInstalledMaps[pScreen->myNum] = pLink->cmap; + CMapReinstallMap(pLink->cmap); + miInstalledMaps[pScreen->myNum] = pMap; + } + } else + CMapReinstallMap(pMap); + } + + pScrn->ChangeGamma = pScreenPriv->ChangeGamma; + if (pScrn->ChangeGamma) + ret = pScrn->ChangeGamma(index, 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 = xf86Screens[pScreen->myNum]; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize != size) + return BadValue; + + RRCrtcGammaSet(crtc, red, green, blue); + + return Success; + } + } + + if(CMapScreenKey == NULL) + 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(miInstalledMaps[pScreen->myNum] && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; + + 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 */ + miInstalledMaps[pScreen->myNum] = pLink->cmap; + CMapReinstallMap(pLink->cmap); + miInstalledMaps[pScreen->myNum] = pMap; + } + } else + CMapReinstallMap(pMap); + } + + return Success; +} + +int +xf86GetGammaRampSize(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) + return crtc->gammaSize; + } + + if(CMapScreenKey == NULL) 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 +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + LOCO *entry; + int shift, sigbits; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize < size) + return BadValue; + + if (!RRCrtcGammaGet(crtc)) + return BadImplementation; + + memcpy(red, crtc->gammaRed, size * sizeof(*red)); + memcpy(green, crtc->gammaGreen, size * sizeof(*green)); + memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); + + return Success; + } + } + + if(CMapScreenKey == NULL) + 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 = xf86Screens[pScreen->myNum]; + + if(pScrn->ChangeGamma) + return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); + + return BadImplementation; +} -- cgit v1.2.3