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