~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to render/miindex.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $XFree86: xc/programs/Xserver/render/miindex.c,v 1.7 2002/11/05 06:05:04 keithp Exp $
 
3
 *
 
4
 * Copyright Ā© 2001 Keith Packard, member of The XFree86 Project, Inc.
 
5
 *
 
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.
 
15
 *
 
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.
 
23
 */
 
24
 
 
25
#ifdef HAVE_DIX_CONFIG_H
 
26
#include <dix-config.h>
 
27
#endif
 
28
 
 
29
#ifndef _MIINDEX_H_
 
30
#define _MIINDEX_H_
 
31
 
 
32
#include "scrnintstr.h"
 
33
#include "gcstruct.h"
 
34
#include "pixmapstr.h"
 
35
#include "windowstr.h"
 
36
#include "mi.h"
 
37
#include "picturestr.h"
 
38
#include "mipict.h"
 
39
#include "colormapst.h"
 
40
 
 
41
#define NUM_CUBE_LEVELS 4
 
42
#define NUM_GRAY_LEVELS 13
 
43
 
 
44
static Bool
 
45
miBuildRenderColormap (ColormapPtr  pColormap, Pixel *pixels, int *nump)
 
46
{
 
47
    int         r, g, b;
 
48
    unsigned short  red, green, blue;
 
49
    Pixel       pixel;
 
50
    Bool        used[MI_MAX_INDEXED];
 
51
    int         needed;
 
52
    int         policy;
 
53
    int         cube, gray;
 
54
    int         i, n;
 
55
    
 
56
    if (pColormap->mid != pColormap->pScreen->defColormap)
 
57
    {
 
58
        policy = PictureCmapPolicyAll;
 
59
    }
 
60
    else
 
61
    {
 
62
        int     avail = pColormap->pVisual->ColormapEntries;
 
63
        policy = PictureCmapPolicy;
 
64
        if (policy == PictureCmapPolicyDefault)
 
65
        {
 
66
            if (avail >= 256 && (pColormap->pVisual->class|DynamicClass) == PseudoColor)
 
67
                policy = PictureCmapPolicyColor;
 
68
            else if (avail >= 64)
 
69
                policy = PictureCmapPolicyGray;
 
70
            else
 
71
                policy = PictureCmapPolicyMono;
 
72
        }
 
73
    }
 
74
    /*
 
75
     * Make sure enough cells are free for the chosen policy
 
76
     */
 
77
    for (;;)
 
78
    {
 
79
        switch (policy) {
 
80
        case PictureCmapPolicyAll:
 
81
            needed = 0;
 
82
            break;
 
83
        case PictureCmapPolicyColor:
 
84
            needed = 71;
 
85
            break;
 
86
        case PictureCmapPolicyGray:
 
87
            needed = 11;
 
88
            break;
 
89
        case PictureCmapPolicyMono:
 
90
        default:
 
91
            needed = 0;
 
92
            break;
 
93
        }
 
94
        if (needed <= pColormap->freeRed)
 
95
            break;
 
96
        policy--;
 
97
    } 
 
98
    
 
99
    /*
 
100
     * Compute size of cube and gray ramps
 
101
     */
 
102
    cube = gray = 0;
 
103
    switch (policy) {
 
104
    case PictureCmapPolicyAll:
 
105
        /*
 
106
         * Allocate as big a cube as possible
 
107
         */
 
108
        if ((pColormap->pVisual->class|DynamicClass) == PseudoColor)
 
109
        {
 
110
            for (cube = 1; cube * cube * cube < pColormap->pVisual->ColormapEntries; cube++)
 
111
                ;
 
112
            cube--;
 
113
            if (cube == 1)
 
114
                cube = 0;
 
115
        }
 
116
        else
 
117
            cube = 0;
 
118
        /*
 
119
         * Figure out how many gray levels to use so that they
 
120
         * line up neatly with the cube
 
121
         */
 
122
        if (cube)
 
123
        {
 
124
            needed = pColormap->pVisual->ColormapEntries - (cube*cube*cube);
 
125
            /* levels to fill in with */
 
126
            gray = needed / (cube - 1);
 
127
            /* total levels */
 
128
            gray = (gray + 1) * (cube - 1) + 1;
 
129
        }
 
130
        else
 
131
            gray = pColormap->pVisual->ColormapEntries;
 
132
        break;
 
133
                
 
134
    case PictureCmapPolicyColor:
 
135
        cube = NUM_CUBE_LEVELS;
 
136
        /* fall through ... */
 
137
    case PictureCmapPolicyGray:
 
138
        gray = NUM_GRAY_LEVELS;
 
139
        break;
 
140
    case PictureCmapPolicyMono:
 
141
    default:
 
142
        gray = 2;
 
143
        break;
 
144
    }
 
145
    
 
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++)
 
