2
* $XFree86: xc/programs/Xserver/render/miindex.c,v 1.7 2002/11/05 06:05:04 keithp Exp $
4
* Copyright Ā© 2001 Keith Packard, member of The XFree86 Project, Inc.
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of Keith Packard not be used in
11
* advertising or publicity pertaining to distribution of the software without
12
* specific, written prior permission. Keith Packard makes no
13
* representations about the suitability of this software for any purpose. It
14
* is provided "as is" without express or implied warranty.
16
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
25
#ifdef HAVE_DIX_CONFIG_H
26
#include <dix-config.h>
32
#include "scrnintstr.h"
34
#include "pixmapstr.h"
35
#include "windowstr.h"
37
#include "picturestr.h"
39
#include "colormapst.h"
41
#define NUM_CUBE_LEVELS 4
42
#define NUM_GRAY_LEVELS 13
45
miBuildRenderColormap (ColormapPtr pColormap, Pixel *pixels, int *nump)
48
unsigned short red, green, blue;
50
Bool used[MI_MAX_INDEXED];
56
if (pColormap->mid != pColormap->pScreen->defColormap)
58
policy = PictureCmapPolicyAll;
62
int avail = pColormap->pVisual->ColormapEntries;
63
policy = PictureCmapPolicy;
64
if (policy == PictureCmapPolicyDefault)
66
if (avail >= 256 && (pColormap->pVisual->class|DynamicClass) == PseudoColor)
67
policy = PictureCmapPolicyColor;
69
policy = PictureCmapPolicyGray;
71
policy = PictureCmapPolicyMono;
75
* Make sure enough cells are free for the chosen policy
80
case PictureCmapPolicyAll:
83
case PictureCmapPolicyColor:
86
case PictureCmapPolicyGray:
89
case PictureCmapPolicyMono:
94
if (needed <= pColormap->freeRed)
100
* Compute size of cube and gray ramps
104
case PictureCmapPolicyAll:
106
* Allocate as big a cube as possible
108
if ((pColormap->pVisual->class|DynamicClass) == PseudoColor)
110
for (cube = 1; cube * cube * cube < pColormap->pVisual->ColormapEntries; cube++)
119
* Figure out how many gray levels to use so that they
120
* line up neatly with the cube
124
needed = pColormap->pVisual->ColormapEntries - (cube*cube*cube);
125
/* levels to fill in with */
126
gray = needed / (cube - 1);
128
gray = (gray + 1) * (cube - 1) + 1;
131
gray = pColormap->pVisual->ColormapEntries;
134
case PictureCmapPolicyColor:
135
cube = NUM_CUBE_LEVELS;
136
/* fall through ... */
137
case PictureCmapPolicyGray:
138
gray = NUM_GRAY_LEVELS;
140
case PictureCmapPolicyMono:
146
memset (used, '\0', pColormap->pVisual->ColormapEntries * sizeof (Bool));
147
for (r = 0; r < cube; r++)
148
for (g = 0; g < cube; g++)
149
for (b = 0; b < cube; b++)
151
red = (r * 65535 + (cube-1)/2) / (cube - 1);
152
green = (g * 65535 + (cube-1)/2) / (cube - 1);
153
blue = (b * 65535 + (cube-1)/2) / (cube - 1);
154
if (AllocColor (pColormap, &red, &green,
155
&blue, &pixel, 0) != Success)
159
for (g = 0; g < gray; g++)
161
red = green = blue = (g * 65535 + (gray-1)/2) / (gray - 1);
162
if (AllocColor (pColormap, &red, &green, &blue, &pixel, 0) != Success)
167
for (i = 0; i < pColormap->pVisual->ColormapEntries; i++)
176
/* 0 <= red, green, blue < 32 */
178
FindBestColor (miIndexedPtr pIndexed, Pixel *pixels, int num,
179
int red, int green, int blue)
181
Pixel best = pixels[0];
182
int bestDist = 1 << 30;
187
Pixel pixel = *pixels++;
188
CARD32 v = pIndexed->rgba[pixel];
190
dr = ((v >> 19) & 0x1f);
191
dg = ((v >> 11) & 0x1f);
192
db = ((v >> 3) & 0x1f);
196
dist = dr * dr + dg * dg + db * db;
206
/* 0 <= gray < 32768 */
208
FindBestGray (miIndexedPtr pIndexed, Pixel *pixels, int num, int gray)
210
Pixel best = pixels[0];
211
int bestDist = 1 << 30;
218
Pixel pixel = *pixels++;
219
CARD32 v = pIndexed->rgba[pixel];
223
dr = gray - (r >> 1);
235
miInitIndexed (ScreenPtr pScreen,
236
PictFormatPtr pFormat)
238
ColormapPtr pColormap = pFormat->index.pColormap;
239
VisualPtr pVisual = pColormap->pVisual;
240
miIndexedPtr pIndexed;
241
Pixel pixels[MI_MAX_INDEXED];
242
xrgb rgb[MI_MAX_INDEXED];
247
if (pVisual->ColormapEntries > MI_MAX_INDEXED)
250
if (pVisual->class & DynamicClass)
252
if (!miBuildRenderColormap (pColormap, pixels, &num))
257
num = pVisual->ColormapEntries;
258
for (p = 0; p < num; p++)
262
pIndexed = xalloc (sizeof (miIndexedRec));
266
pFormat->index.nvalues = num;
267
pFormat->index.pValues = xalloc (num * sizeof (xIndexValue));
268
if (!pFormat->index.pValues)
276
* Build mapping from pixel value to ARGB
278
QueryColors (pColormap, num, pixels, rgb);
279
for (i = 0; i < num; i++)
282
pFormat->index.pValues[i].pixel = p;
283
pFormat->index.pValues[i].red = rgb[i].red;
284
pFormat->index.pValues[i].green = rgb[i].green;
285
pFormat->index.pValues[i].blue = rgb[i].blue;
286
pFormat->index.pValues[i].alpha = 0xffff;
287
pIndexed->rgba[p] = (0xff000000 |
288
((rgb[i].red & 0xff00) << 8) |
289
((rgb[i].green & 0xff00) ) |
290
((rgb[i].blue & 0xff00) >> 8));
294
* Build mapping from RGB to pixel value. This could probably be
295
* done a bit quicker...
297
switch (pVisual->class | DynamicClass) {
299
pIndexed->color = FALSE;
300
for (r = 0; r < 32768; r++)
301
pIndexed->ent[r] = FindBestGray (pIndexed, pixels, num, r);
304
pIndexed->color = TRUE;
306
for (r = 0; r < 32; r++)
307
for (g = 0; g < 32; g++)
308
for (b = 0; b < 32; b++)
310
pIndexed->ent[p] = FindBestColor (pIndexed, pixels, num,
316
pFormat->index.devPrivate = pIndexed;
321
miCloseIndexed (ScreenPtr pScreen,
322
PictFormatPtr pFormat)
324
if (pFormat->index.devPrivate)
326
xfree (pFormat->index.devPrivate);
327
pFormat->index.devPrivate = 0;
329
if (pFormat->index.pValues)
331
xfree (pFormat->index.pValues);
332
pFormat->index.pValues = 0;
337
miUpdateIndexed (ScreenPtr pScreen,
338
PictFormatPtr pFormat,
342
miIndexedPtr pIndexed = pFormat->index.devPrivate;
348
pIndexed->rgba[pdef->pixel] = (0xff000000 |
349
((pdef->red & 0xff00) << 8) |
350
((pdef->green & 0xff00) ) |
351
((pdef->blue & 0xff00) >> 8));
357
#endif /* _MIINDEX_H_ */