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