xref: /OK3568_Linux_fs/external/xserver/hw/xnest/Color.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2 
3 Copyright 1993 by Davor Matic
4 
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and that
8 both that copyright notice and this permission notice appear in
9 supporting documentation.  Davor Matic makes no representations about
10 the suitability of this software for any purpose.  It is provided "as
11 is" without express or implied warranty.
12 
13 */
14 
15 #ifdef HAVE_XNEST_CONFIG_H
16 #include <xnest-config.h>
17 #endif
18 
19 #include <X11/X.h>
20 #include <X11/Xproto.h>
21 #include "scrnintstr.h"
22 #include "window.h"
23 #include "windowstr.h"
24 #include "colormapst.h"
25 #include "resource.h"
26 
27 #include "Xnest.h"
28 
29 #include "Display.h"
30 #include "Screen.h"
31 #include "Color.h"
32 #include "Visual.h"
33 #include "XNWindow.h"
34 #include "Args.h"
35 
36 DevPrivateKeyRec xnestColormapPrivateKeyRec;
37 
38 static DevPrivateKeyRec cmapScrPrivateKeyRec;
39 
40 #define cmapScrPrivateKey (&cmapScrPrivateKeyRec)
41 
42 #define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey))
43 #define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c))
44 
45 Bool
xnestCreateColormap(ColormapPtr pCmap)46 xnestCreateColormap(ColormapPtr pCmap)
47 {
48     VisualPtr pVisual;
49     XColor *colors;
50     int i, ncolors;
51     Pixel red, green, blue;
52     Pixel redInc, greenInc, blueInc;
53 
54     pVisual = pCmap->pVisual;
55     ncolors = pVisual->ColormapEntries;
56 
57     xnestColormapPriv(pCmap)->colormap =
58         XCreateColormap(xnestDisplay,
59                         xnestDefaultWindows[pCmap->pScreen->myNum],
60                         xnestVisual(pVisual),
61                         (pVisual->class & DynamicClass) ? AllocAll : AllocNone);
62 
63     switch (pVisual->class) {
64     case StaticGray:           /* read only */
65         colors = xallocarray(ncolors, sizeof(XColor));
66         for (i = 0; i < ncolors; i++)
67             colors[i].pixel = i;
68         XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
69         for (i = 0; i < ncolors; i++) {
70             pCmap->red[i].co.local.red = colors[i].red;
71             pCmap->red[i].co.local.green = colors[i].red;
72             pCmap->red[i].co.local.blue = colors[i].red;
73         }
74         free(colors);
75         break;
76 
77     case StaticColor:          /* read only */
78         colors = xallocarray(ncolors, sizeof(XColor));
79         for (i = 0; i < ncolors; i++)
80             colors[i].pixel = i;
81         XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
82         for (i = 0; i < ncolors; i++) {
83             pCmap->red[i].co.local.red = colors[i].red;
84             pCmap->red[i].co.local.green = colors[i].green;
85             pCmap->red[i].co.local.blue = colors[i].blue;
86         }
87         free(colors);
88         break;
89 
90     case TrueColor:            /* read only */
91         colors = xallocarray(ncolors, sizeof(XColor));
92         red = green = blue = 0L;
93         redInc = lowbit(pVisual->redMask);
94         greenInc = lowbit(pVisual->greenMask);
95         blueInc = lowbit(pVisual->blueMask);
96         for (i = 0; i < ncolors; i++) {
97             colors[i].pixel = red | green | blue;
98             red += redInc;
99             if (red > pVisual->redMask)
100                 red = 0L;
101             green += greenInc;
102             if (green > pVisual->greenMask)
103                 green = 0L;
104             blue += blueInc;
105             if (blue > pVisual->blueMask)
106                 blue = 0L;
107         }
108         XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
109         for (i = 0; i < ncolors; i++) {
110             pCmap->red[i].co.local.red = colors[i].red;
111             pCmap->green[i].co.local.green = colors[i].green;
112             pCmap->blue[i].co.local.blue = colors[i].blue;
113         }
114         free(colors);
115         break;
116 
117     case GrayScale:            /* read and write */
118         break;
119 
120     case PseudoColor:          /* read and write */
121         break;
122 
123     case DirectColor:          /* read and write */
124         break;
125     }
126 
127     return True;
128 }
129 
130 void
xnestDestroyColormap(ColormapPtr pCmap)131 xnestDestroyColormap(ColormapPtr pCmap)
132 {
133     XFreeColormap(xnestDisplay, xnestColormap(pCmap));
134 }
135 
136 #define SEARCH_PREDICATE \
137   (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i])
138 
139 static int
xnestCountInstalledColormapWindows(WindowPtr pWin,void * ptr)140 xnestCountInstalledColormapWindows(WindowPtr pWin, void *ptr)
141 {
142     xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *) ptr;
143     int i;
144 
145     for (i = 0; i < icws->numCmapIDs; i++)
146         if (SEARCH_PREDICATE) {
147             icws->numWindows++;
148             return WT_DONTWALKCHILDREN;
149         }
150 
151     return WT_WALKCHILDREN;
152 }
153 
154 static int
xnestGetInstalledColormapWindows(WindowPtr pWin,void * ptr)155 xnestGetInstalledColormapWindows(WindowPtr pWin, void *ptr)
156 {
157     xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *) ptr;
158     int i;
159 
160     for (i = 0; i < icws->numCmapIDs; i++)
161         if (SEARCH_PREDICATE) {
162             icws->windows[icws->index++] = xnestWindow(pWin);
163             return WT_DONTWALKCHILDREN;
164         }
165 
166     return WT_WALKCHILDREN;
167 }
168 
169 static Window *xnestOldInstalledColormapWindows = NULL;
170 static int xnestNumOldInstalledColormapWindows = 0;
171 
172 static Bool
xnestSameInstalledColormapWindows(Window * windows,int numWindows)173 xnestSameInstalledColormapWindows(Window *windows, int numWindows)
174 {
175     if (xnestNumOldInstalledColormapWindows != numWindows)
176         return False;
177 
178     if (xnestOldInstalledColormapWindows == windows)
179         return True;
180 
181     if (xnestOldInstalledColormapWindows == NULL || windows == NULL)
182         return False;
183 
184     if (memcmp(xnestOldInstalledColormapWindows, windows,
185                numWindows * sizeof(Window)))
186         return False;
187 
188     return True;
189 }
190 
191 void
xnestSetInstalledColormapWindows(ScreenPtr pScreen)192 xnestSetInstalledColormapWindows(ScreenPtr pScreen)
193 {
194     xnestInstalledColormapWindows icws;
195     int numWindows;
196 
197     icws.cmapIDs = xallocarray(pScreen->maxInstalledCmaps, sizeof(Colormap));
198     icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs);
199     icws.numWindows = 0;
200     WalkTree(pScreen, xnestCountInstalledColormapWindows, (void *) &icws);
201     if (icws.numWindows) {
202         icws.windows = xallocarray(icws.numWindows + 1, sizeof(Window));
203         icws.index = 0;
204         WalkTree(pScreen, xnestGetInstalledColormapWindows, (void *) &icws);
205         icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum];
206         numWindows = icws.numWindows + 1;
207     }
208     else {
209         icws.windows = NULL;
210         numWindows = 0;
211     }
212 
213     free(icws.cmapIDs);
214 
215     if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) {
216         free(xnestOldInstalledColormapWindows);
217 
218 #ifdef _XSERVER64
219         {
220             int i;
221             Window64 *windows = xallocarray(numWindows, sizeof(Window64));
222 
223             for (i = 0; i < numWindows; ++i)
224                 windows[i] = icws.windows[i];
225             XSetWMColormapWindows(xnestDisplay,
226                                   xnestDefaultWindows[pScreen->myNum], windows,
227                                   numWindows);
228             free(windows);
229         }
230 #else
231         XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
232                               icws.windows, numWindows);
233 #endif
234 
235         xnestOldInstalledColormapWindows = icws.windows;
236         xnestNumOldInstalledColormapWindows = icws.numWindows;
237 
238 #ifdef DUMB_WINDOW_MANAGERS
239         /*
240            This code is for dumb window managers.
241            This will only work with default local visual colormaps.
242          */
243         if (icws.numWindows) {
244             WindowPtr pWin;
245             Visual *visual;
246             ColormapPtr pCmap;
247 
248             pWin = xnestWindowPtr(icws.windows[0]);
249             visual = xnestVisualFromID(pScreen, wVisual(pWin));
250 
251             if (visual == xnestDefaultVisual(pScreen))
252                 dixLookupResourceByType((void **) &pCmap, wColormap(pWin),
253                                         RT_COLORMAP, serverClient,
254                                         DixUseAccess);
255             else
256                 dixLookupResourceByType((void **) &pCmap,
257                                         pScreen->defColormap, RT_COLORMAP,
258                                         serverClient, DixUseAccess);
259 
260             XSetWindowColormap(xnestDisplay,
261                                xnestDefaultWindows[pScreen->myNum],
262                                xnestColormap(pCmap));
263         }
264 #endif                          /* DUMB_WINDOW_MANAGERS */
265     }
266     else
267         free(icws.windows);
268 }
269 
270 void
xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)271 xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)
272 {
273     free(xnestOldInstalledColormapWindows);
274 
275 #ifdef _XSERVER64
276     {
277         Window64 window;
278 
279         window = xnestScreenSaverWindows[pScreen->myNum];
280         XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
281                               &window, 1);
282         xnestScreenSaverWindows[pScreen->myNum] = window;
283     }
284 #else
285     XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
286                           &xnestScreenSaverWindows[pScreen->myNum], 1);
287 #endif                          /* _XSERVER64 */
288 
289     xnestOldInstalledColormapWindows = NULL;
290     xnestNumOldInstalledColormapWindows = 0;
291 
292     xnestDirectUninstallColormaps(pScreen);
293 }
294 
295 void
xnestDirectInstallColormaps(ScreenPtr pScreen)296 xnestDirectInstallColormaps(ScreenPtr pScreen)
297 {
298     int i, n;
299     Colormap pCmapIDs[MAXCMAPS];
300 
301     if (!xnestDoDirectColormaps)
302         return;
303 
304     n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs);
305 
306     for (i = 0; i < n; i++) {
307         ColormapPtr pCmap;
308 
309         dixLookupResourceByType((void **) &pCmap, pCmapIDs[i], RT_COLORMAP,
310                                 serverClient, DixInstallAccess);
311         if (pCmap)
312             XInstallColormap(xnestDisplay, xnestColormap(pCmap));
313     }
314 }
315 
316 void
xnestDirectUninstallColormaps(ScreenPtr pScreen)317 xnestDirectUninstallColormaps(ScreenPtr pScreen)
318 {
319     int i, n;
320     Colormap pCmapIDs[MAXCMAPS];
321 
322     if (!xnestDoDirectColormaps)
323         return;
324 
325     n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs);
326 
327     for (i = 0; i < n; i++) {
328         ColormapPtr pCmap;
329 
330         dixLookupResourceByType((void **) &pCmap, pCmapIDs[i], RT_COLORMAP,
331                                 serverClient, DixUninstallAccess);
332         if (pCmap)
333             XUninstallColormap(xnestDisplay, xnestColormap(pCmap));
334     }
335 }
336 
337 void
xnestInstallColormap(ColormapPtr pCmap)338 xnestInstallColormap(ColormapPtr pCmap)
339 {
340     ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen);
341 
342     if (pCmap != pOldCmap) {
343         xnestDirectUninstallColormaps(pCmap->pScreen);
344 
345         /* Uninstall pInstalledMap. Notify all interested parties. */
346         if (pOldCmap != (ColormapPtr) None)
347             WalkTree(pCmap->pScreen, TellLostMap, (void *) &pOldCmap->mid);
348 
349         SetInstalledColormap(pCmap->pScreen, pCmap);
350         WalkTree(pCmap->pScreen, TellGainedMap, (void *) &pCmap->mid);
351 
352         xnestSetInstalledColormapWindows(pCmap->pScreen);
353         xnestDirectInstallColormaps(pCmap->pScreen);
354     }
355 }
356 
357 void
xnestUninstallColormap(ColormapPtr pCmap)358 xnestUninstallColormap(ColormapPtr pCmap)
359 {
360     ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen);
361 
362     if (pCmap == pCurCmap) {
363         if (pCmap->mid != pCmap->pScreen->defColormap) {
364             dixLookupResourceByType((void **) &pCurCmap,
365                                     pCmap->pScreen->defColormap,
366                                     RT_COLORMAP,
367                                     serverClient, DixInstallAccess);
368             (*pCmap->pScreen->InstallColormap) (pCurCmap);
369         }
370     }
371 }
372 
373 static Bool xnestInstalledDefaultColormap = False;
374 
375 int
xnestListInstalledColormaps(ScreenPtr pScreen,Colormap * pCmapIDs)376 xnestListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmapIDs)
377 {
378     if (xnestInstalledDefaultColormap) {
379         *pCmapIDs = GetInstalledColormap(pScreen)->mid;
380         return 1;
381     }
382     else
383         return 0;
384 }
385 
386 void
xnestStoreColors(ColormapPtr pCmap,int nColors,xColorItem * pColors)387 xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem * pColors)
388 {
389     if (pCmap->pVisual->class & DynamicClass)
390 #ifdef _XSERVER64
391     {
392         int i;
393         XColor *pColors64 = xallocarray(nColors, sizeof(XColor));
394 
395         for (i = 0; i < nColors; ++i) {
396             pColors64[i].pixel = pColors[i].pixel;
397             pColors64[i].red = pColors[i].red;
398             pColors64[i].green = pColors[i].green;
399             pColors64[i].blue = pColors[i].blue;
400             pColors64[i].flags = pColors[i].flags;
401         }
402         XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors);
403         free(pColors64);
404     }
405 #else
406         XStoreColors(xnestDisplay, xnestColormap(pCmap),
407                      (XColor *) pColors, nColors);
408 #endif
409 }
410 
411 void
xnestResolveColor(unsigned short * pRed,unsigned short * pGreen,unsigned short * pBlue,VisualPtr pVisual)412 xnestResolveColor(unsigned short *pRed, unsigned short *pGreen,
413                   unsigned short *pBlue, VisualPtr pVisual)
414 {
415     int shift;
416     unsigned int lim;
417 
418     shift = 16 - pVisual->bitsPerRGBValue;
419     lim = (1 << pVisual->bitsPerRGBValue) - 1;
420 
421     if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) {
422         /* rescale to rgb bits */
423         *pRed = ((*pRed >> shift) * 65535) / lim;
424         *pGreen = ((*pGreen >> shift) * 65535) / lim;
425         *pBlue = ((*pBlue >> shift) * 65535) / lim;
426     }
427     else if (pVisual->class == GrayScale) {
428         /* rescale to gray then rgb bits */
429         *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
430         *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
431     }
432     else if (pVisual->class == StaticGray) {
433         unsigned int limg;
434 
435         limg = pVisual->ColormapEntries - 1;
436         /* rescale to gray then [0..limg] then [0..65535] then rgb bits */
437         *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
438         *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg;
439         *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
440     }
441     else {
442         unsigned limr, limg, limb;
443 
444         limr = pVisual->redMask >> pVisual->offsetRed;
445         limg = pVisual->greenMask >> pVisual->offsetGreen;
446         limb = pVisual->blueMask >> pVisual->offsetBlue;
447         /* rescale to [0..limN] then [0..65535] then rgb bits */
448         *pRed = ((((((*pRed * (limr + 1)) >> 16) *
449                     65535) / limr) >> shift) * 65535) / lim;
450         *pGreen = ((((((*pGreen * (limg + 1)) >> 16) *
451                       65535) / limg) >> shift) * 65535) / lim;
452         *pBlue = ((((((*pBlue * (limb + 1)) >> 16) *
453                      65535) / limb) >> shift) * 65535) / lim;
454     }
455 }
456 
457 Bool
xnestCreateDefaultColormap(ScreenPtr pScreen)458 xnestCreateDefaultColormap(ScreenPtr pScreen)
459 {
460     VisualPtr pVisual;
461     ColormapPtr pCmap;
462     unsigned short zero = 0, ones = 0xFFFF;
463     Pixel wp, bp;
464 
465     if (!dixRegisterPrivateKey(&cmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
466         return FALSE;
467 
468     for (pVisual = pScreen->visuals;
469          pVisual->vid != pScreen->rootVisual; pVisual++);
470 
471     if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap,
472                        (pVisual->class & DynamicClass) ? AllocNone : AllocAll,
473                        0)
474         != Success)
475         return False;
476 
477     wp = pScreen->whitePixel;
478     bp = pScreen->blackPixel;
479     if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) !=
480          Success) ||
481         (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != Success))
482         return FALSE;
483     pScreen->whitePixel = wp;
484     pScreen->blackPixel = bp;
485     (*pScreen->InstallColormap) (pCmap);
486 
487     xnestInstalledDefaultColormap = True;
488 
489     return True;
490 }
491