Imported Upstream version 1.15.1
[deb_xorg-server.git] / mi / micmap.c
CommitLineData
a09e091a
JB
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((pointer *) &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/*
239 * In the following sources PC X server vendors may want to delete
240 * "_not_tog" from "#ifdef WIN32_not_tog"
241 */
242#ifdef WIN32_not_tog
243 /*
244 * these are the MS-Windows desktop colors, adjusted for X's 16-bit
245 * color specifications.
246 */
247 static xColorItem citems[] = {
248 {0, 0, 0, 0, 0, 0},
249 {1, 0x8000, 0, 0, 0, 0},
250 {2, 0, 0x8000, 0, 0, 0},
251 {3, 0x8000, 0x8000, 0, 0, 0},
252 {4, 0, 0, 0x8000, 0, 0},
253 {5, 0x8000, 0, 0x8000, 0, 0},
254 {6, 0, 0x8000, 0x8000, 0, 0},
255 {7, 0xc000, 0xc000, 0xc000, 0, 0},
256 {8, 0xc000, 0xdc00, 0xc000, 0, 0},
257 {9, 0xa600, 0xca00, 0xf000, 0, 0},
258 {246, 0xff00, 0xfb00, 0xf000, 0, 0},
259 {247, 0xa000, 0xa000, 0xa400, 0, 0},
260 {248, 0x8000, 0x8000, 0x8000, 0, 0},
261 {249, 0xff00, 0, 0, 0, 0},
262 {250, 0, 0xff00, 0, 0, 0},
263 {251, 0xff00, 0xff00, 0, 0, 0},
264 {252, 0, 0, 0xff00, 0, 0},
265 {253, 0xff00, 0, 0xff00, 0, 0},
266 {254, 0, 0xff00, 0xff00, 0, 0},
267 {255, 0xff00, 0xff00, 0xff00, 0, 0}
268 };
269#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
270 int i;
271#else
272 unsigned short zero = 0, ones = 0xFFFF;
273#endif
274 Pixel wp, bp;
275 VisualPtr pVisual;
276 ColormapPtr cmap;
277 int alloctype;
278
279 if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
280 return FALSE;
281
282 for (pVisual = pScreen->visuals;
283 pVisual->vid != pScreen->rootVisual; pVisual++);
284
285 if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
286 alloctype = AllocNone;
287 else
288 alloctype = AllocAll;
289
290 if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
291 alloctype, 0) != Success)
292 return FALSE;
293
294 if (pScreen->rootDepth > 1) {
295 wp = pScreen->whitePixel;
296 bp = pScreen->blackPixel;
297#ifdef WIN32_not_tog
298 for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
299 if (AllocColor(cmap,
300 &citems[i].red, &citems[i].green, &citems[i].blue,
301 &citems[i].pixel, 0) != Success)
302 return FALSE;
303 }
304#else
305 if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
306 Success) ||
307 (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != Success))
308 return FALSE;
309 pScreen->whitePixel = wp;
310 pScreen->blackPixel = bp;
311#endif
312 }
313
314 (*pScreen->InstallColormap) (cmap);
315 return TRUE;
316}
317
318/*
319 * Default true color bitmasks, should be overridden by
320 * driver
321 */
322
323#define _RZ(d) ((d + 2) / 3)
324#define _RS(d) 0
325#define _RM(d) ((1 << _RZ(d)) - 1)
326#define _GZ(d) ((d - _RZ(d) + 1) / 2)
327#define _GS(d) _RZ(d)
328#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
329#define _BZ(d) (d - _RZ(d) - _GZ(d))
330#define _BS(d) (_RZ(d) + _GZ(d))
331#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
332#define _CE(d) (1 << _RZ(d))
333
334typedef struct _miVisuals {
335 struct _miVisuals *next;
336 int depth;
337 int bitsPerRGB;
338 int visuals;
339 int count;
340 int preferredCVC;
341 Pixel redMask, greenMask, blueMask;
342} miVisualsRec, *miVisualsPtr;
343
344static int miVisualPriority[] = {
345 PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
346};
347
348#define NUM_PRIORITY 6
349
350static miVisualsPtr miVisuals;
351
352void
353miClearVisualTypes(void)
354{
355 miVisualsPtr v;
356
357 while ((v = miVisuals)) {
358 miVisuals = v->next;
359 free(v);
360 }
361}
362
363Bool
364miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
365 int preferredCVC,
366 Pixel redMask, Pixel greenMask, Pixel blueMask)
367{
368 miVisualsPtr new, *prev, v;
369 int count;
370
371 new = malloc(sizeof *new);
372 if (!new)
373 return FALSE;
374 if (!redMask || !greenMask || !blueMask) {
375 redMask = _RM(depth);
376 greenMask = _GM(depth);
377 blueMask = _BM(depth);
378 }
379 new->next = 0;
380 new->depth = depth;
381 new->visuals = visuals;
382 new->bitsPerRGB = bitsPerRGB;
383 new->preferredCVC = preferredCVC;
384 new->redMask = redMask;
385 new->greenMask = greenMask;
386 new->blueMask = blueMask;
387 count = (visuals >> 1) & 033333333333;
388 count = visuals - count - ((count >> 1) & 033333333333);
389 count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */
390 new->count = count;
391 for (prev = &miVisuals; (v = *prev); prev = &v->next);
392 *prev = new;
393 return TRUE;
394}
395
396Bool
397miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
398{
399 return miSetVisualTypesAndMasks(depth, visuals, bitsPerRGB,
400 preferredCVC, 0, 0, 0);
401}
402
403int
404miGetDefaultVisualMask(int depth)
405{
406 if (depth > MAX_PSEUDO_DEPTH)
407 return LARGE_VISUALS;
408 else if (depth >= MIN_TRUE_DEPTH)
409 return ALL_VISUALS;
410 else if (depth == 1)
411 return StaticGrayMask;
412 else
413 return SMALL_VISUALS;
414}
415
416static Bool
417miVisualTypesSet(int depth)
418{
419 miVisualsPtr visuals;
420
421 for (visuals = miVisuals; visuals; visuals = visuals->next)
422 if (visuals->depth == depth)
423 return TRUE;
424 return FALSE;
425}
426
427Bool
428miSetPixmapDepths(void)
429{
430 int d, f;
431
432 /* Add any unlisted depths from the pixmap formats */
433 for (f = 0; f < screenInfo.numPixmapFormats; f++) {
434 d = screenInfo.formats[f].depth;
435 if (!miVisualTypesSet(d)) {
436 if (!miSetVisualTypes(d, 0, 0, -1))
437 return FALSE;
438 }
439 }
440 return TRUE;
441}
442
443/*
444 * Distance to least significant one bit
445 */
446static int
447maskShift(Pixel p)
448{
449 int s;
450
451 if (!p)
452 return 0;
453 s = 0;
454 while (!(p & 1)) {
455 s++;
456 p >>= 1;
457 }
458 return s;
459}
460
461/*
462 * Given a list of formats for a screen, create a list
463 * of visuals and depths for the screen which corespond to
464 * the set which can be used with this version of cfb.
465 */
466
467Bool
468miInitVisuals(VisualPtr * visualp, DepthPtr * depthp, int *nvisualp,
469 int *ndepthp, int *rootDepthp, VisualID * defaultVisp,
470 unsigned long sizes, int bitsPerRGB, int preferredVis)
471{
472 int i, j = 0, k;
473 VisualPtr visual;
474 DepthPtr depth;
475 VisualID *vid;
476 int d, b;
477 int f;
478 int ndepth, nvisual;
479 int nvtype;
480 int vtype;
481 miVisualsPtr visuals, nextVisuals;
482 int *preferredCVCs, *prefp;
483 int first_depth;
484
485 /* none specified, we'll guess from pixmap formats */
486 if (!miVisuals) {
487 for (f = 0; f < screenInfo.numPixmapFormats; f++) {
488 d = screenInfo.formats[f].depth;
489 b = screenInfo.formats[f].bitsPerPixel;
490 if (sizes & (1 << (b - 1)))
491 vtype = miGetDefaultVisualMask(d);
492 else
493 vtype = 0;
494 if (!miSetVisualTypes(d, vtype, bitsPerRGB, -1))
495 return FALSE;
496 }
497 }
498 nvisual = 0;
499 ndepth = 0;
500 for (visuals = miVisuals; visuals; visuals = nextVisuals) {
501 nextVisuals = visuals->next;
502 ndepth++;
503 nvisual += visuals->count;
504 }
505 depth = malloc(ndepth * sizeof(DepthRec));
506 visual = malloc(nvisual * sizeof(VisualRec));
507 preferredCVCs = malloc(ndepth * sizeof(int));
508 if (!depth || !visual || !preferredCVCs) {
509 free(depth);
510 free(visual);
511 free(preferredCVCs);
512 return FALSE;
513 }
514 *depthp = depth;
515 *visualp = visual;
516 *ndepthp = ndepth;
517 *nvisualp = nvisual;
518 prefp = preferredCVCs;
519 for (visuals = miVisuals; visuals; visuals = nextVisuals) {
520 nextVisuals = visuals->next;
521 d = visuals->depth;
522 vtype = visuals->visuals;
523 nvtype = visuals->count;
524 *prefp = visuals->preferredCVC;
525 prefp++;
526 vid = NULL;
527 if (nvtype) {
528 vid = malloc(nvtype * sizeof(VisualID));
529 if (!vid) {
530 free(depth);
531 free(visual);
532 free(preferredCVCs);
533 return FALSE;
534 }
535 }
536 depth->depth = d;
537 depth->numVids = nvtype;
538 depth->vids = vid;
539 depth++;
540 for (i = 0; i < NUM_PRIORITY; i++) {
541 if (!(vtype & (1 << miVisualPriority[i])))
542 continue;
543 visual->class = miVisualPriority[i];
544 visual->bitsPerRGBValue = visuals->bitsPerRGB;
545 visual->ColormapEntries = 1 << d;
546 visual->nplanes = d;
547 visual->vid = *vid = FakeClientID(0);
548 switch (visual->class) {
549 case PseudoColor:
550 case GrayScale:
551 case StaticGray:
552 visual->redMask = 0;
553 visual->greenMask = 0;
554 visual->blueMask = 0;
555 visual->offsetRed = 0;
556 visual->offsetGreen = 0;
557 visual->offsetBlue = 0;
558 break;
559 case DirectColor:
560 case TrueColor:
561 visual->ColormapEntries = _CE(d);
562 /* fall through */
563 case StaticColor:
564 visual->redMask = visuals->redMask;
565 visual->greenMask = visuals->greenMask;
566 visual->blueMask = visuals->blueMask;
567 visual->offsetRed = maskShift(visuals->redMask);
568 visual->offsetGreen = maskShift(visuals->greenMask);
569 visual->offsetBlue = maskShift(visuals->blueMask);
570 }
571 vid++;
572 visual++;
573 }
574 free(visuals);
575 }
576 miVisuals = NULL;
577 visual = *visualp;
578 depth = *depthp;
579
580 /*
581 * if we did not supplyied by a preferred visual class
582 * check if there is a preferred class in one of the depth
583 * structures - if there is, we want to start looking for the
584 * default visual/depth from that depth.
585 */
586 first_depth = 0;
587 if (preferredVis < 0 && defaultColorVisualClass < 0) {
588 for (i = 0; i < ndepth; i++) {
589 if (preferredCVCs[i] >= 0) {
590 first_depth = i;
591 break;
592 }
593 }
594 }
595
596 for (i = first_depth; i < ndepth; i++) {
597 int prefColorVisualClass = -1;
598
599 if (defaultColorVisualClass >= 0)
600 prefColorVisualClass = defaultColorVisualClass;
601 else if (preferredVis >= 0)
602 prefColorVisualClass = preferredVis;
603 else if (preferredCVCs[i] >= 0)
604 prefColorVisualClass = preferredCVCs[i];
605
606 if (*rootDepthp && *rootDepthp != depth[i].depth)
607 continue;
608
609 for (j = 0; j < depth[i].numVids; j++) {
610 for (k = 0; k < nvisual; k++)
611 if (visual[k].vid == depth[i].vids[j])
612 break;
613 if (k == nvisual)
614 continue;
615 if (prefColorVisualClass < 0 ||
616 visual[k].class == prefColorVisualClass)
617 break;
618 }
619 if (j != depth[i].numVids)
620 break;
621 }
622 if (i == ndepth) {
623 i = 0;
624 j = 0;
625 }
626 *rootDepthp = depth[i].depth;
627 *defaultVisp = depth[i].vids[j];
628 free(preferredCVCs);
629
630 return TRUE;
631}