1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 1998-2001 by The XFree86 Project, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 23706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 24706f2543Smrg * the sale, use or other dealings in this Software without prior written 25706f2543Smrg * authorization from the copyright holder(s) and author(s). 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 29706f2543Smrg#include <xorg-config.h> 30706f2543Smrg#endif 31706f2543Smrg 32706f2543Smrg#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) 33706f2543Smrg#include <math.h> 34706f2543Smrg#else 35706f2543Smrg#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ 36706f2543Smrg#include <math.h> 37706f2543Smrg#undef _XOPEN_SOURCE 38706f2543Smrg#endif 39706f2543Smrg 40706f2543Smrg#include <X11/X.h> 41706f2543Smrg#include "misc.h" 42706f2543Smrg#include <X11/Xproto.h> 43706f2543Smrg#include "colormapst.h" 44706f2543Smrg#include "scrnintstr.h" 45706f2543Smrg 46706f2543Smrg#include "resource.h" 47706f2543Smrg 48706f2543Smrg#include "xf86.h" 49706f2543Smrg#include "xf86_OSproc.h" 50706f2543Smrg#include "xf86str.h" 51706f2543Smrg#include "micmap.h" 52706f2543Smrg#include "xf86Crtc.h" 53706f2543Smrg 54706f2543Smrg#ifdef XFreeXDGA 55706f2543Smrg#include <X11/extensions/xf86dgaproto.h> 56706f2543Smrg#include "dgaproc.h" 57706f2543Smrg#endif 58706f2543Smrg 59706f2543Smrg#include "xf86cmap.h" 60706f2543Smrg 61706f2543Smrg#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ 62706f2543Smrg ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field) 63706f2543Smrg#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ 64706f2543Smrg ((pScreen)->field = wrapper) 65706f2543Smrg 66706f2543Smrg#define LOAD_PALETTE(pmap) \ 67706f2543Smrg ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ 68706f2543Smrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ 69706f2543Smrg xf86Screens[pmap->pScreen->myNum]->vtSema || pScreenPriv->isDGAmode)) 70706f2543Smrg 71706f2543Smrg 72706f2543Smrgtypedef struct _CMapLink { 73706f2543Smrg ColormapPtr cmap; 74706f2543Smrg struct _CMapLink *next; 75706f2543Smrg} CMapLink, *CMapLinkPtr; 76706f2543Smrg 77706f2543Smrgtypedef struct { 78706f2543Smrg ScrnInfoPtr pScrn; 79706f2543Smrg CloseScreenProcPtr CloseScreen; 80706f2543Smrg CreateColormapProcPtr CreateColormap; 81706f2543Smrg DestroyColormapProcPtr DestroyColormap; 82706f2543Smrg InstallColormapProcPtr InstallColormap; 83706f2543Smrg StoreColorsProcPtr StoreColors; 84706f2543Smrg Bool (*EnterVT)(int, int); 85706f2543Smrg Bool (*SwitchMode)(int, DisplayModePtr, int); 86706f2543Smrg int (*SetDGAMode)(int, int, DGADevicePtr); 87706f2543Smrg xf86ChangeGammaProc *ChangeGamma; 88706f2543Smrg int maxColors; 89706f2543Smrg int sigRGBbits; 90706f2543Smrg int gammaElements; 91706f2543Smrg LOCO *gamma; 92706f2543Smrg int *PreAllocIndices; 93706f2543Smrg CMapLinkPtr maps; 94706f2543Smrg unsigned int flags; 95706f2543Smrg Bool isDGAmode; 96706f2543Smrg} CMapScreenRec, *CMapScreenPtr; 97706f2543Smrg 98706f2543Smrgtypedef struct { 99706f2543Smrg int numColors; 100706f2543Smrg LOCO *colors; 101706f2543Smrg Bool recalculate; 102706f2543Smrg int overscan; 103706f2543Smrg} CMapColormapRec, *CMapColormapPtr; 104706f2543Smrg 105706f2543Smrgstatic DevPrivateKeyRec CMapScreenKeyRec; 106706f2543Smrg#define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec) 107706f2543Smrg#define CMapScreenKey (&CMapScreenKeyRec) 108706f2543Smrgstatic DevPrivateKeyRec CMapColormapKeyRec; 109706f2543Smrg#define CMapColormapKey (&CMapColormapKeyRec) 110706f2543Smrg 111706f2543Smrgstatic void CMapInstallColormap(ColormapPtr); 112706f2543Smrgstatic void CMapStoreColors(ColormapPtr, int, xColorItem *); 113706f2543Smrgstatic Bool CMapCloseScreen (int, ScreenPtr); 114706f2543Smrgstatic Bool CMapCreateColormap (ColormapPtr); 115706f2543Smrgstatic void CMapDestroyColormap (ColormapPtr); 116706f2543Smrg 117706f2543Smrgstatic Bool CMapEnterVT(int, int); 118706f2543Smrgstatic Bool CMapSwitchMode(int, DisplayModePtr, int); 119706f2543Smrg#ifdef XFreeXDGA 120706f2543Smrgstatic int CMapSetDGAMode(int, int, DGADevicePtr); 121706f2543Smrg#endif 122706f2543Smrgstatic int CMapChangeGamma(int, Gamma); 123706f2543Smrg 124706f2543Smrgstatic void ComputeGamma(CMapScreenPtr); 125706f2543Smrgstatic Bool CMapAllocateColormapPrivate(ColormapPtr); 126706f2543Smrgstatic void CMapRefreshColors(ColormapPtr, int, int*); 127706f2543Smrgstatic void CMapSetOverscan(ColormapPtr, int, int *); 128706f2543Smrgstatic void CMapReinstallMap(ColormapPtr); 129706f2543Smrgstatic void CMapUnwrapScreen(ScreenPtr pScreen); 130706f2543Smrg 131706f2543Smrg 132706f2543SmrgBool xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn) 133706f2543Smrg{ 134706f2543Smrg /* If we support a better colormap system, then pretend we succeeded. */ 135706f2543Smrg if (xf86_crtc_supports_gamma(pScrn)) 136706f2543Smrg return TRUE; 137706f2543Smrg if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0)) 138706f2543Smrg return FALSE; 139706f2543Smrg 140706f2543Smrg if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0)) 141706f2543Smrg return FALSE; 142706f2543Smrg return TRUE; 143706f2543Smrg} 144706f2543Smrg 145706f2543SmrgBool xf86HandleColormaps( 146706f2543Smrg ScreenPtr pScreen, 147706f2543Smrg int maxColors, 148706f2543Smrg int sigRGBbits, 149706f2543Smrg xf86LoadPaletteProc *loadPalette, 150706f2543Smrg xf86SetOverscanProc *setOverscan, 151706f2543Smrg unsigned int flags 152706f2543Smrg){ 153706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 154706f2543Smrg ColormapPtr pDefMap = NULL; 155706f2543Smrg CMapScreenPtr pScreenPriv; 156706f2543Smrg LOCO *gamma; 157706f2543Smrg int *indices; 158706f2543Smrg int elements; 159706f2543Smrg 160706f2543Smrg /* If we support a better colormap system, then pretend we succeeded. */ 161706f2543Smrg if (xf86_crtc_supports_gamma(pScrn)) 162706f2543Smrg return TRUE; 163706f2543Smrg 164706f2543Smrg if(!maxColors || !sigRGBbits || !loadPalette) 165706f2543Smrg return FALSE; 166706f2543Smrg 167706f2543Smrg elements = 1 << sigRGBbits; 168706f2543Smrg 169706f2543Smrg if(!(gamma = malloc(elements * sizeof(LOCO)))) 170706f2543Smrg return FALSE; 171706f2543Smrg 172706f2543Smrg if(!(indices = malloc(maxColors * sizeof(int)))) { 173706f2543Smrg free(gamma); 174706f2543Smrg return FALSE; 175706f2543Smrg } 176706f2543Smrg 177706f2543Smrg if(!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) { 178706f2543Smrg free(gamma); 179706f2543Smrg free(indices); 180706f2543Smrg return FALSE; 181706f2543Smrg } 182706f2543Smrg 183706f2543Smrg dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv); 184706f2543Smrg 185706f2543Smrg pScreenPriv->CloseScreen = pScreen->CloseScreen; 186706f2543Smrg pScreenPriv->CreateColormap = pScreen->CreateColormap; 187706f2543Smrg pScreenPriv->DestroyColormap = pScreen->DestroyColormap; 188706f2543Smrg pScreenPriv->InstallColormap = pScreen->InstallColormap; 189706f2543Smrg pScreenPriv->StoreColors = pScreen->StoreColors; 190706f2543Smrg pScreen->CloseScreen = CMapCloseScreen; 191706f2543Smrg pScreen->CreateColormap = CMapCreateColormap; 192706f2543Smrg pScreen->DestroyColormap = CMapDestroyColormap; 193706f2543Smrg pScreen->InstallColormap = CMapInstallColormap; 194706f2543Smrg pScreen->StoreColors = CMapStoreColors; 195706f2543Smrg 196706f2543Smrg pScreenPriv->pScrn = pScrn; 197706f2543Smrg pScrn->LoadPalette = loadPalette; 198706f2543Smrg pScrn->SetOverscan = setOverscan; 199706f2543Smrg pScreenPriv->maxColors = maxColors; 200706f2543Smrg pScreenPriv->sigRGBbits = sigRGBbits; 201706f2543Smrg pScreenPriv->gammaElements = elements; 202706f2543Smrg pScreenPriv->gamma = gamma; 203706f2543Smrg pScreenPriv->PreAllocIndices = indices; 204706f2543Smrg pScreenPriv->maps = NULL; 205706f2543Smrg pScreenPriv->flags = flags; 206706f2543Smrg pScreenPriv->isDGAmode = FALSE; 207706f2543Smrg 208706f2543Smrg pScreenPriv->EnterVT = pScrn->EnterVT; 209706f2543Smrg pScreenPriv->SwitchMode = pScrn->SwitchMode; 210706f2543Smrg pScreenPriv->SetDGAMode = pScrn->SetDGAMode; 211706f2543Smrg pScreenPriv->ChangeGamma = pScrn->ChangeGamma; 212706f2543Smrg 213706f2543Smrg if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) { 214706f2543Smrg pScrn->EnterVT = CMapEnterVT; 215706f2543Smrg if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode) 216706f2543Smrg pScrn->SwitchMode = CMapSwitchMode; 217706f2543Smrg } 218706f2543Smrg#ifdef XFreeXDGA 219706f2543Smrg pScrn->SetDGAMode = CMapSetDGAMode; 220706f2543Smrg#endif 221706f2543Smrg pScrn->ChangeGamma = CMapChangeGamma; 222706f2543Smrg 223706f2543Smrg ComputeGamma(pScreenPriv); 224706f2543Smrg 225706f2543Smrg /* get the default map */ 226706f2543Smrg dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, 227706f2543Smrg RT_COLORMAP, serverClient, DixInstallAccess); 228706f2543Smrg 229706f2543Smrg if(!CMapAllocateColormapPrivate(pDefMap)) { 230706f2543Smrg CMapUnwrapScreen(pScreen); 231706f2543Smrg return FALSE; 232706f2543Smrg } 233706f2543Smrg 234706f2543Smrg /* Force the initial map to be loaded */ 235706f2543Smrg SetInstalledmiColormap(pScreen, NULL); 236706f2543Smrg CMapInstallColormap(pDefMap); 237706f2543Smrg return TRUE; 238706f2543Smrg} 239706f2543Smrg 240706f2543Smrg 241706f2543Smrg/**** Screen functions ****/ 242706f2543Smrg 243706f2543Smrg 244706f2543Smrgstatic Bool 245706f2543SmrgCMapCloseScreen (int i, ScreenPtr pScreen) 246706f2543Smrg{ 247706f2543Smrg CMapUnwrapScreen(pScreen); 248706f2543Smrg 249706f2543Smrg return (*pScreen->CloseScreen) (i, pScreen); 250706f2543Smrg} 251706f2543Smrg 252706f2543Smrgstatic Bool 253706f2543SmrgCMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) 254706f2543Smrg{ 255706f2543Smrg if (pVisual->nplanes > 16) 256706f2543Smrg return TRUE; 257706f2543Smrg return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); 258706f2543Smrg} 259706f2543Smrg 260706f2543Smrgstatic Bool 261706f2543SmrgCMapAllocateColormapPrivate(ColormapPtr pmap) 262706f2543Smrg{ 263706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 264706f2543Smrg &pmap->pScreen->devPrivates, CMapScreenKey); 265706f2543Smrg CMapColormapPtr pColPriv; 266706f2543Smrg CMapLinkPtr pLink; 267706f2543Smrg int numColors; 268706f2543Smrg LOCO *colors; 269706f2543Smrg 270706f2543Smrg if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) 271706f2543Smrg numColors = pmap->pVisual->ColormapEntries; 272706f2543Smrg else 273706f2543Smrg numColors = 1 << pmap->pVisual->nplanes; 274706f2543Smrg 275706f2543Smrg if(!(colors = malloc(numColors * sizeof(LOCO)))) 276706f2543Smrg return FALSE; 277706f2543Smrg 278706f2543Smrg if(!(pColPriv = malloc(sizeof(CMapColormapRec)))) { 279706f2543Smrg free(colors); 280706f2543Smrg return FALSE; 281706f2543Smrg } 282706f2543Smrg 283706f2543Smrg dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); 284706f2543Smrg 285706f2543Smrg pColPriv->numColors = numColors; 286706f2543Smrg pColPriv->colors = colors; 287706f2543Smrg pColPriv->recalculate = TRUE; 288706f2543Smrg pColPriv->overscan = -1; 289706f2543Smrg 290706f2543Smrg /* add map to list */ 291706f2543Smrg pLink = malloc(sizeof(CMapLink)); 292706f2543Smrg if(pLink) { 293706f2543Smrg pLink->cmap = pmap; 294706f2543Smrg pLink->next = pScreenPriv->maps; 295706f2543Smrg pScreenPriv->maps = pLink; 296706f2543Smrg } 297706f2543Smrg 298706f2543Smrg return TRUE; 299706f2543Smrg} 300706f2543Smrg 301706f2543Smrgstatic Bool 302706f2543SmrgCMapCreateColormap (ColormapPtr pmap) 303706f2543Smrg{ 304706f2543Smrg ScreenPtr pScreen = pmap->pScreen; 305706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 306706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 307706f2543Smrg Bool ret = FALSE; 308706f2543Smrg 309706f2543Smrg pScreen->CreateColormap = pScreenPriv->CreateColormap; 310706f2543Smrg if((*pScreen->CreateColormap)(pmap)) { 311706f2543Smrg if(CMapAllocateColormapPrivate(pmap)) 312706f2543Smrg ret = TRUE; 313706f2543Smrg } 314706f2543Smrg pScreen->CreateColormap = CMapCreateColormap; 315706f2543Smrg 316706f2543Smrg return ret; 317706f2543Smrg} 318706f2543Smrg 319706f2543Smrgstatic void 320706f2543SmrgCMapDestroyColormap (ColormapPtr cmap) 321706f2543Smrg{ 322706f2543Smrg ScreenPtr pScreen = cmap->pScreen; 323706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 324706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 325706f2543Smrg CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( 326706f2543Smrg &cmap->devPrivates, CMapColormapKey); 327706f2543Smrg CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps; 328706f2543Smrg 329706f2543Smrg if(pColPriv) { 330706f2543Smrg free(pColPriv->colors); 331706f2543Smrg free(pColPriv); 332706f2543Smrg } 333706f2543Smrg 334706f2543Smrg /* remove map from list */ 335706f2543Smrg while(pLink) { 336706f2543Smrg if(pLink->cmap == cmap) { 337706f2543Smrg if(prevLink) 338706f2543Smrg prevLink->next = pLink->next; 339706f2543Smrg else 340706f2543Smrg pScreenPriv->maps = pLink->next; 341706f2543Smrg free(pLink); 342706f2543Smrg break; 343706f2543Smrg } 344706f2543Smrg prevLink = pLink; 345706f2543Smrg pLink = pLink->next; 346706f2543Smrg } 347706f2543Smrg 348706f2543Smrg if(pScreenPriv->DestroyColormap) { 349706f2543Smrg pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 350706f2543Smrg (*pScreen->DestroyColormap)(cmap); 351706f2543Smrg pScreen->DestroyColormap = CMapDestroyColormap; 352706f2543Smrg } 353706f2543Smrg} 354706f2543Smrg 355706f2543Smrg 356706f2543Smrg 357706f2543Smrgstatic void 358706f2543SmrgCMapStoreColors( 359706f2543Smrg ColormapPtr pmap, 360706f2543Smrg int ndef, 361706f2543Smrg xColorItem *pdefs 362706f2543Smrg){ 363706f2543Smrg ScreenPtr pScreen = pmap->pScreen; 364706f2543Smrg VisualPtr pVisual = pmap->pVisual; 365706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 366706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 367706f2543Smrg int *indices = pScreenPriv->PreAllocIndices; 368706f2543Smrg int num = ndef; 369706f2543Smrg 370706f2543Smrg /* At the moment this isn't necessary since there's nobody below us */ 371706f2543Smrg pScreen->StoreColors = pScreenPriv->StoreColors; 372706f2543Smrg (*pScreen->StoreColors)(pmap, ndef, pdefs); 373706f2543Smrg pScreen->StoreColors = CMapStoreColors; 374706f2543Smrg 375706f2543Smrg /* should never get here for these */ 376706f2543Smrg if( (pVisual->class == TrueColor) || 377706f2543Smrg (pVisual->class == StaticColor) || 378706f2543Smrg (pVisual->class == StaticGray)) 379706f2543Smrg return; 380706f2543Smrg 381706f2543Smrg if(pVisual->class == DirectColor) { 382706f2543Smrg CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( 383706f2543Smrg &pmap->devPrivates, CMapColormapKey); 384706f2543Smrg int i; 385706f2543Smrg 386706f2543Smrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 387706f2543Smrg int index; 388706f2543Smrg 389706f2543Smrg num = 0; 390706f2543Smrg while(ndef--) { 391706f2543Smrg if(pdefs[ndef].flags & DoRed) { 392706f2543Smrg index = (pdefs[ndef].pixel & pVisual->redMask) >> 393706f2543Smrg pVisual->offsetRed; 394706f2543Smrg i = num; 395706f2543Smrg while(i--) 396706f2543Smrg if(indices[i] == index) break; 397706f2543Smrg if(i == -1) 398706f2543Smrg indices[num++] = index; 399706f2543Smrg } 400706f2543Smrg if(pdefs[ndef].flags & DoGreen) { 401706f2543Smrg index = (pdefs[ndef].pixel & pVisual->greenMask) >> 402706f2543Smrg pVisual->offsetGreen; 403706f2543Smrg i = num; 404706f2543Smrg while(i--) 405706f2543Smrg if(indices[i] == index) break; 406706f2543Smrg if(i == -1) 407706f2543Smrg indices[num++] = index; 408706f2543Smrg } 409706f2543Smrg if(pdefs[ndef].flags & DoBlue) { 410706f2543Smrg index = (pdefs[ndef].pixel & pVisual->blueMask) >> 411706f2543Smrg pVisual->offsetBlue; 412706f2543Smrg i = num; 413706f2543Smrg while(i--) 414706f2543Smrg if(indices[i] == index) break; 415706f2543Smrg if(i == -1) 416706f2543Smrg indices[num++] = index; 417706f2543Smrg } 418706f2543Smrg } 419706f2543Smrg 420706f2543Smrg } else { 421706f2543Smrg /* not really as overkill as it seems */ 422706f2543Smrg num = pColPriv->numColors; 423706f2543Smrg for(i = 0; i < pColPriv->numColors; i++) 424706f2543Smrg indices[i] = i; 425706f2543Smrg } 426706f2543Smrg } else { 427706f2543Smrg while(ndef--) 428706f2543Smrg indices[ndef] = pdefs[ndef].pixel; 429706f2543Smrg } 430706f2543Smrg 431706f2543Smrg CMapRefreshColors(pmap, num, indices); 432706f2543Smrg} 433706f2543Smrg 434706f2543Smrg 435706f2543Smrgstatic void 436706f2543SmrgCMapInstallColormap(ColormapPtr pmap) 437706f2543Smrg{ 438706f2543Smrg ScreenPtr pScreen = pmap->pScreen; 439706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 440706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 441706f2543Smrg 442706f2543Smrg if (pmap == GetInstalledmiColormap(pmap->pScreen)) 443706f2543Smrg return; 444706f2543Smrg 445706f2543Smrg pScreen->InstallColormap = pScreenPriv->InstallColormap; 446706f2543Smrg (*pScreen->InstallColormap)(pmap); 447706f2543Smrg pScreen->InstallColormap = CMapInstallColormap; 448706f2543Smrg 449706f2543Smrg /* Important. We let the lower layers, namely DGA, 450706f2543Smrg overwrite the choice of Colormap to install */ 451706f2543Smrg if (GetInstalledmiColormap(pmap->pScreen)) 452706f2543Smrg pmap = GetInstalledmiColormap(pmap->pScreen); 453706f2543Smrg 454706f2543Smrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 455706f2543Smrg (pmap->pVisual->class == TrueColor) && 456706f2543Smrg CMapColormapUseMax(pmap->pVisual, pScreenPriv)) 457706f2543Smrg return; 458706f2543Smrg 459706f2543Smrg if(LOAD_PALETTE(pmap)) 460706f2543Smrg CMapReinstallMap(pmap); 461706f2543Smrg} 462706f2543Smrg 463706f2543Smrg 464706f2543Smrg/**** ScrnInfoRec functions ****/ 465706f2543Smrg 466706f2543Smrgstatic Bool 467706f2543SmrgCMapEnterVT(int index, int flags) 468706f2543Smrg{ 469706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 470706f2543Smrg ScreenPtr pScreen = screenInfo.screens[index]; 471706f2543Smrg Bool ret; 472706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 473706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 474706f2543Smrg 475706f2543Smrg pScrn->EnterVT = pScreenPriv->EnterVT; 476706f2543Smrg ret = (*pScreenPriv->EnterVT)(index, flags); 477706f2543Smrg pScreenPriv->EnterVT = pScrn->EnterVT; 478706f2543Smrg pScrn->EnterVT = CMapEnterVT; 479706f2543Smrg if(ret) { 480706f2543Smrg if(GetInstalledmiColormap(pScreen)) 481706f2543Smrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 482706f2543Smrg return TRUE; 483706f2543Smrg } 484706f2543Smrg return FALSE; 485706f2543Smrg} 486706f2543Smrg 487706f2543Smrg 488706f2543Smrgstatic Bool 489706f2543SmrgCMapSwitchMode(int index, DisplayModePtr mode, int flags) 490706f2543Smrg{ 491706f2543Smrg ScreenPtr pScreen = screenInfo.screens[index]; 492706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 493706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 494706f2543Smrg 495706f2543Smrg if((*pScreenPriv->SwitchMode)(index, mode, flags)) { 496706f2543Smrg if(GetInstalledmiColormap(pScreen)) 497706f2543Smrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 498706f2543Smrg return TRUE; 499706f2543Smrg } 500706f2543Smrg return FALSE; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrg#ifdef XFreeXDGA 504706f2543Smrgstatic int 505706f2543SmrgCMapSetDGAMode(int index, int num, DGADevicePtr dev) 506706f2543Smrg{ 507706f2543Smrg ScreenPtr pScreen = screenInfo.screens[index]; 508706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 509706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 510706f2543Smrg int ret; 511706f2543Smrg 512706f2543Smrg ret = (*pScreenPriv->SetDGAMode)(index, num, dev); 513706f2543Smrg 514706f2543Smrg pScreenPriv->isDGAmode = DGAActive(index); 515706f2543Smrg 516706f2543Smrg if(!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) 517706f2543Smrg && xf86Screens[pScreen->myNum]->vtSema) 518706f2543Smrg CMapReinstallMap(GetInstalledmiColormap(pScreen)); 519706f2543Smrg 520706f2543Smrg return ret; 521706f2543Smrg} 522706f2543Smrg#endif 523706f2543Smrg 524706f2543Smrg 525706f2543Smrg/**** Utilities ****/ 526706f2543Smrg 527706f2543Smrgstatic void 528706f2543SmrgCMapReinstallMap(ColormapPtr pmap) 529706f2543Smrg{ 530706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 531706f2543Smrg &pmap->pScreen->devPrivates, CMapScreenKey); 532706f2543Smrg CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate( 533706f2543Smrg &pmap->devPrivates, CMapColormapKey); 534706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; 535706f2543Smrg int i = cmapPriv->numColors; 536706f2543Smrg int *indices = pScreenPriv->PreAllocIndices; 537706f2543Smrg 538706f2543Smrg while(i--) 539706f2543Smrg indices[i] = i; 540706f2543Smrg 541706f2543Smrg if(cmapPriv->recalculate) 542706f2543Smrg CMapRefreshColors(pmap, cmapPriv->numColors, indices); 543706f2543Smrg else { 544706f2543Smrg (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors, 545706f2543Smrg indices, cmapPriv->colors, pmap->pVisual); 546706f2543Smrg if (pScrn->SetOverscan) { 547706f2543Smrg#ifdef DEBUGOVERSCAN 548706f2543Smrg ErrorF("SetOverscan() called from CMapReinstallMap\n"); 549706f2543Smrg#endif 550706f2543Smrg pScrn->SetOverscan(pScrn, cmapPriv->overscan); 551706f2543Smrg } 552706f2543Smrg } 553706f2543Smrg 554706f2543Smrg cmapPriv->recalculate = FALSE; 555706f2543Smrg} 556706f2543Smrg 557706f2543Smrg 558706f2543Smrgstatic void 559706f2543SmrgCMapRefreshColors(ColormapPtr pmap, int defs, int* indices) 560706f2543Smrg{ 561706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 562706f2543Smrg &pmap->pScreen->devPrivates, CMapScreenKey); 563706f2543Smrg CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( 564706f2543Smrg &pmap->devPrivates, CMapColormapKey); 565706f2543Smrg VisualPtr pVisual = pmap->pVisual; 566706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; 567706f2543Smrg int numColors, i; 568706f2543Smrg LOCO *gamma, *colors; 569706f2543Smrg EntryPtr entry; 570706f2543Smrg int reds, greens, blues, maxValue, index, shift; 571706f2543Smrg 572706f2543Smrg numColors = pColPriv->numColors; 573706f2543Smrg shift = 16 - pScreenPriv->sigRGBbits; 574706f2543Smrg maxValue = (1 << pScreenPriv->sigRGBbits) - 1; 575706f2543Smrg gamma = pScreenPriv->gamma; 576706f2543Smrg colors = pColPriv->colors; 577706f2543Smrg 578706f2543Smrg reds = pVisual->redMask >> pVisual->offsetRed; 579706f2543Smrg greens = pVisual->greenMask >> pVisual->offsetGreen; 580706f2543Smrg blues = pVisual->blueMask >> pVisual->offsetBlue; 581706f2543Smrg 582706f2543Smrg switch(pVisual->class) { 583706f2543Smrg case StaticGray: 584706f2543Smrg for(i = 0; i < numColors; i++) { 585706f2543Smrg index = (i+1) * maxValue / numColors; 586706f2543Smrg colors[i].red = gamma[index].red; 587706f2543Smrg colors[i].green = gamma[index].green; 588706f2543Smrg colors[i].blue = gamma[index].blue; 589706f2543Smrg } 590706f2543Smrg break; 591706f2543Smrg case TrueColor: 592706f2543Smrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 593706f2543Smrg for(i = 0; i <= reds; i++) 594706f2543Smrg colors[i].red = gamma[i * maxValue / reds].red; 595706f2543Smrg for(i = 0; i <= greens; i++) 596706f2543Smrg colors[i].green = gamma[i * maxValue / greens].green; 597706f2543Smrg for(i = 0; i <= blues; i++) 598706f2543Smrg colors[i].blue = gamma[i * maxValue / blues].blue; 599706f2543Smrg break; 600706f2543Smrg } 601706f2543Smrg for(i = 0; i < numColors; i++) { 602706f2543Smrg colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) * 603706f2543Smrg maxValue / reds].red; 604706f2543Smrg colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) * 605706f2543Smrg maxValue / greens].green; 606706f2543Smrg colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) * 607706f2543Smrg maxValue / blues].blue; 608706f2543Smrg } 609706f2543Smrg break; 610706f2543Smrg case StaticColor: 611706f2543Smrg case PseudoColor: 612706f2543Smrg case GrayScale: 613706f2543Smrg for(i = 0; i < defs; i++) { 614706f2543Smrg index = indices[i]; 615706f2543Smrg entry = (EntryPtr)&pmap->red[index]; 616706f2543Smrg 617706f2543Smrg if(entry->fShared) { 618706f2543Smrg colors[index].red = 619706f2543Smrg gamma[entry->co.shco.red->color >> shift].red; 620706f2543Smrg colors[index].green = 621706f2543Smrg gamma[entry->co.shco.green->color >> shift].green; 622706f2543Smrg colors[index].blue = 623706f2543Smrg gamma[entry->co.shco.blue->color >> shift].blue; 624706f2543Smrg } else { 625706f2543Smrg colors[index].red = 626706f2543Smrg gamma[entry->co.local.red >> shift].red; 627706f2543Smrg colors[index].green = 628706f2543Smrg gamma[entry->co.local.green >> shift].green; 629706f2543Smrg colors[index].blue = 630706f2543Smrg gamma[entry->co.local.blue >> shift].blue; 631706f2543Smrg } 632706f2543Smrg } 633706f2543Smrg break; 634706f2543Smrg case DirectColor: 635706f2543Smrg if (CMapColormapUseMax(pVisual, pScreenPriv)) { 636706f2543Smrg for(i = 0; i < defs; i++) { 637706f2543Smrg index = indices[i]; 638706f2543Smrg if(index <= reds) 639706f2543Smrg colors[index].red = 640706f2543Smrg gamma[pmap->red[index].co.local.red >> shift].red; 641706f2543Smrg if(index <= greens) 642706f2543Smrg colors[index].green = 643706f2543Smrg gamma[pmap->green[index].co.local.green >> shift].green; 644706f2543Smrg if(index <= blues) 645706f2543Smrg colors[index].blue = 646706f2543Smrg gamma[pmap->blue[index].co.local.blue >> shift].blue; 647706f2543Smrg 648706f2543Smrg } 649706f2543Smrg break; 650706f2543Smrg } 651706f2543Smrg for(i = 0; i < defs; i++) { 652706f2543Smrg index = indices[i]; 653706f2543Smrg 654706f2543Smrg colors[index].red = gamma[pmap->red[ 655706f2543Smrg (index >> pVisual->offsetRed) & reds 656706f2543Smrg ].co.local.red >> shift].red; 657706f2543Smrg colors[index].green = gamma[pmap->green[ 658706f2543Smrg (index >> pVisual->offsetGreen) & greens 659706f2543Smrg ].co.local.green >> shift].green; 660706f2543Smrg colors[index].blue = gamma[pmap->blue[ 661706f2543Smrg (index >> pVisual->offsetBlue) & blues 662706f2543Smrg ].co.local.blue >> shift].blue; 663706f2543Smrg } 664706f2543Smrg break; 665706f2543Smrg } 666706f2543Smrg 667706f2543Smrg 668706f2543Smrg if(LOAD_PALETTE(pmap)) 669706f2543Smrg (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices, 670706f2543Smrg colors, pmap->pVisual); 671706f2543Smrg 672706f2543Smrg if (pScrn->SetOverscan) 673706f2543Smrg CMapSetOverscan(pmap, defs, indices); 674706f2543Smrg 675706f2543Smrg} 676706f2543Smrg 677706f2543Smrgstatic Bool 678706f2543SmrgCMapCompareColors(LOCO *color1, LOCO *color2) 679706f2543Smrg{ 680706f2543Smrg /* return TRUE if the color1 is "closer" to black than color2 */ 681706f2543Smrg#ifdef DEBUGOVERSCAN 682706f2543Smrg ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n", 683706f2543Smrg color1->red, color1->green, color1->blue, 684706f2543Smrg color2->red, color2->green, color2->blue, 685706f2543Smrg color1->red + color1->green + color1->blue, 686706f2543Smrg color2->red + color2->green + color2->blue); 687706f2543Smrg#endif 688706f2543Smrg return (color1->red + color1->green + color1->blue < 689706f2543Smrg color2->red + color2->green + color2->blue); 690706f2543Smrg} 691706f2543Smrg 692706f2543Smrgstatic void 693706f2543SmrgCMapSetOverscan(ColormapPtr pmap, int defs, int *indices) 694706f2543Smrg{ 695706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 696706f2543Smrg &pmap->pScreen->devPrivates, CMapScreenKey); 697706f2543Smrg CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( 698706f2543Smrg &pmap->devPrivates, CMapColormapKey); 699706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; 700706f2543Smrg VisualPtr pVisual = pmap->pVisual; 701706f2543Smrg int i; 702706f2543Smrg LOCO *colors; 703706f2543Smrg int index; 704706f2543Smrg Bool newOverscan = FALSE; 705706f2543Smrg int overscan, tmpOverscan; 706706f2543Smrg 707706f2543Smrg colors = pColPriv->colors; 708706f2543Smrg overscan = pColPriv->overscan; 709706f2543Smrg 710706f2543Smrg /* 711706f2543Smrg * Search for a new overscan index in the following cases: 712706f2543Smrg * 713706f2543Smrg * - The index hasn't yet been initialised. In this case search 714706f2543Smrg * for an index that is black or a close match to black. 715706f2543Smrg * 716706f2543Smrg * - The colour of the old index is changed. In this case search 717706f2543Smrg * all indices for a black or close match to black. 718706f2543Smrg * 719706f2543Smrg * - The colour of the old index wasn't black. In this case only 720706f2543Smrg * search the indices that were changed for a better match to black. 721706f2543Smrg */ 722706f2543Smrg 723706f2543Smrg switch (pVisual->class) { 724706f2543Smrg case StaticGray: 725706f2543Smrg case TrueColor: 726706f2543Smrg /* Should only come here once. Initialise the overscan index to 0 */ 727706f2543Smrg overscan = 0; 728706f2543Smrg newOverscan = TRUE; 729706f2543Smrg break; 730706f2543Smrg case StaticColor: 731706f2543Smrg /* 732706f2543Smrg * Only come here once, but search for the overscan in the same way 733706f2543Smrg * as for the other cases. 734706f2543Smrg */ 735706f2543Smrg case DirectColor: 736706f2543Smrg case PseudoColor: 737706f2543Smrg case GrayScale: 738706f2543Smrg if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { 739706f2543Smrg /* Uninitialised */ 740706f2543Smrg newOverscan = TRUE; 741706f2543Smrg } else { 742706f2543Smrg /* Check if the overscan was changed */ 743706f2543Smrg for (i = 0; i < defs; i++) { 744706f2543Smrg index = indices[i]; 745706f2543Smrg if (index == overscan) { 746706f2543Smrg newOverscan = TRUE; 747706f2543Smrg break; 748706f2543Smrg } 749706f2543Smrg } 750706f2543Smrg } 751706f2543Smrg if (newOverscan) { 752706f2543Smrg /* The overscan is either uninitialised or it has been changed */ 753706f2543Smrg 754706f2543Smrg if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) 755706f2543Smrg tmpOverscan = pScreenPriv->maxColors - 1; 756706f2543Smrg else 757706f2543Smrg tmpOverscan = overscan; 758706f2543Smrg 759706f2543Smrg /* search all entries for a close match to black */ 760706f2543Smrg for (i = pScreenPriv->maxColors - 1; i >= 0; i--) { 761706f2543Smrg if (colors[i].red == 0 && colors[i].green == 0 && 762706f2543Smrg colors[i].blue == 0) { 763706f2543Smrg overscan = i; 764706f2543Smrg#ifdef DEBUGOVERSCAN 765706f2543Smrg ErrorF("Black found at index 0x%02x\n", i); 766706f2543Smrg#endif 767706f2543Smrg break; 768706f2543Smrg } else { 769706f2543Smrg#ifdef DEBUGOVERSCAN 770706f2543Smrg ErrorF("0x%02x: ", i); 771706f2543Smrg#endif 772706f2543Smrg if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { 773706f2543Smrg tmpOverscan = i; 774706f2543Smrg#ifdef DEBUGOVERSCAN 775706f2543Smrg ErrorF("possible \"Black\" at index 0x%02x\n", i); 776706f2543Smrg#endif 777706f2543Smrg } 778706f2543Smrg } 779706f2543Smrg } 780706f2543Smrg if (i < 0) 781706f2543Smrg overscan = tmpOverscan; 782706f2543Smrg } else { 783706f2543Smrg /* Check of the old overscan wasn't black */ 784706f2543Smrg if (colors[overscan].red != 0 || colors[overscan].green != 0 || 785706f2543Smrg colors[overscan].blue != 0) { 786706f2543Smrg int oldOverscan = tmpOverscan = overscan; 787706f2543Smrg /* See of there is now a better match */ 788706f2543Smrg for (i = 0; i < defs; i++) { 789706f2543Smrg index = indices[i]; 790706f2543Smrg if (colors[index].red == 0 && colors[index].green == 0 && 791706f2543Smrg colors[index].blue == 0) { 792706f2543Smrg overscan = index; 793706f2543Smrg#ifdef DEBUGOVERSCAN 794706f2543Smrg ErrorF("Black found at index 0x%02x\n", index); 795706f2543Smrg#endif 796706f2543Smrg break; 797706f2543Smrg } else { 798706f2543Smrg#ifdef DEBUGOVERSCAN 799706f2543Smrg ErrorF("0x%02x: ", index); 800706f2543Smrg#endif 801706f2543Smrg if (CMapCompareColors(&colors[index], 802706f2543Smrg &colors[tmpOverscan])) { 803706f2543Smrg tmpOverscan = index; 804706f2543Smrg#ifdef DEBUGOVERSCAN 805706f2543Smrg ErrorF("possible \"Black\" at index 0x%02x\n", 806706f2543Smrg index); 807706f2543Smrg#endif 808706f2543Smrg } 809706f2543Smrg } 810706f2543Smrg } 811706f2543Smrg if (i == defs) 812706f2543Smrg overscan = tmpOverscan; 813706f2543Smrg if (overscan != oldOverscan) 814706f2543Smrg newOverscan = TRUE; 815706f2543Smrg } 816706f2543Smrg } 817706f2543Smrg break; 818706f2543Smrg } 819706f2543Smrg if (newOverscan) { 820706f2543Smrg pColPriv->overscan = overscan; 821706f2543Smrg if (LOAD_PALETTE(pmap)) { 822706f2543Smrg#ifdef DEBUGOVERSCAN 823706f2543Smrg ErrorF("SetOverscan() called from CmapSetOverscan\n"); 824706f2543Smrg#endif 825706f2543Smrg pScrn->SetOverscan(pScreenPriv->pScrn, overscan); 826706f2543Smrg } 827706f2543Smrg } 828706f2543Smrg} 829706f2543Smrg 830706f2543Smrgstatic void 831706f2543SmrgCMapUnwrapScreen(ScreenPtr pScreen) 832706f2543Smrg{ 833706f2543Smrg CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( 834706f2543Smrg &pScreen->devPrivates, CMapScreenKey); 835706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 836706f2543Smrg 837706f2543Smrg pScreen->CloseScreen = pScreenPriv->CloseScreen; 838706f2543Smrg pScreen->CreateColormap = pScreenPriv->CreateColormap; 839706f2543Smrg pScreen->DestroyColormap = pScreenPriv->DestroyColormap; 840706f2543Smrg pScreen->InstallColormap = pScreenPriv->InstallColormap; 841706f2543Smrg pScreen->StoreColors = pScreenPriv->StoreColors; 842706f2543Smrg 843706f2543Smrg pScrn->EnterVT = pScreenPriv->EnterVT; 844706f2543Smrg pScrn->SwitchMode = pScreenPriv->SwitchMode; 845706f2543Smrg pScrn->SetDGAMode = pScreenPriv->SetDGAMode; 846706f2543Smrg pScrn->ChangeGamma = pScreenPriv->ChangeGamma; 847706f2543Smrg 848706f2543Smrg free(pScreenPriv->gamma); 849706f2543Smrg free(pScreenPriv->PreAllocIndices); 850706f2543Smrg free(pScreenPriv); 851706f2543Smrg} 852706f2543Smrg 853706f2543Smrg 854706f2543Smrgstatic void 855706f2543SmrgComputeGamma(CMapScreenPtr priv) 856706f2543Smrg{ 857706f2543Smrg int elements = priv->gammaElements - 1; 858706f2543Smrg double RedGamma, GreenGamma, BlueGamma; 859706f2543Smrg int i; 860706f2543Smrg 861706f2543Smrg#ifndef DONT_CHECK_GAMMA 862706f2543Smrg /* This check is to catch drivers that are not initialising pScrn->gamma */ 863706f2543Smrg if (priv->pScrn->gamma.red < GAMMA_MIN || 864706f2543Smrg priv->pScrn->gamma.red > GAMMA_MAX || 865706f2543Smrg priv->pScrn->gamma.green < GAMMA_MIN || 866706f2543Smrg priv->pScrn->gamma.green > GAMMA_MAX || 867706f2543Smrg priv->pScrn->gamma.blue < GAMMA_MIN || 868706f2543Smrg priv->pScrn->gamma.blue > GAMMA_MAX) { 869706f2543Smrg 870706f2543Smrg xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, 871706f2543Smrg "The %s driver didn't call xf86SetGamma() to initialise\n" 872706f2543Smrg "\tthe gamma values.\n", priv->pScrn->driverName); 873706f2543Smrg xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, 874706f2543Smrg "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); 875706f2543Smrg priv->pScrn->gamma.red = 1.0; 876706f2543Smrg priv->pScrn->gamma.green = 1.0; 877706f2543Smrg priv->pScrn->gamma.blue = 1.0; 878706f2543Smrg } 879706f2543Smrg#endif 880706f2543Smrg 881706f2543Smrg RedGamma = 1.0 / (double)priv->pScrn->gamma.red; 882706f2543Smrg GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; 883706f2543Smrg BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue; 884706f2543Smrg 885706f2543Smrg for(i = 0; i <= elements; i++) { 886706f2543Smrg if(RedGamma == 1.0) 887706f2543Smrg priv->gamma[i].red = i; 888706f2543Smrg else 889706f2543Smrg priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements, 890706f2543Smrg RedGamma) * (double)elements + 0.5); 891706f2543Smrg 892706f2543Smrg if(GreenGamma == 1.0) 893706f2543Smrg priv->gamma[i].green = i; 894706f2543Smrg else 895706f2543Smrg priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements, 896706f2543Smrg GreenGamma) * (double)elements + 0.5); 897706f2543Smrg 898706f2543Smrg if(BlueGamma == 1.0) 899706f2543Smrg priv->gamma[i].blue = i; 900706f2543Smrg else 901706f2543Smrg priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements, 902706f2543Smrg BlueGamma) * (double)elements + 0.5); 903706f2543Smrg } 904706f2543Smrg} 905706f2543Smrg 906706f2543Smrg 907706f2543Smrgint 908706f2543SmrgCMapChangeGamma( 909706f2543Smrg int index, 910706f2543Smrg Gamma gamma 911706f2543Smrg){ 912706f2543Smrg int ret = Success; 913706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 914706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 915706f2543Smrg CMapColormapPtr pColPriv; 916706f2543Smrg CMapScreenPtr pScreenPriv; 917706f2543Smrg CMapLinkPtr pLink; 918706f2543Smrg 919706f2543Smrg /* Is this sufficient checking ? */ 920706f2543Smrg if(!CMapScreenKeyRegistered) 921706f2543Smrg return BadImplementation; 922706f2543Smrg 923706f2543Smrg pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, 924706f2543Smrg CMapScreenKey); 925706f2543Smrg if(!pScreenPriv) 926706f2543Smrg return BadImplementation; 927706f2543Smrg 928706f2543Smrg if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX || 929706f2543Smrg gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX || 930706f2543Smrg gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX) 931706f2543Smrg return BadValue; 932706f2543Smrg 933706f2543Smrg pScrn->gamma.red = gamma.red; 934706f2543Smrg pScrn->gamma.green = gamma.green; 935706f2543Smrg pScrn->gamma.blue = gamma.blue; 936706f2543Smrg 937706f2543Smrg ComputeGamma(pScreenPriv); 938706f2543Smrg 939706f2543Smrg /* mark all colormaps on this screen */ 940706f2543Smrg pLink = pScreenPriv->maps; 941706f2543Smrg while(pLink) { 942706f2543Smrg pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, 943706f2543Smrg CMapColormapKey); 944706f2543Smrg pColPriv->recalculate = TRUE; 945706f2543Smrg pLink = pLink->next; 946706f2543Smrg } 947706f2543Smrg 948706f2543Smrg if(GetInstalledmiColormap(pScreen) && 949706f2543Smrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || 950706f2543Smrg pScrn->vtSema || pScreenPriv->isDGAmode)) { 951706f2543Smrg ColormapPtr pMap = GetInstalledmiColormap(pScreen); 952706f2543Smrg 953706f2543Smrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 954706f2543Smrg (pMap->pVisual->class == TrueColor) && 955706f2543Smrg CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { 956706f2543Smrg 957706f2543Smrg /* if the current map doesn't have a palette look 958706f2543Smrg for another map to change the gamma on. */ 959706f2543Smrg 960706f2543Smrg pLink = pScreenPriv->maps; 961706f2543Smrg while(pLink) { 962706f2543Smrg if(pLink->cmap->pVisual->class == PseudoColor) 963706f2543Smrg break; 964706f2543Smrg pLink = pLink->next; 965706f2543Smrg } 966706f2543Smrg 967706f2543Smrg if(pLink) { 968706f2543Smrg /* need to trick CMapRefreshColors() into thinking 969706f2543Smrg this is the currently installed map */ 970706f2543Smrg SetInstalledmiColormap(pScreen, pLink->cmap); 971706f2543Smrg CMapReinstallMap(pLink->cmap); 972706f2543Smrg SetInstalledmiColormap(pScreen, pMap); 973706f2543Smrg } 974706f2543Smrg } else 975706f2543Smrg CMapReinstallMap(pMap); 976706f2543Smrg } 977706f2543Smrg 978706f2543Smrg pScrn->ChangeGamma = pScreenPriv->ChangeGamma; 979706f2543Smrg if (pScrn->ChangeGamma) 980706f2543Smrg ret = pScrn->ChangeGamma(index, gamma); 981706f2543Smrg pScrn->ChangeGamma = CMapChangeGamma; 982706f2543Smrg 983706f2543Smrg return ret; 984706f2543Smrg} 985706f2543Smrg 986706f2543Smrg 987706f2543Smrgstatic void 988706f2543SmrgComputeGammaRamp ( 989706f2543Smrg CMapScreenPtr priv, 990706f2543Smrg unsigned short *red, 991706f2543Smrg unsigned short *green, 992706f2543Smrg unsigned short *blue 993706f2543Smrg){ 994706f2543Smrg int elements = priv->gammaElements; 995706f2543Smrg LOCO *entry = priv->gamma; 996706f2543Smrg int shift = 16 - priv->sigRGBbits; 997706f2543Smrg 998706f2543Smrg while(elements--) { 999706f2543Smrg entry->red = *(red++) >> shift; 1000706f2543Smrg entry->green = *(green++) >> shift; 1001706f2543Smrg entry->blue = *(blue++) >> shift; 1002706f2543Smrg entry++; 1003706f2543Smrg } 1004706f2543Smrg} 1005706f2543Smrg 1006706f2543Smrgint 1007706f2543Smrgxf86ChangeGammaRamp( 1008706f2543Smrg ScreenPtr pScreen, 1009706f2543Smrg int size, 1010706f2543Smrg unsigned short *red, 1011706f2543Smrg unsigned short *green, 1012706f2543Smrg unsigned short *blue 1013706f2543Smrg){ 1014706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1015706f2543Smrg CMapColormapPtr pColPriv; 1016706f2543Smrg CMapScreenPtr pScreenPriv; 1017706f2543Smrg CMapLinkPtr pLink; 1018706f2543Smrg 1019706f2543Smrg if (xf86_crtc_supports_gamma(pScrn)) { 1020706f2543Smrg RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); 1021706f2543Smrg 1022706f2543Smrg if (crtc) { 1023706f2543Smrg if (crtc->gammaSize != size) 1024706f2543Smrg return BadValue; 1025706f2543Smrg 1026706f2543Smrg RRCrtcGammaSet(crtc, red, green, blue); 1027706f2543Smrg 1028706f2543Smrg return Success; 1029706f2543Smrg } 1030706f2543Smrg } 1031706f2543Smrg 1032706f2543Smrg if(!CMapScreenKeyRegistered) 1033706f2543Smrg return BadImplementation; 1034706f2543Smrg 1035706f2543Smrg pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, 1036706f2543Smrg CMapScreenKey); 1037706f2543Smrg if(!pScreenPriv) 1038706f2543Smrg return BadImplementation; 1039706f2543Smrg 1040706f2543Smrg if(pScreenPriv->gammaElements != size) 1041706f2543Smrg return BadValue; 1042706f2543Smrg 1043706f2543Smrg ComputeGammaRamp(pScreenPriv, red, green, blue); 1044706f2543Smrg 1045706f2543Smrg /* mark all colormaps on this screen */ 1046706f2543Smrg pLink = pScreenPriv->maps; 1047706f2543Smrg while(pLink) { 1048706f2543Smrg pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, 1049706f2543Smrg CMapColormapKey); 1050706f2543Smrg pColPriv->recalculate = TRUE; 1051706f2543Smrg pLink = pLink->next; 1052706f2543Smrg } 1053706f2543Smrg 1054706f2543Smrg if(GetInstalledmiColormap(pScreen) && 1055706f2543Smrg ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || 1056706f2543Smrg pScrn->vtSema || pScreenPriv->isDGAmode)) { 1057706f2543Smrg ColormapPtr pMap = GetInstalledmiColormap(pScreen); 1058706f2543Smrg 1059706f2543Smrg if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && 1060706f2543Smrg (pMap->pVisual->class == TrueColor) && 1061706f2543Smrg CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { 1062706f2543Smrg 1063706f2543Smrg /* if the current map doesn't have a palette look 1064706f2543Smrg for another map to change the gamma on. */ 1065706f2543Smrg 1066706f2543Smrg pLink = pScreenPriv->maps; 1067706f2543Smrg while(pLink) { 1068706f2543Smrg if(pLink->cmap->pVisual->class == PseudoColor) 1069706f2543Smrg break; 1070706f2543Smrg pLink = pLink->next; 1071706f2543Smrg } 1072706f2543Smrg 1073706f2543Smrg if(pLink) { 1074706f2543Smrg /* need to trick CMapRefreshColors() into thinking 1075706f2543Smrg this is the currently installed map */ 1076706f2543Smrg SetInstalledmiColormap(pScreen, pLink->cmap); 1077706f2543Smrg CMapReinstallMap(pLink->cmap); 1078706f2543Smrg SetInstalledmiColormap(pScreen, pMap); 1079706f2543Smrg } 1080706f2543Smrg } else 1081706f2543Smrg CMapReinstallMap(pMap); 1082706f2543Smrg } 1083706f2543Smrg 1084706f2543Smrg return Success; 1085706f2543Smrg} 1086706f2543Smrg 1087706f2543Smrgint 1088706f2543Smrgxf86GetGammaRampSize(ScreenPtr pScreen) 1089706f2543Smrg{ 1090706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1091706f2543Smrg CMapScreenPtr pScreenPriv; 1092706f2543Smrg 1093706f2543Smrg if (xf86_crtc_supports_gamma(pScrn)) { 1094706f2543Smrg RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); 1095706f2543Smrg 1096706f2543Smrg if (crtc) 1097706f2543Smrg return crtc->gammaSize; 1098706f2543Smrg } 1099706f2543Smrg 1100706f2543Smrg if(!CMapScreenKeyRegistered) return 0; 1101706f2543Smrg 1102706f2543Smrg pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, 1103706f2543Smrg CMapScreenKey); 1104706f2543Smrg if(!pScreenPriv) return 0; 1105706f2543Smrg 1106706f2543Smrg return pScreenPriv->gammaElements; 1107706f2543Smrg} 1108706f2543Smrg 1109706f2543Smrgint 1110706f2543Smrgxf86GetGammaRamp( 1111706f2543Smrg ScreenPtr pScreen, 1112706f2543Smrg int size, 1113706f2543Smrg unsigned short *red, 1114706f2543Smrg unsigned short *green, 1115706f2543Smrg unsigned short *blue 1116706f2543Smrg){ 1117706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1118706f2543Smrg CMapScreenPtr pScreenPriv; 1119706f2543Smrg LOCO *entry; 1120706f2543Smrg int shift, sigbits; 1121706f2543Smrg 1122706f2543Smrg if (xf86_crtc_supports_gamma(pScrn)) { 1123706f2543Smrg RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); 1124706f2543Smrg 1125706f2543Smrg if (crtc) { 1126706f2543Smrg if (crtc->gammaSize < size) 1127706f2543Smrg return BadValue; 1128706f2543Smrg 1129706f2543Smrg if (!RRCrtcGammaGet(crtc)) 1130706f2543Smrg return BadImplementation; 1131706f2543Smrg 1132706f2543Smrg memcpy(red, crtc->gammaRed, size * sizeof(*red)); 1133706f2543Smrg memcpy(green, crtc->gammaGreen, size * sizeof(*green)); 1134706f2543Smrg memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); 1135706f2543Smrg 1136706f2543Smrg return Success; 1137706f2543Smrg } 1138706f2543Smrg } 1139706f2543Smrg 1140706f2543Smrg if(!CMapScreenKeyRegistered) 1141706f2543Smrg return BadImplementation; 1142706f2543Smrg 1143706f2543Smrg pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, 1144706f2543Smrg CMapScreenKey); 1145706f2543Smrg if(!pScreenPriv) 1146706f2543Smrg return BadImplementation; 1147706f2543Smrg 1148706f2543Smrg if(size > pScreenPriv->gammaElements) 1149706f2543Smrg return BadValue; 1150706f2543Smrg 1151706f2543Smrg entry = pScreenPriv->gamma; 1152706f2543Smrg sigbits = pScreenPriv->sigRGBbits; 1153706f2543Smrg 1154706f2543Smrg while(size--) { 1155706f2543Smrg *red = entry->red << (16 - sigbits); 1156706f2543Smrg *green = entry->green << (16 - sigbits); 1157706f2543Smrg *blue = entry->blue << (16 - sigbits); 1158706f2543Smrg shift = sigbits; 1159706f2543Smrg while(shift < 16) { 1160706f2543Smrg *red |= *red >> shift; 1161706f2543Smrg *green |= *green >> shift; 1162706f2543Smrg *blue |= *blue >> shift; 1163706f2543Smrg shift += sigbits; 1164706f2543Smrg } 1165706f2543Smrg red++; green++; blue++; 1166706f2543Smrg entry++; 1167706f2543Smrg } 1168706f2543Smrg 1169706f2543Smrg return Success; 1170706f2543Smrg} 1171706f2543Smrg 1172706f2543Smrgint 1173706f2543Smrgxf86ChangeGamma( 1174706f2543Smrg ScreenPtr pScreen, 1175706f2543Smrg Gamma gamma 1176706f2543Smrg){ 1177706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1178706f2543Smrg 1179706f2543Smrg if(pScrn->ChangeGamma) 1180706f2543Smrg return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); 1181706f2543Smrg 1182706f2543Smrg return BadImplementation; 1183706f2543Smrg} 1184