xref: /qemu/ui/vnc-palette.c (revision 5136a0526989fdfd8799ae4e29ff43d5b80ee37e)
1*5136a052SCorentin Chary /*
2*5136a052SCorentin Chary  * QEMU VNC display driver: palette hash table
3*5136a052SCorentin Chary  *
4*5136a052SCorentin Chary  * From libvncserver/libvncserver/tight.c
5*5136a052SCorentin Chary  * Copyright (C) 2000, 2001 Const Kaplinsky.  All Rights Reserved.
6*5136a052SCorentin Chary  * Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
7*5136a052SCorentin Chary  *
8*5136a052SCorentin Chary  * Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
9*5136a052SCorentin Chary  *
10*5136a052SCorentin Chary  * Permission is hereby granted, free of charge, to any person obtaining a copy
11*5136a052SCorentin Chary  * of this software and associated documentation files (the "Software"), to deal
12*5136a052SCorentin Chary  * in the Software without restriction, including without limitation the rights
13*5136a052SCorentin Chary  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14*5136a052SCorentin Chary  * copies of the Software, and to permit persons to whom the Software is
15*5136a052SCorentin Chary  * furnished to do so, subject to the following conditions:
16*5136a052SCorentin Chary  *
17*5136a052SCorentin Chary  * The above copyright notice and this permission notice shall be included in
18*5136a052SCorentin Chary  * all copies or substantial portions of the Software.
19*5136a052SCorentin Chary  *
20*5136a052SCorentin Chary  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21*5136a052SCorentin Chary  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22*5136a052SCorentin Chary  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23*5136a052SCorentin Chary  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24*5136a052SCorentin Chary  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25*5136a052SCorentin Chary  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26*5136a052SCorentin Chary  * THE SOFTWARE.
27*5136a052SCorentin Chary  */
28*5136a052SCorentin Chary 
29*5136a052SCorentin Chary #include "vnc-palette.h"
30*5136a052SCorentin Chary 
31*5136a052SCorentin Chary static VncPaletteEntry *palette_find(const VncPalette *palette,
32*5136a052SCorentin Chary                                      uint32_t color, unsigned int hash)
33*5136a052SCorentin Chary {
34*5136a052SCorentin Chary     VncPaletteEntry *entry;
35*5136a052SCorentin Chary 
36*5136a052SCorentin Chary     QLIST_FOREACH(entry, &palette->table[hash], next) {
37*5136a052SCorentin Chary         if (entry->color == color) {
38*5136a052SCorentin Chary             return entry;
39*5136a052SCorentin Chary         }
40*5136a052SCorentin Chary     }
41*5136a052SCorentin Chary 
42*5136a052SCorentin Chary     return NULL;
43*5136a052SCorentin Chary }
44*5136a052SCorentin Chary 
45*5136a052SCorentin Chary static unsigned int palette_hash(uint32_t rgb, int bpp)
46*5136a052SCorentin Chary {
47*5136a052SCorentin Chary     if (bpp == 16) {
48*5136a052SCorentin Chary         return ((unsigned int)(((rgb >> 8) + rgb) & 0xFF));
49*5136a052SCorentin Chary     } else {
50*5136a052SCorentin Chary         return ((unsigned int)(((rgb >> 16) + (rgb >> 8)) & 0xFF));
51*5136a052SCorentin Chary     }
52*5136a052SCorentin Chary }
53*5136a052SCorentin Chary 
54*5136a052SCorentin Chary VncPalette *palette_new(size_t max, int bpp)
55*5136a052SCorentin Chary {
56*5136a052SCorentin Chary     VncPalette *palette;
57*5136a052SCorentin Chary 
58*5136a052SCorentin Chary     palette = qemu_mallocz(sizeof(*palette));
59*5136a052SCorentin Chary     palette->max = max;
60*5136a052SCorentin Chary     palette->bpp = bpp;
61*5136a052SCorentin Chary     return palette;
62*5136a052SCorentin Chary }
63*5136a052SCorentin Chary 
64*5136a052SCorentin Chary void palette_destroy(VncPalette *palette)
65*5136a052SCorentin Chary {
66*5136a052SCorentin Chary     int i;
67*5136a052SCorentin Chary 
68*5136a052SCorentin Chary     if (palette == NULL) {
69*5136a052SCorentin Chary         return ;
70*5136a052SCorentin Chary     }
71*5136a052SCorentin Chary 
72*5136a052SCorentin Chary     for (i = 0; i < VNC_PALETTE_HASH_SIZE; i++) {
73*5136a052SCorentin Chary         VncPaletteEntry *entry = QLIST_FIRST(&palette->table[i]);
74*5136a052SCorentin Chary         while (entry) {
75*5136a052SCorentin Chary             VncPaletteEntry *tmp = QLIST_NEXT(entry, next);
76*5136a052SCorentin Chary             QLIST_REMOVE(entry, next);
77*5136a052SCorentin Chary             qemu_free(entry);
78*5136a052SCorentin Chary             entry = tmp;
79*5136a052SCorentin Chary         }
80*5136a052SCorentin Chary     }
81*5136a052SCorentin Chary 
82*5136a052SCorentin Chary     qemu_free(palette);
83*5136a052SCorentin Chary }
84*5136a052SCorentin Chary 
85*5136a052SCorentin Chary int palette_put(VncPalette *palette, uint32_t color)
86*5136a052SCorentin Chary {
87*5136a052SCorentin Chary     unsigned int hash;
88*5136a052SCorentin Chary     unsigned int idx = palette->size;
89*5136a052SCorentin Chary     VncPaletteEntry *entry;
90*5136a052SCorentin Chary 
91*5136a052SCorentin Chary     hash = palette_hash(color, palette->bpp) % VNC_PALETTE_HASH_SIZE;
92*5136a052SCorentin Chary     entry = palette_find(palette, color, hash);
93*5136a052SCorentin Chary 
94*5136a052SCorentin Chary     if (!entry && palette->size >= palette->max) {
95*5136a052SCorentin Chary         return 0;
96*5136a052SCorentin Chary     }
97*5136a052SCorentin Chary     if (!entry) {
98*5136a052SCorentin Chary         VncPaletteEntry *entry;
99*5136a052SCorentin Chary 
100*5136a052SCorentin Chary         entry = qemu_mallocz(sizeof(*entry));
101*5136a052SCorentin Chary         entry->color = color;
102*5136a052SCorentin Chary         entry->idx = idx;
103*5136a052SCorentin Chary         QLIST_INSERT_HEAD(&palette->table[hash], entry, next);
104*5136a052SCorentin Chary         palette->size++;
105*5136a052SCorentin Chary     }
106*5136a052SCorentin Chary     return palette->size;
107*5136a052SCorentin Chary }
108*5136a052SCorentin Chary 
109*5136a052SCorentin Chary int palette_idx(const VncPalette *palette, uint32_t color)
110*5136a052SCorentin Chary {
111*5136a052SCorentin Chary     VncPaletteEntry *entry;
112*5136a052SCorentin Chary     unsigned int hash;
113*5136a052SCorentin Chary 
114*5136a052SCorentin Chary     hash = palette_hash(color, palette->bpp) % VNC_PALETTE_HASH_SIZE;
115*5136a052SCorentin Chary     entry = palette_find(palette, color, hash);
116*5136a052SCorentin Chary     return (entry == NULL ? -1 : entry->idx);
117*5136a052SCorentin Chary }
118*5136a052SCorentin Chary 
119*5136a052SCorentin Chary size_t palette_size(const VncPalette *palette)
120*5136a052SCorentin Chary {
121*5136a052SCorentin Chary     return palette->size;
122*5136a052SCorentin Chary }
123*5136a052SCorentin Chary 
124*5136a052SCorentin Chary void palette_iter(const VncPalette *palette,
125*5136a052SCorentin Chary                   void (*iter)(int idx, uint32_t color, void *opaque),
126*5136a052SCorentin Chary                   void *opaque)
127*5136a052SCorentin Chary {
128*5136a052SCorentin Chary     int i;
129*5136a052SCorentin Chary     VncPaletteEntry *entry;
130*5136a052SCorentin Chary 
131*5136a052SCorentin Chary     for (i = 0; i < VNC_PALETTE_HASH_SIZE; i++) {
132*5136a052SCorentin Chary         QLIST_FOREACH(entry, &palette->table[i], next) {
133*5136a052SCorentin Chary             iter(entry->idx, entry->color, opaque);
134*5136a052SCorentin Chary         }
135*5136a052SCorentin Chary     }
136*5136a052SCorentin Chary }
137