3 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
31 #include "scrnintstr.h"
33 #include "pixmapstr.h"
34 #include "windowstr.h"
36 #include "picturestr.h"
38 #include "colormapst.h"
40 #define NUM_CUBE_LEVELS 4
41 #define NUM_GRAY_LEVELS 13
44 miBuildRenderColormap(ColormapPtr pColormap
, Pixel
* pixels
, int *nump
)
47 unsigned short red
, green
, blue
;
49 Bool used
[MI_MAX_INDEXED
];
55 if (pColormap
->mid
!= pColormap
->pScreen
->defColormap
) {
56 policy
= PictureCmapPolicyAll
;
59 int avail
= pColormap
->pVisual
->ColormapEntries
;
61 policy
= PictureCmapPolicy
;
62 if (policy
== PictureCmapPolicyDefault
) {
64 (pColormap
->pVisual
->class | DynamicClass
) == PseudoColor
)
65 policy
= PictureCmapPolicyColor
;
67 policy
= PictureCmapPolicyGray
;
69 policy
= PictureCmapPolicyMono
;
73 * Make sure enough cells are free for the chosen policy
77 case PictureCmapPolicyAll
:
80 case PictureCmapPolicyColor
:
83 case PictureCmapPolicyGray
:
86 case PictureCmapPolicyMono
:
91 if (needed
<= pColormap
->freeRed
)
97 * Compute size of cube and gray ramps
101 case PictureCmapPolicyAll
:
103 * Allocate as big a cube as possible
105 if ((pColormap
->pVisual
->class | DynamicClass
) == PseudoColor
) {
107 cube
* cube
* cube
< pColormap
->pVisual
->ColormapEntries
;
116 * Figure out how many gray levels to use so that they
117 * line up neatly with the cube
120 needed
= pColormap
->pVisual
->ColormapEntries
- (cube
* cube
* cube
);
121 /* levels to fill in with */
122 gray
= needed
/ (cube
- 1);
124 gray
= (gray
+ 1) * (cube
- 1) + 1;
127 gray
= pColormap
->pVisual
->ColormapEntries
;
130 case PictureCmapPolicyColor
:
131 cube
= NUM_CUBE_LEVELS
;
132 /* fall through ... */
133 case PictureCmapPolicyGray
:
134 gray
= NUM_GRAY_LEVELS
;
136 case PictureCmapPolicyMono
:
142 memset(used
, '\0', pColormap
->pVisual
->ColormapEntries
* sizeof(Bool
));
143 for (r
= 0; r
< cube
; r
++)
144 for (g
= 0; g
< cube
; g
++)
145 for (b
= 0; b
< cube
; b
++) {
147 red
= (r
* 65535 + (cube
- 1) / 2) / (cube
- 1);
148 green
= (g
* 65535 + (cube
- 1) / 2) / (cube
- 1);
149 blue
= (b
* 65535 + (cube
- 1) / 2) / (cube
- 1);
150 if (AllocColor(pColormap
, &red
, &green
,
151 &blue
, &pixel
, 0) != Success
)
155 for (g
= 0; g
< gray
; g
++) {
157 red
= green
= blue
= (g
* 65535 + (gray
- 1) / 2) / (gray
- 1);
158 if (AllocColor(pColormap
, &red
, &green
, &blue
, &pixel
, 0) != Success
)
163 for (i
= 0; i
< pColormap
->pVisual
->ColormapEntries
; i
++)
172 /* 0 <= red, green, blue < 32 */
174 FindBestColor(miIndexedPtr pIndexed
, Pixel
* pixels
, int num
,
175 int red
, int green
, int blue
)
177 Pixel best
= pixels
[0];
178 int bestDist
= 1 << 30;
183 Pixel pixel
= *pixels
++;
184 CARD32 v
= pIndexed
->rgba
[pixel
];
186 dr
= ((v
>> 19) & 0x1f);
187 dg
= ((v
>> 11) & 0x1f);
188 db
= ((v
>> 3) & 0x1f);
192 dist
= dr
* dr
+ dg
* dg
+ db
* db
;
193 if (dist
< bestDist
) {
201 /* 0 <= gray < 32768 */
203 FindBestGray(miIndexedPtr pIndexed
, Pixel
* pixels
, int num
, int gray
)
205 Pixel best
= pixels
[0];
206 int bestDist
= 1 << 30;
212 Pixel pixel
= *pixels
++;
213 CARD32 v
= pIndexed
->rgba
[pixel
];
217 dr
= gray
- (r
>> 1);
219 if (dist
< bestDist
) {
228 miInitIndexed(ScreenPtr pScreen
, PictFormatPtr pFormat
)
230 ColormapPtr pColormap
= pFormat
->index
.pColormap
;
231 VisualPtr pVisual
= pColormap
->pVisual
;
232 miIndexedPtr pIndexed
;
233 Pixel pixels
[MI_MAX_INDEXED
];
234 xrgb rgb
[MI_MAX_INDEXED
];
239 if (pVisual
->ColormapEntries
> MI_MAX_INDEXED
)
242 if (pVisual
->class & DynamicClass
) {
243 if (!miBuildRenderColormap(pColormap
, pixels
, &num
))
247 num
= pVisual
->ColormapEntries
;
248 for (p
= 0; p
< num
; p
++)
252 pIndexed
= malloc(sizeof(miIndexedRec
));
256 pFormat
->index
.nvalues
= num
;
257 pFormat
->index
.pValues
= xallocarray(num
, sizeof(xIndexValue
));
258 if (!pFormat
->index
.pValues
) {
264 * Build mapping from pixel value to ARGB
266 QueryColors(pColormap
, num
, pixels
, rgb
, serverClient
);
267 for (i
= 0; i
< num
; i
++) {
269 pFormat
->index
.pValues
[i
].pixel
= p
;
270 pFormat
->index
.pValues
[i
].red
= rgb
[i
].red
;
271 pFormat
->index
.pValues
[i
].green
= rgb
[i
].green
;
272 pFormat
->index
.pValues
[i
].blue
= rgb
[i
].blue
;
273 pFormat
->index
.pValues
[i
].alpha
= 0xffff;
274 pIndexed
->rgba
[p
] = (0xff000000 |
275 ((rgb
[i
].red
& 0xff00) << 8) |
276 ((rgb
[i
].green
& 0xff00)) |
277 ((rgb
[i
].blue
& 0xff00) >> 8));
281 * Build mapping from RGB to pixel value. This could probably be
282 * done a bit quicker...
284 switch (pVisual
->class | DynamicClass
) {
286 pIndexed
->color
= FALSE
;
287 for (r
= 0; r
< 32768; r
++)
288 pIndexed
->ent
[r
] = FindBestGray(pIndexed
, pixels
, num
, r
);
291 pIndexed
->color
= TRUE
;
293 for (r
= 0; r
< 32; r
++)
294 for (g
= 0; g
< 32; g
++)
295 for (b
= 0; b
< 32; b
++) {
296 pIndexed
->ent
[p
] = FindBestColor(pIndexed
, pixels
, num
,
302 pFormat
->index
.devPrivate
= pIndexed
;
307 miCloseIndexed(ScreenPtr pScreen
, PictFormatPtr pFormat
)
309 free(pFormat
->index
.devPrivate
);
310 pFormat
->index
.devPrivate
= NULL
;
311 free(pFormat
->index
.pValues
);
312 pFormat
->index
.pValues
= NULL
;
316 miUpdateIndexed(ScreenPtr pScreen
,
317 PictFormatPtr pFormat
, int ndef
, xColorItem
* pdef
)
319 miIndexedPtr pIndexed
= pFormat
->index
.devPrivate
;
323 pIndexed
->rgba
[pdef
->pixel
] = (0xff000000 |
324 ((pdef
->red
& 0xff00) << 8) |
325 ((pdef
->green
& 0xff00)) |
326 ((pdef
->blue
& 0xff00) >> 8));
332 #endif /* _MIINDEX_H_ */