150
            {
 
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)
 
156
                    return FALSE;
 
157
                used[pixel] = TRUE;
 
158
            }
 
159
    for (g = 0; g < gray; g++)
 
160
    {
 
161
        red = green = blue = (g * 65535 + (gray-1)/2) / (gray - 1);
 
162
        if (AllocColor (pColormap, &red, &green, &blue, &pixel, 0) != Success)
 
163
            return FALSE;
 
164
        used[pixel] = TRUE;
 
165
    }
 
166
    n = 0;
 
167
    for (i = 0; i < pColormap->pVisual->ColormapEntries; i++)
 
168
        if (used[i])
 
169
            pixels[n++] = i;
 
170
 
 
171
    *nump = n;
 
172
    
 
173
    return TRUE;
 
174
}
 
175
 
 
176
/* 0 <= red, green, blue < 32 */
 
177
static Pixel
 
178
FindBestColor (miIndexedPtr pIndexed, Pixel *pixels, int num,
 
179
               int red, int green, int blue)
 
180
{
 
181
    Pixel   best = pixels[0];
 
182
    int     bestDist = 1 << 30;
 
183
    int     dist;
 
184
    int     dr, dg, db;
 
185
    while (num--)
 
186
    {
 
187
        Pixel   pixel = *pixels++;
 
188
        CARD32  v = pIndexed->rgba[pixel];
 
189
 
 
190
        dr = ((v >> 19) & 0x1f);
 
191
        dg = ((v >> 11) & 0x1f);
 
192
        db = ((v >> 3) & 0x1f);
 
193
        dr = dr - red;
 
194
        dg = dg - green;
 
195
        db = db - blue;
 
196
        dist = dr * dr + dg * dg + db * db;
 
197
        if (dist < bestDist)
 
198
        {
 
199
            bestDist = dist;
 
200
            best = pixel;
 
201
        }
 
202
    }
 
203
    return best;
 
204
}
 
205
 
 
206
/* 0 <= gray < 32768 */
 
207
static Pixel
 
208
FindBestGray (miIndexedPtr pIndexed, Pixel *pixels, int num, int gray)
 
209
{
 
210
    Pixel   best = pixels[0];
 
211
    int     bestDist = 1 << 30;
 
212
    int     dist;
 
213
    int     dr;
 
214
    int     r;
 
215
    
 
216
    while (num--)
 
217
    {
 
218
        Pixel   pixel = *pixels++;
 
219
        CARD32  v = pIndexed->rgba[pixel];
 
220
 
 
221
        r = v & 0xff;
 
222
        r = r | (r << 8);
 
223
        dr = gray - (r >> 1);
 
224
        dist = dr * dr;
 
225
        if (dist < bestDist)
 
226
        {
 
227
            bestDist = dist;
 
228
            best = pixel;
 
229
        }
 
230
    }
 
231
    return best;
 
232
}
 
233
 
 
234
Bool
 
235
miInitIndexed (ScreenPtr        pScreen,
 
236
               PictFormatPtr    pFormat)
 
237
{
 
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];
 
243
    int             num;
 
