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 43static int 44 winListInstalledColormaps(ScreenPtr pScreen, Colormap * pmaps); 45 46static void 47 winStoreColors(ColormapPtr pmap, int ndef, xColorItem * pdefs); 48 49static void 50 winInstallColormap(ColormapPtr pmap); 51 52static void 53 winUninstallColormap(ColormapPtr pmap); 54 55static void 56 57winResolveColor(unsigned short *pred, 58 unsigned short *pgreen, 59 unsigned short *pblue, VisualPtr pVisual); 60 61static Bool 62 winCreateColormap(ColormapPtr pmap); 63 64static void 65 winDestroyColormap(ColormapPtr pmap); 66 67static Bool 68 winGetPaletteDIB(ScreenPtr pScreen, ColormapPtr pcmap); 69 70static Bool 71 winGetPaletteDD(ScreenPtr pScreen, ColormapPtr pcmap); 72 73/* 74 * Set screen functions for colormaps 75 */ 76 77void 78winSetColormapFunctions(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 */ 95static int 96winListInstalledColormaps(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 */ 111static void 112winInstallColormap(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 */ 154static void 155winUninstallColormap(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 */ 187static void 188winStoreColors(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 */ 235static void 236winResolveColor(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 */ 248static Bool 249winCreateColormap(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 */ 296static void 297winDestroyColormap(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 323static Bool 324winGetPaletteDIB(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 399static Bool 400winGetPaletteDD(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 486Bool 487winCreateDefColormap(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