1 /*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
27 *
28 * Authors: Dakshinamurthy Karra
29 * Suhaib M Siddiqi
30 * Peter Busch
31 * Harold L Hunt II
32 */
33
34 #ifdef HAVE_XWIN_CONFIG_H
35 #include <xwin-config.h>
36 #endif
37 #include "win.h"
38
39 /*
40 * Local prototypes
41 */
42
43 static int
44 winListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps);
45
46 static void
47 winStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs);
48
49 static void
50 winInstallColormap(ColormapPtr pmap);
51
52 static void
53 winUninstallColormap(ColormapPtr pmap);
54
55 static void
56
57 winResolveColor(unsigned short *pred,
58 unsigned short *pgreen,
59 unsigned short *pblue, VisualPtr pVisual);
60
61 static Bool
62 winCreateColormap(ColormapPtr pmap);
63
64 static void
65 winDestroyColormap(ColormapPtr pmap);
66
67 static Bool
68 winGetPaletteDIB(ScreenPtr pScreen, ColormapPtr pcmap);
69
70 static Bool
71 winGetPaletteDD(ScreenPtr pScreen, ColormapPtr pcmap);
72
73 /*
74 * Set screen functions for colormaps
75 */
76
77 void
winSetColormapFunctions(ScreenPtr pScreen)78 winSetColormapFunctions(ScreenPtr pScreen)
79 {
80 pScreen->CreateColormap = winCreateColormap;
81 pScreen->DestroyColormap = winDestroyColormap;
82 pScreen->InstallColormap = winInstallColormap;
83 pScreen->UninstallColormap = winUninstallColormap;
84 pScreen->ListInstalledColormaps = winListInstalledColormaps;
85 pScreen->StoreColors = winStoreColors;
86 pScreen->ResolveColor = winResolveColor;
87 }
88
89 /* See Porting Layer Definition - p. 30 */
90 /*
91 * Walk the list of installed colormaps, filling the pmaps list
92 * with the resource ids of the installed maps, and return
93 * a count of the total number of installed maps.
94 */
95 static int
winListInstalledColormaps(ScreenPtr pScreen,Colormap * pmaps)96 winListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps)
97 {
98 winScreenPriv(pScreen);
99
100 /*
101 * There will only be one installed colormap, so we only need
102 * to return one id, and the count of installed maps will always
103 * be one.
104 */
105 *pmaps = pScreenPriv->pcmapInstalled->mid;
106 return 1;
107 }
108
109 /* See Porting Layer Definition - p. 30 */
110 /* See Programming Windows - p. 663 */
111 static void
winInstallColormap(ColormapPtr pColormap)112 winInstallColormap(ColormapPtr pColormap)
113 {
114 ScreenPtr pScreen = pColormap->pScreen;
115
116 winScreenPriv(pScreen);
117 ColormapPtr oldpmap = pScreenPriv->pcmapInstalled;
118
119 #if CYGDEBUG
120 winDebug("winInstallColormap\n");
121 #endif
122
123 /* Did the colormap actually change? */
124 if (pColormap != oldpmap) {
125 #if CYGDEBUG
126 winDebug("winInstallColormap - Colormap has changed, attempt "
127 "to install.\n");
128 #endif
129
130 /* Was there a previous colormap? */
131 if (oldpmap != (ColormapPtr) None) {
132 /* There was a previous colormap; tell clients it is gone */
133 WalkTree(pColormap->pScreen, TellLostMap, (char *) &oldpmap->mid);
134 }
135
136 /* Install new colormap */
137 pScreenPriv->pcmapInstalled = pColormap;
138 WalkTree(pColormap->pScreen, TellGainedMap, (char *) &pColormap->mid);
139
140 /* Call the engine specific colormap install procedure */
141 if (!((*pScreenPriv->pwinInstallColormap) (pColormap))) {
142 winErrorFVerb(2,
143 "winInstallColormap - Screen specific colormap install "
144 "procedure failed. Continuing, but colors may be "
145 "messed up from now on.\n");
146 }
147 }
148
149 /* Save a pointer to the newly installed colormap */
150 pScreenPriv->pcmapInstalled = pColormap;
151 }
152
153 /* See Porting Layer Definition - p. 30 */
154 static void
winUninstallColormap(ColormapPtr pmap)155 winUninstallColormap(ColormapPtr pmap)
156 {
157 winScreenPriv(pmap->pScreen);
158 ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
159
160 #if CYGDEBUG
161 winDebug("winUninstallColormap\n");
162 #endif
163
164 /* Is the colormap currently installed? */
165 if (pmap != curpmap) {
166 /* Colormap not installed, nothing to do */
167 return;
168 }
169
170 /* Clear the installed colormap flag */
171 pScreenPriv->pcmapInstalled = NULL;
172
173 /*
174 * NOTE: The default colormap does not get "uninstalled" before
175 * it is destroyed.
176 */
177
178 /* Install the default cmap in place of the cmap to be uninstalled */
179 if (pmap->mid != pmap->pScreen->defColormap) {
180 dixLookupResourceByType((void *) &curpmap, pmap->pScreen->defColormap,
181 RT_COLORMAP, NullClient, DixUnknownAccess);
182 (*pmap->pScreen->InstallColormap) (curpmap);
183 }
184 }
185
186 /* See Porting Layer Definition - p. 30 */
187 static void
winStoreColors(ColormapPtr pmap,int ndef,xColorItem * pdefs)188 winStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs)
189 {
190 ScreenPtr pScreen = pmap->pScreen;
191
192 winScreenPriv(pScreen);
193 winCmapPriv(pmap);
194 int i;
195 unsigned short nRed, nGreen, nBlue;
196
197 #if CYGDEBUG
198 if (ndef != 1)
199 winDebug("winStoreColors - ndef: %d\n", ndef);
200 #endif
201
202 /* Save the new colors in the colormap privates */
203 for (i = 0; i < ndef; ++i) {
204 /* Adjust the colors from the X color spec to the Windows color spec */
205 nRed = pdefs[i].red >> 8;
206 nGreen = pdefs[i].green >> 8;
207 nBlue = pdefs[i].blue >> 8;
208
209 /* Copy the colors to a palette entry table */
210 pCmapPriv->peColors[pdefs[0].pixel + i].peRed = nRed;
211 pCmapPriv->peColors[pdefs[0].pixel + i].peGreen = nGreen;
212 pCmapPriv->peColors[pdefs[0].pixel + i].peBlue = nBlue;
213
214 /* Copy the colors to a RGBQUAD table */
215 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbRed = nRed;
216 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbGreen = nGreen;
217 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbBlue = nBlue;
218
219 #if CYGDEBUG
220 winDebug("winStoreColors - nRed %d nGreen %d nBlue %d\n",
221 nRed, nGreen, nBlue);
222 #endif
223 }
224
225 /* Call the engine specific store colors procedure */
226 if (!((pScreenPriv->pwinStoreColors) (pmap, ndef, pdefs))) {
227 winErrorFVerb(2,
228 "winStoreColors - Engine cpecific color storage procedure "
229 "failed. Continuing, but colors may be messed up from now "
230 "on.\n");
231 }
232 }
233
234 /* See Porting Layer Definition - p. 30 */
235 static void
winResolveColor(unsigned short * pred,unsigned short * pgreen,unsigned short * pblue,VisualPtr pVisual)236 winResolveColor(unsigned short *pred,
237 unsigned short *pgreen,
238 unsigned short *pblue, VisualPtr pVisual)
239 {
240 #if CYGDEBUG
241 winDebug("winResolveColor ()\n");
242 #endif
243
244 miResolveColor(pred, pgreen, pblue, pVisual);
245 }
246
247 /* See Porting Layer Definition - p. 29 */
248 static Bool
winCreateColormap(ColormapPtr pmap)249 winCreateColormap(ColormapPtr pmap)
250 {
251 winPrivCmapPtr pCmapPriv = NULL;
252 ScreenPtr pScreen = pmap->pScreen;
253
254 winScreenPriv(pScreen);
255
256 #if CYGDEBUG
257 winDebug("winCreateColormap\n");
258 #endif
259
260 /* Allocate colormap privates */
261 if (!winAllocateCmapPrivates(pmap)) {
262 ErrorF("winCreateColorma - Couldn't allocate cmap privates\n");
263 return FALSE;
264 }
265
266 /* Get a pointer to the newly allocated privates */
267 pCmapPriv = winGetCmapPriv(pmap);
268
269 /*
270 * FIXME: This is some evil hackery to help in handling some X clients
271 * that expect the top pixel to be white. This "help" only lasts until
272 * some client overwrites the top colormap entry.
273 *
274 * We don't want to actually allocate the top entry, as that causes
275 * problems with X clients that need 7 planes (128 colors) in the default
276 * colormap, such as Magic 7.1.
277 */
278 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbRed = 255;
279 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbGreen = 255;
280 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbBlue = 255;
281 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peRed = 255;
282 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peGreen = 255;
283 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peBlue = 255;
284
285 /* Call the engine specific colormap initialization procedure */
286 if (!((*pScreenPriv->pwinCreateColormap) (pmap))) {
287 ErrorF("winCreateColormap - Engine specific colormap creation "
288 "procedure failed. Aborting.\n");
289 return FALSE;
290 }
291
292 return TRUE;
293 }
294
295 /* See Porting Layer Definition - p. 29, 30 */
296 static void
winDestroyColormap(ColormapPtr pColormap)297 winDestroyColormap(ColormapPtr pColormap)
298 {
299 winScreenPriv(pColormap->pScreen);
300 winCmapPriv(pColormap);
301
302 /* Call the engine specific colormap destruction procedure */
303 if (!((*pScreenPriv->pwinDestroyColormap) (pColormap))) {
304 winErrorFVerb(2,
305 "winDestroyColormap - Engine specific colormap destruction "
306 "procedure failed. Continuing, but it is possible that memory "
307 "was leaked, or that colors will be messed up from now on.\n");
308 }
309
310 /* Free the colormap privates */
311 free(pCmapPriv);
312 winSetCmapPriv(pColormap, NULL);
313
314 #if CYGDEBUG
315 winDebug("winDestroyColormap - Returning\n");
316 #endif
317 }
318
319 /*
320 * Internal function to load the palette used by the Shadow DIB
321 */
322
323 static Bool
winGetPaletteDIB(ScreenPtr pScreen,ColormapPtr pcmap)324 winGetPaletteDIB(ScreenPtr pScreen, ColormapPtr pcmap)
325 {
326 winScreenPriv(pScreen);
327 int i;
328 Pixel pixel; /* Pixel == CARD32 */
329 CARD16 nRed, nGreen, nBlue; /* CARD16 == unsigned short */
330 UINT uiColorsRetrieved = 0;
331 RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES];
332
333 /* Get the color table for the screen */
334 uiColorsRetrieved = GetDIBColorTable(pScreenPriv->hdcScreen,
335 0, WIN_NUM_PALETTE_ENTRIES, rgbColors);
336 if (uiColorsRetrieved == 0) {
337 ErrorF("winGetPaletteDIB - Could not retrieve screen color table\n");
338 return FALSE;
339 }
340
341 #if CYGDEBUG
342 winDebug("winGetPaletteDIB - Retrieved %d colors from DIB\n",
343 uiColorsRetrieved);
344 #endif
345
346 /* Set the DIB color table to the default screen palette */
347 if (SetDIBColorTable(pScreenPriv->hdcShadow,
348 0, uiColorsRetrieved, rgbColors) == 0) {
349 ErrorF("winGetPaletteDIB - SetDIBColorTable () failed\n");
350 return FALSE;
351 }
352
353 /* Alloc each color in the DIB color table */
354 for (i = 0; i < uiColorsRetrieved; ++i) {
355 pixel = i;
356
357 /* Extract the color values for current palette entry */
358 nRed = rgbColors[i].rgbRed << 8;
359 nGreen = rgbColors[i].rgbGreen << 8;
360 nBlue = rgbColors[i].rgbBlue << 8;
361
362 #if CYGDEBUG
363 winDebug("winGetPaletteDIB - Allocating a color: %u; "
364 "%d %d %d\n", (unsigned int)pixel, nRed, nGreen, nBlue);
365 #endif
366
367 /* Allocate a entry in the X colormap */
368 if (AllocColor(pcmap, &nRed, &nGreen, &nBlue, &pixel, 0) != Success) {
369 ErrorF("winGetPaletteDIB - AllocColor () failed, pixel %d\n", i);
370 return FALSE;
371 }
372
373 if (i != pixel
374 || nRed != rgbColors[i].rgbRed
375 || nGreen != rgbColors[i].rgbGreen
376 || nBlue != rgbColors[i].rgbBlue) {
377 winDebug("winGetPaletteDIB - Got: %d; "
378 "%d %d %d\n", (int) pixel, nRed, nGreen, nBlue);
379 }
380
381 /* FIXME: Not sure that this bit is needed at all */
382 pcmap->red[i].co.local.red = nRed;
383 pcmap->red[i].co.local.green = nGreen;
384 pcmap->red[i].co.local.blue = nBlue;
385 }
386
387 /* System is using a colormap */
388 /* Set the black and white pixel indices */
389 pScreen->whitePixel = uiColorsRetrieved - 1;
390 pScreen->blackPixel = 0;
391
392 return TRUE;
393 }
394
395 /*
396 * Internal function to load the standard system palette being used by DD
397 */
398
399 static Bool
winGetPaletteDD(ScreenPtr pScreen,ColormapPtr pcmap)400 winGetPaletteDD(ScreenPtr pScreen, ColormapPtr pcmap)
401 {
402 int i;
403 Pixel pixel; /* Pixel == CARD32 */
404 CARD16 nRed, nGreen, nBlue; /* CARD16 == unsigned short */
405 UINT uiSystemPaletteEntries;
406 LPPALETTEENTRY ppeColors = NULL;
407 HDC hdc = NULL;
408
409 /* Get a DC to obtain the default palette */
410 hdc = GetDC(NULL);
411 if (hdc == NULL) {
412 ErrorF("winGetPaletteDD - Couldn't get a DC\n");
413 return FALSE;
414 }
415
416 /* Get the number of entries in the system palette */
417 uiSystemPaletteEntries = GetSystemPaletteEntries(hdc, 0, 0, NULL);
418 if (uiSystemPaletteEntries == 0) {
419 ErrorF("winGetPaletteDD - Unable to determine number of "
420 "system palette entries\n");
421 return FALSE;
422 }
423
424 #if CYGDEBUG
425 winDebug("winGetPaletteDD - uiSystemPaletteEntries %d\n",
426 uiSystemPaletteEntries);
427 #endif
428
429 /* Allocate palette entries structure */
430 ppeColors = malloc(uiSystemPaletteEntries * sizeof(PALETTEENTRY));
431 if (ppeColors == NULL) {
432 ErrorF("winGetPaletteDD - malloc () for colormap failed\n");
433 return FALSE;
434 }
435
436 /* Get system palette entries */
437 GetSystemPaletteEntries(hdc, 0, uiSystemPaletteEntries, ppeColors);
438
439 /* Allocate an X colormap entry for every system palette entry */
440 for (i = 0; i < uiSystemPaletteEntries; ++i) {
441 pixel = i;
442
443 /* Extract the color values for current palette entry */
444 nRed = ppeColors[i].peRed << 8;
445 nGreen = ppeColors[i].peGreen << 8;
446 nBlue = ppeColors[i].peBlue << 8;
447 #if CYGDEBUG
448 winDebug("winGetPaletteDD - Allocating a color: %u; "
449 "%d %d %d\n", (unsigned int)pixel, nRed, nGreen, nBlue);
450 #endif
451 if (AllocColor(pcmap, &nRed, &nGreen, &nBlue, &pixel, 0) != Success) {
452 ErrorF("winGetPaletteDD - AllocColor () failed, pixel %d\n", i);
453 free(ppeColors);
454 ppeColors = NULL;
455 return FALSE;
456 }
457
458 pcmap->red[i].co.local.red = nRed;
459 pcmap->red[i].co.local.green = nGreen;
460 pcmap->red[i].co.local.blue = nBlue;
461 }
462
463 /* System is using a colormap */
464 /* Set the black and white pixel indices */
465 pScreen->whitePixel = uiSystemPaletteEntries - 1;
466 pScreen->blackPixel = 0;
467
468 /* Free colormap */
469 free(ppeColors);
470 ppeColors = NULL;
471
472 /* Free the DC */
473 if (hdc != NULL) {
474 ReleaseDC(NULL, hdc);
475 hdc = NULL;
476 }
477
478 return TRUE;
479 }
480
481 /*
482 * Install the standard fb colormap, or the GDI colormap,
483 * depending on the current screen depth.
484 */
485
486 Bool
winCreateDefColormap(ScreenPtr pScreen)487 winCreateDefColormap(ScreenPtr pScreen)
488 {
489 winScreenPriv(pScreen);
490 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
491 unsigned short zero = 0, ones = 0xFFFF;
492 VisualPtr pVisual = pScreenPriv->pRootVisual;
493 ColormapPtr pcmap = NULL;
494 Pixel wp, bp;
495
496 #if CYGDEBUG
497 winDebug("winCreateDefColormap\n");
498 #endif
499
500 /* Use standard fb colormaps for non palettized color modes */
501 if (pScreenInfo->dwBPP > 8) {
502 winDebug("winCreateDefColormap - Deferring to "
503 "fbCreateDefColormap ()\n");
504 return fbCreateDefColormap(pScreen);
505 }
506
507 /*
508 * AllocAll for non-Dynamic visual classes,
509 * AllocNone for Dynamic visual classes.
510 */
511
512 /*
513 * Dynamic visual classes allow the colors of the color map
514 * to be changed by clients.
515 */
516
517 #if CYGDEBUG
518 winDebug("winCreateDefColormap - defColormap: %lu\n", pScreen->defColormap);
519 #endif
520
521 /* Allocate an X colormap, owned by client 0 */
522 if (CreateColormap(pScreen->defColormap,
523 pScreen,
524 pVisual,
525 &pcmap,
526 (pVisual->class & DynamicClass) ? AllocNone : AllocAll,
527 0) != Success) {
528 ErrorF("winCreateDefColormap - CreateColormap failed\n");
529 return FALSE;
530 }
531 if (pcmap == NULL) {
532 ErrorF("winCreateDefColormap - Colormap could not be created\n");
533 return FALSE;
534 }
535
536 #if CYGDEBUG
537 winDebug("winCreateDefColormap - Created a colormap\n");
538 #endif
539
540 /* Branch on the visual class */
541 if (!(pVisual->class & DynamicClass)) {
542 /* Branch on engine type */
543 if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) {
544 /* Load the colors being used by the Shadow DIB */
545 if (!winGetPaletteDIB(pScreen, pcmap)) {
546 ErrorF("winCreateDefColormap - Couldn't get DIB colors\n");
547 return FALSE;
548 }
549 }
550 else {
551 /* Load the colors from the default system palette */
552 if (!winGetPaletteDD(pScreen, pcmap)) {
553 ErrorF("winCreateDefColormap - Couldn't get colors "
554 "for DD\n");
555 return FALSE;
556 }
557 }
558 }
559 else {
560 wp = pScreen->whitePixel;
561 bp = pScreen->blackPixel;
562
563 /* Allocate a black and white pixel */
564 if ((AllocColor(pcmap, &ones, &ones, &ones, &wp, 0) != Success)
565 || (AllocColor(pcmap, &zero, &zero, &zero, &bp, 0) != Success)) {
566 ErrorF("winCreateDefColormap - Couldn't allocate bp or wp\n");
567 return FALSE;
568 }
569
570 pScreen->whitePixel = wp;
571 pScreen->blackPixel = bp;
572
573 #if 0
574 /* Have to reserve first 10 and last ten pixels in DirectDraw windowed */
575 if (pScreenInfo->dwEngine != WIN_SERVER_SHADOW_GDI) {
576 int k;
577 Pixel p;
578
579 for (k = 1; k < 10; ++k) {
580 p = k;
581 if (AllocColor(pcmap, &ones, &ones, &ones, &p, 0) != Success)
582 FatalError("Foo!\n");
583 }
584
585 for (k = 245; k < 255; ++k) {
586 p = k;
587 if (AllocColor(pcmap, &zero, &zero, &zero, &p, 0) != Success)
588 FatalError("Baz!\n");
589 }
590 }
591 #endif
592 }
593
594 /* Install the created colormap */
595 (*pScreen->InstallColormap) (pcmap);
596
597 #if CYGDEBUG
598 winDebug("winCreateDefColormap - Returning\n");
599 #endif
600
601 return TRUE;
602 }
603