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