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