244
    int             i;
 
245
    Pixel           p, r, g, b;
 
246
 
 
247
    if (pVisual->ColormapEntries > MI_MAX_INDEXED)
 
248
        return FALSE;
 
249
    
 
250
    if (pVisual->class & DynamicClass)
 
251
    {
 
252
        if (!miBuildRenderColormap (pColormap, pixels, &num))
 
253
            return FALSE;
 
254
    }
 
255
    else
 
256
    {
 
257
        num = pVisual->ColormapEntries;
 
258
        for (p = 0; p < num; p++)
 
259
            pixels[p] = p;
 
260
    }
 
261
    
 
262
    pIndexed = xalloc (sizeof (miIndexedRec));
 
263
    if (!pIndexed)
 
264
        return FALSE;
 
265
    
 
266
    pFormat->index.nvalues = num;
 
267
    pFormat->index.pValues = xalloc (num * sizeof (xIndexValue));
 
268
    if (!pFormat->index.pValues)
 
269
    {
 
270
        xfree (pIndexed);
 
271
        return FALSE;
 
272
    }
 
273
    
 
274
    
 
275
    /*
 
276
     * Build mapping from pixel value to ARGB
 
277
     */
 
278
    QueryColors (pColormap, num, pixels, rgb);
 
279
    for (i = 0; i < num; i++)
 
280
    {
 
281
        p = pixels[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));
 
291
    }
 
292
 
 
293
    /*
 
294
     * Build mapping from RGB to pixel value.  This could probably be
 
295
     * done a bit quicker...
 
296
     */
 
297
    switch (pVisual->class | DynamicClass) {
 
298
    case GrayScale:
 
299
        pIndexed->color = FALSE;
 
300
        for (r = 0; r < 32768; r++)
 
301
            pIndexed->ent[r] = FindBestGray (pIndexed, pixels, num, r);
 
302
        break;
 
303
    case PseudoColor:
 
304
        pIndexed->color = TRUE;
 
305
        p = 0;
 
306
        for (r = 0; r < 32; r++)
 
307
            for (g = 0; g < 32; g++)
 
308
                for (b = 0; b < 32; b++)
 
309
                {
 
310
                    pIndexed->ent[p] = FindBestColor (pIndexed, pixels, num,
 
311
                                                      r, g, b);
 
312
                    p++;
 
313
                }
 
314
        break;
 
315
    }
 
316
    pFormat->index.devPrivate = pIndexed;
 
317
    return TRUE;
 
318
}
 
319
 
 
320
void
 
321
miCloseIndexed (ScreenPtr       pScreen,
 
322
                PictFormatPtr   pFormat)
 
323
{
 
324
    if (pFormat->index.devPrivate)
 
325
    {
 
326
        xfree (pFormat->index.devPrivate);
 
327
        pFormat->index.devPrivate = 0;
 
328
    }
 
329
    if (pFormat->index.pValues)
 
330
    {
 
331
        xfree (pFormat->index.pValues);
 
332
        pFormat->index.pValues = 0;
 
333
    }
 
334
}
 
335
 
 
336
void
 
337
miUpdateIndexed (ScreenPtr      pScreen,
 
338
                 PictFormatPtr  pFormat,
 
339
                 int            ndef,
 
340
                 xColorItem     *pdef)
 
341
{
 
342
    miIndexedPtr pIndexed = pFormat->index.devPrivate;
 
343
 
 
344
    if (pIndexed)
 
345
    {
 
346
        while (ndef--)
 
347
        {
 
348
            pIndexed->rgba[pdef->pixel] = (0xff000000 |
 
349
                                           ((pdef->red   & 0xff00) << 8) |
 
350
                                           ((pdef->green & 0xff00)     ) |
 
351
                                           ((pdef->blue  & 0xff00) >> 8));
 
352
            pdef++;
 
353
        }
 
354
    }
 
355
}
 
356
 
 
357
#endif /* _MIINDEX_H_ */