kcmap.c revision 05b261ec
1/*
2 * Copyright � 1999 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <kdrive-config.h>
25#endif
26#include "kdrive.h"
27
28/*
29 * Put the entire colormap into the DAC
30 */
31
32void
33KdSetColormap (ScreenPtr pScreen, int fb)
34{
35    KdScreenPriv(pScreen);
36    ColormapPtr	pCmap = pScreenPriv->pInstalledmap[fb];
37    Pixel	pixels[KD_MAX_PSEUDO_SIZE];
38    xrgb	colors[KD_MAX_PSEUDO_SIZE];
39    xColorItem	defs[KD_MAX_PSEUDO_SIZE];
40    int		i;
41
42    if (!pScreenPriv->card->cfuncs->putColors)
43	return;
44    if (pScreenPriv->screen->fb[fb].depth > KD_MAX_PSEUDO_DEPTH)
45	return;
46
47    if (!pScreenPriv->enabled)
48	return;
49
50    if (!pCmap)
51	return;
52
53    /*
54     * Make DIX convert pixels into RGB values -- this handles
55     * true/direct as well as pseudo/static visuals
56     */
57
58    for (i = 0; i < (1 << pScreenPriv->screen->fb[fb].depth); i++)
59	pixels[i] = i;
60
61    QueryColors (pCmap, (1 << pScreenPriv->screen->fb[fb].depth), pixels, colors);
62
63    for (i = 0; i < (1 << pScreenPriv->screen->fb[fb].depth); i++)
64    {
65	defs[i].pixel = i;
66	defs[i].red = colors[i].red;
67	defs[i].green = colors[i].green;
68	defs[i].blue = colors[i].blue;
69	defs[i].flags = DoRed|DoGreen|DoBlue;
70    }
71
72    (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, fb,
73					     (1 << pScreenPriv->screen->fb[fb].depth),
74					     defs);
75
76    /* recolor hardware cursor */
77    if (pScreenPriv->card->cfuncs->recolorCursor)
78	(*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0);
79}
80
81/*
82 * When the hardware is enabled, save the hardware colors and store
83 * the current colormap
84 */
85void
86KdEnableColormap (ScreenPtr pScreen)
87{
88    KdScreenPriv(pScreen);
89    int	    i;
90    int	    fb;
91    Bool    done = FALSE;
92
93    if (!pScreenPriv->card->cfuncs->putColors)
94	return;
95    for (fb = 0; fb < KD_MAX_FB && pScreenPriv->screen->fb[fb].depth; fb++)
96    {
97	if (pScreenPriv->screen->fb[fb].depth <= KD_MAX_PSEUDO_DEPTH && !done)
98	{
99	    for (i = 0; i < (1 << pScreenPriv->screen->fb[fb].depth); i++)
100		pScreenPriv->systemPalette[i].pixel = i;
101	    (*pScreenPriv->card->cfuncs->getColors) (pScreen, fb,
102						   (1 << pScreenPriv->screen->fb[fb].depth),
103						   pScreenPriv->systemPalette);
104	    done = TRUE;
105	}
106	KdSetColormap (pScreen, fb);
107    }
108}
109
110void
111KdDisableColormap (ScreenPtr pScreen)
112{
113    KdScreenPriv(pScreen);
114    int	    fb;
115
116    if (!pScreenPriv->card->cfuncs->putColors)
117	return;
118    for (fb = 0; fb < KD_MAX_FB && pScreenPriv->screen->fb[fb].depth; fb++)
119    {
120	if (pScreenPriv->screen->fb[fb].depth <= KD_MAX_PSEUDO_DEPTH)
121	{
122	    (*pScreenPriv->card->cfuncs->putColors) (pScreen, fb,
123						     (1 << pScreenPriv->screen->fb[fb].depth),
124						     pScreenPriv->systemPalette);
125	    break;
126	}
127    }
128}
129
130static int
131KdColormapFb (ColormapPtr   pCmap)
132{
133    ScreenPtr	pScreen = pCmap->pScreen;
134    KdScreenPriv (pScreen);
135    KdScreenInfo    *screen = pScreenPriv->screen;
136    int		d;
137    DepthPtr	depth;
138    int		v;
139    VisualID	vid = pCmap->pVisual->vid;
140    int		fb;
141
142    if (screen->fb[1].depth)
143    {
144	for (d = 0; d < pScreen->numDepths; d++)
145	{
146	    depth = &pScreen->allowedDepths[d];
147	    for (v = 0; v < depth->numVids; v++)
148	    {
149		if (depth->vids[v] == vid)
150		{
151		    for (fb = 0; fb < KD_MAX_FB && screen->fb[fb].depth; fb++)
152		    {
153			if (depth->depth == screen->fb[fb].depth)
154			    return fb;
155		    }
156		}
157	    }
158	}
159    }
160    return 0;
161}
162
163/*
164 * KdInstallColormap
165 *
166 * This function is called when the server receives a request to install a
167 * colormap or when the server needs to install one on its own, like when
168 * there's no window manager running and the user has moved the pointer over
169 * an X client window.  It needs to build an identity Windows palette for the
170 * colormap and realize it into the Windows system palette.
171 */
172void
173KdInstallColormap (ColormapPtr pCmap)
174{
175    KdScreenPriv(pCmap->pScreen);
176    int		fb = KdColormapFb (pCmap);
177
178    if (pCmap == pScreenPriv->pInstalledmap[fb])
179	return;
180
181    /* Tell X clients that the installed colormap is going away. */
182    if (pScreenPriv->pInstalledmap[fb])
183	WalkTree(pScreenPriv->pInstalledmap[fb]->pScreen, TellLostMap,
184		 (pointer) &(pScreenPriv->pInstalledmap[fb]->mid));
185
186    /* Take note of the new installed colorscreen-> */
187    pScreenPriv->pInstalledmap[fb] = pCmap;
188
189    KdSetColormap (pCmap->pScreen, fb);
190
191    /* Tell X clients of the new colormap */
192    WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid));
193}
194
195/*
196 * KdUninstallColormap
197 *
198 * This function uninstalls a colormap by either installing
199 * the default X colormap or erasing the installed colormap pointer.
200 * The default X colormap itself cannot be uninstalled.
201 */
202void
203KdUninstallColormap (ColormapPtr pCmap)
204{
205    KdScreenPriv(pCmap->pScreen);
206    int		fb = KdColormapFb (pCmap);
207    Colormap	defMapID;
208    ColormapPtr defMap;
209
210    /* ignore if not installed */
211    if (pCmap != pScreenPriv->pInstalledmap[fb])
212	return;
213
214    /* ignore attempts to uninstall default colormap */
215    defMapID = pCmap->pScreen->defColormap;
216    if ((Colormap) pCmap->mid == defMapID)
217	return;
218
219    /* install default if on same fb */
220    defMap = (ColormapPtr) LookupIDByType(defMapID, RT_COLORMAP);
221    if (defMap && KdColormapFb (defMap) == fb)
222	(*pCmap->pScreen->InstallColormap)(defMap);
223    else
224    {
225	/* uninstall and clear colormap pointer */
226	WalkTree(pCmap->pScreen, TellLostMap,
227		 (pointer) &(pCmap->mid));
228	pScreenPriv->pInstalledmap[fb] = 0;
229    }
230}
231
232int
233KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps)
234{
235    KdScreenPriv(pScreen);
236    int		fb;
237    int		n = 0;
238
239    for (fb = 0; fb < KD_MAX_FB && pScreenPriv->screen->fb[fb].depth; fb++)
240    {
241	if (pScreenPriv->pInstalledmap[fb])
242	{
243	    *pCmaps++ = pScreenPriv->pInstalledmap[fb]->mid;
244	    n++;
245	}
246    }
247    return n;
248}
249
250/*
251 * KdStoreColors
252 *
253 * This function is called whenever the server receives a request to store
254 * color values into one or more entries in the currently installed X
255 * colormap; it can be either the default colormap or a private colorscreen->
256 */
257void
258KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs)
259{
260    KdScreenPriv(pCmap->pScreen);
261    VisualPtr           pVisual;
262    xColorItem          expanddefs[KD_MAX_PSEUDO_SIZE];
263    int			fb = KdColormapFb (pCmap);
264
265    if (pCmap != pScreenPriv->pInstalledmap[fb])
266	return;
267
268    if (!pScreenPriv->card->cfuncs->putColors)
269	return;
270
271    if (pScreenPriv->screen->fb[fb].depth > KD_MAX_PSEUDO_DEPTH)
272	return;
273
274    if (!pScreenPriv->enabled)
275	return;
276
277    /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
278    pVisual = pCmap->pVisual;
279    if ((pVisual->class | DynamicClass) == DirectColor)
280    {
281	/*
282	 * Expand DirectColor or TrueColor color values into a PseudoColor
283	 * format.  Defer to the Color Framebuffer (CFB) code to do that.
284	 */
285	ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
286	pdefs = expanddefs;
287    }
288
289    (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, fb, ndef, pdefs);
290
291    /* recolor hardware cursor */
292    if (pScreenPriv->card->cfuncs->recolorCursor)
293	(*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs);
294}
295