1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <direct/debug.h>
32 #include <direct/memcpy.h>
33 #include <direct/thread.h>
34
35 #include <core/core.h>
36 #include <core/core_parts.h>
37 #include <core/palette.h>
38 #include <core/colorhash.h>
39
40 #include <misc/util.h>
41 #include <gfx/convert.h>
42
43
44 D_DEBUG_DOMAIN( Core_ColorHash, "Core/ColorHash", "DirectFB ColorHash Core" );
45
46
47 #define HASH_SIZE 823
48
49 typedef struct {
50 unsigned int pixel;
51 unsigned int index;
52 u32 palette_id;
53 } Colorhash;
54
55 /**********************************************************************************************************************/
56
57 typedef struct {
58 int magic;
59 } DFBColorHashCoreShared;
60
61 struct __DFB_DFBColorHashCore {
62 int magic;
63
64 CoreDFB *core;
65
66 DFBColorHashCoreShared *shared;
67
68 Colorhash *hash;
69 unsigned int hash_users;
70 DirectMutex hash_lock;
71 };
72
73 DFB_CORE_PART( colorhash_core, ColorHashCore );
74
75 /**********************************************************************************************************************/
76
77 static DFBColorHashCore *core_colorhash; /* FIXME */
78
79
80 static DFBResult
dfb_colorhash_core_initialize(CoreDFB * core,DFBColorHashCore * data,DFBColorHashCoreShared * shared)81 dfb_colorhash_core_initialize( CoreDFB *core,
82 DFBColorHashCore *data,
83 DFBColorHashCoreShared *shared )
84 {
85 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_initialize( %p, %p, %p )\n", core, data, shared );
86
87 D_ASSERT( data != NULL );
88 D_ASSERT( shared != NULL );
89
90 core_colorhash = data; /* FIXME */
91
92 data->core = core;
93 data->shared = shared;
94
95 data->hash = D_CALLOC( HASH_SIZE, sizeof (Colorhash) );
96 if (!data->hash)
97 return D_OOM();
98
99 direct_mutex_init( &data->hash_lock );
100
101 D_MAGIC_SET( data, DFBColorHashCore );
102 D_MAGIC_SET( shared, DFBColorHashCoreShared );
103
104 return DFB_OK;
105 }
106
107 static DFBResult
dfb_colorhash_core_join(CoreDFB * core,DFBColorHashCore * data,DFBColorHashCoreShared * shared)108 dfb_colorhash_core_join( CoreDFB *core,
109 DFBColorHashCore *data,
110 DFBColorHashCoreShared *shared )
111 {
112 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_join( %p, %p, %p )\n", core, data, shared );
113
114 D_ASSERT( data != NULL );
115 D_MAGIC_ASSERT( shared, DFBColorHashCoreShared );
116
117 core_colorhash = data; /* FIXME */
118
119 data->core = core;
120 data->shared = shared;
121
122 data->hash = D_CALLOC( HASH_SIZE, sizeof (Colorhash) );
123 if (!data->hash)
124 return D_OOM();
125
126 direct_mutex_init( &data->hash_lock );
127
128 D_MAGIC_SET( data, DFBColorHashCore );
129
130 return DFB_OK;
131 }
132
133 static DFBResult
dfb_colorhash_core_shutdown(DFBColorHashCore * data,bool emergency)134 dfb_colorhash_core_shutdown( DFBColorHashCore *data,
135 bool emergency )
136 {
137 DFBColorHashCoreShared *shared;
138
139 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " );
140
141 D_MAGIC_ASSERT( data, DFBColorHashCore );
142 D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );
143
144 shared = data->shared;
145
146 direct_mutex_deinit( &data->hash_lock );
147
148 D_FREE( data->hash );
149
150 D_MAGIC_CLEAR( data );
151 D_MAGIC_CLEAR( shared );
152
153 return DFB_OK;
154 }
155
156 static DFBResult
dfb_colorhash_core_leave(DFBColorHashCore * data,bool emergency)157 dfb_colorhash_core_leave( DFBColorHashCore *data,
158 bool emergency )
159 {
160 DFBColorHashCoreShared *shared;
161
162 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " );
163
164 D_MAGIC_ASSERT( data, DFBColorHashCore );
165 D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );
166
167 shared = data->shared;
168
169 direct_mutex_deinit( &data->hash_lock );
170
171 D_FREE( data->hash );
172
173 D_MAGIC_CLEAR( data );
174
175 return DFB_OK;
176 }
177
178 static DFBResult
dfb_colorhash_core_suspend(DFBColorHashCore * data)179 dfb_colorhash_core_suspend( DFBColorHashCore *data )
180 {
181 DFBColorHashCoreShared *shared;
182
183 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_suspend( %p )\n", data );
184
185 D_MAGIC_ASSERT( data, DFBColorHashCore );
186 D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );
187
188 shared = data->shared;
189
190 return DFB_OK;
191 }
192
193 static DFBResult
dfb_colorhash_core_resume(DFBColorHashCore * data)194 dfb_colorhash_core_resume( DFBColorHashCore *data )
195 {
196 DFBColorHashCoreShared *shared;
197
198 D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_resume( %p )\n", data );
199
200 D_MAGIC_ASSERT( data, DFBColorHashCore );
201 D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared );
202
203 shared = data->shared;
204
205 return DFB_OK;
206 }
207
208 /**********************************************************************************************************************/
209
210 unsigned int
dfb_colorhash_lookup(DFBColorHashCore * core,CorePalette * palette,u8 r,u8 g,u8 b,u8 a)211 dfb_colorhash_lookup( DFBColorHashCore *core,
212 CorePalette *palette,
213 u8 r,
214 u8 g,
215 u8 b,
216 u8 a )
217 {
218 unsigned int pixel = PIXEL_ARGB(a, r, g, b);
219 unsigned int index = (pixel ^ (unsigned long) palette) % HASH_SIZE;
220 DFBColorHashCoreShared *shared;
221
222 // D_ASSUME( core != NULL );
223
224 if (core) {
225 D_MAGIC_ASSERT( core, DFBColorHashCore );
226 D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared );
227 }
228 else
229 core = core_colorhash;
230
231 shared = core->shared;
232
233 D_ASSERT( core->hash != NULL );
234
235 direct_mutex_lock( &core->hash_lock );
236
237 /* try a lookup in the hash table */
238 if (core->hash[index].palette_id == palette->object.id && core->hash[index].pixel == pixel) {
239 /* set the return value */
240 index = core->hash[index].index;
241 } else { /* look for the closest match */
242 DFBColor *entries = palette->entries;
243 int min_diff = 0;
244 unsigned int i, min_index = 0;
245
246 for (i = 0; i < palette->num_entries; i++) {
247 int diff;
248
249 int r_diff = (int) entries[i].r - (int) r;
250 int g_diff = (int) entries[i].g - (int) g;
251 int b_diff = (int) entries[i].b - (int) b;
252 int a_diff = (int) entries[i].a - (int) a;
253
254 if (a)
255 diff = (r_diff * r_diff + g_diff * g_diff +
256 b_diff * b_diff + ((a_diff * a_diff) >> 6));
257 else
258 diff = (r_diff + g_diff + b_diff + (a_diff * a_diff));
259
260 if (i == 0 || diff < min_diff) {
261 min_diff = diff;
262 min_index = i;
263 }
264
265 if (!diff)
266 break;
267 }
268
269 /* store the matching entry in the hash table */
270 core->hash[index].pixel = pixel;
271 core->hash[index].index = min_index;
272 core->hash[index].palette_id = palette->object.id;
273
274 /* set the return value */
275 index = min_index;
276 }
277
278 direct_mutex_unlock( &core->hash_lock );
279
280 return index;
281 }
282
283 void
dfb_colorhash_invalidate(DFBColorHashCore * core,CorePalette * palette)284 dfb_colorhash_invalidate( DFBColorHashCore *core,
285 CorePalette *palette )
286 {
287 unsigned int index = HASH_SIZE - 1;
288 DFBColorHashCoreShared *shared;
289
290 // D_ASSUME( core != NULL );
291
292 if (core) {
293 D_MAGIC_ASSERT( core, DFBColorHashCore );
294 D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared );
295 }
296 else
297 core = core_colorhash;
298
299 shared = core->shared;
300
301 D_ASSERT( core->hash != NULL );
302
303 direct_mutex_lock( &core->hash_lock );
304
305 /* invalidate all entries owned by this palette */
306 do {
307 if (core->hash[index].palette_id == palette->object.id)
308 core->hash[index].palette_id = 0;
309 } while (index--);
310
311 direct_mutex_unlock( &core->hash_lock );
312 }
313
314