105b261ecSmrg/* 205b261ecSmrg * Copyright (c) 1998-2001 by The XFree86 Project, Inc. 305b261ecSmrg * 405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 505b261ecSmrg * copy of this software and associated documentation files (the "Software"), 605b261ecSmrg * to deal in the Software without restriction, including without limitation 705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 905b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1005b261ecSmrg * 1105b261ecSmrg * The above copyright notice and this permission notice shall be included in 1205b261ecSmrg * all copies or substantial portions of the Software. 1305b261ecSmrg * 1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1705b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1805b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1905b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2005b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 2105b261ecSmrg * 2205b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 2305b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 2405b261ecSmrg * the sale, use or other dealings in this Software without prior written 2505b261ecSmrg * authorization from the copyright holder(s) and author(s). 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 2905b261ecSmrg#include <xorg-config.h> 3005b261ecSmrg#endif 3105b261ecSmrg 321b5d61b8Smrg#if defined(_XOPEN_SOURCE) || defined(__sun) && defined(__SVR4) 3305b261ecSmrg#include <math.h> 3405b261ecSmrg#else 3535c4bbdfSmrg#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ 3605b261ecSmrg#include <math.h> 3705b261ecSmrg#undef _XOPEN_SOURCE 3805b261ecSmrg#endif 3905b261ecSmrg 4005b261ecSmrg#include <X11/X.h> 4105b261ecSmrg#include "misc.h" 4205b261ecSmrg#include <X11/Xproto.h> 4305b261ecSmrg#include "colormapst.h" 4405b261ecSmrg#include "scrnintstr.h" 4505b261ecSmrg 4605b261ecSmrg#include "resource.h" 4705b261ecSmrg 4805b261ecSmrg#include "xf86.h" 4905b261ecSmrg#include "xf86_OSproc.h" 5005b261ecSmrg#include "xf86str.h" 5105b261ecSmrg#include "micmap.h" 521b5d61b8Smrg#include "xf86RandR12.h" 536747b715Smrg#include "xf86Crtc.h" 5405b261ecSmrg 5505b261ecSmrg#ifdef XFreeXDGA 566747b715Smrg#include <X11/extensions/xf86dgaproto.h> 5705b261ecSmrg#include "dgaproc.h" 5805b261ecSmrg#endif 5905b261ecSmrg 6005b261ecSmrg#include "xf86cmap.h" 6105b261ecSmrg 6205b261ecSmrg#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ 634642e01fSmrg ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field) 6405b261ecSmrg#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ 6505b261ecSmrg ((pScreen)->field = wrapper) 6605b261ecSmrg 676747b715Smrg#define LOAD_PALETTE(pmap) \ 686747b715Smrg ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ 6905b261ecSmrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ 7035c4bbdfSmrg xf86ScreenToScrn(pmap->pScreen)->vtSema || pScreenPriv->isDGAmode)) 7105b261ecSmrg 7205b261ecSmrgtypedef struct _CMapLink { 7335c4bbdfSmrg ColormapPtr cmap; 7435c4bbdfSmrg struct _CMapLink *next; 7505b261ecSmrg} CMapLink, *CMapLinkPtr; 7605b261ecSmrg 7705b261ecSmrgtypedef struct { 7835c4bbdfSmrg CloseScreenProcPtr CloseScreen; 7935c4bbdfSmrg CreateColormapProcPtr CreateColormap; 8035c4bbdfSmrg DestroyColormapProcPtr DestroyColormap; 8135c4bbdfSmrg InstallColormapProcPtr InstallColormap; 8235c4bbdfSmrg StoreColorsProcPtr StoreColors; 8335c4bbdfSmrg Bool (*EnterVT) (ScrnInfoPtr); 8435c4bbdfSmrg Bool (*SwitchMode) (ScrnInfoPtr, DisplayModePtr); 8535c4bbdfSmrg int (*SetDGAMode) (ScrnInfoPtr, int, DGADevicePtr); 8635c4bbdfSmrg xf86ChangeGammaProc *ChangeGamma; 8735c4bbdfSmrg int maxColors; 8835c4bbdfSmrg int sigRGBbits; 8935c4bbdfSmrg int gammaElements; 9035c4bbdfSmrg LOCO *gamma; 9135c4bbdfSmrg int *PreAllocIndices; 9235c4bbdfSmrg CMapLinkPtr maps; 9335c4bbdfSmrg unsigned int flags; 9435c4bbdfSmrg Bool isDGAmode; 9505b261ecSmrg} CMapScreenRec, *CMapScreenPtr; 9605b261ecSmrg 9705b261ecSmrgtypedef struct { 9835c4bbdfSmrg int numColors; 9935c4bbdfSmrg LOCO *colors; 10035c4bbdfSmrg Bool recalculate; 10135c4bbdfSmrg int overscan; 10205b261ecSmrg} CMapColormapRec, *CMapColormapPtr; 10305b261ecSmrg 1046747b715Smrgstatic DevPrivateKeyRec CMapScreenKeyRec; 10535c4bbdfSmrg 1066747b715Smrg#define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec) 1076747b715Smrg#define CMapScreenKey (&CMapScreenKeyRec) 1086747b715Smrgstatic DevPrivateKeyRec CMapColormapKeyRec; 10935c4bbdfSmrg 1106747b715Smrg#define CMapColormapKey (&CMapColormapKeyRec) 11105b261ecSmrg 11205b261ecSmrgstatic void CMapInstallColormap(ColormapPtr); 11305b261ecSmrgstatic void CMapStoreColors(ColormapPtr, int, xColorItem *); 11435c4bbdfSmrgstatic Bool CMapCloseScreen(ScreenPtr); 11535c4bbdfSmrgstatic Bool CMapCreateColormap(ColormapPtr); 11635c4bbdfSmrgstatic void CMapDestroyColormap(ColormapPtr); 11735c4bbdfSmrg 11835c4bbdfSmrgstatic Bool CMapEnterVT(ScrnInfoPtr); 11935c4bbdfSmrgstatic Bool CMapSwitchMode(ScrnInfoPtr, DisplayModePtr); 12005b261ecSmrg 1216747b715Smrg#ifdef XFreeXDGA 12235c4bbdfSmrgstatic int CMapSetDGAMode(ScrnInfoPtr, int, DGADevicePtr); 1236747b715Smrg#endif 12435c4bbdfSmrgstatic int CMapChangeGamma(ScrnInfoPtr, Gamma); 12505b261ecSmrg 12635c4bbdfSmrgstatic void ComputeGamma(ScrnInfoPtr, CMapScreenPtr); 12705b261ecSmrgstatic Bool CMapAllocateColormapPrivate(ColormapPtr); 12835c4bbdfSmrgstatic void CMapRefreshColors(ColormapPtr, int, int *); 12905b261ecSmrgstatic void CMapSetOverscan(ColormapPtr, int, int *); 13005b261ecSmrgstatic void CMapReinstallMap(ColormapPtr); 13105b261ecSmrgstatic void CMapUnwrapScreen(ScreenPtr pScreen); 13205b261ecSmrg 13335c4bbdfSmrgBool 13435c4bbdfSmrgxf86ColormapAllocatePrivates(ScrnInfoPtr pScrn) 1356747b715Smrg{ 1366747b715Smrg if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0)) 13735c4bbdfSmrg return FALSE; 1386747b715Smrg 1396747b715Smrg if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0)) 14035c4bbdfSmrg return FALSE; 1416747b715Smrg return TRUE; 1426747b715Smrg} 14305b261ecSmrg 14435c4bbdfSmrgBool 14535c4bbdfSmrgxf86HandleColormaps(ScreenPtr pScreen, 14635c4bbdfSmrg int maxColors, 14735c4bbdfSmrg int sigRGBbits, 14835c4bbdfSmrg xf86LoadPaletteProc * loadPalette, 14935c4bbdfSmrg xf86SetOverscanProc * setOverscan, unsigned int flags) 15035c4bbdfSmrg{ 15135c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 15205b261ecSmrg ColormapPtr pDefMap = NULL; 15335c4bbdfSmrg CMapScreenPtr pScreenPriv; 15435c4bbdfSmrg LOCO *gamma; 15535c4bbdfSmrg int *indices; 15605b261ecSmrg int elements; 15705b261ecSmrg 1581b5d61b8Smrg if (!maxColors || !sigRGBbits || 1591b5d61b8Smrg (!loadPalette && !xf86_crtc_supports_gamma(pScrn))) 16035c4bbdfSmrg return FALSE; 16105b261ecSmrg 16205b261ecSmrg elements = 1 << sigRGBbits; 16305b261ecSmrg 16435c4bbdfSmrg if (!(gamma = xallocarray(elements, sizeof(LOCO)))) 16535c4bbdfSmrg return FALSE; 16605b261ecSmrg 16735c4bbdfSmrg if (!(indices = xallocarray(maxColors, sizeof(int)))) { 16835c4bbdfSmrg free(gamma); 16935c4bbdfSmrg return FALSE; 17005b261ecSmrg } 17135c4bbdfSmrg 17235c4bbdfSmrg if (!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) { 17335c4bbdfSmrg free(gamma); 17435c4bbdfSmrg free(indices); 17535c4bbdfSmrg return FALSE; 17605b261ecSmrg } 17705b261ecSmrg 1786747b715Smrg dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv); 17935c4bbdfSmrg 18005b261ecSmrg pScreenPriv->CloseScreen = pScreen->CloseScreen; 18105b261ecSmrg pScreenPriv->CreateColormap = pScreen->CreateColormap; 18205b261ecSmrg pScreenPriv->DestroyColormap = pScreen->DestroyColormap; 18305b261ecSmrg pScreenPriv->InstallColormap = pScreen->InstallColormap; 18405b261ecSmrg pScreenPriv->StoreColors = pScreen->StoreColors; 18505b261ecSmrg pScreen->CloseScreen = CMapCloseScreen; 18605b261ecSmrg pScreen->CreateColormap = CMapCreateColormap; 18705b261ecSmrg pScreen->DestroyColormap = CMapDestroyColormap; 18805b261ecSmrg pScreen->InstallColormap = CMapInstallColormap; 18905b261ecSmrg pScreen->StoreColors = CMapStoreColors; 19005b261ecSmrg 19105b261ecSmrg pScrn->LoadPalette = loadPalette; 19205b261ecSmrg pScrn->SetOverscan = setOverscan; 19305b261ecSmrg pScreenPriv->maxColors = maxColors; 19405b261ecSmrg pScreenPriv->sigRGBbits = sigRGBbits; 19505b261ecSmrg pScreenPriv->gammaElements = elements; 19605b261ecSmrg pScreenPriv->gamma = gamma; 19705b261ecSmrg pScreenPriv->PreAllocIndices = indices; 19805b261ecSmrg pScreenPriv->maps = NULL; 19905b261ecSmrg pScreenPriv->flags = flags; 20005b261ecSmrg pScreenPriv->isDGAmode = FALSE; 20105b261ecSmrg 20205b261ecSmrg pScreenPriv->EnterVT = pScrn->EnterVT; 20305b261ecSmrg pScreenPriv->SwitchMode = pScrn->SwitchMode; 20435c4bbdfSmrg pScreenPriv->SetDGAMode = pScrn->SetDGAMode; 2056747b715Smrg pScreenPriv->ChangeGamma = pScrn->ChangeGamma; 20605b261ecSmrg 20705b261ecSmrg if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) { 20835c4bbdfSmrg pScrn->EnterVT = CMapEnterVT; 20935c4bbdfSmrg if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode) 21035c4bbdfSmrg pScrn->SwitchMode = CMapSwitchMode; 21105b261ecSmrg } 21205b261ecSmrg#ifdef XFreeXDGA 21305b261ecSmrg pScrn->SetDGAMode = CMapSetDGAMode; 21405b261ecSmrg#endif 21505b261ecSmrg pScrn->ChangeGamma = CMapChangeGamma; 21635c4bbdfSmrg 21735c4bbdfSmrg ComputeGamma(pScrn, pScreenPriv); 21805b261ecSmrg 21905b261ecSmrg /* get the default map */ 22035c4bbdfSmrg dixLookupResourceByType((void **) &pDefMap, pScreen->defColormap, 22135c4bbdfSmrg RT_COLORMAP, serverClient, DixInstallAccess); 22235c4bbdfSmrg 22335c4bbdfSmrg if (!CMapAllocateColormapPrivate(pDefMap)) { 22405b261ecSmrg CMapUnwrapScreen(pScreen); 22535c4bbdfSmrg return FALSE; 22605b261ecSmrg } 22705b261ecSmrg 2281b5d61b8Smrg if (xf86_crtc_supports_gamma(pScrn)) { 2291b5d61b8Smrg pScrn->LoadPalette = xf86RandR12LoadPalette; 2301b5d61b8Smrg 2311b5d61b8Smrg if (!xf86RandR12InitGamma(pScrn, elements)) { 2321b5d61b8Smrg CMapUnwrapScreen(pScreen); 2331b5d61b8Smrg return FALSE; 2341b5d61b8Smrg } 2351b5d61b8Smrg } 2361b5d61b8Smrg 23705b261ecSmrg /* Force the initial map to be loaded */ 2386747b715Smrg SetInstalledmiColormap(pScreen, NULL); 23905b261ecSmrg CMapInstallColormap(pDefMap); 24005b261ecSmrg return TRUE; 24105b261ecSmrg} 24205b261ecSmrg 24305b261ecSmrg/**** Screen functions ****/ 24405b261ecSmrg 24505b261ecSmrgstatic Bool 24635c4bbdfSmrgCMapCloseScreen(ScreenPtr pScreen) 24705b261ecSmrg{ 24805b261ecSmrg CMapUnwrapScreen(pScreen); 24905b261ecSmrg 25035c4bbdfSmrg return (*pScreen->CloseScreen) (pScreen); 25105b261ecSmrg} 25205b261ecSmrg 25305b261ecSmrgstatic Bool 25405b261ecSmrgCMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) 25505b261ecSmrg{ 25605b261ecSmrg if (pVisual->nplanes > 16) 25705b261ecSmrg return TRUE; 25805b261ecSmrg return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); 25905b261ecSmrg} 26005b261ecSmrg 26105b261ecSmrgstatic Bool 26205b261ecSmrgCMapAllocateColormapPrivate(ColormapPtr pmap) 26305b261ecSmrg{ 26435c4bbdfSmrg CMapScreenPtr pScreenPriv = 26535c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, 26635c4bbdfSmrg CMapScreenKey); 26705b261ecSmrg CMapColormapPtr pColPriv; 26805b261ecSmrg CMapLinkPtr pLink; 26905b261ecSmrg int numColors; 27005b261ecSmrg LOCO *colors; 27105b261ecSmrg 27205b261ecSmrg if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) 27335c4bbdfSmrg numColors = pmap->pVisual->ColormapEntries; 27435c4bbdfSmrg else 27535c4bbdfSmrg numColors = 1 << pmap->pVisual->nplanes; 27605b261ecSmrg 27735c4bbdfSmrg if (!(colors = xallocarray(numColors, sizeof(LOCO)))) 27835c4bbdfSmrg return FALSE; 27905b261ecSmrg 28035c4bbdfSmrg if (!(pColPriv = malloc(sizeof(CMapColormapRec)))) { 28135c4bbdfSmrg free(colors); 28235c4bbdfSmrg return FALSE; 28335c4bbdfSmrg } 28405b261ecSmrg 2854642e01fSmrg dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); 28635c4bbdfSmrg 28705b261ecSmrg pColPriv->numColors = numColors; 28805b261ecSmrg pColPriv->colors = colors; 28905b261ecSmrg pColPriv->recalculate = TRUE; 29005b261ecSmrg pColPriv->overscan = -1; 29105b261ecSmrg 29205b261ecSmrg /* add map to list */ 2936747b715Smrg pLink = malloc(sizeof(CMapLink)); 29435c4bbdfSmrg if (pLink) { 29535c4bbdfSmrg pLink->cmap = pmap; 29635c4bbdfSmrg pLink->next = pScreenPriv->maps; 29735c4bbdfSmrg pScreenPriv->maps = pLink; 29805b261ecSmrg } 29905b261ecSmrg 30005b261ecSmrg return TRUE; 30105b261ecSmrg} 30205b261ecSmrg 30335c4bbdfSmrgstatic Bool 30435c4bbdfSmrgCMapCreateColormap(ColormapPtr pmap) 30505b261ecSmrg{ 30605b261ecSmrg ScreenPtr pScreen = pmap->pScreen; 30735c4bbdfSmrg CMapScreenPtr pScreenPriv = 30835c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 30905b261ecSmrg Bool ret = FALSE; 31005b261ecSmrg 31105b261ecSmrg pScreen->CreateColormap = pScreenPriv->CreateColormap; 31235c4bbdfSmrg if ((*pScreen->CreateColormap) (pmap)) { 31335c4bbdfSmrg if (CMapAllocateColormapPrivate(pmap)) 31435c4bbdfSmrg ret = TRUE; 31505b261ecSmrg } 31605b261ecSmrg pScreen->CreateColormap = CMapCreateColormap; 31705b261ecSmrg 31805b261ecSmrg return ret; 31905b261ecSmrg} 32005b261ecSmrg 32105b261ecSmrgstatic void 32235c4bbdfSmrgCMapDestroyColormap(ColormapPtr cmap) 32305b261ecSmrg{ 32405b261ecSmrg ScreenPtr pScreen = cmap->pScreen; 32535c4bbdfSmrg CMapScreenPtr pScreenPriv = 32635c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 32735c4bbdfSmrg CMapColormapPtr pColPriv = 32835c4bbdfSmrg (CMapColormapPtr) dixLookupPrivate(&cmap->devPrivates, CMapColormapKey); 32905b261ecSmrg CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps; 33005b261ecSmrg 33135c4bbdfSmrg if (pColPriv) { 33235c4bbdfSmrg free(pColPriv->colors); 33335c4bbdfSmrg free(pColPriv); 33405b261ecSmrg } 33535c4bbdfSmrg 33605b261ecSmrg /* remove map from list */ 33735c4bbdfSmrg while (pLink) { 33835c4bbdfSmrg if (pLink->cmap == cmap) { 33935c4bbdfSmrg if (prevLink) 34035c4bbdfSmrg prevLink->next = pLink->next; 34135c4bbdfSmrg else 34235c4bbdfSmrg pScreenPriv->maps = pLink->next; 34335c4bbdfSmrg free(pLink); 34435c4bbdfSmrg break; 34535c4bbdfSmrg } 34635c4bbdfSmrg prevLink = pLink; 34735c4bbdfSmrg pLink = pLink->next; 34805b261ecSmrg } 34905b261ecSmrg 35035c4bbdfSmrg if (pScreenPriv->DestroyColormap) { 35135c4bbdfSmrg pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 35235c4bbdfSmrg (*pScreen->DestroyColormap) (cmap); 35335c4bbdfSmrg pScreen->DestroyColormap = CMapDestroyColormap; 35405b261ecSmrg } 35505b261ecSmrg} 35605b261ecSmrg 35705b261ecSmrgstatic void 35835c4bbdfSmrgCMapStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs) 35935c4bbdfSmrg{ 36035c4bbdfSmrg ScreenPtr pScreen = pmap->pScreen; 36135c4bbdfSmrg VisualPtr pVisual = pmap->pVisual; 36235c4bbdfSmrg CMapScreenPtr pScreenPriv = 36335c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 36435c4bbdfSmrg int *indices = pScreenPriv->PreAllocIndices; 36535c4bbdfSmrg int num = ndef; 36605b261ecSmrg 36705b261ecSmrg /* At the moment this isn't necessary since there's nobody below us */ 36805b261ecSmrg pScreen->StoreColors = pScreenPriv->StoreColors; 36935c4bbdfSmrg (*pScreen->StoreColors) (pmap, ndef, pdefs); 37005b261ecSmrg pScreen->StoreColors = CMapStoreColors; 37105b261ecSmrg 37205b261ecSmrg /* should never get here for these */ 37335c4bbdfSmrg if ((pVisual->class == TrueColor) || 37435c4bbdfSmrg (pVisual->class == StaticColor) || (pVisual->class == StaticGray)) 37535c4bbdfSmrg return; 37635c4bbdfSmrg 37735c4bbdfSmrg if (pVisual->class == DirectColor) { 37835c4bbdfSmrg CMapColormapPtr pColPriv = 37935c4bbdfSmrg (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, 38035c4bbdfSmrg CMapColormapKey); 38135c4bbdfSmrg int i; 38235c4bbdfSmrg 38335c4bbdfSmrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 38435c4bbdfSmrg int index; 38535c4bbdfSmrg 38635c4bbdfSmrg num = 0; 38735c4bbdfSmrg while (ndef--) { 38835c4bbdfSmrg if (pdefs[ndef].flags & DoRed) { 38935c4bbdfSmrg index = (pdefs[ndef].pixel & pVisual->redMask) >> 39035c4bbdfSmrg pVisual->offsetRed; 39135c4bbdfSmrg i = num; 39235c4bbdfSmrg while (i--) 39335c4bbdfSmrg if (indices[i] == index) 39435c4bbdfSmrg break; 39535c4bbdfSmrg if (i == -1) 39635c4bbdfSmrg indices[num++] = index; 39735c4bbdfSmrg } 39835c4bbdfSmrg if (pdefs[ndef].flags & DoGreen) { 39935c4bbdfSmrg index = (pdefs[ndef].pixel & pVisual->greenMask) >> 40035c4bbdfSmrg pVisual->offsetGreen; 40135c4bbdfSmrg i = num; 40235c4bbdfSmrg while (i--) 40335c4bbdfSmrg if (indices[i] == index) 40435c4bbdfSmrg break; 40535c4bbdfSmrg if (i == -1) 40635c4bbdfSmrg indices[num++] = index; 40735c4bbdfSmrg } 40835c4bbdfSmrg if (pdefs[ndef].flags & DoBlue) { 40935c4bbdfSmrg index = (pdefs[ndef].pixel & pVisual->blueMask) >> 41035c4bbdfSmrg pVisual->offsetBlue; 41135c4bbdfSmrg i = num; 41235c4bbdfSmrg while (i--) 41335c4bbdfSmrg if (indices[i] == index) 41435c4bbdfSmrg break; 41535c4bbdfSmrg if (i == -1) 41635c4bbdfSmrg indices[num++] = index; 41735c4bbdfSmrg } 41835c4bbdfSmrg } 41935c4bbdfSmrg 42035c4bbdfSmrg } 42135c4bbdfSmrg else { 42235c4bbdfSmrg /* not really as overkill as it seems */ 42335c4bbdfSmrg num = pColPriv->numColors; 42435c4bbdfSmrg for (i = 0; i < pColPriv->numColors; i++) 42535c4bbdfSmrg indices[i] = i; 42635c4bbdfSmrg } 42735c4bbdfSmrg } 42835c4bbdfSmrg else { 42935c4bbdfSmrg while (ndef--) 43035c4bbdfSmrg indices[ndef] = pdefs[ndef].pixel; 43135c4bbdfSmrg } 43205b261ecSmrg 43305b261ecSmrg CMapRefreshColors(pmap, num, indices); 43405b261ecSmrg} 43505b261ecSmrg 43605b261ecSmrgstatic void 43705b261ecSmrgCMapInstallColormap(ColormapPtr pmap) 43805b261ecSmrg{ 43935c4bbdfSmrg ScreenPtr pScreen = pmap->pScreen; 44035c4bbdfSmrg CMapScreenPtr pScreenPriv = 44135c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 44205b261ecSmrg 4436747b715Smrg if (pmap == GetInstalledmiColormap(pmap->pScreen)) 44435c4bbdfSmrg return; 44505b261ecSmrg 44605b261ecSmrg pScreen->InstallColormap = pScreenPriv->InstallColormap; 44735c4bbdfSmrg (*pScreen->InstallColormap) (pmap); 44805b261ecSmrg pScreen->InstallColormap = CMapInstallColormap; 44905b261ecSmrg 45035c4bbdfSmrg /* Important. We let the lower layers, namely DGA, 45105b261ecSmrg overwrite the choice of Colormap to install */ 4526747b715Smrg if (GetInstalledmiColormap(pmap->pScreen)) 45335c4bbdfSmrg pmap = GetInstalledmiColormap(pmap->pScreen); 45405b261ecSmrg 45505b261ecSmrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 45635c4bbdfSmrg (pmap->pVisual->class == TrueColor) && 45735c4bbdfSmrg CMapColormapUseMax(pmap->pVisual, pScreenPriv)) 45835c4bbdfSmrg return; 45905b261ecSmrg 46035c4bbdfSmrg if (LOAD_PALETTE(pmap)) 46135c4bbdfSmrg CMapReinstallMap(pmap); 46205b261ecSmrg} 46305b261ecSmrg 46405b261ecSmrg/**** ScrnInfoRec functions ****/ 46505b261ecSmrg 46635c4bbdfSmrgstatic Bool 46735c4bbdfSmrgCMapEnterVT(ScrnInfoPtr pScrn) 46805b261ecSmrg{ 46935c4bbdfSmrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 4706747b715Smrg Bool ret; 47135c4bbdfSmrg CMapScreenPtr pScreenPriv = 47235c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 47305b261ecSmrg 4746747b715Smrg pScrn->EnterVT = pScreenPriv->EnterVT; 47535c4bbdfSmrg ret = (*pScreenPriv->EnterVT) (pScrn); 4766747b715Smrg pScreenPriv->EnterVT = pScrn->EnterVT; 4776747b715Smrg pScrn->EnterVT = CMapEnterVT; 47835c4bbdfSmrg if (ret) { 47935c4bbdfSmrg if (GetInstalledmiColormap(pScreen)) 48035c4bbdfSmrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 48135c4bbdfSmrg return TRUE; 48205b261ecSmrg } 48305b261ecSmrg return FALSE; 48405b261ecSmrg} 48505b261ecSmrg 48635c4bbdfSmrgstatic Bool 48735c4bbdfSmrgCMapSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 48805b261ecSmrg{ 48935c4bbdfSmrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 49035c4bbdfSmrg CMapScreenPtr pScreenPriv = 49135c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 49235c4bbdfSmrg 49335c4bbdfSmrg if ((*pScreenPriv->SwitchMode) (pScrn, mode)) { 49435c4bbdfSmrg if (GetInstalledmiColormap(pScreen)) 49535c4bbdfSmrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 49635c4bbdfSmrg return TRUE; 49705b261ecSmrg } 49805b261ecSmrg return FALSE; 49905b261ecSmrg} 50005b261ecSmrg 50105b261ecSmrg#ifdef XFreeXDGA 50235c4bbdfSmrgstatic int 50335c4bbdfSmrgCMapSetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr dev) 50405b261ecSmrg{ 50535c4bbdfSmrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 50635c4bbdfSmrg CMapScreenPtr pScreenPriv = 50735c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 50805b261ecSmrg int ret; 50905b261ecSmrg 51035c4bbdfSmrg ret = (*pScreenPriv->SetDGAMode) (pScrn, num, dev); 51105b261ecSmrg 51235c4bbdfSmrg pScreenPriv->isDGAmode = DGAActive(pScrn->scrnIndex); 51305b261ecSmrg 51435c4bbdfSmrg if (!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) 51535c4bbdfSmrg && xf86ScreenToScrn(pScreen)->vtSema) 51635c4bbdfSmrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 51705b261ecSmrg 51805b261ecSmrg return ret; 51905b261ecSmrg} 52005b261ecSmrg#endif 52105b261ecSmrg 52205b261ecSmrg/**** Utilities ****/ 52305b261ecSmrg 52405b261ecSmrgstatic void 52505b261ecSmrgCMapReinstallMap(ColormapPtr pmap) 52605b261ecSmrg{ 52735c4bbdfSmrg CMapScreenPtr pScreenPriv = 52835c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, 52935c4bbdfSmrg CMapScreenKey); 53035c4bbdfSmrg CMapColormapPtr cmapPriv = 53135c4bbdfSmrg (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey); 53235c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen); 53305b261ecSmrg int i = cmapPriv->numColors; 53405b261ecSmrg int *indices = pScreenPriv->PreAllocIndices; 53505b261ecSmrg 53635c4bbdfSmrg while (i--) 53735c4bbdfSmrg indices[i] = i; 53835c4bbdfSmrg 53935c4bbdfSmrg if (cmapPriv->recalculate) 54035c4bbdfSmrg CMapRefreshColors(pmap, cmapPriv->numColors, indices); 54105b261ecSmrg else { 54235c4bbdfSmrg (*pScrn->LoadPalette) (pScrn, cmapPriv->numColors, 54335c4bbdfSmrg indices, cmapPriv->colors, pmap->pVisual); 54435c4bbdfSmrg if (pScrn->SetOverscan) { 54505b261ecSmrg#ifdef DEBUGOVERSCAN 54635c4bbdfSmrg ErrorF("SetOverscan() called from CMapReinstallMap\n"); 54705b261ecSmrg#endif 54835c4bbdfSmrg pScrn->SetOverscan(pScrn, cmapPriv->overscan); 54935c4bbdfSmrg } 55005b261ecSmrg } 55105b261ecSmrg 55205b261ecSmrg cmapPriv->recalculate = FALSE; 55305b261ecSmrg} 55405b261ecSmrg 55535c4bbdfSmrgstatic void 55635c4bbdfSmrgCMapRefreshColors(ColormapPtr pmap, int defs, int *indices) 55705b261ecSmrg{ 55835c4bbdfSmrg CMapScreenPtr pScreenPriv = 55935c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, 56035c4bbdfSmrg CMapScreenKey); 56135c4bbdfSmrg CMapColormapPtr pColPriv = 56235c4bbdfSmrg (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey); 56305b261ecSmrg VisualPtr pVisual = pmap->pVisual; 56435c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen); 56505b261ecSmrg int numColors, i; 56605b261ecSmrg LOCO *gamma, *colors; 56705b261ecSmrg EntryPtr entry; 56805b261ecSmrg int reds, greens, blues, maxValue, index, shift; 56905b261ecSmrg 57005b261ecSmrg numColors = pColPriv->numColors; 57105b261ecSmrg shift = 16 - pScreenPriv->sigRGBbits; 57205b261ecSmrg maxValue = (1 << pScreenPriv->sigRGBbits) - 1; 57305b261ecSmrg gamma = pScreenPriv->gamma; 57405b261ecSmrg colors = pColPriv->colors; 57505b261ecSmrg 57605b261ecSmrg reds = pVisual->redMask >> pVisual->offsetRed; 57705b261ecSmrg greens = pVisual->greenMask >> pVisual->offsetGreen; 57805b261ecSmrg blues = pVisual->blueMask >> pVisual->offsetBlue; 57905b261ecSmrg 58035c4bbdfSmrg switch (pVisual->class) { 58105b261ecSmrg case StaticGray: 58235c4bbdfSmrg for (i = 0; i < numColors; i++) { 58335c4bbdfSmrg index = (i + 1) * maxValue / numColors; 58435c4bbdfSmrg colors[i].red = gamma[index].red; 58535c4bbdfSmrg colors[i].green = gamma[index].green; 58635c4bbdfSmrg colors[i].blue = gamma[index].blue; 58735c4bbdfSmrg } 58835c4bbdfSmrg break; 58905b261ecSmrg case TrueColor: 59005b261ecSmrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 59135c4bbdfSmrg for (i = 0; i <= reds; i++) 59235c4bbdfSmrg colors[i].red = gamma[i * maxValue / reds].red; 59335c4bbdfSmrg for (i = 0; i <= greens; i++) 59435c4bbdfSmrg colors[i].green = gamma[i * maxValue / greens].green; 59535c4bbdfSmrg for (i = 0; i <= blues; i++) 59635c4bbdfSmrg colors[i].blue = gamma[i * maxValue / blues].blue; 59735c4bbdfSmrg break; 59835c4bbdfSmrg } 59935c4bbdfSmrg for (i = 0; i < numColors; i++) { 60035c4bbdfSmrg colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) * 60135c4bbdfSmrg maxValue / reds].red; 60235c4bbdfSmrg colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) * 60335c4bbdfSmrg maxValue / greens].green; 60435c4bbdfSmrg colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) * 60535c4bbdfSmrg maxValue / blues].blue; 60635c4bbdfSmrg } 60735c4bbdfSmrg break; 60805b261ecSmrg case StaticColor: 60905b261ecSmrg case PseudoColor: 61005b261ecSmrg case GrayScale: 61135c4bbdfSmrg for (i = 0; i < defs; i++) { 61235c4bbdfSmrg index = indices[i]; 61335c4bbdfSmrg entry = (EntryPtr) &pmap->red[index]; 61435c4bbdfSmrg 61535c4bbdfSmrg if (entry->fShared) { 61635c4bbdfSmrg colors[index].red = 61735c4bbdfSmrg gamma[entry->co.shco.red->color >> shift].red; 61835c4bbdfSmrg colors[index].green = 61935c4bbdfSmrg gamma[entry->co.shco.green->color >> shift].green; 62035c4bbdfSmrg colors[index].blue = 62135c4bbdfSmrg gamma[entry->co.shco.blue->color >> shift].blue; 62235c4bbdfSmrg } 62335c4bbdfSmrg else { 62435c4bbdfSmrg colors[index].red = gamma[entry->co.local.red >> shift].red; 62535c4bbdfSmrg colors[index].green = 62635c4bbdfSmrg gamma[entry->co.local.green >> shift].green; 62735c4bbdfSmrg colors[index].blue = gamma[entry->co.local.blue >> shift].blue; 62835c4bbdfSmrg } 62935c4bbdfSmrg } 63035c4bbdfSmrg break; 63105b261ecSmrg case DirectColor: 63205b261ecSmrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 63335c4bbdfSmrg for (i = 0; i < defs; i++) { 63435c4bbdfSmrg index = indices[i]; 63535c4bbdfSmrg if (index <= reds) 63635c4bbdfSmrg colors[index].red = 63735c4bbdfSmrg gamma[pmap->red[index].co.local.red >> shift].red; 63835c4bbdfSmrg if (index <= greens) 63935c4bbdfSmrg colors[index].green = 64035c4bbdfSmrg gamma[pmap->green[index].co.local.green >> shift].green; 64135c4bbdfSmrg if (index <= blues) 64235c4bbdfSmrg colors[index].blue = 64335c4bbdfSmrg gamma[pmap->blue[index].co.local.blue >> shift].blue; 64405b261ecSmrg 64535c4bbdfSmrg } 64635c4bbdfSmrg break; 64735c4bbdfSmrg } 64835c4bbdfSmrg for (i = 0; i < defs; i++) { 64935c4bbdfSmrg index = indices[i]; 65035c4bbdfSmrg 65135c4bbdfSmrg colors[index].red = gamma[pmap->red[(index >> pVisual-> 65235c4bbdfSmrg offsetRed) & reds].co.local. 65335c4bbdfSmrg red >> shift].red; 65435c4bbdfSmrg colors[index].green = 65535c4bbdfSmrg gamma[pmap->green[(index >> pVisual->offsetGreen) & greens].co. 65635c4bbdfSmrg local.green >> shift].green; 65735c4bbdfSmrg colors[index].blue = 65835c4bbdfSmrg gamma[pmap->blue[(index >> pVisual->offsetBlue) & blues].co. 65935c4bbdfSmrg local.blue >> shift].blue; 66035c4bbdfSmrg } 66135c4bbdfSmrg break; 66235c4bbdfSmrg } 66305b261ecSmrg 66435c4bbdfSmrg if (LOAD_PALETTE(pmap)) 66535c4bbdfSmrg (*pScrn->LoadPalette) (pScrn, defs, indices, colors, pmap->pVisual); 66605b261ecSmrg 66705b261ecSmrg if (pScrn->SetOverscan) 66835c4bbdfSmrg CMapSetOverscan(pmap, defs, indices); 66905b261ecSmrg 67005b261ecSmrg} 67105b261ecSmrg 67205b261ecSmrgstatic Bool 67335c4bbdfSmrgCMapCompareColors(LOCO * color1, LOCO * color2) 67405b261ecSmrg{ 67505b261ecSmrg /* return TRUE if the color1 is "closer" to black than color2 */ 67605b261ecSmrg#ifdef DEBUGOVERSCAN 67705b261ecSmrg ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n", 67835c4bbdfSmrg color1->red, color1->green, color1->blue, 67935c4bbdfSmrg color2->red, color2->green, color2->blue, 68035c4bbdfSmrg color1->red + color1->green + color1->blue, 68135c4bbdfSmrg color2->red + color2->green + color2->blue); 68205b261ecSmrg#endif 68305b261ecSmrg return (color1->red + color1->green + color1->blue < 68435c4bbdfSmrg color2->red + color2->green + color2->blue); 68505b261ecSmrg} 68605b261ecSmrg 68705b261ecSmrgstatic void 68805b261ecSmrgCMapSetOverscan(ColormapPtr pmap, int defs, int *indices) 68905b261ecSmrg{ 69035c4bbdfSmrg CMapScreenPtr pScreenPriv = 69135c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, 69235c4bbdfSmrg CMapScreenKey); 69335c4bbdfSmrg CMapColormapPtr pColPriv = 69435c4bbdfSmrg (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey); 69535c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen); 69605b261ecSmrg VisualPtr pVisual = pmap->pVisual; 69705b261ecSmrg int i; 69805b261ecSmrg LOCO *colors; 69905b261ecSmrg int index; 70005b261ecSmrg Bool newOverscan = FALSE; 70105b261ecSmrg int overscan, tmpOverscan; 70205b261ecSmrg 70305b261ecSmrg colors = pColPriv->colors; 70405b261ecSmrg overscan = pColPriv->overscan; 70505b261ecSmrg 70605b261ecSmrg /* 70705b261ecSmrg * Search for a new overscan index in the following cases: 70805b261ecSmrg * 70905b261ecSmrg * - The index hasn't yet been initialised. In this case search 71005b261ecSmrg * for an index that is black or a close match to black. 71105b261ecSmrg * 71205b261ecSmrg * - The colour of the old index is changed. In this case search 71305b261ecSmrg * all indices for a black or close match to black. 71405b261ecSmrg * 71505b261ecSmrg * - The colour of the old index wasn't black. In this case only 71605b261ecSmrg * search the indices that were changed for a better match to black. 71705b261ecSmrg */ 71805b261ecSmrg 71905b261ecSmrg switch (pVisual->class) { 72005b261ecSmrg case StaticGray: 72105b261ecSmrg case TrueColor: 72235c4bbdfSmrg /* Should only come here once. Initialise the overscan index to 0 */ 72335c4bbdfSmrg overscan = 0; 72435c4bbdfSmrg newOverscan = TRUE; 72535c4bbdfSmrg break; 72605b261ecSmrg case StaticColor: 72735c4bbdfSmrg /* 72805b261ecSmrg * Only come here once, but search for the overscan in the same way 72905b261ecSmrg * as for the other cases. 73035c4bbdfSmrg */ 73105b261ecSmrg case DirectColor: 73205b261ecSmrg case PseudoColor: 73305b261ecSmrg case GrayScale: 73435c4bbdfSmrg if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { 73535c4bbdfSmrg /* Uninitialised */ 73635c4bbdfSmrg newOverscan = TRUE; 73735c4bbdfSmrg } 73835c4bbdfSmrg else { 73935c4bbdfSmrg /* Check if the overscan was changed */ 74035c4bbdfSmrg for (i = 0; i < defs; i++) { 74135c4bbdfSmrg index = indices[i]; 74235c4bbdfSmrg if (index == overscan) { 74335c4bbdfSmrg newOverscan = TRUE; 74435c4bbdfSmrg break; 74535c4bbdfSmrg } 74635c4bbdfSmrg } 74735c4bbdfSmrg } 74835c4bbdfSmrg if (newOverscan) { 74935c4bbdfSmrg /* The overscan is either uninitialised or it has been changed */ 75035c4bbdfSmrg 75135c4bbdfSmrg if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) 75235c4bbdfSmrg tmpOverscan = pScreenPriv->maxColors - 1; 75335c4bbdfSmrg else 75435c4bbdfSmrg tmpOverscan = overscan; 75535c4bbdfSmrg 75635c4bbdfSmrg /* search all entries for a close match to black */ 75735c4bbdfSmrg for (i = pScreenPriv->maxColors - 1; i >= 0; i--) { 75835c4bbdfSmrg if (colors[i].red == 0 && colors[i].green == 0 && 75935c4bbdfSmrg colors[i].blue == 0) { 76035c4bbdfSmrg overscan = i; 76105b261ecSmrg#ifdef DEBUGOVERSCAN 76235c4bbdfSmrg ErrorF("Black found at index 0x%02x\n", i); 76305b261ecSmrg#endif 76435c4bbdfSmrg break; 76535c4bbdfSmrg } 76635c4bbdfSmrg else { 76705b261ecSmrg#ifdef DEBUGOVERSCAN 76835c4bbdfSmrg ErrorF("0x%02x: ", i); 76905b261ecSmrg#endif 77035c4bbdfSmrg if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { 77135c4bbdfSmrg tmpOverscan = i; 77205b261ecSmrg#ifdef DEBUGOVERSCAN 77335c4bbdfSmrg ErrorF("possible \"Black\" at index 0x%02x\n", i); 77405b261ecSmrg#endif 77535c4bbdfSmrg } 77635c4bbdfSmrg } 77735c4bbdfSmrg } 77835c4bbdfSmrg if (i < 0) 77935c4bbdfSmrg overscan = tmpOverscan; 78035c4bbdfSmrg } 78135c4bbdfSmrg else { 78235c4bbdfSmrg /* Check of the old overscan wasn't black */ 78335c4bbdfSmrg if (colors[overscan].red != 0 || colors[overscan].green != 0 || 78435c4bbdfSmrg colors[overscan].blue != 0) { 78535c4bbdfSmrg int oldOverscan = tmpOverscan = overscan; 78635c4bbdfSmrg 78735c4bbdfSmrg /* See of there is now a better match */ 78835c4bbdfSmrg for (i = 0; i < defs; i++) { 78935c4bbdfSmrg index = indices[i]; 79035c4bbdfSmrg if (colors[index].red == 0 && colors[index].green == 0 && 79135c4bbdfSmrg colors[index].blue == 0) { 79235c4bbdfSmrg overscan = index; 79305b261ecSmrg#ifdef DEBUGOVERSCAN 79435c4bbdfSmrg ErrorF("Black found at index 0x%02x\n", index); 79505b261ecSmrg#endif 79635c4bbdfSmrg break; 79735c4bbdfSmrg } 79835c4bbdfSmrg else { 79905b261ecSmrg#ifdef DEBUGOVERSCAN 80035c4bbdfSmrg ErrorF("0x%02x: ", index); 80105b261ecSmrg#endif 80235c4bbdfSmrg if (CMapCompareColors(&colors[index], 80335c4bbdfSmrg &colors[tmpOverscan])) { 80435c4bbdfSmrg tmpOverscan = index; 80505b261ecSmrg#ifdef DEBUGOVERSCAN 80635c4bbdfSmrg ErrorF("possible \"Black\" at index 0x%02x\n", 80735c4bbdfSmrg index); 80805b261ecSmrg#endif 80935c4bbdfSmrg } 81035c4bbdfSmrg } 81135c4bbdfSmrg } 81235c4bbdfSmrg if (i == defs) 81335c4bbdfSmrg overscan = tmpOverscan; 81435c4bbdfSmrg if (overscan != oldOverscan) 81535c4bbdfSmrg newOverscan = TRUE; 81635c4bbdfSmrg } 81735c4bbdfSmrg } 81835c4bbdfSmrg break; 81905b261ecSmrg } 82005b261ecSmrg if (newOverscan) { 82135c4bbdfSmrg pColPriv->overscan = overscan; 82235c4bbdfSmrg if (LOAD_PALETTE(pmap)) { 82305b261ecSmrg#ifdef DEBUGOVERSCAN 82435c4bbdfSmrg ErrorF("SetOverscan() called from CmapSetOverscan\n"); 82505b261ecSmrg#endif 82635c4bbdfSmrg pScrn->SetOverscan(pScrn, overscan); 82735c4bbdfSmrg } 82805b261ecSmrg } 82905b261ecSmrg} 83005b261ecSmrg 83105b261ecSmrgstatic void 83205b261ecSmrgCMapUnwrapScreen(ScreenPtr pScreen) 83305b261ecSmrg{ 83435c4bbdfSmrg CMapScreenPtr pScreenPriv = 83535c4bbdfSmrg (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); 83635c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 83705b261ecSmrg 83805b261ecSmrg pScreen->CloseScreen = pScreenPriv->CloseScreen; 83905b261ecSmrg pScreen->CreateColormap = pScreenPriv->CreateColormap; 84005b261ecSmrg pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 84105b261ecSmrg pScreen->InstallColormap = pScreenPriv->InstallColormap; 84205b261ecSmrg pScreen->StoreColors = pScreenPriv->StoreColors; 84305b261ecSmrg 84435c4bbdfSmrg pScrn->EnterVT = pScreenPriv->EnterVT; 84535c4bbdfSmrg pScrn->SwitchMode = pScreenPriv->SwitchMode; 84635c4bbdfSmrg pScrn->SetDGAMode = pScreenPriv->SetDGAMode; 8476747b715Smrg pScrn->ChangeGamma = pScreenPriv->ChangeGamma; 84805b261ecSmrg 8496747b715Smrg free(pScreenPriv->gamma); 8506747b715Smrg free(pScreenPriv->PreAllocIndices); 8516747b715Smrg free(pScreenPriv); 85205b261ecSmrg} 85305b261ecSmrg 85435c4bbdfSmrgstatic void 85535c4bbdfSmrgComputeGamma(ScrnInfoPtr pScrn, CMapScreenPtr priv) 85605b261ecSmrg{ 85705b261ecSmrg int elements = priv->gammaElements - 1; 85805b261ecSmrg double RedGamma, GreenGamma, BlueGamma; 85905b261ecSmrg int i; 86005b261ecSmrg 86105b261ecSmrg#ifndef DONT_CHECK_GAMMA 86205b261ecSmrg /* This check is to catch drivers that are not initialising pScrn->gamma */ 86335c4bbdfSmrg if (pScrn->gamma.red < GAMMA_MIN || pScrn->gamma.red > GAMMA_MAX || 86435c4bbdfSmrg pScrn->gamma.green < GAMMA_MIN || pScrn->gamma.green > GAMMA_MAX || 86535c4bbdfSmrg pScrn->gamma.blue < GAMMA_MIN || pScrn->gamma.blue > GAMMA_MAX) { 86635c4bbdfSmrg 86735c4bbdfSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0, 86835c4bbdfSmrg "The %s driver didn't call xf86SetGamma() to initialise\n" 86935c4bbdfSmrg "\tthe gamma values.\n", pScrn->driverName); 87035c4bbdfSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 0, 87135c4bbdfSmrg "PLEASE FIX THE `%s' DRIVER!\n", 87235c4bbdfSmrg pScrn->driverName); 87335c4bbdfSmrg pScrn->gamma.red = 1.0; 87435c4bbdfSmrg pScrn->gamma.green = 1.0; 87535c4bbdfSmrg pScrn->gamma.blue = 1.0; 87605b261ecSmrg } 87705b261ecSmrg#endif 87805b261ecSmrg 87935c4bbdfSmrg RedGamma = 1.0 / (double) pScrn->gamma.red; 88035c4bbdfSmrg GreenGamma = 1.0 / (double) pScrn->gamma.green; 88135c4bbdfSmrg BlueGamma = 1.0 / (double) pScrn->gamma.blue; 88235c4bbdfSmrg 88335c4bbdfSmrg for (i = 0; i <= elements; i++) { 88435c4bbdfSmrg if (RedGamma == 1.0) 88535c4bbdfSmrg priv->gamma[i].red = i; 88635c4bbdfSmrg else 88735c4bbdfSmrg priv->gamma[i].red = (CARD16) (pow((double) i / (double) elements, 88835c4bbdfSmrg RedGamma) * (double) elements + 88935c4bbdfSmrg 0.5); 89035c4bbdfSmrg 89135c4bbdfSmrg if (GreenGamma == 1.0) 89235c4bbdfSmrg priv->gamma[i].green = i; 89335c4bbdfSmrg else 89435c4bbdfSmrg priv->gamma[i].green = (CARD16) (pow((double) i / (double) elements, 89535c4bbdfSmrg GreenGamma) * 89635c4bbdfSmrg (double) elements + 0.5); 89735c4bbdfSmrg 89835c4bbdfSmrg if (BlueGamma == 1.0) 89935c4bbdfSmrg priv->gamma[i].blue = i; 90035c4bbdfSmrg else 90135c4bbdfSmrg priv->gamma[i].blue = (CARD16) (pow((double) i / (double) elements, 90235c4bbdfSmrg BlueGamma) * (double) elements + 90335c4bbdfSmrg 0.5); 90405b261ecSmrg } 90505b261ecSmrg} 90605b261ecSmrg 90705b261ecSmrgint 90835c4bbdfSmrgCMapChangeGamma(ScrnInfoPtr pScrn, Gamma gamma) 90935c4bbdfSmrg{ 9106747b715Smrg int ret = Success; 91135c4bbdfSmrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 91205b261ecSmrg CMapColormapPtr pColPriv; 91305b261ecSmrg CMapScreenPtr pScreenPriv; 91405b261ecSmrg CMapLinkPtr pLink; 91535c4bbdfSmrg 91605b261ecSmrg /* Is this sufficient checking ? */ 91735c4bbdfSmrg if (!CMapScreenKeyRegistered) 91835c4bbdfSmrg return BadImplementation; 91935c4bbdfSmrg 92035c4bbdfSmrg pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 92135c4bbdfSmrg CMapScreenKey); 92235c4bbdfSmrg if (!pScreenPriv) 92335c4bbdfSmrg return BadImplementation; 92435c4bbdfSmrg 92505b261ecSmrg if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX || 92635c4bbdfSmrg gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX || 92735c4bbdfSmrg gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX) 92835c4bbdfSmrg return BadValue; 92905b261ecSmrg 93005b261ecSmrg pScrn->gamma.red = gamma.red; 93105b261ecSmrg pScrn->gamma.green = gamma.green; 93205b261ecSmrg pScrn->gamma.blue = gamma.blue; 93305b261ecSmrg 93435c4bbdfSmrg ComputeGamma(pScrn, pScreenPriv); 93505b261ecSmrg 93605b261ecSmrg /* mark all colormaps on this screen */ 93705b261ecSmrg pLink = pScreenPriv->maps; 93835c4bbdfSmrg while (pLink) { 93935c4bbdfSmrg pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates, 94035c4bbdfSmrg CMapColormapKey); 94135c4bbdfSmrg pColPriv->recalculate = TRUE; 94235c4bbdfSmrg pLink = pLink->next; 94305b261ecSmrg } 94405b261ecSmrg 94535c4bbdfSmrg if (GetInstalledmiColormap(pScreen) && 94635c4bbdfSmrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || 94735c4bbdfSmrg pScrn->vtSema || pScreenPriv->isDGAmode)) { 94835c4bbdfSmrg ColormapPtr pMap = GetInstalledmiColormap(pScreen); 94935c4bbdfSmrg 95035c4bbdfSmrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 95135c4bbdfSmrg (pMap->pVisual->class == TrueColor) && 95235c4bbdfSmrg CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { 95335c4bbdfSmrg 95435c4bbdfSmrg /* if the current map doesn't have a palette look 95535c4bbdfSmrg for another map to change the gamma on. */ 95635c4bbdfSmrg 95735c4bbdfSmrg pLink = pScreenPriv->maps; 95835c4bbdfSmrg while (pLink) { 95935c4bbdfSmrg if (pLink->cmap->pVisual->class == PseudoColor) 96035c4bbdfSmrg break; 96135c4bbdfSmrg pLink = pLink->next; 96235c4bbdfSmrg } 96335c4bbdfSmrg 96435c4bbdfSmrg if (pLink) { 96535c4bbdfSmrg /* need to trick CMapRefreshColors() into thinking 96635c4bbdfSmrg this is the currently installed map */ 96735c4bbdfSmrg SetInstalledmiColormap(pScreen, pLink->cmap); 96835c4bbdfSmrg CMapReinstallMap(pLink->cmap); 96935c4bbdfSmrg SetInstalledmiColormap(pScreen, pMap); 97035c4bbdfSmrg } 97135c4bbdfSmrg } 97235c4bbdfSmrg else 97335c4bbdfSmrg CMapReinstallMap(pMap); 97405b261ecSmrg } 97505b261ecSmrg 9766747b715Smrg pScrn->ChangeGamma = pScreenPriv->ChangeGamma; 9776747b715Smrg if (pScrn->ChangeGamma) 97835c4bbdfSmrg ret = pScrn->ChangeGamma(pScrn, gamma); 9796747b715Smrg pScrn->ChangeGamma = CMapChangeGamma; 9806747b715Smrg 9816747b715Smrg return ret; 98205b261ecSmrg} 98305b261ecSmrg 98405b261ecSmrgstatic void 98535c4bbdfSmrgComputeGammaRamp(CMapScreenPtr priv, 98635c4bbdfSmrg unsigned short *red, 98735c4bbdfSmrg unsigned short *green, unsigned short *blue) 98835c4bbdfSmrg{ 98905b261ecSmrg int elements = priv->gammaElements; 99005b261ecSmrg LOCO *entry = priv->gamma; 99105b261ecSmrg int shift = 16 - priv->sigRGBbits; 99205b261ecSmrg 99335c4bbdfSmrg while (elements--) { 99435c4bbdfSmrg entry->red = *(red++) >> shift; 99535c4bbdfSmrg entry->green = *(green++) >> shift; 99635c4bbdfSmrg entry->blue = *(blue++) >> shift; 99735c4bbdfSmrg entry++; 99805b261ecSmrg } 99905b261ecSmrg} 100005b261ecSmrg 10016747b715Smrgint 100235c4bbdfSmrgxf86ChangeGammaRamp(ScreenPtr pScreen, 100335c4bbdfSmrg int size, 100435c4bbdfSmrg unsigned short *red, 100535c4bbdfSmrg unsigned short *green, unsigned short *blue) 100635c4bbdfSmrg{ 100735c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 100805b261ecSmrg CMapColormapPtr pColPriv; 100905b261ecSmrg CMapScreenPtr pScreenPriv; 101005b261ecSmrg CMapLinkPtr pLink; 101105b261ecSmrg 101235c4bbdfSmrg if (!CMapScreenKeyRegistered) 101305b261ecSmrg return BadImplementation; 101405b261ecSmrg 101535c4bbdfSmrg pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 101635c4bbdfSmrg CMapScreenKey); 101735c4bbdfSmrg if (!pScreenPriv) 101805b261ecSmrg return BadImplementation; 101905b261ecSmrg 102035c4bbdfSmrg if (pScreenPriv->gammaElements != size) 102135c4bbdfSmrg return BadValue; 102205b261ecSmrg 102305b261ecSmrg ComputeGammaRamp(pScreenPriv, red, green, blue); 102405b261ecSmrg 102505b261ecSmrg /* mark all colormaps on this screen */ 102605b261ecSmrg pLink = pScreenPriv->maps; 102735c4bbdfSmrg while (pLink) { 102835c4bbdfSmrg pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates, 102935c4bbdfSmrg CMapColormapKey); 103005b261ecSmrg pColPriv->recalculate = TRUE; 103105b261ecSmrg pLink = pLink->next; 103205b261ecSmrg } 103305b261ecSmrg 103435c4bbdfSmrg if (GetInstalledmiColormap(pScreen) && 103535c4bbdfSmrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || 103635c4bbdfSmrg pScrn->vtSema || pScreenPriv->isDGAmode)) { 10376747b715Smrg ColormapPtr pMap = GetInstalledmiColormap(pScreen); 103805b261ecSmrg 103905b261ecSmrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 104005b261ecSmrg (pMap->pVisual->class == TrueColor) && 104135c4bbdfSmrg CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { 104205b261ecSmrg 104305b261ecSmrg /* if the current map doesn't have a palette look 104435c4bbdfSmrg for another map to change the gamma on. */ 104505b261ecSmrg 104605b261ecSmrg pLink = pScreenPriv->maps; 104735c4bbdfSmrg while (pLink) { 104835c4bbdfSmrg if (pLink->cmap->pVisual->class == PseudoColor) 104905b261ecSmrg break; 105005b261ecSmrg pLink = pLink->next; 105105b261ecSmrg } 105205b261ecSmrg 105335c4bbdfSmrg if (pLink) { 105405b261ecSmrg /* need to trick CMapRefreshColors() into thinking 105505b261ecSmrg this is the currently installed map */ 10566747b715Smrg SetInstalledmiColormap(pScreen, pLink->cmap); 105705b261ecSmrg CMapReinstallMap(pLink->cmap); 10586747b715Smrg SetInstalledmiColormap(pScreen, pMap); 105905b261ecSmrg } 106035c4bbdfSmrg } 106135c4bbdfSmrg else 106205b261ecSmrg CMapReinstallMap(pMap); 106305b261ecSmrg } 106405b261ecSmrg 106505b261ecSmrg return Success; 106605b261ecSmrg} 106705b261ecSmrg 10686747b715Smrgint 106905b261ecSmrgxf86GetGammaRampSize(ScreenPtr pScreen) 107005b261ecSmrg{ 107105b261ecSmrg CMapScreenPtr pScreenPriv; 107205b261ecSmrg 107335c4bbdfSmrg if (!CMapScreenKeyRegistered) 107435c4bbdfSmrg return 0; 107505b261ecSmrg 107635c4bbdfSmrg pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 107735c4bbdfSmrg CMapScreenKey); 107835c4bbdfSmrg if (!pScreenPriv) 107935c4bbdfSmrg return 0; 108005b261ecSmrg 108105b261ecSmrg return pScreenPriv->gammaElements; 108205b261ecSmrg} 108305b261ecSmrg 10846747b715Smrgint 108535c4bbdfSmrgxf86GetGammaRamp(ScreenPtr pScreen, 108635c4bbdfSmrg int size, 108735c4bbdfSmrg unsigned short *red, 108835c4bbdfSmrg unsigned short *green, unsigned short *blue) 108935c4bbdfSmrg{ 109005b261ecSmrg CMapScreenPtr pScreenPriv; 109105b261ecSmrg LOCO *entry; 109205b261ecSmrg int shift, sigbits; 109305b261ecSmrg 109435c4bbdfSmrg if (!CMapScreenKeyRegistered) 109535c4bbdfSmrg return BadImplementation; 109605b261ecSmrg 109735c4bbdfSmrg pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 109835c4bbdfSmrg CMapScreenKey); 109935c4bbdfSmrg if (!pScreenPriv) 110035c4bbdfSmrg return BadImplementation; 110105b261ecSmrg 110235c4bbdfSmrg if (size > pScreenPriv->gammaElements) 110335c4bbdfSmrg return BadValue; 110405b261ecSmrg 110505b261ecSmrg entry = pScreenPriv->gamma; 110605b261ecSmrg sigbits = pScreenPriv->sigRGBbits; 110705b261ecSmrg 110835c4bbdfSmrg while (size--) { 110935c4bbdfSmrg *red = entry->red << (16 - sigbits); 111035c4bbdfSmrg *green = entry->green << (16 - sigbits); 111135c4bbdfSmrg *blue = entry->blue << (16 - sigbits); 111235c4bbdfSmrg shift = sigbits; 111335c4bbdfSmrg while (shift < 16) { 111435c4bbdfSmrg *red |= *red >> shift; 111535c4bbdfSmrg *green |= *green >> shift; 111635c4bbdfSmrg *blue |= *blue >> shift; 111735c4bbdfSmrg shift += sigbits; 111835c4bbdfSmrg } 111935c4bbdfSmrg red++; 112035c4bbdfSmrg green++; 112135c4bbdfSmrg blue++; 112205b261ecSmrg entry++; 112305b261ecSmrg } 112405b261ecSmrg 112505b261ecSmrg return Success; 112605b261ecSmrg} 112705b261ecSmrg 112805b261ecSmrgint 112935c4bbdfSmrgxf86ChangeGamma(ScreenPtr pScreen, Gamma gamma) 113035c4bbdfSmrg{ 113135c4bbdfSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 113235c4bbdfSmrg 113335c4bbdfSmrg if (pScrn->ChangeGamma) 113435c4bbdfSmrg return (*pScrn->ChangeGamma) (pScrn, gamma); 113505b261ecSmrg 11366747b715Smrg return BadImplementation; 113705b261ecSmrg} 1138