Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 30811:50e0f6942e43
Implement Win32 mutexes.
Implement Win32 mutexes; they used to just be mapped on top of events, which
is not the same thing at all.
The implementation is pretty much the obvious one, similar to the
current critical section implementation and the semaphore implementation;
a single lock count protected by a pthread mutex, and an event lockers can
sleep on to know when the mutex is available.
Also make CreateMutexA and ReleaseMutex available even if QuickTime codecs
support is not configured.
author | sesse |
---|---|
date | Sat, 06 Mar 2010 10:13:37 +0000 |
parents | 48d020c5ceca |
children | e64df5862cea |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * libass is free software; you can redistribute it and/or modify |
26723 | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
11 * libass is distributed in the hope that it will be useful, |
26723 | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
17 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
20 |
18937 | 21 #include "config.h" |
22 | |
22292 | 23 #include <inttypes.h> |
18937 | 24 #include <ft2build.h> |
25 #include FT_FREETYPE_H | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
26 #include FT_GLYPH_H |
18937 | 27 |
28 #include <assert.h> | |
29 | |
30200 | 30 #include "ass_utils.h" |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21348
diff
changeset
|
31 #include "ass.h" |
18937 | 32 #include "ass_fontconfig.h" |
21322 | 33 #include "ass_font.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
34 #include "ass_bitmap.h" |
18937 | 35 #include "ass_cache.h" |
36 | |
30200 | 37 static unsigned hashmap_hash(void *buf, size_t len) |
38 { | |
39 return fnv_32a_buf(buf, len, FNV1_32A_INIT); | |
40 } | |
23016 | 41 |
30200 | 42 static int hashmap_key_compare(void *a, void *b, size_t size) |
23016 | 43 { |
30200 | 44 return memcmp(a, b, size) == 0; |
23016 | 45 } |
30200 | 46 |
47 static void hashmap_item_dtor(void *key, size_t key_size, void *value, | |
48 size_t value_size) | |
23016 | 49 { |
30200 | 50 free(key); |
51 free(value); | |
23016 | 52 } |
53 | |
30200 | 54 Hashmap *hashmap_init(ASS_Library *library, size_t key_size, |
55 size_t value_size, int nbuckets, | |
56 HashmapItemDtor item_dtor, | |
57 HashmapKeyCompare key_compare, | |
58 HashmapHash hash) | |
23016 | 59 { |
30200 | 60 Hashmap *map = calloc(1, sizeof(Hashmap)); |
61 map->library = library; | |
62 map->nbuckets = nbuckets; | |
63 map->key_size = key_size; | |
64 map->value_size = value_size; | |
65 map->root = calloc(nbuckets, sizeof(hashmap_item_p)); | |
66 map->item_dtor = item_dtor ? item_dtor : hashmap_item_dtor; | |
67 map->key_compare = key_compare ? key_compare : hashmap_key_compare; | |
68 map->hash = hash ? hash : hashmap_hash; | |
69 return map; | |
23016 | 70 } |
18937 | 71 |
30200 | 72 void hashmap_done(Hashmap *map) |
23016 | 73 { |
30200 | 74 int i; |
75 // print stats | |
76 if (map->count > 0 || map->hit_count + map->miss_count > 0) | |
77 ass_msg(map->library, MSGL_V, | |
78 "cache statistics: \n total accesses: %d\n hits: %d\n " | |
79 "misses: %d\n object count: %d", | |
80 map->hit_count + map->miss_count, map->hit_count, | |
81 map->miss_count, map->count); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
82 |
30200 | 83 for (i = 0; i < map->nbuckets; ++i) { |
84 HashmapItem *item = map->root[i]; | |
85 while (item) { | |
86 HashmapItem *next = item->next; | |
87 map->item_dtor(item->key, map->key_size, item->value, | |
88 map->value_size); | |
89 free(item); | |
90 item = next; | |
91 } | |
92 } | |
93 free(map->root); | |
94 free(map); | |
23016 | 95 } |
18937 | 96 |
23016 | 97 // does nothing if key already exists |
30200 | 98 void *hashmap_insert(Hashmap *map, void *key, void *value) |
23016 | 99 { |
30200 | 100 unsigned hash = map->hash(key, map->key_size); |
101 HashmapItem **next = map->root + (hash % map->nbuckets); | |
102 while (*next) { | |
103 if (map->key_compare(key, (*next)->key, map->key_size)) | |
104 return (*next)->value; | |
105 next = &((*next)->next); | |
106 assert(next); | |
107 } | |
108 (*next) = malloc(sizeof(HashmapItem)); | |
109 (*next)->key = malloc(map->key_size); | |
110 (*next)->value = malloc(map->value_size); | |
111 memcpy((*next)->key, key, map->key_size); | |
112 memcpy((*next)->value, value, map->value_size); | |
113 (*next)->next = 0; | |
23016 | 114 |
30200 | 115 map->count++; |
116 return (*next)->value; | |
23016 | 117 } |
118 | |
30200 | 119 void *hashmap_find(Hashmap *map, void *key) |
23016 | 120 { |
30200 | 121 unsigned hash = map->hash(key, map->key_size); |
122 HashmapItem *item = map->root[hash % map->nbuckets]; | |
123 while (item) { | |
124 if (map->key_compare(key, item->key, map->key_size)) { | |
125 map->hit_count++; | |
126 return item->value; | |
127 } | |
128 item = item->next; | |
129 } | |
130 map->miss_count++; | |
131 return 0; | |
23016 | 132 } |
133 | |
134 //--------------------------------- | |
135 // font cache | |
136 | |
30200 | 137 static unsigned font_desc_hash(void *buf, size_t len) |
23016 | 138 { |
30200 | 139 ASS_FontDesc *desc = buf; |
140 unsigned hval; | |
141 hval = fnv_32a_str(desc->family, FNV1_32A_INIT); | |
142 hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval); | |
143 hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval); | |
144 return hval; | |
23016 | 145 } |
146 | |
30200 | 147 static int font_compare(void *key1, void *key2, size_t key_size) |
148 { | |
149 ASS_FontDesc *a = key1; | |
150 ASS_FontDesc *b = key2; | |
151 if (strcmp(a->family, b->family) != 0) | |
152 return 0; | |
153 if (a->bold != b->bold) | |
154 return 0; | |
155 if (a->italic != b->italic) | |
156 return 0; | |
157 if (a->treat_family_as_pattern != b->treat_family_as_pattern) | |
158 return 0; | |
159 return 1; | |
18937 | 160 } |
161 | |
30200 | 162 static void font_hash_dtor(void *key, size_t key_size, void *value, |
163 size_t value_size) | |
23016 | 164 { |
30200 | 165 ass_font_free(value); |
166 free(key); | |
23016 | 167 } |
168 | |
30200 | 169 ASS_Font *ass_font_cache_find(Hashmap *font_cache, |
170 ASS_FontDesc *desc) | |
18937 | 171 { |
30200 | 172 return hashmap_find(font_cache, desc); |
21317 | 173 } |
18937 | 174 |
21317 | 175 /** |
176 * \brief Add a face struct to cache. | |
177 * \param font font struct | |
178 */ | |
30200 | 179 void *ass_font_cache_add(Hashmap *font_cache, ASS_Font *font) |
21317 | 180 { |
30200 | 181 return hashmap_insert(font_cache, &(font->desc), font); |
18937 | 182 } |
183 | |
30200 | 184 Hashmap *ass_font_cache_init(ASS_Library *library) |
18937 | 185 { |
30200 | 186 Hashmap *font_cache; |
187 font_cache = hashmap_init(library, sizeof(ASS_FontDesc), | |
188 sizeof(ASS_Font), | |
189 1000, | |
190 font_hash_dtor, font_compare, font_desc_hash); | |
191 return font_cache; | |
18937 | 192 } |
193 | |
30200 | 194 void ass_font_cache_done(Hashmap *font_cache) |
18937 | 195 { |
30200 | 196 hashmap_done(font_cache); |
18937 | 197 } |
198 | |
30200 | 199 |
200 // Create hash/compare functions for bitmap and glyph | |
201 #define CREATE_HASH_FUNCTIONS | |
202 #include "ass_cache_template.h" | |
203 #define CREATE_COMPARISON_FUNCTIONS | |
204 #include "ass_cache_template.h" | |
205 | |
18937 | 206 //--------------------------------- |
23017 | 207 // bitmap cache |
18937 | 208 |
30200 | 209 static void bitmap_hash_dtor(void *key, size_t key_size, void *value, |
210 size_t value_size) | |
23016 | 211 { |
30200 | 212 BitmapHashValue *v = value; |
213 if (v->bm) | |
214 ass_free_bitmap(v->bm); | |
215 if (v->bm_o) | |
216 ass_free_bitmap(v->bm_o); | |
217 if (v->bm_s) | |
218 ass_free_bitmap(v->bm_s); | |
219 free(key); | |
220 free(value); | |
18937 | 221 } |
222 | |
30200 | 223 void *cache_add_bitmap(Hashmap *bitmap_cache, BitmapHashKey *key, |
224 BitmapHashValue *val) | |
18937 | 225 { |
30200 | 226 // Note: this is only an approximation |
227 if (val->bm_o) | |
228 bitmap_cache->cache_size += val->bm_o->w * val->bm_o->h * 3; | |
229 else if (val->bm) | |
230 bitmap_cache->cache_size += val->bm->w * val->bm->h * 3; | |
231 | |
232 return hashmap_insert(bitmap_cache, key, val); | |
18937 | 233 } |
234 | |
235 /** | |
23017 | 236 * \brief Get a bitmap from bitmap cache. |
18937 | 237 * \param key hash key |
238 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
239 */ |
30200 | 240 BitmapHashValue *cache_find_bitmap(Hashmap *bitmap_cache, |
241 BitmapHashKey *key) | |
18937 | 242 { |
30200 | 243 return hashmap_find(bitmap_cache, key); |
18937 | 244 } |
245 | |
30200 | 246 Hashmap *ass_bitmap_cache_init(ASS_Library *library) |
18937 | 247 { |
30200 | 248 Hashmap *bitmap_cache; |
249 bitmap_cache = hashmap_init(library, | |
250 sizeof(BitmapHashKey), | |
251 sizeof(BitmapHashValue), | |
252 0xFFFF + 13, | |
253 bitmap_hash_dtor, bitmap_compare, | |
254 bitmap_hash); | |
255 return bitmap_cache; | |
18937 | 256 } |
257 | |
30200 | 258 void ass_bitmap_cache_done(Hashmap *bitmap_cache) |
18937 | 259 { |
30200 | 260 hashmap_done(bitmap_cache); |
18937 | 261 } |
262 | |
30200 | 263 Hashmap *ass_bitmap_cache_reset(Hashmap *bitmap_cache) |
19539 | 264 { |
30200 | 265 ASS_Library *lib = bitmap_cache->library; |
266 | |
267 ass_bitmap_cache_done(bitmap_cache); | |
268 return ass_bitmap_cache_init(lib); | |
19539 | 269 } |
270 | |
23018 | 271 //--------------------------------- |
272 // glyph cache | |
273 | |
30200 | 274 static void glyph_hash_dtor(void *key, size_t key_size, void *value, |
275 size_t value_size) | |
23018 | 276 { |
30200 | 277 GlyphHashValue *v = value; |
278 if (v->glyph) | |
279 FT_Done_Glyph(v->glyph); | |
280 if (v->outline_glyph) | |
281 FT_Done_Glyph(v->outline_glyph); | |
282 free(key); | |
283 free(value); | |
23018 | 284 } |
285 | |
30200 | 286 void *cache_add_glyph(Hashmap *glyph_cache, GlyphHashKey *key, |
287 GlyphHashValue *val) | |
23018 | 288 { |
30200 | 289 return hashmap_insert(glyph_cache, key, val); |
23018 | 290 } |
291 | |
292 /** | |
293 * \brief Get a glyph from glyph cache. | |
294 * \param key hash key | |
295 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
296 */ |
30200 | 297 GlyphHashValue *cache_find_glyph(Hashmap *glyph_cache, |
298 GlyphHashKey *key) | |
23018 | 299 { |
30200 | 300 return hashmap_find(glyph_cache, key); |
23018 | 301 } |
302 | |
30200 | 303 Hashmap *ass_glyph_cache_init(ASS_Library *library) |
23018 | 304 { |
30200 | 305 Hashmap *glyph_cache; |
306 glyph_cache = hashmap_init(library, sizeof(GlyphHashKey), | |
307 sizeof(GlyphHashValue), | |
308 0xFFFF + 13, | |
309 glyph_hash_dtor, glyph_compare, glyph_hash); | |
310 return glyph_cache; | |
23018 | 311 } |
312 | |
30200 | 313 void ass_glyph_cache_done(Hashmap *glyph_cache) |
23018 | 314 { |
30200 | 315 hashmap_done(glyph_cache); |
23018 | 316 } |
317 | |
30200 | 318 Hashmap *ass_glyph_cache_reset(Hashmap *glyph_cache) |
23018 | 319 { |
30200 | 320 ASS_Library *lib = glyph_cache->library; |
321 | |
322 ass_glyph_cache_done(glyph_cache); | |
323 return ass_glyph_cache_init(lib); | |
23018 | 324 } |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
325 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
326 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
327 //--------------------------------- |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
328 // composite cache |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
329 |
30200 | 330 static void composite_hash_dtor(void *key, size_t key_size, void *value, |
331 size_t value_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
332 { |
30200 | 333 CompositeHashValue *v = value; |
334 free(v->a); | |
335 free(v->b); | |
336 free(key); | |
337 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
338 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
339 |
30200 | 340 void *cache_add_composite(Hashmap *composite_cache, |
341 CompositeHashKey *key, | |
342 CompositeHashValue *val) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
343 { |
30200 | 344 return hashmap_insert(composite_cache, key, val); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
345 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
346 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
347 /** |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
348 * \brief Get a composite bitmap from composite cache. |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
349 * \param key hash key |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
350 * \return requested hash val or 0 if not found |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
351 */ |
30200 | 352 CompositeHashValue *cache_find_composite(Hashmap *composite_cache, |
353 CompositeHashKey *key) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
354 { |
30200 | 355 return hashmap_find(composite_cache, key); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
356 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
357 |
30200 | 358 Hashmap *ass_composite_cache_init(ASS_Library *library) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
359 { |
30200 | 360 Hashmap *composite_cache; |
361 composite_cache = hashmap_init(library, sizeof(CompositeHashKey), | |
362 sizeof(CompositeHashValue), | |
363 0xFFFF + 13, | |
364 composite_hash_dtor, composite_compare, | |
365 composite_hash); | |
366 return composite_cache; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
367 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
368 |
30200 | 369 void ass_composite_cache_done(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
370 { |
30200 | 371 hashmap_done(composite_cache); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
372 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
373 |
30200 | 374 Hashmap *ass_composite_cache_reset(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
375 { |
30200 | 376 ASS_Library *lib = composite_cache->library; |
377 | |
378 ass_composite_cache_done(composite_cache); | |
379 return ass_composite_cache_init(lib); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
380 } |