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