2 * Copyright (c) 1998-2001 by The XFree86 Project, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
28 #ifdef HAVE_XORG_CONFIG_H
29 #include <xorg-config.h>
32 #if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4)
35 #define _XOPEN_SOURCE /* to get prototype for pow on some systems */
42 #include <X11/Xproto.h>
43 #include "colormapst.h"
44 #include "scrnintstr.h"
49 #include "xf86_OSproc.h"
55 #include <X11/extensions/xf86dgaproto.h>
61 #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
62 ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field)
63 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
64 ((pScreen)->field = wrapper)
66 #define LOAD_PALETTE(pmap) \
67 ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \
68 ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \
69 xf86ScreenToScrn(pmap->pScreen)->vtSema || pScreenPriv->isDGAmode))
71 typedef struct _CMapLink
{
73 struct _CMapLink
*next
;
74 } CMapLink
, *CMapLinkPtr
;
78 CloseScreenProcPtr CloseScreen
;
79 CreateColormapProcPtr CreateColormap
;
80 DestroyColormapProcPtr DestroyColormap
;
81 InstallColormapProcPtr InstallColormap
;
82 StoreColorsProcPtr StoreColors
;
83 Bool (*EnterVT
) (ScrnInfoPtr
);
84 Bool (*SwitchMode
) (ScrnInfoPtr
, DisplayModePtr
);
85 int (*SetDGAMode
) (ScrnInfoPtr
, int, DGADevicePtr
);
86 xf86ChangeGammaProc
*ChangeGamma
;
95 } CMapScreenRec
, *CMapScreenPtr
;
102 } CMapColormapRec
, *CMapColormapPtr
;
104 static DevPrivateKeyRec CMapScreenKeyRec
;
106 #define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec)
107 #define CMapScreenKey (&CMapScreenKeyRec)
108 static DevPrivateKeyRec CMapColormapKeyRec
;
110 #define CMapColormapKey (&CMapColormapKeyRec)
112 static void CMapInstallColormap(ColormapPtr
);
113 static void CMapStoreColors(ColormapPtr
, int, xColorItem
*);
114 static Bool
CMapCloseScreen(ScreenPtr
);
115 static Bool
CMapCreateColormap(ColormapPtr
);
116 static void CMapDestroyColormap(ColormapPtr
);
118 static Bool
CMapEnterVT(ScrnInfoPtr
);
119 static Bool
CMapSwitchMode(ScrnInfoPtr
, DisplayModePtr
);
122 static int CMapSetDGAMode(ScrnInfoPtr
, int, DGADevicePtr
);
124 static int CMapChangeGamma(ScrnInfoPtr
, Gamma
);
126 static void ComputeGamma(CMapScreenPtr
);
127 static Bool
CMapAllocateColormapPrivate(ColormapPtr
);
128 static void CMapRefreshColors(ColormapPtr
, int, int *);
129 static void CMapSetOverscan(ColormapPtr
, int, int *);
130 static void CMapReinstallMap(ColormapPtr
);
131 static void CMapUnwrapScreen(ScreenPtr pScreen
);
134 xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn
)
136 /* If we support a better colormap system, then pretend we succeeded. */
137 if (xf86_crtc_supports_gamma(pScrn
))
139 if (!dixRegisterPrivateKey(&CMapScreenKeyRec
, PRIVATE_SCREEN
, 0))
142 if (!dixRegisterPrivateKey(&CMapColormapKeyRec
, PRIVATE_COLORMAP
, 0))
148 xf86HandleColormaps(ScreenPtr pScreen
,
151 xf86LoadPaletteProc
* loadPalette
,
152 xf86SetOverscanProc
* setOverscan
, unsigned int flags
)
154 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
155 ColormapPtr pDefMap
= NULL
;
156 CMapScreenPtr pScreenPriv
;
161 /* If we support a better colormap system, then pretend we succeeded. */
162 if (xf86_crtc_supports_gamma(pScrn
))
165 if (!maxColors
|| !sigRGBbits
|| !loadPalette
)
168 elements
= 1 << sigRGBbits
;
170 if (!(gamma
= malloc(elements
* sizeof(LOCO
))))
173 if (!(indices
= malloc(maxColors
* sizeof(int)))) {
178 if (!(pScreenPriv
= malloc(sizeof(CMapScreenRec
)))) {
184 dixSetPrivate(&pScreen
->devPrivates
, &CMapScreenKeyRec
, pScreenPriv
);
186 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
187 pScreenPriv
->CreateColormap
= pScreen
->CreateColormap
;
188 pScreenPriv
->DestroyColormap
= pScreen
->DestroyColormap
;
189 pScreenPriv
->InstallColormap
= pScreen
->InstallColormap
;
190 pScreenPriv
->StoreColors
= pScreen
->StoreColors
;
191 pScreen
->CloseScreen
= CMapCloseScreen
;
192 pScreen
->CreateColormap
= CMapCreateColormap
;
193 pScreen
->DestroyColormap
= CMapDestroyColormap
;
194 pScreen
->InstallColormap
= CMapInstallColormap
;
195 pScreen
->StoreColors
= CMapStoreColors
;
197 pScreenPriv
->pScrn
= pScrn
;
198 pScrn
->LoadPalette
= loadPalette
;
199 pScrn
->SetOverscan
= setOverscan
;
200 pScreenPriv
->maxColors
= maxColors
;
201 pScreenPriv
->sigRGBbits
= sigRGBbits
;
202 pScreenPriv
->gammaElements
= elements
;
203 pScreenPriv
->gamma
= gamma
;
204 pScreenPriv
->PreAllocIndices
= indices
;
205 pScreenPriv
->maps
= NULL
;
206 pScreenPriv
->flags
= flags
;
207 pScreenPriv
->isDGAmode
= FALSE
;
209 pScreenPriv
->EnterVT
= pScrn
->EnterVT
;
210 pScreenPriv
->SwitchMode
= pScrn
->SwitchMode
;
211 pScreenPriv
->SetDGAMode
= pScrn
->SetDGAMode
;
212 pScreenPriv
->ChangeGamma
= pScrn
->ChangeGamma
;
214 if (!(flags
& CMAP_LOAD_EVEN_IF_OFFSCREEN
)) {
215 pScrn
->EnterVT
= CMapEnterVT
;
216 if ((flags
& CMAP_RELOAD_ON_MODE_SWITCH
) && pScrn
->SwitchMode
)
217 pScrn
->SwitchMode
= CMapSwitchMode
;
220 pScrn
->SetDGAMode
= CMapSetDGAMode
;
222 pScrn
->ChangeGamma
= CMapChangeGamma
;
224 ComputeGamma(pScreenPriv
);
226 /* get the default map */
227 dixLookupResourceByType((pointer
*) &pDefMap
, pScreen
->defColormap
,
228 RT_COLORMAP
, serverClient
, DixInstallAccess
);
230 if (!CMapAllocateColormapPrivate(pDefMap
)) {
231 CMapUnwrapScreen(pScreen
);
235 /* Force the initial map to be loaded */
236 SetInstalledmiColormap(pScreen
, NULL
);
237 CMapInstallColormap(pDefMap
);
241 /**** Screen functions ****/
244 CMapCloseScreen(ScreenPtr pScreen
)
246 CMapUnwrapScreen(pScreen
);
248 return (*pScreen
->CloseScreen
) (pScreen
);
252 CMapColormapUseMax(VisualPtr pVisual
, CMapScreenPtr pScreenPriv
)
254 if (pVisual
->nplanes
> 16)
256 return ((1 << pVisual
->nplanes
) > pScreenPriv
->maxColors
);
260 CMapAllocateColormapPrivate(ColormapPtr pmap
)
262 CMapScreenPtr pScreenPriv
=
263 (CMapScreenPtr
) dixLookupPrivate(&pmap
->pScreen
->devPrivates
,
265 CMapColormapPtr pColPriv
;
270 if (CMapColormapUseMax(pmap
->pVisual
, pScreenPriv
))
271 numColors
= pmap
->pVisual
->ColormapEntries
;
273 numColors
= 1 << pmap
->pVisual
->nplanes
;
275 if (!(colors
= malloc(numColors
* sizeof(LOCO
))))
278 if (!(pColPriv
= malloc(sizeof(CMapColormapRec
)))) {
283 dixSetPrivate(&pmap
->devPrivates
, CMapColormapKey
, pColPriv
);
285 pColPriv
->numColors
= numColors
;
286 pColPriv
->colors
= colors
;
287 pColPriv
->recalculate
= TRUE
;
288 pColPriv
->overscan
= -1;
290 /* add map to list */
291 pLink
= malloc(sizeof(CMapLink
));
294 pLink
->next
= pScreenPriv
->maps
;
295 pScreenPriv
->maps
= pLink
;
302 CMapCreateColormap(ColormapPtr pmap
)
304 ScreenPtr pScreen
= pmap
->pScreen
;
305 CMapScreenPtr pScreenPriv
=
306 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
309 pScreen
->CreateColormap
= pScreenPriv
->CreateColormap
;
310 if ((*pScreen
->CreateColormap
) (pmap
)) {
311 if (CMapAllocateColormapPrivate(pmap
))
314 pScreen
->CreateColormap
= CMapCreateColormap
;
320 CMapDestroyColormap(ColormapPtr cmap
)
322 ScreenPtr pScreen
= cmap
->pScreen
;
323 CMapScreenPtr pScreenPriv
=
324 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
325 CMapColormapPtr pColPriv
=
326 (CMapColormapPtr
) dixLookupPrivate(&cmap
->devPrivates
, CMapColormapKey
);
327 CMapLinkPtr prevLink
= NULL
, pLink
= pScreenPriv
->maps
;
330 free(pColPriv
->colors
);
334 /* remove map from list */
336 if (pLink
->cmap
== cmap
) {
338 prevLink
->next
= pLink
->next
;
340 pScreenPriv
->maps
= pLink
->next
;
348 if (pScreenPriv
->DestroyColormap
) {
349 pScreen
->DestroyColormap
= pScreenPriv
->DestroyColormap
;
350 (*pScreen
->DestroyColormap
) (cmap
);
351 pScreen
->DestroyColormap
= CMapDestroyColormap
;
356 CMapStoreColors(ColormapPtr pmap
, int ndef
, xColorItem
* pdefs
)
358 ScreenPtr pScreen
= pmap
->pScreen
;
359 VisualPtr pVisual
= pmap
->pVisual
;
360 CMapScreenPtr pScreenPriv
=
361 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
362 int *indices
= pScreenPriv
->PreAllocIndices
;
365 /* At the moment this isn't necessary since there's nobody below us */
366 pScreen
->StoreColors
= pScreenPriv
->StoreColors
;
367 (*pScreen
->StoreColors
) (pmap
, ndef
, pdefs
);
368 pScreen
->StoreColors
= CMapStoreColors
;
370 /* should never get here for these */
371 if ((pVisual
->class == TrueColor
) ||
372 (pVisual
->class == StaticColor
) || (pVisual
->class == StaticGray
))
375 if (pVisual
->class == DirectColor
) {
376 CMapColormapPtr pColPriv
=
377 (CMapColormapPtr
) dixLookupPrivate(&pmap
->devPrivates
,
381 if (CMapColormapUseMax(pVisual
, pScreenPriv
)) {
386 if (pdefs
[ndef
].flags
& DoRed
) {
387 index
= (pdefs
[ndef
].pixel
& pVisual
->redMask
) >>
391 if (indices
[i
] == index
)
394 indices
[num
++] = index
;
396 if (pdefs
[ndef
].flags
& DoGreen
) {
397 index
= (pdefs
[ndef
].pixel
& pVisual
->greenMask
) >>
398 pVisual
->offsetGreen
;
401 if (indices
[i
] == index
)
404 indices
[num
++] = index
;
406 if (pdefs
[ndef
].flags
& DoBlue
) {
407 index
= (pdefs
[ndef
].pixel
& pVisual
->blueMask
) >>
411 if (indices
[i
] == index
)
414 indices
[num
++] = index
;
420 /* not really as overkill as it seems */
421 num
= pColPriv
->numColors
;
422 for (i
= 0; i
< pColPriv
->numColors
; i
++)
428 indices
[ndef
] = pdefs
[ndef
].pixel
;
431 CMapRefreshColors(pmap
, num
, indices
);
435 CMapInstallColormap(ColormapPtr pmap
)
437 ScreenPtr pScreen
= pmap
->pScreen
;
438 CMapScreenPtr pScreenPriv
=
439 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
441 if (pmap
== GetInstalledmiColormap(pmap
->pScreen
))
444 pScreen
->InstallColormap
= pScreenPriv
->InstallColormap
;
445 (*pScreen
->InstallColormap
) (pmap
);
446 pScreen
->InstallColormap
= CMapInstallColormap
;
448 /* Important. We let the lower layers, namely DGA,
449 overwrite the choice of Colormap to install */
450 if (GetInstalledmiColormap(pmap
->pScreen
))
451 pmap
= GetInstalledmiColormap(pmap
->pScreen
);
453 if (!(pScreenPriv
->flags
& CMAP_PALETTED_TRUECOLOR
) &&
454 (pmap
->pVisual
->class == TrueColor
) &&
455 CMapColormapUseMax(pmap
->pVisual
, pScreenPriv
))
458 if (LOAD_PALETTE(pmap
))
459 CMapReinstallMap(pmap
);
462 /**** ScrnInfoRec functions ****/
465 CMapEnterVT(ScrnInfoPtr pScrn
)
467 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
469 CMapScreenPtr pScreenPriv
=
470 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
472 pScrn
->EnterVT
= pScreenPriv
->EnterVT
;
473 ret
= (*pScreenPriv
->EnterVT
) (pScrn
);
474 pScreenPriv
->EnterVT
= pScrn
->EnterVT
;
475 pScrn
->EnterVT
= CMapEnterVT
;
477 if (GetInstalledmiColormap(pScreen
))
478 CMapReinstallMap(GetInstalledmiColormap(pScreen
));
485 CMapSwitchMode(ScrnInfoPtr pScrn
, DisplayModePtr mode
)
487 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
488 CMapScreenPtr pScreenPriv
=
489 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
491 if ((*pScreenPriv
->SwitchMode
) (pScrn
, mode
)) {
492 if (GetInstalledmiColormap(pScreen
))
493 CMapReinstallMap(GetInstalledmiColormap(pScreen
));
501 CMapSetDGAMode(ScrnInfoPtr pScrn
, int num
, DGADevicePtr dev
)
503 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
504 CMapScreenPtr pScreenPriv
=
505 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
508 ret
= (*pScreenPriv
->SetDGAMode
) (pScrn
, num
, dev
);
510 pScreenPriv
->isDGAmode
= DGAActive(pScrn
->scrnIndex
);
512 if (!pScreenPriv
->isDGAmode
&& GetInstalledmiColormap(pScreen
)
513 && xf86ScreenToScrn(pScreen
)->vtSema
)
514 CMapReinstallMap(GetInstalledmiColormap(pScreen
));
520 /**** Utilities ****/
523 CMapReinstallMap(ColormapPtr pmap
)
525 CMapScreenPtr pScreenPriv
=
526 (CMapScreenPtr
) dixLookupPrivate(&pmap
->pScreen
->devPrivates
,
528 CMapColormapPtr cmapPriv
=
529 (CMapColormapPtr
) dixLookupPrivate(&pmap
->devPrivates
, CMapColormapKey
);
530 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pmap
->pScreen
);
531 int i
= cmapPriv
->numColors
;
532 int *indices
= pScreenPriv
->PreAllocIndices
;
537 if (cmapPriv
->recalculate
)
538 CMapRefreshColors(pmap
, cmapPriv
->numColors
, indices
);
540 (*pScrn
->LoadPalette
) (pScrn
, cmapPriv
->numColors
,
541 indices
, cmapPriv
->colors
, pmap
->pVisual
);
542 if (pScrn
->SetOverscan
) {
544 ErrorF("SetOverscan() called from CMapReinstallMap\n");
546 pScrn
->SetOverscan(pScrn
, cmapPriv
->overscan
);
550 cmapPriv
->recalculate
= FALSE
;
554 CMapRefreshColors(ColormapPtr pmap
, int defs
, int *indices
)
556 CMapScreenPtr pScreenPriv
=
557 (CMapScreenPtr
) dixLookupPrivate(&pmap
->pScreen
->devPrivates
,
559 CMapColormapPtr pColPriv
=
560 (CMapColormapPtr
) dixLookupPrivate(&pmap
->devPrivates
, CMapColormapKey
);
561 VisualPtr pVisual
= pmap
->pVisual
;
562 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pmap
->pScreen
);
564 LOCO
*gamma
, *colors
;
566 int reds
, greens
, blues
, maxValue
, index
, shift
;
568 numColors
= pColPriv
->numColors
;
569 shift
= 16 - pScreenPriv
->sigRGBbits
;
570 maxValue
= (1 << pScreenPriv
->sigRGBbits
) - 1;
571 gamma
= pScreenPriv
->gamma
;
572 colors
= pColPriv
->colors
;
574 reds
= pVisual
->redMask
>> pVisual
->offsetRed
;
575 greens
= pVisual
->greenMask
>> pVisual
->offsetGreen
;
576 blues
= pVisual
->blueMask
>> pVisual
->offsetBlue
;
578 switch (pVisual
->class) {
580 for (i
= 0; i
< numColors
; i
++) {
581 index
= (i
+ 1) * maxValue
/ numColors
;
582 colors
[i
].red
= gamma
[index
].red
;
583 colors
[i
].green
= gamma
[index
].green
;
584 colors
[i
].blue
= gamma
[index
].blue
;
588 if (CMapColormapUseMax(pVisual
, pScreenPriv
)) {
589 for (i
= 0; i
<= reds
; i
++)
590 colors
[i
].red
= gamma
[i
* maxValue
/ reds
].red
;
591 for (i
= 0; i
<= greens
; i
++)
592 colors
[i
].green
= gamma
[i
* maxValue
/ greens
].green
;
593 for (i
= 0; i
<= blues
; i
++)
594 colors
[i
].blue
= gamma
[i
* maxValue
/ blues
].blue
;
597 for (i
= 0; i
< numColors
; i
++) {
598 colors
[i
].red
= gamma
[((i
>> pVisual
->offsetRed
) & reds
) *
599 maxValue
/ reds
].red
;
600 colors
[i
].green
= gamma
[((i
>> pVisual
->offsetGreen
) & greens
) *
601 maxValue
/ greens
].green
;
602 colors
[i
].blue
= gamma
[((i
>> pVisual
->offsetBlue
) & blues
) *
603 maxValue
/ blues
].blue
;
609 for (i
= 0; i
< defs
; i
++) {
611 entry
= (EntryPtr
) &pmap
->red
[index
];
613 if (entry
->fShared
) {
615 gamma
[entry
->co
.shco
.red
->color
>> shift
].red
;
616 colors
[index
].green
=
617 gamma
[entry
->co
.shco
.green
->color
>> shift
].green
;
619 gamma
[entry
->co
.shco
.blue
->color
>> shift
].blue
;
622 colors
[index
].red
= gamma
[entry
->co
.local
.red
>> shift
].red
;
623 colors
[index
].green
=
624 gamma
[entry
->co
.local
.green
>> shift
].green
;
625 colors
[index
].blue
= gamma
[entry
->co
.local
.blue
>> shift
].blue
;
630 if (CMapColormapUseMax(pVisual
, pScreenPriv
)) {
631 for (i
= 0; i
< defs
; i
++) {
635 gamma
[pmap
->red
[index
].co
.local
.red
>> shift
].red
;
637 colors
[index
].green
=
638 gamma
[pmap
->green
[index
].co
.local
.green
>> shift
].green
;
641 gamma
[pmap
->blue
[index
].co
.local
.blue
>> shift
].blue
;
646 for (i
= 0; i
< defs
; i
++) {
649 colors
[index
].red
= gamma
[pmap
->red
[(index
>> pVisual
->
650 offsetRed
) & reds
].co
.local
.
652 colors
[index
].green
=
653 gamma
[pmap
->green
[(index
>> pVisual
->offsetGreen
) & greens
].co
.
654 local
.green
>> shift
].green
;
656 gamma
[pmap
->blue
[(index
>> pVisual
->offsetBlue
) & blues
].co
.
657 local
.blue
>> shift
].blue
;
662 if (LOAD_PALETTE(pmap
))
663 (*pScrn
->LoadPalette
) (pScreenPriv
->pScrn
, defs
, indices
,
664 colors
, pmap
->pVisual
);
666 if (pScrn
->SetOverscan
)
667 CMapSetOverscan(pmap
, defs
, indices
);
672 CMapCompareColors(LOCO
* color1
, LOCO
* color2
)
674 /* return TRUE if the color1 is "closer" to black than color2 */
676 ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n",
677 color1
->red
, color1
->green
, color1
->blue
,
678 color2
->red
, color2
->green
, color2
->blue
,
679 color1
->red
+ color1
->green
+ color1
->blue
,
680 color2
->red
+ color2
->green
+ color2
->blue
);
682 return (color1
->red
+ color1
->green
+ color1
->blue
<
683 color2
->red
+ color2
->green
+ color2
->blue
);
687 CMapSetOverscan(ColormapPtr pmap
, int defs
, int *indices
)
689 CMapScreenPtr pScreenPriv
=
690 (CMapScreenPtr
) dixLookupPrivate(&pmap
->pScreen
->devPrivates
,
692 CMapColormapPtr pColPriv
=
693 (CMapColormapPtr
) dixLookupPrivate(&pmap
->devPrivates
, CMapColormapKey
);
694 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pmap
->pScreen
);
695 VisualPtr pVisual
= pmap
->pVisual
;
699 Bool newOverscan
= FALSE
;
700 int overscan
, tmpOverscan
;
702 colors
= pColPriv
->colors
;
703 overscan
= pColPriv
->overscan
;
706 * Search for a new overscan index in the following cases:
708 * - The index hasn't yet been initialised. In this case search
709 * for an index that is black or a close match to black.
711 * - The colour of the old index is changed. In this case search
712 * all indices for a black or close match to black.
714 * - The colour of the old index wasn't black. In this case only
715 * search the indices that were changed for a better match to black.
718 switch (pVisual
->class) {
721 /* Should only come here once. Initialise the overscan index to 0 */
727 * Only come here once, but search for the overscan in the same way
728 * as for the other cases.
733 if (overscan
< 0 || overscan
> pScreenPriv
->maxColors
- 1) {
738 /* Check if the overscan was changed */
739 for (i
= 0; i
< defs
; i
++) {
741 if (index
== overscan
) {
748 /* The overscan is either uninitialised or it has been changed */
750 if (overscan
< 0 || overscan
> pScreenPriv
->maxColors
- 1)
751 tmpOverscan
= pScreenPriv
->maxColors
- 1;
753 tmpOverscan
= overscan
;
755 /* search all entries for a close match to black */
756 for (i
= pScreenPriv
->maxColors
- 1; i
>= 0; i
--) {
757 if (colors
[i
].red
== 0 && colors
[i
].green
== 0 &&
758 colors
[i
].blue
== 0) {
761 ErrorF("Black found at index 0x%02x\n", i
);
767 ErrorF("0x%02x: ", i
);
769 if (CMapCompareColors(&colors
[i
], &colors
[tmpOverscan
])) {
772 ErrorF("possible \"Black\" at index 0x%02x\n", i
);
778 overscan
= tmpOverscan
;
781 /* Check of the old overscan wasn't black */
782 if (colors
[overscan
].red
!= 0 || colors
[overscan
].green
!= 0 ||
783 colors
[overscan
].blue
!= 0) {
784 int oldOverscan
= tmpOverscan
= overscan
;
786 /* See of there is now a better match */
787 for (i
= 0; i
< defs
; i
++) {
789 if (colors
[index
].red
== 0 && colors
[index
].green
== 0 &&
790 colors
[index
].blue
== 0) {
793 ErrorF("Black found at index 0x%02x\n", index
);
799 ErrorF("0x%02x: ", index
);
801 if (CMapCompareColors(&colors
[index
],
802 &colors
[tmpOverscan
])) {
805 ErrorF("possible \"Black\" at index 0x%02x\n",
812 overscan
= tmpOverscan
;
813 if (overscan
!= oldOverscan
)
820 pColPriv
->overscan
= overscan
;
821 if (LOAD_PALETTE(pmap
)) {
823 ErrorF("SetOverscan() called from CmapSetOverscan\n");
825 pScrn
->SetOverscan(pScreenPriv
->pScrn
, overscan
);
831 CMapUnwrapScreen(ScreenPtr pScreen
)
833 CMapScreenPtr pScreenPriv
=
834 (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, CMapScreenKey
);
835 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
837 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
838 pScreen
->CreateColormap
= pScreenPriv
->CreateColormap
;
839 pScreen
->DestroyColormap
= pScreenPriv
->DestroyColormap
;
840 pScreen
->InstallColormap
= pScreenPriv
->InstallColormap
;
841 pScreen
->StoreColors
= pScreenPriv
->StoreColors
;
843 pScrn
->EnterVT
= pScreenPriv
->EnterVT
;
844 pScrn
->SwitchMode
= pScreenPriv
->SwitchMode
;
845 pScrn
->SetDGAMode
= pScreenPriv
->SetDGAMode
;
846 pScrn
->ChangeGamma
= pScreenPriv
->ChangeGamma
;
848 free(pScreenPriv
->gamma
);
849 free(pScreenPriv
->PreAllocIndices
);
854 ComputeGamma(CMapScreenPtr priv
)
856 int elements
= priv
->gammaElements
- 1;
857 double RedGamma
, GreenGamma
, BlueGamma
;
860 #ifndef DONT_CHECK_GAMMA
861 /* This check is to catch drivers that are not initialising pScrn->gamma */
862 if (priv
->pScrn
->gamma
.red
< GAMMA_MIN
||
863 priv
->pScrn
->gamma
.red
> GAMMA_MAX
||
864 priv
->pScrn
->gamma
.green
< GAMMA_MIN
||
865 priv
->pScrn
->gamma
.green
> GAMMA_MAX
||
866 priv
->pScrn
->gamma
.blue
< GAMMA_MIN
||
867 priv
->pScrn
->gamma
.blue
> GAMMA_MAX
) {
869 xf86DrvMsgVerb(priv
->pScrn
->scrnIndex
, X_WARNING
, 0,
870 "The %s driver didn't call xf86SetGamma() to initialise\n"
871 "\tthe gamma values.\n", priv
->pScrn
->driverName
);
872 xf86DrvMsgVerb(priv
->pScrn
->scrnIndex
, X_WARNING
, 0,
873 "PLEASE FIX THE `%s' DRIVER!\n",
874 priv
->pScrn
->driverName
);
875 priv
->pScrn
->gamma
.red
= 1.0;
876 priv
->pScrn
->gamma
.green
= 1.0;
877 priv
->pScrn
->gamma
.blue
= 1.0;
881 RedGamma
= 1.0 / (double) priv
->pScrn
->gamma
.red
;
882 GreenGamma
= 1.0 / (double) priv
->pScrn
->gamma
.green
;
883 BlueGamma
= 1.0 / (double) priv
->pScrn
->gamma
.blue
;
885 for (i
= 0; i
<= elements
; i
++) {
887 priv
->gamma
[i
].red
= i
;
889 priv
->gamma
[i
].red
= (CARD16
) (pow((double) i
/ (double) elements
,
890 RedGamma
) * (double) elements
+
893 if (GreenGamma
== 1.0)
894 priv
->gamma
[i
].green
= i
;
896 priv
->gamma
[i
].green
= (CARD16
) (pow((double) i
/ (double) elements
,
898 (double) elements
+ 0.5);
900 if (BlueGamma
== 1.0)
901 priv
->gamma
[i
].blue
= i
;
903 priv
->gamma
[i
].blue
= (CARD16
) (pow((double) i
/ (double) elements
,
904 BlueGamma
) * (double) elements
+
910 CMapChangeGamma(ScrnInfoPtr pScrn
, Gamma gamma
)
913 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
914 CMapColormapPtr pColPriv
;
915 CMapScreenPtr pScreenPriv
;
918 /* Is this sufficient checking ? */
919 if (!CMapScreenKeyRegistered
)
920 return BadImplementation
;
922 pScreenPriv
= (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
925 return BadImplementation
;
927 if (gamma
.red
< GAMMA_MIN
|| gamma
.red
> GAMMA_MAX
||
928 gamma
.green
< GAMMA_MIN
|| gamma
.green
> GAMMA_MAX
||
929 gamma
.blue
< GAMMA_MIN
|| gamma
.blue
> GAMMA_MAX
)
932 pScrn
->gamma
.red
= gamma
.red
;
933 pScrn
->gamma
.green
= gamma
.green
;
934 pScrn
->gamma
.blue
= gamma
.blue
;
936 ComputeGamma(pScreenPriv
);
938 /* mark all colormaps on this screen */
939 pLink
= pScreenPriv
->maps
;
941 pColPriv
= (CMapColormapPtr
) dixLookupPrivate(&pLink
->cmap
->devPrivates
,
943 pColPriv
->recalculate
= TRUE
;
947 if (GetInstalledmiColormap(pScreen
) &&
948 ((pScreenPriv
->flags
& CMAP_LOAD_EVEN_IF_OFFSCREEN
) ||
949 pScrn
->vtSema
|| pScreenPriv
->isDGAmode
)) {
950 ColormapPtr pMap
= GetInstalledmiColormap(pScreen
);
952 if (!(pScreenPriv
->flags
& CMAP_PALETTED_TRUECOLOR
) &&
953 (pMap
->pVisual
->class == TrueColor
) &&
954 CMapColormapUseMax(pMap
->pVisual
, pScreenPriv
)) {
956 /* if the current map doesn't have a palette look
957 for another map to change the gamma on. */
959 pLink
= pScreenPriv
->maps
;
961 if (pLink
->cmap
->pVisual
->class == PseudoColor
)
967 /* need to trick CMapRefreshColors() into thinking
968 this is the currently installed map */
969 SetInstalledmiColormap(pScreen
, pLink
->cmap
);
970 CMapReinstallMap(pLink
->cmap
);
971 SetInstalledmiColormap(pScreen
, pMap
);
975 CMapReinstallMap(pMap
);
978 pScrn
->ChangeGamma
= pScreenPriv
->ChangeGamma
;
979 if (pScrn
->ChangeGamma
)
980 ret
= pScrn
->ChangeGamma(pScrn
, gamma
);
981 pScrn
->ChangeGamma
= CMapChangeGamma
;
987 ComputeGammaRamp(CMapScreenPtr priv
,
989 unsigned short *green
, unsigned short *blue
)
991 int elements
= priv
->gammaElements
;
992 LOCO
*entry
= priv
->gamma
;
993 int shift
= 16 - priv
->sigRGBbits
;
996 entry
->red
= *(red
++) >> shift
;
997 entry
->green
= *(green
++) >> shift
;
998 entry
->blue
= *(blue
++) >> shift
;
1004 xf86ChangeGammaRamp(ScreenPtr pScreen
,
1006 unsigned short *red
,
1007 unsigned short *green
, unsigned short *blue
)
1009 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1010 CMapColormapPtr pColPriv
;
1011 CMapScreenPtr pScreenPriv
;
1014 if (xf86_crtc_supports_gamma(pScrn
)) {
1015 RRCrtcPtr crtc
= xf86CompatRRCrtc(pScrn
);
1018 if (crtc
->gammaSize
!= size
)
1021 RRCrtcGammaSet(crtc
, red
, green
, blue
);
1027 if (!CMapScreenKeyRegistered
)
1028 return BadImplementation
;
1030 pScreenPriv
= (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1033 return BadImplementation
;
1035 if (pScreenPriv
->gammaElements
!= size
)
1038 ComputeGammaRamp(pScreenPriv
, red
, green
, blue
);
1040 /* mark all colormaps on this screen */
1041 pLink
= pScreenPriv
->maps
;
1043 pColPriv
= (CMapColormapPtr
) dixLookupPrivate(&pLink
->cmap
->devPrivates
,
1045 pColPriv
->recalculate
= TRUE
;
1046 pLink
= pLink
->next
;
1049 if (GetInstalledmiColormap(pScreen
) &&
1050 ((pScreenPriv
->flags
& CMAP_LOAD_EVEN_IF_OFFSCREEN
) ||
1051 pScrn
->vtSema
|| pScreenPriv
->isDGAmode
)) {
1052 ColormapPtr pMap
= GetInstalledmiColormap(pScreen
);
1054 if (!(pScreenPriv
->flags
& CMAP_PALETTED_TRUECOLOR
) &&
1055 (pMap
->pVisual
->class == TrueColor
) &&
1056 CMapColormapUseMax(pMap
->pVisual
, pScreenPriv
)) {
1058 /* if the current map doesn't have a palette look
1059 for another map to change the gamma on. */
1061 pLink
= pScreenPriv
->maps
;
1063 if (pLink
->cmap
->pVisual
->class == PseudoColor
)
1065 pLink
= pLink
->next
;
1069 /* need to trick CMapRefreshColors() into thinking
1070 this is the currently installed map */
1071 SetInstalledmiColormap(pScreen
, pLink
->cmap
);
1072 CMapReinstallMap(pLink
->cmap
);
1073 SetInstalledmiColormap(pScreen
, pMap
);
1077 CMapReinstallMap(pMap
);
1084 xf86GetGammaRampSize(ScreenPtr pScreen
)
1086 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1087 CMapScreenPtr pScreenPriv
;
1089 if (xf86_crtc_supports_gamma(pScrn
)) {
1090 RRCrtcPtr crtc
= xf86CompatRRCrtc(pScrn
);
1093 return crtc
->gammaSize
;
1096 if (!CMapScreenKeyRegistered
)
1099 pScreenPriv
= (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1104 return pScreenPriv
->gammaElements
;
1108 xf86GetGammaRamp(ScreenPtr pScreen
,
1110 unsigned short *red
,
1111 unsigned short *green
, unsigned short *blue
)
1113 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1114 CMapScreenPtr pScreenPriv
;
1118 if (xf86_crtc_supports_gamma(pScrn
)) {
1119 RRCrtcPtr crtc
= xf86CompatRRCrtc(pScrn
);
1122 if (crtc
->gammaSize
< size
)
1125 if (!RRCrtcGammaGet(crtc
))
1126 return BadImplementation
;
1128 memcpy(red
, crtc
->gammaRed
, size
* sizeof(*red
));
1129 memcpy(green
, crtc
->gammaGreen
, size
* sizeof(*green
));
1130 memcpy(blue
, crtc
->gammaBlue
, size
* sizeof(*blue
));
1136 if (!CMapScreenKeyRegistered
)
1137 return BadImplementation
;
1139 pScreenPriv
= (CMapScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
1142 return BadImplementation
;
1144 if (size
> pScreenPriv
->gammaElements
)
1147 entry
= pScreenPriv
->gamma
;
1148 sigbits
= pScreenPriv
->sigRGBbits
;
1151 *red
= entry
->red
<< (16 - sigbits
);
1152 *green
= entry
->green
<< (16 - sigbits
);
1153 *blue
= entry
->blue
<< (16 - sigbits
);
1155 while (shift
< 16) {
1156 *red
|= *red
>> shift
;
1157 *green
|= *green
>> shift
;
1158 *blue
|= *blue
>> shift
;
1171 xf86ChangeGamma(ScreenPtr pScreen
, Gamma gamma
)
1173 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1175 if (pScrn
->ChangeGamma
)
1176 return (*pScrn
->ChangeGamma
) (pScrn
, gamma
);
1178 return BadImplementation
;