Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright (c) 1998-2001 by The XFree86 Project, Inc. | |
3 | * | |
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: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
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. | |
21 | * | |
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). | |
26 | */ | |
27 | ||
28 | #ifdef HAVE_XORG_CONFIG_H | |
29 | #include <xorg-config.h> | |
30 | #endif | |
31 | ||
32 | #if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) | |
33 | #include <math.h> | |
34 | #else | |
35 | #define _XOPEN_SOURCE /* to get prototype for pow on some systems */ | |
36 | #include <math.h> | |
37 | #undef _XOPEN_SOURCE | |
38 | #endif | |
39 | ||
40 | #include <X11/X.h> | |
41 | #include "misc.h" | |
42 | #include <X11/Xproto.h> | |
43 | #include "colormapst.h" | |
44 | #include "scrnintstr.h" | |
45 | ||
46 | #include "resource.h" | |
47 | ||
48 | #include "xf86.h" | |
49 | #include "xf86_OSproc.h" | |
50 | #include "xf86str.h" | |
51 | #include "micmap.h" | |
52 | #include "xf86Crtc.h" | |
53 | ||
54 | #ifdef XFreeXDGA | |
55 | #include <X11/extensions/xf86dgaproto.h> | |
56 | #include "dgaproc.h" | |
57 | #endif | |
58 | ||
59 | #include "xf86cmap.h" | |
60 | ||
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) | |
65 | ||
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)) | |
70 | ||
71 | typedef struct _CMapLink { | |
72 | ColormapPtr cmap; | |
73 | struct _CMapLink *next; | |
74 | } CMapLink, *CMapLinkPtr; | |
75 | ||
76 | typedef struct { | |
77 | ScrnInfoPtr pScrn; | |
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; | |
87 | int maxColors; | |
88 | int sigRGBbits; | |
89 | int gammaElements; | |
90 | LOCO *gamma; | |
91 | int *PreAllocIndices; | |
92 | CMapLinkPtr maps; | |
93 | unsigned int flags; | |
94 | Bool isDGAmode; | |
95 | } CMapScreenRec, *CMapScreenPtr; | |
96 | ||
97 | typedef struct { | |
98 | int numColors; | |
99 | LOCO *colors; | |
100 | Bool recalculate; | |
101 | int overscan; | |
102 | } CMapColormapRec, *CMapColormapPtr; | |
103 | ||
104 | static DevPrivateKeyRec CMapScreenKeyRec; | |
105 | ||
106 | #define CMapScreenKeyRegistered dixPrivateKeyRegistered(&CMapScreenKeyRec) | |
107 | #define CMapScreenKey (&CMapScreenKeyRec) | |
108 | static DevPrivateKeyRec CMapColormapKeyRec; | |
109 | ||
110 | #define CMapColormapKey (&CMapColormapKeyRec) | |
111 | ||
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); | |
117 | ||
118 | static Bool CMapEnterVT(ScrnInfoPtr); | |
119 | static Bool CMapSwitchMode(ScrnInfoPtr, DisplayModePtr); | |
120 | ||
121 | #ifdef XFreeXDGA | |
122 | static int CMapSetDGAMode(ScrnInfoPtr, int, DGADevicePtr); | |
123 | #endif | |
124 | static int CMapChangeGamma(ScrnInfoPtr, Gamma); | |
125 | ||
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); | |
132 | ||
133 | Bool | |
134 | xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn) | |
135 | { | |
136 | /* If we support a better colormap system, then pretend we succeeded. */ | |
137 | if (xf86_crtc_supports_gamma(pScrn)) | |
138 | return TRUE; | |
139 | if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0)) | |
140 | return FALSE; | |
141 | ||
142 | if (!dixRegisterPrivateKey(&CMapColormapKeyRec, PRIVATE_COLORMAP, 0)) | |
143 | return FALSE; | |
144 | return TRUE; | |
145 | } | |
146 | ||
147 | Bool | |
148 | xf86HandleColormaps(ScreenPtr pScreen, | |
149 | int maxColors, | |
150 | int sigRGBbits, | |
151 | xf86LoadPaletteProc * loadPalette, | |
152 | xf86SetOverscanProc * setOverscan, unsigned int flags) | |
153 | { | |
154 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
155 | ColormapPtr pDefMap = NULL; | |
156 | CMapScreenPtr pScreenPriv; | |
157 | LOCO *gamma; | |
158 | int *indices; | |
159 | int elements; | |
160 | ||
161 | /* If we support a better colormap system, then pretend we succeeded. */ | |
162 | if (xf86_crtc_supports_gamma(pScrn)) | |
163 | return TRUE; | |
164 | ||
165 | if (!maxColors || !sigRGBbits || !loadPalette) | |
166 | return FALSE; | |
167 | ||
168 | elements = 1 << sigRGBbits; | |
169 | ||
170 | if (!(gamma = malloc(elements * sizeof(LOCO)))) | |
171 | return FALSE; | |
172 | ||
173 | if (!(indices = malloc(maxColors * sizeof(int)))) { | |
174 | free(gamma); | |
175 | return FALSE; | |
176 | } | |
177 | ||
178 | if (!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) { | |
179 | free(gamma); | |
180 | free(indices); | |
181 | return FALSE; | |
182 | } | |
183 | ||
184 | dixSetPrivate(&pScreen->devPrivates, &CMapScreenKeyRec, pScreenPriv); | |
185 | ||
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; | |
196 | ||
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; | |
208 | ||
209 | pScreenPriv->EnterVT = pScrn->EnterVT; | |
210 | pScreenPriv->SwitchMode = pScrn->SwitchMode; | |
211 | pScreenPriv->SetDGAMode = pScrn->SetDGAMode; | |
212 | pScreenPriv->ChangeGamma = pScrn->ChangeGamma; | |
213 | ||
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; | |
218 | } | |
219 | #ifdef XFreeXDGA | |
220 | pScrn->SetDGAMode = CMapSetDGAMode; | |
221 | #endif | |
222 | pScrn->ChangeGamma = CMapChangeGamma; | |
223 | ||
224 | ComputeGamma(pScreenPriv); | |
225 | ||
226 | /* get the default map */ | |
227 | dixLookupResourceByType((pointer *) &pDefMap, pScreen->defColormap, | |
228 | RT_COLORMAP, serverClient, DixInstallAccess); | |
229 | ||
230 | if (!CMapAllocateColormapPrivate(pDefMap)) { | |
231 | CMapUnwrapScreen(pScreen); | |
232 | return FALSE; | |
233 | } | |
234 | ||
235 | /* Force the initial map to be loaded */ | |
236 | SetInstalledmiColormap(pScreen, NULL); | |
237 | CMapInstallColormap(pDefMap); | |
238 | return TRUE; | |
239 | } | |
240 | ||
241 | /**** Screen functions ****/ | |
242 | ||
243 | static Bool | |
244 | CMapCloseScreen(ScreenPtr pScreen) | |
245 | { | |
246 | CMapUnwrapScreen(pScreen); | |
247 | ||
248 | return (*pScreen->CloseScreen) (pScreen); | |
249 | } | |
250 | ||
251 | static Bool | |
252 | CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) | |
253 | { | |
254 | if (pVisual->nplanes > 16) | |
255 | return TRUE; | |
256 | return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); | |
257 | } | |
258 | ||
259 | static Bool | |
260 | CMapAllocateColormapPrivate(ColormapPtr pmap) | |
261 | { | |
262 | CMapScreenPtr pScreenPriv = | |
263 | (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, | |
264 | CMapScreenKey); | |
265 | CMapColormapPtr pColPriv; | |
266 | CMapLinkPtr pLink; | |
267 | int numColors; | |
268 | LOCO *colors; | |
269 | ||
270 | if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) | |
271 | numColors = pmap->pVisual->ColormapEntries; | |
272 | else | |
273 | numColors = 1 << pmap->pVisual->nplanes; | |
274 | ||
275 | if (!(colors = malloc(numColors * sizeof(LOCO)))) | |
276 | return FALSE; | |
277 | ||
278 | if (!(pColPriv = malloc(sizeof(CMapColormapRec)))) { | |
279 | free(colors); | |
280 | return FALSE; | |
281 | } | |
282 | ||
283 | dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); | |
284 | ||
285 | pColPriv->numColors = numColors; | |
286 | pColPriv->colors = colors; | |
287 | pColPriv->recalculate = TRUE; | |
288 | pColPriv->overscan = -1; | |
289 | ||
290 | /* add map to list */ | |
291 | pLink = malloc(sizeof(CMapLink)); | |
292 | if (pLink) { | |
293 | pLink->cmap = pmap; | |
294 | pLink->next = pScreenPriv->maps; | |
295 | pScreenPriv->maps = pLink; | |
296 | } | |
297 | ||
298 | return TRUE; | |
299 | } | |
300 | ||
301 | static Bool | |
302 | CMapCreateColormap(ColormapPtr pmap) | |
303 | { | |
304 | ScreenPtr pScreen = pmap->pScreen; | |
305 | CMapScreenPtr pScreenPriv = | |
306 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
307 | Bool ret = FALSE; | |
308 | ||
309 | pScreen->CreateColormap = pScreenPriv->CreateColormap; | |
310 | if ((*pScreen->CreateColormap) (pmap)) { | |
311 | if (CMapAllocateColormapPrivate(pmap)) | |
312 | ret = TRUE; | |
313 | } | |
314 | pScreen->CreateColormap = CMapCreateColormap; | |
315 | ||
316 | return ret; | |
317 | } | |
318 | ||
319 | static void | |
320 | CMapDestroyColormap(ColormapPtr cmap) | |
321 | { | |
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; | |
328 | ||
329 | if (pColPriv) { | |
330 | free(pColPriv->colors); | |
331 | free(pColPriv); | |
332 | } | |
333 | ||
334 | /* remove map from list */ | |
335 | while (pLink) { | |
336 | if (pLink->cmap == cmap) { | |
337 | if (prevLink) | |
338 | prevLink->next = pLink->next; | |
339 | else | |
340 | pScreenPriv->maps = pLink->next; | |
341 | free(pLink); | |
342 | break; | |
343 | } | |
344 | prevLink = pLink; | |
345 | pLink = pLink->next; | |
346 | } | |
347 | ||
348 | if (pScreenPriv->DestroyColormap) { | |
349 | pScreen->DestroyColormap = pScreenPriv->DestroyColormap; | |
350 | (*pScreen->DestroyColormap) (cmap); | |
351 | pScreen->DestroyColormap = CMapDestroyColormap; | |
352 | } | |
353 | } | |
354 | ||
355 | static void | |
356 | CMapStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs) | |
357 | { | |
358 | ScreenPtr pScreen = pmap->pScreen; | |
359 | VisualPtr pVisual = pmap->pVisual; | |
360 | CMapScreenPtr pScreenPriv = | |
361 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
362 | int *indices = pScreenPriv->PreAllocIndices; | |
363 | int num = ndef; | |
364 | ||
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; | |
369 | ||
370 | /* should never get here for these */ | |
371 | if ((pVisual->class == TrueColor) || | |
372 | (pVisual->class == StaticColor) || (pVisual->class == StaticGray)) | |
373 | return; | |
374 | ||
375 | if (pVisual->class == DirectColor) { | |
376 | CMapColormapPtr pColPriv = | |
377 | (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, | |
378 | CMapColormapKey); | |
379 | int i; | |
380 | ||
381 | if (CMapColormapUseMax(pVisual, pScreenPriv)) { | |
382 | int index; | |
383 | ||
384 | num = 0; | |
385 | while (ndef--) { | |
386 | if (pdefs[ndef].flags & DoRed) { | |
387 | index = (pdefs[ndef].pixel & pVisual->redMask) >> | |
388 | pVisual->offsetRed; | |
389 | i = num; | |
390 | while (i--) | |
391 | if (indices[i] == index) | |
392 | break; | |
393 | if (i == -1) | |
394 | indices[num++] = index; | |
395 | } | |
396 | if (pdefs[ndef].flags & DoGreen) { | |
397 | index = (pdefs[ndef].pixel & pVisual->greenMask) >> | |
398 | pVisual->offsetGreen; | |
399 | i = num; | |
400 | while (i--) | |
401 | if (indices[i] == index) | |
402 | break; | |
403 | if (i == -1) | |
404 | indices[num++] = index; | |
405 | } | |
406 | if (pdefs[ndef].flags & DoBlue) { | |
407 | index = (pdefs[ndef].pixel & pVisual->blueMask) >> | |
408 | pVisual->offsetBlue; | |
409 | i = num; | |
410 | while (i--) | |
411 | if (indices[i] == index) | |
412 | break; | |
413 | if (i == -1) | |
414 | indices[num++] = index; | |
415 | } | |
416 | } | |
417 | ||
418 | } | |
419 | else { | |
420 | /* not really as overkill as it seems */ | |
421 | num = pColPriv->numColors; | |
422 | for (i = 0; i < pColPriv->numColors; i++) | |
423 | indices[i] = i; | |
424 | } | |
425 | } | |
426 | else { | |
427 | while (ndef--) | |
428 | indices[ndef] = pdefs[ndef].pixel; | |
429 | } | |
430 | ||
431 | CMapRefreshColors(pmap, num, indices); | |
432 | } | |
433 | ||
434 | static void | |
435 | CMapInstallColormap(ColormapPtr pmap) | |
436 | { | |
437 | ScreenPtr pScreen = pmap->pScreen; | |
438 | CMapScreenPtr pScreenPriv = | |
439 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
440 | ||
441 | if (pmap == GetInstalledmiColormap(pmap->pScreen)) | |
442 | return; | |
443 | ||
444 | pScreen->InstallColormap = pScreenPriv->InstallColormap; | |
445 | (*pScreen->InstallColormap) (pmap); | |
446 | pScreen->InstallColormap = CMapInstallColormap; | |
447 | ||
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); | |
452 | ||
453 | if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && | |
454 | (pmap->pVisual->class == TrueColor) && | |
455 | CMapColormapUseMax(pmap->pVisual, pScreenPriv)) | |
456 | return; | |
457 | ||
458 | if (LOAD_PALETTE(pmap)) | |
459 | CMapReinstallMap(pmap); | |
460 | } | |
461 | ||
462 | /**** ScrnInfoRec functions ****/ | |
463 | ||
464 | static Bool | |
465 | CMapEnterVT(ScrnInfoPtr pScrn) | |
466 | { | |
467 | ScreenPtr pScreen = xf86ScrnToScreen(pScrn); | |
468 | Bool ret; | |
469 | CMapScreenPtr pScreenPriv = | |
470 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
471 | ||
472 | pScrn->EnterVT = pScreenPriv->EnterVT; | |
473 | ret = (*pScreenPriv->EnterVT) (pScrn); | |
474 | pScreenPriv->EnterVT = pScrn->EnterVT; | |
475 | pScrn->EnterVT = CMapEnterVT; | |
476 | if (ret) { | |
477 | if (GetInstalledmiColormap(pScreen)) | |
478 | CMapReinstallMap(GetInstalledmiColormap(pScreen)); | |
479 | return TRUE; | |
480 | } | |
481 | return FALSE; | |
482 | } | |
483 | ||
484 | static Bool | |
485 | CMapSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) | |
486 | { | |
487 | ScreenPtr pScreen = xf86ScrnToScreen(pScrn); | |
488 | CMapScreenPtr pScreenPriv = | |
489 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
490 | ||
491 | if ((*pScreenPriv->SwitchMode) (pScrn, mode)) { | |
492 | if (GetInstalledmiColormap(pScreen)) | |
493 | CMapReinstallMap(GetInstalledmiColormap(pScreen)); | |
494 | return TRUE; | |
495 | } | |
496 | return FALSE; | |
497 | } | |
498 | ||
499 | #ifdef XFreeXDGA | |
500 | static int | |
501 | CMapSetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr dev) | |
502 | { | |
503 | ScreenPtr pScreen = xf86ScrnToScreen(pScrn); | |
504 | CMapScreenPtr pScreenPriv = | |
505 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
506 | int ret; | |
507 | ||
508 | ret = (*pScreenPriv->SetDGAMode) (pScrn, num, dev); | |
509 | ||
510 | pScreenPriv->isDGAmode = DGAActive(pScrn->scrnIndex); | |
511 | ||
512 | if (!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) | |
513 | && xf86ScreenToScrn(pScreen)->vtSema) | |
514 | CMapReinstallMap(GetInstalledmiColormap(pScreen)); | |
515 | ||
516 | return ret; | |
517 | } | |
518 | #endif | |
519 | ||
520 | /**** Utilities ****/ | |
521 | ||
522 | static void | |
523 | CMapReinstallMap(ColormapPtr pmap) | |
524 | { | |
525 | CMapScreenPtr pScreenPriv = | |
526 | (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, | |
527 | CMapScreenKey); | |
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; | |
533 | ||
534 | while (i--) | |
535 | indices[i] = i; | |
536 | ||
537 | if (cmapPriv->recalculate) | |
538 | CMapRefreshColors(pmap, cmapPriv->numColors, indices); | |
539 | else { | |
540 | (*pScrn->LoadPalette) (pScrn, cmapPriv->numColors, | |
541 | indices, cmapPriv->colors, pmap->pVisual); | |
542 | if (pScrn->SetOverscan) { | |
543 | #ifdef DEBUGOVERSCAN | |
544 | ErrorF("SetOverscan() called from CMapReinstallMap\n"); | |
545 | #endif | |
546 | pScrn->SetOverscan(pScrn, cmapPriv->overscan); | |
547 | } | |
548 | } | |
549 | ||
550 | cmapPriv->recalculate = FALSE; | |
551 | } | |
552 | ||
553 | static void | |
554 | CMapRefreshColors(ColormapPtr pmap, int defs, int *indices) | |
555 | { | |
556 | CMapScreenPtr pScreenPriv = | |
557 | (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, | |
558 | CMapScreenKey); | |
559 | CMapColormapPtr pColPriv = | |
560 | (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey); | |
561 | VisualPtr pVisual = pmap->pVisual; | |
562 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen); | |
563 | int numColors, i; | |
564 | LOCO *gamma, *colors; | |
565 | EntryPtr entry; | |
566 | int reds, greens, blues, maxValue, index, shift; | |
567 | ||
568 | numColors = pColPriv->numColors; | |
569 | shift = 16 - pScreenPriv->sigRGBbits; | |
570 | maxValue = (1 << pScreenPriv->sigRGBbits) - 1; | |
571 | gamma = pScreenPriv->gamma; | |
572 | colors = pColPriv->colors; | |
573 | ||
574 | reds = pVisual->redMask >> pVisual->offsetRed; | |
575 | greens = pVisual->greenMask >> pVisual->offsetGreen; | |
576 | blues = pVisual->blueMask >> pVisual->offsetBlue; | |
577 | ||
578 | switch (pVisual->class) { | |
579 | case StaticGray: | |
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; | |
585 | } | |
586 | break; | |
587 | case TrueColor: | |
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; | |
595 | break; | |
596 | } | |
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; | |
604 | } | |
605 | break; | |
606 | case StaticColor: | |
607 | case PseudoColor: | |
608 | case GrayScale: | |
609 | for (i = 0; i < defs; i++) { | |
610 | index = indices[i]; | |
611 | entry = (EntryPtr) &pmap->red[index]; | |
612 | ||
613 | if (entry->fShared) { | |
614 | colors[index].red = | |
615 | gamma[entry->co.shco.red->color >> shift].red; | |
616 | colors[index].green = | |
617 | gamma[entry->co.shco.green->color >> shift].green; | |
618 | colors[index].blue = | |
619 | gamma[entry->co.shco.blue->color >> shift].blue; | |
620 | } | |
621 | else { | |
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; | |
626 | } | |
627 | } | |
628 | break; | |
629 | case DirectColor: | |
630 | if (CMapColormapUseMax(pVisual, pScreenPriv)) { | |
631 | for (i = 0; i < defs; i++) { | |
632 | index = indices[i]; | |
633 | if (index <= reds) | |
634 | colors[index].red = | |
635 | gamma[pmap->red[index].co.local.red >> shift].red; | |
636 | if (index <= greens) | |
637 | colors[index].green = | |
638 | gamma[pmap->green[index].co.local.green >> shift].green; | |
639 | if (index <= blues) | |
640 | colors[index].blue = | |
641 | gamma[pmap->blue[index].co.local.blue >> shift].blue; | |
642 | ||
643 | } | |
644 | break; | |
645 | } | |
646 | for (i = 0; i < defs; i++) { | |
647 | index = indices[i]; | |
648 | ||
649 | colors[index].red = gamma[pmap->red[(index >> pVisual-> | |
650 | offsetRed) & reds].co.local. | |
651 | red >> shift].red; | |
652 | colors[index].green = | |
653 | gamma[pmap->green[(index >> pVisual->offsetGreen) & greens].co. | |
654 | local.green >> shift].green; | |
655 | colors[index].blue = | |
656 | gamma[pmap->blue[(index >> pVisual->offsetBlue) & blues].co. | |
657 | local.blue >> shift].blue; | |
658 | } | |
659 | break; | |
660 | } | |
661 | ||
662 | if (LOAD_PALETTE(pmap)) | |
663 | (*pScrn->LoadPalette) (pScreenPriv->pScrn, defs, indices, | |
664 | colors, pmap->pVisual); | |
665 | ||
666 | if (pScrn->SetOverscan) | |
667 | CMapSetOverscan(pmap, defs, indices); | |
668 | ||
669 | } | |
670 | ||
671 | static Bool | |
672 | CMapCompareColors(LOCO * color1, LOCO * color2) | |
673 | { | |
674 | /* return TRUE if the color1 is "closer" to black than color2 */ | |
675 | #ifdef DEBUGOVERSCAN | |
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); | |
681 | #endif | |
682 | return (color1->red + color1->green + color1->blue < | |
683 | color2->red + color2->green + color2->blue); | |
684 | } | |
685 | ||
686 | static void | |
687 | CMapSetOverscan(ColormapPtr pmap, int defs, int *indices) | |
688 | { | |
689 | CMapScreenPtr pScreenPriv = | |
690 | (CMapScreenPtr) dixLookupPrivate(&pmap->pScreen->devPrivates, | |
691 | CMapScreenKey); | |
692 | CMapColormapPtr pColPriv = | |
693 | (CMapColormapPtr) dixLookupPrivate(&pmap->devPrivates, CMapColormapKey); | |
694 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pmap->pScreen); | |
695 | VisualPtr pVisual = pmap->pVisual; | |
696 | int i; | |
697 | LOCO *colors; | |
698 | int index; | |
699 | Bool newOverscan = FALSE; | |
700 | int overscan, tmpOverscan; | |
701 | ||
702 | colors = pColPriv->colors; | |
703 | overscan = pColPriv->overscan; | |
704 | ||
705 | /* | |
706 | * Search for a new overscan index in the following cases: | |
707 | * | |
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. | |
710 | * | |
711 | * - The colour of the old index is changed. In this case search | |
712 | * all indices for a black or close match to black. | |
713 | * | |
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. | |
716 | */ | |
717 | ||
718 | switch (pVisual->class) { | |
719 | case StaticGray: | |
720 | case TrueColor: | |
721 | /* Should only come here once. Initialise the overscan index to 0 */ | |
722 | overscan = 0; | |
723 | newOverscan = TRUE; | |
724 | break; | |
725 | case StaticColor: | |
726 | /* | |
727 | * Only come here once, but search for the overscan in the same way | |
728 | * as for the other cases. | |
729 | */ | |
730 | case DirectColor: | |
731 | case PseudoColor: | |
732 | case GrayScale: | |
733 | if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { | |
734 | /* Uninitialised */ | |
735 | newOverscan = TRUE; | |
736 | } | |
737 | else { | |
738 | /* Check if the overscan was changed */ | |
739 | for (i = 0; i < defs; i++) { | |
740 | index = indices[i]; | |
741 | if (index == overscan) { | |
742 | newOverscan = TRUE; | |
743 | break; | |
744 | } | |
745 | } | |
746 | } | |
747 | if (newOverscan) { | |
748 | /* The overscan is either uninitialised or it has been changed */ | |
749 | ||
750 | if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) | |
751 | tmpOverscan = pScreenPriv->maxColors - 1; | |
752 | else | |
753 | tmpOverscan = overscan; | |
754 | ||
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) { | |
759 | overscan = i; | |
760 | #ifdef DEBUGOVERSCAN | |
761 | ErrorF("Black found at index 0x%02x\n", i); | |
762 | #endif | |
763 | break; | |
764 | } | |
765 | else { | |
766 | #ifdef DEBUGOVERSCAN | |
767 | ErrorF("0x%02x: ", i); | |
768 | #endif | |
769 | if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { | |
770 | tmpOverscan = i; | |
771 | #ifdef DEBUGOVERSCAN | |
772 | ErrorF("possible \"Black\" at index 0x%02x\n", i); | |
773 | #endif | |
774 | } | |
775 | } | |
776 | } | |
777 | if (i < 0) | |
778 | overscan = tmpOverscan; | |
779 | } | |
780 | else { | |
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; | |
785 | ||
786 | /* See of there is now a better match */ | |
787 | for (i = 0; i < defs; i++) { | |
788 | index = indices[i]; | |
789 | if (colors[index].red == 0 && colors[index].green == 0 && | |
790 | colors[index].blue == 0) { | |
791 | overscan = index; | |
792 | #ifdef DEBUGOVERSCAN | |
793 | ErrorF("Black found at index 0x%02x\n", index); | |
794 | #endif | |
795 | break; | |
796 | } | |
797 | else { | |
798 | #ifdef DEBUGOVERSCAN | |
799 | ErrorF("0x%02x: ", index); | |
800 | #endif | |
801 | if (CMapCompareColors(&colors[index], | |
802 | &colors[tmpOverscan])) { | |
803 | tmpOverscan = index; | |
804 | #ifdef DEBUGOVERSCAN | |
805 | ErrorF("possible \"Black\" at index 0x%02x\n", | |
806 | index); | |
807 | #endif | |
808 | } | |
809 | } | |
810 | } | |
811 | if (i == defs) | |
812 | overscan = tmpOverscan; | |
813 | if (overscan != oldOverscan) | |
814 | newOverscan = TRUE; | |
815 | } | |
816 | } | |
817 | break; | |
818 | } | |
819 | if (newOverscan) { | |
820 | pColPriv->overscan = overscan; | |
821 | if (LOAD_PALETTE(pmap)) { | |
822 | #ifdef DEBUGOVERSCAN | |
823 | ErrorF("SetOverscan() called from CmapSetOverscan\n"); | |
824 | #endif | |
825 | pScrn->SetOverscan(pScreenPriv->pScrn, overscan); | |
826 | } | |
827 | } | |
828 | } | |
829 | ||
830 | static void | |
831 | CMapUnwrapScreen(ScreenPtr pScreen) | |
832 | { | |
833 | CMapScreenPtr pScreenPriv = | |
834 | (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, CMapScreenKey); | |
835 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
836 | ||
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; | |
842 | ||
843 | pScrn->EnterVT = pScreenPriv->EnterVT; | |
844 | pScrn->SwitchMode = pScreenPriv->SwitchMode; | |
845 | pScrn->SetDGAMode = pScreenPriv->SetDGAMode; | |
846 | pScrn->ChangeGamma = pScreenPriv->ChangeGamma; | |
847 | ||
848 | free(pScreenPriv->gamma); | |
849 | free(pScreenPriv->PreAllocIndices); | |
850 | free(pScreenPriv); | |
851 | } | |
852 | ||
853 | static void | |
854 | ComputeGamma(CMapScreenPtr priv) | |
855 | { | |
856 | int elements = priv->gammaElements - 1; | |
857 | double RedGamma, GreenGamma, BlueGamma; | |
858 | int i; | |
859 | ||
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) { | |
868 | ||
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; | |
878 | } | |
879 | #endif | |
880 | ||
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; | |
884 | ||
885 | for (i = 0; i <= elements; i++) { | |
886 | if (RedGamma == 1.0) | |
887 | priv->gamma[i].red = i; | |
888 | else | |
889 | priv->gamma[i].red = (CARD16) (pow((double) i / (double) elements, | |
890 | RedGamma) * (double) elements + | |
891 | 0.5); | |
892 | ||
893 | if (GreenGamma == 1.0) | |
894 | priv->gamma[i].green = i; | |
895 | else | |
896 | priv->gamma[i].green = (CARD16) (pow((double) i / (double) elements, | |
897 | GreenGamma) * | |
898 | (double) elements + 0.5); | |
899 | ||
900 | if (BlueGamma == 1.0) | |
901 | priv->gamma[i].blue = i; | |
902 | else | |
903 | priv->gamma[i].blue = (CARD16) (pow((double) i / (double) elements, | |
904 | BlueGamma) * (double) elements + | |
905 | 0.5); | |
906 | } | |
907 | } | |
908 | ||
909 | int | |
910 | CMapChangeGamma(ScrnInfoPtr pScrn, Gamma gamma) | |
911 | { | |
912 | int ret = Success; | |
913 | ScreenPtr pScreen = xf86ScrnToScreen(pScrn); | |
914 | CMapColormapPtr pColPriv; | |
915 | CMapScreenPtr pScreenPriv; | |
916 | CMapLinkPtr pLink; | |
917 | ||
918 | /* Is this sufficient checking ? */ | |
919 | if (!CMapScreenKeyRegistered) | |
920 | return BadImplementation; | |
921 | ||
922 | pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
923 | CMapScreenKey); | |
924 | if (!pScreenPriv) | |
925 | return BadImplementation; | |
926 | ||
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) | |
930 | return BadValue; | |
931 | ||
932 | pScrn->gamma.red = gamma.red; | |
933 | pScrn->gamma.green = gamma.green; | |
934 | pScrn->gamma.blue = gamma.blue; | |
935 | ||
936 | ComputeGamma(pScreenPriv); | |
937 | ||
938 | /* mark all colormaps on this screen */ | |
939 | pLink = pScreenPriv->maps; | |
940 | while (pLink) { | |
941 | pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates, | |
942 | CMapColormapKey); | |
943 | pColPriv->recalculate = TRUE; | |
944 | pLink = pLink->next; | |
945 | } | |
946 | ||
947 | if (GetInstalledmiColormap(pScreen) && | |
948 | ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || | |
949 | pScrn->vtSema || pScreenPriv->isDGAmode)) { | |
950 | ColormapPtr pMap = GetInstalledmiColormap(pScreen); | |
951 | ||
952 | if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && | |
953 | (pMap->pVisual->class == TrueColor) && | |
954 | CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { | |
955 | ||
956 | /* if the current map doesn't have a palette look | |
957 | for another map to change the gamma on. */ | |
958 | ||
959 | pLink = pScreenPriv->maps; | |
960 | while (pLink) { | |
961 | if (pLink->cmap->pVisual->class == PseudoColor) | |
962 | break; | |
963 | pLink = pLink->next; | |
964 | } | |
965 | ||
966 | if (pLink) { | |
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); | |
972 | } | |
973 | } | |
974 | else | |
975 | CMapReinstallMap(pMap); | |
976 | } | |
977 | ||
978 | pScrn->ChangeGamma = pScreenPriv->ChangeGamma; | |
979 | if (pScrn->ChangeGamma) | |
980 | ret = pScrn->ChangeGamma(pScrn, gamma); | |
981 | pScrn->ChangeGamma = CMapChangeGamma; | |
982 | ||
983 | return ret; | |
984 | } | |
985 | ||
986 | static void | |
987 | ComputeGammaRamp(CMapScreenPtr priv, | |
988 | unsigned short *red, | |
989 | unsigned short *green, unsigned short *blue) | |
990 | { | |
991 | int elements = priv->gammaElements; | |
992 | LOCO *entry = priv->gamma; | |
993 | int shift = 16 - priv->sigRGBbits; | |
994 | ||
995 | while (elements--) { | |
996 | entry->red = *(red++) >> shift; | |
997 | entry->green = *(green++) >> shift; | |
998 | entry->blue = *(blue++) >> shift; | |
999 | entry++; | |
1000 | } | |
1001 | } | |
1002 | ||
1003 | int | |
1004 | xf86ChangeGammaRamp(ScreenPtr pScreen, | |
1005 | int size, | |
1006 | unsigned short *red, | |
1007 | unsigned short *green, unsigned short *blue) | |
1008 | { | |
1009 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
1010 | CMapColormapPtr pColPriv; | |
1011 | CMapScreenPtr pScreenPriv; | |
1012 | CMapLinkPtr pLink; | |
1013 | ||
1014 | if (xf86_crtc_supports_gamma(pScrn)) { | |
1015 | RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); | |
1016 | ||
1017 | if (crtc) { | |
1018 | if (crtc->gammaSize != size) | |
1019 | return BadValue; | |
1020 | ||
1021 | RRCrtcGammaSet(crtc, red, green, blue); | |
1022 | ||
1023 | return Success; | |
1024 | } | |
1025 | } | |
1026 | ||
1027 | if (!CMapScreenKeyRegistered) | |
1028 | return BadImplementation; | |
1029 | ||
1030 | pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
1031 | CMapScreenKey); | |
1032 | if (!pScreenPriv) | |
1033 | return BadImplementation; | |
1034 | ||
1035 | if (pScreenPriv->gammaElements != size) | |
1036 | return BadValue; | |
1037 | ||
1038 | ComputeGammaRamp(pScreenPriv, red, green, blue); | |
1039 | ||
1040 | /* mark all colormaps on this screen */ | |
1041 | pLink = pScreenPriv->maps; | |
1042 | while (pLink) { | |
1043 | pColPriv = (CMapColormapPtr) dixLookupPrivate(&pLink->cmap->devPrivates, | |
1044 | CMapColormapKey); | |
1045 | pColPriv->recalculate = TRUE; | |
1046 | pLink = pLink->next; | |
1047 | } | |
1048 | ||
1049 | if (GetInstalledmiColormap(pScreen) && | |
1050 | ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || | |
1051 | pScrn->vtSema || pScreenPriv->isDGAmode)) { | |
1052 | ColormapPtr pMap = GetInstalledmiColormap(pScreen); | |
1053 | ||
1054 | if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && | |
1055 | (pMap->pVisual->class == TrueColor) && | |
1056 | CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { | |
1057 | ||
1058 | /* if the current map doesn't have a palette look | |
1059 | for another map to change the gamma on. */ | |
1060 | ||
1061 | pLink = pScreenPriv->maps; | |
1062 | while (pLink) { | |
1063 | if (pLink->cmap->pVisual->class == PseudoColor) | |
1064 | break; | |
1065 | pLink = pLink->next; | |
1066 | } | |
1067 | ||
1068 | if (pLink) { | |
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); | |
1074 | } | |
1075 | } | |
1076 | else | |
1077 | CMapReinstallMap(pMap); | |
1078 | } | |
1079 | ||
1080 | return Success; | |
1081 | } | |
1082 | ||
1083 | int | |
1084 | xf86GetGammaRampSize(ScreenPtr pScreen) | |
1085 | { | |
1086 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
1087 | CMapScreenPtr pScreenPriv; | |
1088 | ||
1089 | if (xf86_crtc_supports_gamma(pScrn)) { | |
1090 | RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); | |
1091 | ||
1092 | if (crtc) | |
1093 | return crtc->gammaSize; | |
1094 | } | |
1095 | ||
1096 | if (!CMapScreenKeyRegistered) | |
1097 | return 0; | |
1098 | ||
1099 | pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
1100 | CMapScreenKey); | |
1101 | if (!pScreenPriv) | |
1102 | return 0; | |
1103 | ||
1104 | return pScreenPriv->gammaElements; | |
1105 | } | |
1106 | ||
1107 | int | |
1108 | xf86GetGammaRamp(ScreenPtr pScreen, | |
1109 | int size, | |
1110 | unsigned short *red, | |
1111 | unsigned short *green, unsigned short *blue) | |
1112 | { | |
1113 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
1114 | CMapScreenPtr pScreenPriv; | |
1115 | LOCO *entry; | |
1116 | int shift, sigbits; | |
1117 | ||
1118 | if (xf86_crtc_supports_gamma(pScrn)) { | |
1119 | RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); | |
1120 | ||
1121 | if (crtc) { | |
1122 | if (crtc->gammaSize < size) | |
1123 | return BadValue; | |
1124 | ||
1125 | if (!RRCrtcGammaGet(crtc)) | |
1126 | return BadImplementation; | |
1127 | ||
1128 | memcpy(red, crtc->gammaRed, size * sizeof(*red)); | |
1129 | memcpy(green, crtc->gammaGreen, size * sizeof(*green)); | |
1130 | memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); | |
1131 | ||
1132 | return Success; | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | if (!CMapScreenKeyRegistered) | |
1137 | return BadImplementation; | |
1138 | ||
1139 | pScreenPriv = (CMapScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
1140 | CMapScreenKey); | |
1141 | if (!pScreenPriv) | |
1142 | return BadImplementation; | |
1143 | ||
1144 | if (size > pScreenPriv->gammaElements) | |
1145 | return BadValue; | |
1146 | ||
1147 | entry = pScreenPriv->gamma; | |
1148 | sigbits = pScreenPriv->sigRGBbits; | |
1149 | ||
1150 | while (size--) { | |
1151 | *red = entry->red << (16 - sigbits); | |
1152 | *green = entry->green << (16 - sigbits); | |
1153 | *blue = entry->blue << (16 - sigbits); | |
1154 | shift = sigbits; | |
1155 | while (shift < 16) { | |
1156 | *red |= *red >> shift; | |
1157 | *green |= *green >> shift; | |
1158 | *blue |= *blue >> shift; | |
1159 | shift += sigbits; | |
1160 | } | |
1161 | red++; | |
1162 | green++; | |
1163 | blue++; | |
1164 | entry++; | |
1165 | } | |
1166 | ||
1167 | return Success; | |
1168 | } | |
1169 | ||
1170 | int | |
1171 | xf86ChangeGamma(ScreenPtr pScreen, Gamma gamma) | |
1172 | { | |
1173 | ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); | |
1174 | ||
1175 | if (pScrn->ChangeGamma) | |
1176 | return (*pScrn->ChangeGamma) (pScrn, gamma); | |
1177 | ||
1178 | return BadImplementation; | |
1179 | } |