micmap.c revision 05b261ec
1/************************************************************ 2Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, and distribute this 7software and its documentation for any purpose and without 8fee is hereby granted, provided that the above copyright no- 9tice appear in all copies and that both that copyright no- 10tice and this permission notice appear in supporting docu- 11mentation, and that the names of Sun or X Consortium 12not be used in advertising or publicity pertaining to 13distribution of the software without specific prior 14written permission. Sun and X Consortium make no 15representations about the suitability of this software for 16any purpose. It is provided "as is" without any express or 17implied warranty. 18 19SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 20INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 21NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 22ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 23ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 24PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 25OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 26THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 28********************************************************/ 29 30/* 31 * This is based on cfbcmap.c. The functions here are useful independently 32 * of cfb, which is the reason for including them here. How "mi" these 33 * are may be debatable. 34 */ 35 36 37#ifdef HAVE_DIX_CONFIG_H 38#include <dix-config.h> 39#endif 40 41#include <X11/X.h> 42#include <X11/Xproto.h> 43#include "scrnintstr.h" 44#include "colormapst.h" 45#include "resource.h" 46#include "globals.h" 47#include "micmap.h" 48 49_X_EXPORT ColormapPtr miInstalledMaps[MAXSCREENS]; 50 51static Bool miDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, 52 int *ndepthp, int *rootDepthp, VisualID *defaultVisp, 53 unsigned long sizes, int bitsPerRGB, int preferredVis); 54 55_X_EXPORT miInitVisualsProcPtr miInitVisualsProc = miDoInitVisuals; 56 57_X_EXPORT int 58miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) 59{ 60 if (miInstalledMaps[pScreen->myNum]) { 61 *pmaps = miInstalledMaps[pScreen->myNum]->mid; 62 return (1); 63 } 64 return 0; 65} 66 67_X_EXPORT void 68miInstallColormap(ColormapPtr pmap) 69{ 70 int index = pmap->pScreen->myNum; 71 ColormapPtr oldpmap = miInstalledMaps[index]; 72 73 if(pmap != oldpmap) 74 { 75 /* Uninstall pInstalledMap. No hardware changes required, just 76 * notify all interested parties. */ 77 if(oldpmap != (ColormapPtr)None) 78 WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); 79 /* Install pmap */ 80 miInstalledMaps[index] = pmap; 81 WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); 82 83 } 84} 85 86_X_EXPORT void 87miUninstallColormap(ColormapPtr pmap) 88{ 89 int index = pmap->pScreen->myNum; 90 ColormapPtr curpmap = miInstalledMaps[index]; 91 92 if(pmap == curpmap) 93 { 94 if (pmap->mid != pmap->pScreen->defColormap) 95 { 96 curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, 97 RT_COLORMAP); 98 (*pmap->pScreen->InstallColormap)(curpmap); 99 } 100 } 101} 102 103_X_EXPORT void 104miResolveColor(unsigned short *pred, unsigned short *pgreen, 105 unsigned short *pblue, VisualPtr pVisual) 106{ 107 int shift = 16 - pVisual->bitsPerRGBValue; 108 unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; 109 110 if ((pVisual->class | DynamicClass) == GrayScale) 111 { 112 /* rescale to gray then rgb bits */ 113 *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; 114 *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; 115 } 116 else 117 { 118 /* rescale to rgb bits */ 119 *pred = ((*pred >> shift) * 65535) / lim; 120 *pgreen = ((*pgreen >> shift) * 65535) / lim; 121 *pblue = ((*pblue >> shift) * 65535) / lim; 122 } 123} 124 125_X_EXPORT Bool 126miInitializeColormap(ColormapPtr pmap) 127{ 128 unsigned i; 129 VisualPtr pVisual; 130 unsigned lim, maxent, shift; 131 132 pVisual = pmap->pVisual; 133 lim = (1 << pVisual->bitsPerRGBValue) - 1; 134 shift = 16 - pVisual->bitsPerRGBValue; 135 maxent = pVisual->ColormapEntries - 1; 136 if (pVisual->class == TrueColor) 137 { 138 unsigned limr, limg, limb; 139 140 limr = pVisual->redMask >> pVisual->offsetRed; 141 limg = pVisual->greenMask >> pVisual->offsetGreen; 142 limb = pVisual->blueMask >> pVisual->offsetBlue; 143 for(i = 0; i <= maxent; i++) 144 { 145 /* rescale to [0..65535] then rgb bits */ 146 pmap->red[i].co.local.red = 147 ((((i * 65535) / limr) >> shift) * 65535) / lim; 148 pmap->green[i].co.local.green = 149 ((((i * 65535) / limg) >> shift) * 65535) / lim; 150 pmap->blue[i].co.local.blue = 151 ((((i * 65535) / limb) >> shift) * 65535) / lim; 152 } 153 } 154 else if (pVisual->class == StaticColor) 155 { 156 unsigned limr, limg, limb; 157 158 limr = pVisual->redMask >> pVisual->offsetRed; 159 limg = pVisual->greenMask >> pVisual->offsetGreen; 160 limb = pVisual->blueMask >> pVisual->offsetBlue; 161 for(i = 0; i <= maxent; i++) 162 { 163 /* rescale to [0..65535] then rgb bits */ 164 pmap->red[i].co.local.red = 165 ((((((i & pVisual->redMask) >> pVisual->offsetRed) 166 * 65535) / limr) >> shift) * 65535) / lim; 167 pmap->red[i].co.local.green = 168 ((((((i & pVisual->greenMask) >> pVisual->offsetGreen) 169 * 65535) / limg) >> shift) * 65535) / lim; 170 pmap->red[i].co.local.blue = 171 ((((((i & pVisual->blueMask) >> pVisual->offsetBlue) 172 * 65535) / limb) >> shift) * 65535) / lim; 173 } 174 } 175 else if (pVisual->class == StaticGray) 176 { 177 for(i = 0; i <= maxent; i++) 178 { 179 /* rescale to [0..65535] then rgb bits */ 180 pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) 181 * 65535) / lim; 182 pmap->red[i].co.local.green = pmap->red[i].co.local.red; 183 pmap->red[i].co.local.blue = pmap->red[i].co.local.red; 184 } 185 } 186 return TRUE; 187} 188 189/* When simulating DirectColor on PseudoColor hardware, multiple 190 entries of the colormap must be updated 191 */ 192 193#define AddElement(mask) { \ 194 pixel = red | green | blue; \ 195 for (i = 0; i < nresult; i++) \ 196 if (outdefs[i].pixel == pixel) \ 197 break; \ 198 if (i == nresult) \ 199 { \ 200 nresult++; \ 201 outdefs[i].pixel = pixel; \ 202 outdefs[i].flags = 0; \ 203 } \ 204 outdefs[i].flags |= (mask); \ 205 outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ 206 outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ 207 outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ 208} 209 210_X_EXPORT int 211miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs, 212 xColorItem *outdefs) 213{ 214 int red, green, blue; 215 int maxred, maxgreen, maxblue; 216 int stepred, stepgreen, stepblue; 217 VisualPtr pVisual; 218 int pixel; 219 int nresult; 220 int i; 221 222 pVisual = pmap->pVisual; 223 224 stepred = 1 << pVisual->offsetRed; 225 stepgreen = 1 << pVisual->offsetGreen; 226 stepblue = 1 << pVisual->offsetBlue; 227 maxred = pVisual->redMask; 228 maxgreen = pVisual->greenMask; 229 maxblue = pVisual->blueMask; 230 nresult = 0; 231 for (;ndef--; indefs++) 232 { 233 if (indefs->flags & DoRed) 234 { 235 red = indefs->pixel & pVisual->redMask; 236 for (green = 0; green <= maxgreen; green += stepgreen) 237 { 238 for (blue = 0; blue <= maxblue; blue += stepblue) 239 { 240 AddElement (DoRed) 241 } 242 } 243 } 244 if (indefs->flags & DoGreen) 245 { 246 green = indefs->pixel & pVisual->greenMask; 247 for (red = 0; red <= maxred; red += stepred) 248 { 249 for (blue = 0; blue <= maxblue; blue += stepblue) 250 { 251 AddElement (DoGreen) 252 } 253 } 254 } 255 if (indefs->flags & DoBlue) 256 { 257 blue = indefs->pixel & pVisual->blueMask; 258 for (red = 0; red <= maxred; red += stepred) 259 { 260 for (green = 0; green <= maxgreen; green += stepgreen) 261 { 262 AddElement (DoBlue) 263 } 264 } 265 } 266 } 267 return nresult; 268} 269 270_X_EXPORT Bool 271miCreateDefColormap(ScreenPtr pScreen) 272{ 273/* 274 * In the following sources PC X server vendors may want to delete 275 * "_not_tog" from "#ifdef WIN32_not_tog" 276 */ 277#ifdef WIN32_not_tog 278 /* 279 * these are the MS-Windows desktop colors, adjusted for X's 16-bit 280 * color specifications. 281 */ 282 static xColorItem citems[] = { 283 { 0, 0, 0, 0, 0, 0 }, 284 { 1, 0x8000, 0, 0, 0, 0 }, 285 { 2, 0, 0x8000, 0, 0, 0 }, 286 { 3, 0x8000, 0x8000, 0, 0, 0 }, 287 { 4, 0, 0, 0x8000, 0, 0 }, 288 { 5, 0x8000, 0, 0x8000, 0, 0 }, 289 { 6, 0, 0x8000, 0x8000, 0, 0 }, 290 { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, 291 { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, 292 { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, 293 { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, 294 { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, 295 { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, 296 { 249, 0xff00, 0, 0, 0, 0 }, 297 { 250, 0, 0xff00, 0, 0, 0 }, 298 { 251, 0xff00, 0xff00, 0, 0, 0 }, 299 { 252, 0, 0, 0xff00, 0, 0 }, 300 { 253, 0xff00, 0, 0xff00, 0, 0 }, 301 { 254, 0, 0xff00, 0xff00, 0, 0 }, 302 { 255, 0xff00, 0xff00, 0xff00, 0, 0 } 303 }; 304#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0] 305 int i; 306#else 307 unsigned short zero = 0, ones = 0xFFFF; 308#endif 309 Pixel wp, bp; 310 VisualPtr pVisual; 311 ColormapPtr cmap; 312 int alloctype; 313 314 for (pVisual = pScreen->visuals; 315 pVisual->vid != pScreen->rootVisual; 316 pVisual++) 317 ; 318 319 if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass)) 320 alloctype = AllocNone; 321 else 322 alloctype = AllocAll; 323 324 if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, 325 alloctype, 0) != Success) 326 return FALSE; 327 328 if (pScreen->rootDepth > 1) { 329 wp = pScreen->whitePixel; 330 bp = pScreen->blackPixel; 331#ifdef WIN32_not_tog 332 for (i = 0; i < NUM_DESKTOP_COLORS; i++) { 333 if (AllocColor (cmap, 334 &citems[i].red, &citems[i].green, &citems[i].blue, 335 &citems[i].pixel, 0) != Success) 336 return FALSE; 337 } 338#else 339 if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != 340 Success) || 341 (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != 342 Success)) 343 return FALSE; 344 pScreen->whitePixel = wp; 345 pScreen->blackPixel = bp; 346#endif 347 } 348 349 (*pScreen->InstallColormap)(cmap); 350 return TRUE; 351} 352 353/* 354 * Default true color bitmasks, should be overridden by 355 * driver 356 */ 357 358#define _RZ(d) ((d + 2) / 3) 359#define _RS(d) 0 360#define _RM(d) ((1 << _RZ(d)) - 1) 361#define _GZ(d) ((d - _RZ(d) + 1) / 2) 362#define _GS(d) _RZ(d) 363#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) 364#define _BZ(d) (d - _RZ(d) - _GZ(d)) 365#define _BS(d) (_RZ(d) + _GZ(d)) 366#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) 367#define _CE(d) (1 << _RZ(d)) 368 369typedef struct _miVisuals { 370 struct _miVisuals *next; 371 int depth; 372 int bitsPerRGB; 373 int visuals; 374 int count; 375 int preferredCVC; 376 Pixel redMask, greenMask, blueMask; 377} miVisualsRec, *miVisualsPtr; 378 379static int miVisualPriority[] = { 380 PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray 381}; 382 383#define NUM_PRIORITY 6 384 385static miVisualsPtr miVisuals; 386 387_X_EXPORT void 388miClearVisualTypes(void) 389{ 390 miVisualsPtr v; 391 392 while ((v = miVisuals)) { 393 miVisuals = v->next; 394 xfree(v); 395 } 396} 397 398 399_X_EXPORT Bool 400miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB, 401 int preferredCVC, 402 Pixel redMask, Pixel greenMask, Pixel blueMask) 403{ 404 miVisualsPtr new, *prev, v; 405 int count; 406 407 new = (miVisualsPtr) xalloc (sizeof *new); 408 if (!new) 409 return FALSE; 410 if (!redMask || !greenMask || !blueMask) 411 { 412 redMask = _RM(depth); 413 greenMask = _GM(depth); 414 blueMask = _BM(depth); 415 } 416 new->next = 0; 417 new->depth = depth; 418 new->visuals = visuals; 419 new->bitsPerRGB = bitsPerRGB; 420 new->preferredCVC = preferredCVC; 421 new->redMask = redMask; 422 new->greenMask = greenMask; 423 new->blueMask = blueMask; 424 count = (visuals >> 1) & 033333333333; 425 count = visuals - count - ((count >> 1) & 033333333333); 426 count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ 427 new->count = count; 428 for (prev = &miVisuals; (v = *prev); prev = &v->next); 429 *prev = new; 430 return TRUE; 431} 432 433_X_EXPORT Bool 434miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC) 435{ 436 return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, 437 preferredCVC, 0, 0, 0); 438} 439 440_X_EXPORT int 441miGetDefaultVisualMask(int depth) 442{ 443 if (depth > MAX_PSEUDO_DEPTH) 444 return LARGE_VISUALS; 445 else if (depth >= MIN_TRUE_DEPTH) 446 return ALL_VISUALS; 447 else if (depth == 1) 448 return StaticGrayMask; 449 else 450 return SMALL_VISUALS; 451} 452 453static Bool 454miVisualTypesSet (int depth) 455{ 456 miVisualsPtr visuals; 457 458 for (visuals = miVisuals; visuals; visuals = visuals->next) 459 if (visuals->depth == depth) 460 return TRUE; 461 return FALSE; 462} 463 464_X_EXPORT Bool 465miSetPixmapDepths (void) 466{ 467 int d, f; 468 469 /* Add any unlisted depths from the pixmap formats */ 470 for (f = 0; f < screenInfo.numPixmapFormats; f++) 471 { 472 d = screenInfo.formats[f].depth; 473 if (!miVisualTypesSet (d)) 474 { 475 if (!miSetVisualTypes (d, 0, 0, -1)) 476 return FALSE; 477 } 478 } 479 return TRUE; 480} 481 482_X_EXPORT Bool 483miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, 484 int *ndepthp, int *rootDepthp, VisualID *defaultVisp, 485 unsigned long sizes, int bitsPerRGB, int preferredVis) 486 487{ 488 if (miInitVisualsProc) 489 return miInitVisualsProc(visualp, depthp, nvisualp, ndepthp, 490 rootDepthp, defaultVisp, sizes, bitsPerRGB, 491 preferredVis); 492 else 493 return FALSE; 494} 495 496/* 497 * Distance to least significant one bit 498 */ 499static int 500maskShift (Pixel p) 501{ 502 int s; 503 504 if (!p) return 0; 505 s = 0; 506 while (!(p & 1)) 507 { 508 s++; 509 p >>= 1; 510 } 511 return s; 512} 513 514/* 515 * Given a list of formats for a screen, create a list 516 * of visuals and depths for the screen which corespond to 517 * the set which can be used with this version of cfb. 518 */ 519 520static Bool 521miDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, 522 int *ndepthp, int *rootDepthp, VisualID *defaultVisp, 523 unsigned long sizes, int bitsPerRGB, int preferredVis) 524{ 525 int i, j = 0, k; 526 VisualPtr visual; 527 DepthPtr depth; 528 VisualID *vid; 529 int d, b; 530 int f; 531 int ndepth, nvisual; 532 int nvtype; 533 int vtype; 534 miVisualsPtr visuals, nextVisuals; 535 int *preferredCVCs, *prefp; 536 int first_depth; 537 538 /* none specified, we'll guess from pixmap formats */ 539 if (!miVisuals) 540 { 541 for (f = 0; f < screenInfo.numPixmapFormats; f++) 542 { 543 d = screenInfo.formats[f].depth; 544 b = screenInfo.formats[f].bitsPerPixel; 545 if (sizes & (1 << (b - 1))) 546 vtype = miGetDefaultVisualMask(d); 547 else 548 vtype = 0; 549 if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1)) 550 return FALSE; 551 } 552 } 553 nvisual = 0; 554 ndepth = 0; 555 for (visuals = miVisuals; visuals; visuals = nextVisuals) 556 { 557 nextVisuals = visuals->next; 558 ndepth++; 559 nvisual += visuals->count; 560 } 561 depth = (DepthPtr) xalloc (ndepth * sizeof (DepthRec)); 562 visual = (VisualPtr) xalloc (nvisual * sizeof (VisualRec)); 563 preferredCVCs = (int *)xalloc(ndepth * sizeof(int)); 564 if (!depth || !visual || !preferredCVCs) 565 { 566 xfree (depth); 567 xfree (visual); 568 xfree (preferredCVCs); 569 return FALSE; 570 } 571 *depthp = depth; 572 *visualp = visual; 573 *ndepthp = ndepth; 574 *nvisualp = nvisual; 575 prefp = preferredCVCs; 576 for (visuals = miVisuals; visuals; visuals = nextVisuals) 577 { 578 nextVisuals = visuals->next; 579 d = visuals->depth; 580 vtype = visuals->visuals; 581 nvtype = visuals->count; 582 *prefp = visuals->preferredCVC; 583 prefp++; 584 vid = NULL; 585 if (nvtype) 586 { 587 vid = (VisualID *) xalloc (nvtype * sizeof (VisualID)); 588 if (!vid) { 589 xfree(preferredCVCs); 590 return FALSE; 591 } 592 } 593 depth->depth = d; 594 depth->numVids = nvtype; 595 depth->vids = vid; 596 depth++; 597 for (i = 0; i < NUM_PRIORITY; i++) { 598 if (! (vtype & (1 << miVisualPriority[i]))) 599 continue; 600 visual->class = miVisualPriority[i]; 601 visual->bitsPerRGBValue = visuals->bitsPerRGB; 602 visual->ColormapEntries = 1 << d; 603 visual->nplanes = d; 604 visual->vid = *vid = FakeClientID (0); 605 switch (visual->class) { 606 case PseudoColor: 607 case GrayScale: 608 case StaticGray: 609 visual->redMask = 0; 610 visual->greenMask = 0; 611 visual->blueMask = 0; 612 visual->offsetRed = 0; 613 visual->offsetGreen = 0; 614 visual->offsetBlue = 0; 615 break; 616 case DirectColor: 617 case TrueColor: 618 visual->ColormapEntries = _CE(d); 619 /* fall through */ 620 case StaticColor: 621 visual->redMask = visuals->redMask; 622 visual->greenMask = visuals->greenMask; 623 visual->blueMask = visuals->blueMask; 624 visual->offsetRed = maskShift (visuals->redMask); 625 visual->offsetGreen = maskShift (visuals->greenMask); 626 visual->offsetBlue = maskShift (visuals->blueMask); 627 } 628 vid++; 629 visual++; 630 } 631 xfree (visuals); 632 } 633 miVisuals = NULL; 634 visual = *visualp; 635 depth = *depthp; 636 637 /* 638 * if we did not supplyied by a preferred visual class 639 * check if there is a preferred class in one of the depth 640 * structures - if there is, we want to start looking for the 641 * default visual/depth from that depth. 642 */ 643 first_depth = 0; 644 if (preferredVis < 0 && defaultColorVisualClass < 0 ) { 645 for (i = 0; i < ndepth; i++) { 646 if (preferredCVCs[i] >= 0) { 647 first_depth = i; 648 break; 649 } 650 } 651 } 652 653 for (i = first_depth; i < ndepth; i++) 654 { 655 int prefColorVisualClass = -1; 656 657 if (defaultColorVisualClass >= 0) 658 prefColorVisualClass = defaultColorVisualClass; 659 else if (preferredVis >= 0) 660 prefColorVisualClass = preferredVis; 661 else if (preferredCVCs[i] >= 0) 662 prefColorVisualClass = preferredCVCs[i]; 663 664 if (*rootDepthp && *rootDepthp != depth[i].depth) 665 continue; 666 667 for (j = 0; j < depth[i].numVids; j++) 668 { 669 for (k = 0; k < nvisual; k++) 670 if (visual[k].vid == depth[i].vids[j]) 671 break; 672 if (k == nvisual) 673 continue; 674 if (prefColorVisualClass < 0 || 675 visual[k].class == prefColorVisualClass) 676 break; 677 } 678 if (j != depth[i].numVids) 679 break; 680 } 681 if (i == ndepth) { 682 i = 0; 683 j = 0; 684 } 685 *rootDepthp = depth[i].depth; 686 *defaultVisp = depth[i].vids[j]; 687 xfree(preferredCVCs); 688 689 return TRUE; 690} 691 692void 693miResetInitVisuals(void) 694{ 695 miInitVisualsProc = miDoInitVisuals; 696} 697 698