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_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26#include "kdrive.h"
27
28/*
29 * Put the entire colormap into the DAC
30 */
31
32static void
33KdSetColormap(ScreenPtr pScreen)
34{
35    KdScreenPriv(pScreen);
36    ColormapPtr pCmap = pScreenPriv->pInstalledmap;
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.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.depth); i++)
59        pixels[i] = i;
60
61    QueryColors(pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors,
62                serverClient);
63
64    for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) {
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,
73                                             (1 << pScreenPriv->screen->fb.
74                                              depth), defs);
75}
76
77/*
78 * When the hardware is enabled, save the hardware colors and store
79 * the current colormap
80 */
81void
82KdEnableColormap(ScreenPtr pScreen)
83{
84    KdScreenPriv(pScreen);
85    int i;
86
87    if (!pScreenPriv->card->cfuncs->putColors)
88        return;
89
90    if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) {
91        for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
92            pScreenPriv->systemPalette[i].pixel = i;
93        (*pScreenPriv->card->cfuncs->getColors) (pScreen,
94                                                 (1 << pScreenPriv->screen->fb.
95                                                  depth),
96                                                 pScreenPriv->systemPalette);
97    }
98    KdSetColormap(pScreen);
99}
100
101void
102KdDisableColormap(ScreenPtr pScreen)
103{
104    KdScreenPriv(pScreen);
105
106    if (!pScreenPriv->card->cfuncs->putColors)
107        return;
108
109    if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) {
110        (*pScreenPriv->card->cfuncs->putColors) (pScreen,
111                                                 (1 << pScreenPriv->screen->fb.
112                                                  depth),
113                                                 pScreenPriv->systemPalette);
114    }
115}
116
117/*
118 * KdInstallColormap
119 *
120 * This function is called when the server receives a request to install a
121 * colormap or when the server needs to install one on its own, like when
122 * there's no window manager running and the user has moved the pointer over
123 * an X client window.  It needs to build an identity Windows palette for the
124 * colormap and realize it into the Windows system palette.
125 */
126void
127KdInstallColormap(ColormapPtr pCmap)
128{
129    KdScreenPriv(pCmap->pScreen);
130
131    if (pCmap == pScreenPriv->pInstalledmap)
132        return;
133
134    /* Tell X clients that the installed colormap is going away. */
135    if (pScreenPriv->pInstalledmap)
136        WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
137                 (void *) &(pScreenPriv->pInstalledmap->mid));
138
139    /* Take note of the new installed colorscreen-> */
140    pScreenPriv->pInstalledmap = pCmap;
141
142    KdSetColormap(pCmap->pScreen);
143
144    /* Tell X clients of the new colormap */
145    WalkTree(pCmap->pScreen, TellGainedMap, (void *) &(pCmap->mid));
146}
147
148/*
149 * KdUninstallColormap
150 *
151 * This function uninstalls a colormap by either installing
152 * the default X colormap or erasing the installed colormap pointer.
153 * The default X colormap itself cannot be uninstalled.
154 */
155void
156KdUninstallColormap(ColormapPtr pCmap)
157{
158    KdScreenPriv(pCmap->pScreen);
159    Colormap defMapID;
160    ColormapPtr defMap;
161
162    /* ignore if not installed */
163    if (pCmap != pScreenPriv->pInstalledmap)
164        return;
165
166    /* ignore attempts to uninstall default colormap */
167    defMapID = pCmap->pScreen->defColormap;
168    if ((Colormap) pCmap->mid == defMapID)
169        return;
170
171    /* install default */
172    dixLookupResourceByType((void **) &defMap, defMapID, RT_COLORMAP,
173                            serverClient, DixInstallAccess);
174    if (defMap)
175        (*pCmap->pScreen->InstallColormap) (defMap);
176    else {
177        /* uninstall and clear colormap pointer */
178        WalkTree(pCmap->pScreen, TellLostMap, (void *) &(pCmap->mid));
179        pScreenPriv->pInstalledmap = 0;
180    }
181}
182
183int
184KdListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmaps)
185{
186    KdScreenPriv(pScreen);
187    int n = 0;
188
189    if (pScreenPriv->pInstalledmap) {
190        *pCmaps++ = pScreenPriv->pInstalledmap->mid;
191        n++;
192    }
193    return n;
194}
195
196/*
197 * KdStoreColors
198 *
199 * This function is called whenever the server receives a request to store
200 * color values into one or more entries in the currently installed X
201 * colormap; it can be either the default colormap or a private colorscreen->
202 */
203void
204KdStoreColors(ColormapPtr pCmap, int ndef, xColorItem * pdefs)
205{
206    KdScreenPriv(pCmap->pScreen);
207    VisualPtr pVisual;
208    xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
209
210    if (pCmap != pScreenPriv->pInstalledmap)
211        return;
212
213    if (!pScreenPriv->card->cfuncs->putColors)
214        return;
215
216    if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
217        return;
218
219    if (!pScreenPriv->enabled)
220        return;
221
222    /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
223    pVisual = pCmap->pVisual;
224    if ((pVisual->class | DynamicClass) == DirectColor) {
225        /*
226         * Expand DirectColor or TrueColor color values into a PseudoColor
227         * format.  Defer to the Color Framebuffer (CFB) code to do that.
228         */
229        ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
230        pdefs = expanddefs;
231    }
232
233    (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
234}
235