wincmap.c revision 9ace9065
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/* 41 * Local prototypes 42 */ 43 44static int 45winListInstalledColormaps (ScreenPtr pScreen, Colormap *pmaps); 46 47static void 48winStoreColors (ColormapPtr pmap, int ndef, xColorItem *pdefs); 49 50static void 51winInstallColormap (ColormapPtr pmap); 52 53static void 54winUninstallColormap (ColormapPtr pmap); 55 56static void 57winResolveColor (unsigned short *pred, 58 unsigned short *pgreen, 59 unsigned short *pblue, 60 VisualPtr pVisual); 61 62static Bool 63winCreateColormap (ColormapPtr pmap); 64 65static void 66winDestroyColormap (ColormapPtr pmap); 67 68static Bool 69winGetPaletteDIB (ScreenPtr pScreen, ColormapPtr pcmap); 70 71static Bool 72winGetPaletteDD (ScreenPtr pScreen, ColormapPtr pcmap); 73 74 75/* 76 * Set screen functions for colormaps 77 */ 78 79void 80winSetColormapFunctions (ScreenPtr pScreen) 81{ 82 pScreen->CreateColormap = winCreateColormap; 83 pScreen->DestroyColormap = winDestroyColormap; 84 pScreen->InstallColormap = winInstallColormap; 85 pScreen->UninstallColormap = winUninstallColormap; 86 pScreen->ListInstalledColormaps = winListInstalledColormaps; 87 pScreen->StoreColors = winStoreColors; 88 pScreen->ResolveColor = winResolveColor; 89} 90 91 92/* See Porting Layer Definition - p. 30 */ 93/* 94 * Walk the list of installed colormaps, filling the pmaps list 95 * with the resource ids of the installed maps, and return 96 * a count of the total number of installed maps. 97 */ 98static int 99winListInstalledColormaps (ScreenPtr pScreen, Colormap *pmaps) 100{ 101 winScreenPriv(pScreen); 102 103 /* 104 * There will only be one installed colormap, so we only need 105 * to return one id, and the count of installed maps will always 106 * be one. 107 */ 108 *pmaps = pScreenPriv->pcmapInstalled->mid; 109 return 1; 110} 111 112 113/* See Porting Layer Definition - p. 30 */ 114/* See Programming Windows - p. 663 */ 115static void 116winInstallColormap (ColormapPtr pColormap) 117{ 118 ScreenPtr pScreen = pColormap->pScreen; 119 winScreenPriv(pScreen); 120 ColormapPtr oldpmap = pScreenPriv->pcmapInstalled; 121 122#if CYGDEBUG 123 winDebug ("winInstallColormap\n"); 124#endif 125 126 /* Did the colormap actually change? */ 127 if (pColormap != oldpmap) 128 { 129#if CYGDEBUG 130 winDebug ("winInstallColormap - Colormap has changed, attempt " 131 "to install.\n"); 132#endif 133 134 /* Was there a previous colormap? */ 135 if (oldpmap != (ColormapPtr) None) 136 { 137 /* There was a previous colormap; tell clients it is gone */ 138 WalkTree (pColormap->pScreen, TellLostMap, (char *)&oldpmap->mid); 139 } 140 141 /* Install new colormap */ 142 pScreenPriv->pcmapInstalled = pColormap; 143 WalkTree (pColormap->pScreen, TellGainedMap, (char *)&pColormap->mid); 144 145 /* Call the engine specific colormap install procedure */ 146 if (!((*pScreenPriv->pwinInstallColormap) (pColormap))) 147 { 148 winErrorFVerb (2, "winInstallColormap - Screen specific colormap install " 149 "procedure failed. Continuing, but colors may be " 150 "messed up from now on.\n"); 151 } 152 } 153 154 /* Save a pointer to the newly installed colormap */ 155 pScreenPriv->pcmapInstalled = pColormap; 156} 157 158 159/* See Porting Layer Definition - p. 30 */ 160static void 161winUninstallColormap (ColormapPtr pmap) 162{ 163 winScreenPriv(pmap->pScreen); 164 ColormapPtr curpmap = pScreenPriv->pcmapInstalled; 165 166#if CYGDEBUG 167 winDebug ("winUninstallColormap\n"); 168#endif 169 170 /* Is the colormap currently installed? */ 171 if (pmap != curpmap) 172 { 173 /* Colormap not installed, nothing to do */ 174 return; 175 } 176 177 /* Clear the installed colormap flag */ 178 pScreenPriv->pcmapInstalled = NULL; 179 180 /* 181 * NOTE: The default colormap does not get "uninstalled" before 182 * it is destroyed. 183 */ 184 185 /* Install the default cmap in place of the cmap to be uninstalled */ 186 if (pmap->mid != pmap->pScreen->defColormap) 187 { 188 dixLookupResourceByType((pointer) &curpmap, pmap->pScreen->defColormap, 189 RT_COLORMAP, NullClient, DixUnknownAccess); 190 (*pmap->pScreen->InstallColormap) (curpmap); 191 } 192} 193 194 195/* See Porting Layer Definition - p. 30 */ 196static void 197winStoreColors (ColormapPtr pmap, 198 int ndef, 199 xColorItem *pdefs) 200{ 201 ScreenPtr pScreen = pmap->pScreen; 202 winScreenPriv(pScreen); 203 winCmapPriv(pmap); 204 int i; 205 unsigned short nRed, nGreen, nBlue; 206 207#if CYGDEBUG 208 if (ndef != 1) 209 winDebug ("winStoreColors - ndef: %d\n", 210 ndef); 211#endif 212 213 /* Save the new colors in the colormap privates */ 214 for (i = 0; i < ndef; ++i) 215 { 216 /* Adjust the colors from the X color spec to the Windows color spec */ 217 nRed = pdefs[i].red >> 8; 218 nGreen = pdefs[i].green >> 8; 219 nBlue = pdefs[i].blue >> 8; 220 221 /* Copy the colors to a palette entry table */ 222 pCmapPriv->peColors[pdefs[0].pixel + i].peRed = nRed; 223 pCmapPriv->peColors[pdefs[0].pixel + i].peGreen = nGreen; 224 pCmapPriv->peColors[pdefs[0].pixel + i].peBlue = nBlue; 225 226 /* Copy the colors to a RGBQUAD table */ 227 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbRed = nRed; 228 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbGreen = nGreen; 229 pCmapPriv->rgbColors[pdefs[0].pixel + i].rgbBlue = nBlue; 230 231#if CYGDEBUG 232 winDebug ("winStoreColors - nRed %d nGreen %d nBlue %d\n", 233 nRed, nGreen, nBlue); 234#endif 235 } 236 237 /* Call the engine specific store colors procedure */ 238 if (!((pScreenPriv->pwinStoreColors) (pmap, ndef, pdefs))) 239 { 240 winErrorFVerb (2, "winStoreColors - Engine cpecific color storage procedure " 241 "failed. Continuing, but colors may be messed up from now " 242 "on.\n"); 243 } 244} 245 246 247/* See Porting Layer Definition - p. 30 */ 248static void 249winResolveColor (unsigned short *pred, 250 unsigned short *pgreen, 251 unsigned short *pblue, 252 VisualPtr pVisual) 253{ 254#if CYGDEBUG 255 winDebug ("winResolveColor ()\n"); 256#endif 257 258 miResolveColor (pred, pgreen, pblue, pVisual); 259} 260 261 262/* See Porting Layer Definition - p. 29 */ 263static Bool 264winCreateColormap (ColormapPtr pmap) 265{ 266 winPrivCmapPtr pCmapPriv = NULL; 267 ScreenPtr pScreen = pmap->pScreen; 268 winScreenPriv(pScreen); 269 270#if CYGDEBUG 271 winDebug ("winCreateColormap\n"); 272#endif 273 274 /* Allocate colormap privates */ 275 if (!winAllocateCmapPrivates (pmap)) 276 { 277 ErrorF ("winCreateColorma - Couldn't allocate cmap privates\n"); 278 return FALSE; 279 } 280 281 /* Get a pointer to the newly allocated privates */ 282 pCmapPriv = winGetCmapPriv (pmap); 283 284 /* 285 * FIXME: This is some evil hackery to help in handling some X clients 286 * that expect the top pixel to be white. This "help" only lasts until 287 * some client overwrites the top colormap entry. 288 * 289 * We don't want to actually allocate the top entry, as that causes 290 * problems with X clients that need 7 planes (128 colors) in the default 291 * colormap, such as Magic 7.1. 292 */ 293 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbRed = 255; 294 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbGreen = 255; 295 pCmapPriv->rgbColors[WIN_NUM_PALETTE_ENTRIES - 1].rgbBlue = 255; 296 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peRed = 255; 297 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peGreen = 255; 298 pCmapPriv->peColors[WIN_NUM_PALETTE_ENTRIES - 1].peBlue = 255; 299 300 /* Call the engine specific colormap initialization procedure */ 301 if (!((*pScreenPriv->pwinCreateColormap) (pmap))) 302 { 303 ErrorF ("winCreateColormap - Engine specific colormap creation " 304 "procedure failed. Aborting.\n"); 305 return FALSE; 306 } 307 308 return TRUE; 309} 310 311 312/* See Porting Layer Definition - p. 29, 30 */ 313static void 314winDestroyColormap (ColormapPtr pColormap) 315{ 316 winScreenPriv(pColormap->pScreen); 317 winCmapPriv(pColormap); 318 319 /* Call the engine specific colormap destruction procedure */ 320 if (!((*pScreenPriv->pwinDestroyColormap) (pColormap))) 321 { 322 winErrorFVerb (2, "winDestroyColormap - Engine specific colormap destruction " 323 "procedure failed. Continuing, but it is possible that memory " 324 "was leaked, or that colors will be messed up from now on.\n"); 325 } 326 327 /* Free the colormap privates */ 328 free (pCmapPriv); 329 winSetCmapPriv (pColormap, NULL); 330 331#if CYGDEBUG 332 winDebug ("winDestroyColormap - Returning\n"); 333#endif 334} 335 336 337/* 338 * Internal function to load the palette used by the Shadow DIB 339 */ 340 341static Bool 342winGetPaletteDIB (ScreenPtr pScreen, ColormapPtr pcmap) 343{ 344 winScreenPriv(pScreen); 345 int i; 346 Pixel pixel; /* Pixel == CARD32 */ 347 CARD16 nRed, nGreen, nBlue; /* CARD16 == unsigned short */ 348 UINT uiColorsRetrieved = 0; 349 RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES]; 350 351 /* Get the color table for the screen */ 352 uiColorsRetrieved = GetDIBColorTable (pScreenPriv->hdcScreen, 353 0, 354 WIN_NUM_PALETTE_ENTRIES, 355 rgbColors); 356 if (uiColorsRetrieved == 0) 357 { 358 ErrorF ("winGetPaletteDIB - Could not retrieve screen color table\n"); 359 return FALSE; 360 } 361 362#if CYGDEBUG 363 winDebug ("winGetPaletteDIB - Retrieved %d colors from DIB\n", 364 uiColorsRetrieved); 365#endif 366 367 /* Set the DIB color table to the default screen palette */ 368 if (SetDIBColorTable (pScreenPriv->hdcShadow, 369 0, 370 uiColorsRetrieved, 371 rgbColors) == 0) 372 { 373 ErrorF ("winGetPaletteDIB - SetDIBColorTable () failed\n"); 374 return FALSE; 375 } 376 377 /* Alloc each color in the DIB color table */ 378 for (i = 0; i < uiColorsRetrieved; ++i) 379 { 380 pixel = i; 381 382 /* Extract the color values for current palette entry */ 383 nRed = rgbColors[i].rgbRed << 8; 384 nGreen = rgbColors[i].rgbGreen << 8; 385 nBlue = rgbColors[i].rgbBlue << 8; 386 387#if CYGDEBUG 388 winDebug ("winGetPaletteDIB - Allocating a color: %d; " 389 "%d %d %d\n", 390 pixel, nRed, nGreen, nBlue); 391#endif 392 393 /* Allocate a entry in the X colormap */ 394 if (AllocColor (pcmap, 395 &nRed, 396 &nGreen, 397 &nBlue, 398 &pixel, 399 0) != Success) 400 { 401 ErrorF ("winGetPaletteDIB - AllocColor () failed, pixel %d\n", 402 i); 403 return FALSE; 404 } 405 406 if (i != pixel 407 || nRed != rgbColors[i].rgbRed 408 || nGreen != rgbColors[i].rgbGreen 409 || nBlue != rgbColors[i].rgbBlue) 410 { 411 winDebug ("winGetPaletteDIB - Got: %d; " 412 "%d %d %d\n", 413 (int) pixel, nRed, nGreen, nBlue); 414 } 415 416 /* FIXME: Not sure that this bit is needed at all */ 417 pcmap->red[i].co.local.red = nRed; 418 pcmap->red[i].co.local.green = nGreen; 419 pcmap->red[i].co.local.blue = nBlue; 420 } 421 422 /* System is using a colormap */ 423 /* Set the black and white pixel indices */ 424 pScreen->whitePixel = uiColorsRetrieved - 1; 425 pScreen->blackPixel = 0; 426 427 return TRUE; 428} 429 430 431/* 432 * Internal function to load the standard system palette being used by DD 433 */ 434 435static Bool 436winGetPaletteDD (ScreenPtr pScreen, ColormapPtr pcmap) 437{ 438 int i; 439 Pixel pixel; /* Pixel == CARD32 */ 440 CARD16 nRed, nGreen, nBlue; /* CARD16 == unsigned short */ 441 UINT uiSystemPaletteEntries; 442 LPPALETTEENTRY ppeColors = NULL; 443 HDC hdc = NULL; 444 445 /* Get a DC to obtain the default palette */ 446 hdc = GetDC (NULL); 447 if (hdc == NULL) 448 { 449 ErrorF ("winGetPaletteDD - Couldn't get a DC\n"); 450 return FALSE; 451 } 452 453 /* Get the number of entries in the system palette */ 454 uiSystemPaletteEntries = GetSystemPaletteEntries (hdc, 455 0, 0, NULL); 456 if (uiSystemPaletteEntries == 0) 457 { 458 ErrorF ("winGetPaletteDD - Unable to determine number of " 459 "system palette entries\n"); 460 return FALSE; 461 } 462 463#if CYGDEBUG 464 winDebug ("winGetPaletteDD - uiSystemPaletteEntries %d\n", 465 uiSystemPaletteEntries); 466#endif 467 468 /* Allocate palette entries structure */ 469 ppeColors = malloc (uiSystemPaletteEntries * sizeof (PALETTEENTRY)); 470 if (ppeColors == NULL) 471 { 472 ErrorF ("winGetPaletteDD - malloc () for colormap failed\n"); 473 return FALSE; 474 } 475 476 /* Get system palette entries */ 477 GetSystemPaletteEntries (hdc, 478 0, uiSystemPaletteEntries, ppeColors); 479 480 /* Allocate an X colormap entry for every system palette entry */ 481 for (i = 0; i < uiSystemPaletteEntries; ++i) 482 { 483 pixel = i; 484 485 /* Extract the color values for current palette entry */ 486 nRed = ppeColors[i].peRed << 8; 487 nGreen = ppeColors[i].peGreen << 8; 488 nBlue = ppeColors[i].peBlue << 8; 489#if CYGDEBUG 490 winDebug ("winGetPaletteDD - Allocating a color: %d; " 491 "%d %d %d\n", 492 pixel, nRed, nGreen, nBlue); 493#endif 494 if (AllocColor (pcmap, 495 &nRed, 496 &nGreen, 497 &nBlue, 498 &pixel, 499 0) != Success) 500 { 501 ErrorF ("winGetPaletteDD - AllocColor () failed, pixel %d\n", 502 i); 503 free (ppeColors); 504 ppeColors = NULL; 505 return FALSE; 506 } 507 508 pcmap->red[i].co.local.red = nRed; 509 pcmap->red[i].co.local.green = nGreen; 510 pcmap->red[i].co.local.blue = nBlue; 511 } 512 513 /* System is using a colormap */ 514 /* Set the black and white pixel indices */ 515 pScreen->whitePixel = uiSystemPaletteEntries - 1; 516 pScreen->blackPixel = 0; 517 518 /* Free colormap */ 519 free(ppeColors); 520 ppeColors = NULL; 521 522 /* Free the DC */ 523 if (hdc != NULL) 524 { 525 ReleaseDC (NULL, hdc); 526 hdc = NULL; 527 } 528 529 return TRUE; 530} 531 532 533/* 534 * Install the standard fb colormap, or the GDI colormap, 535 * depending on the current screen depth. 536 */ 537 538Bool 539winCreateDefColormap (ScreenPtr pScreen) 540{ 541 winScreenPriv(pScreen); 542 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 543 unsigned short zero = 0, ones = 0xFFFF; 544 VisualPtr pVisual = pScreenPriv->pRootVisual; 545 ColormapPtr pcmap = NULL; 546 Pixel wp, bp; 547 548#if CYGDEBUG 549 winDebug ("winCreateDefColormap\n"); 550#endif 551 552 /* Use standard fb colormaps for non palettized color modes */ 553 if (pScreenInfo->dwBPP > 8) 554 { 555 winDebug ("winCreateDefColormap - Deferring to " \ 556 "fbCreateDefColormap ()\n"); 557 return fbCreateDefColormap (pScreen); 558 } 559 560 /* 561 * AllocAll for non-Dynamic visual classes, 562 * AllocNone for Dynamic visual classes. 563 */ 564 565 /* 566 * Dynamic visual classes allow the colors of the color map 567 * to be changed by clients. 568 */ 569 570#if CYGDEBUG 571 winDebug ("winCreateDefColormap - defColormap: %d\n", 572 pScreen->defColormap); 573#endif 574 575 /* Allocate an X colormap, owned by client 0 */ 576 if (CreateColormap (pScreen->defColormap, 577 pScreen, 578 pVisual, 579 &pcmap, 580 (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 581 0) != Success) 582 { 583 ErrorF ("winCreateDefColormap - CreateColormap failed\n"); 584 return FALSE; 585 } 586 if (pcmap == NULL) 587 { 588 ErrorF ("winCreateDefColormap - Colormap could not be created\n"); 589 return FALSE; 590 } 591 592#if CYGDEBUG 593 winDebug ("winCreateDefColormap - Created a colormap\n"); 594#endif 595 596 /* Branch on the visual class */ 597 if (!(pVisual->class & DynamicClass)) 598 { 599 /* Branch on engine type */ 600 if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) 601 { 602 /* Load the colors being used by the Shadow DIB */ 603 if (!winGetPaletteDIB (pScreen, pcmap)) 604 { 605 ErrorF ("winCreateDefColormap - Couldn't get DIB colors\n"); 606 return FALSE; 607 } 608 } 609 else 610 { 611 /* Load the colors from the default system palette */ 612 if (!winGetPaletteDD (pScreen, pcmap)) 613 { 614 ErrorF ("winCreateDefColormap - Couldn't get colors " 615 "for DD\n"); 616 return FALSE; 617 } 618 } 619 } 620 else 621 { 622 wp = pScreen->whitePixel; 623 bp = pScreen->blackPixel; 624 625 /* Allocate a black and white pixel */ 626 if ((AllocColor (pcmap, &ones, &ones, &ones, &wp, 0) != 627 Success) 628 || 629 (AllocColor (pcmap, &zero, &zero, &zero, &bp, 0) != 630 Success)) 631 { 632 ErrorF ("winCreateDefColormap - Couldn't allocate bp or wp\n"); 633 return FALSE; 634 } 635 636 pScreen->whitePixel = wp; 637 pScreen->blackPixel = bp; 638 639#if 0 640 /* Have to reserve first 10 and last ten pixels in DirectDraw windowed */ 641 if (pScreenInfo->dwEngine != WIN_SERVER_SHADOW_GDI) 642 { 643 int k; 644 Pixel p; 645 646 for (k = 1; k < 10; ++k) 647 { 648 p = k; 649 if (AllocColor (pcmap, &ones, &ones, &ones, &p, 0) != Success) 650 FatalError ("Foo!\n"); 651 } 652 653 for (k = 245; k < 255; ++k) 654 { 655 p = k; 656 if (AllocColor (pcmap, &zero, &zero, &zero, &p, 0) != Success) 657 FatalError ("Baz!\n"); 658 } 659 } 660#endif 661 } 662 663 /* Install the created colormap */ 664 (*pScreen->InstallColormap)(pcmap); 665 666#if CYGDEBUG 667 winDebug ("winCreateDefColormap - Returning\n"); 668#endif 669 670 return TRUE; 671} 672