]> git.saurik.com Git - wxWidgets.git/blob - src/gdk_imlib/cache.c
One that got away
[wxWidgets.git] / src / gdk_imlib / cache.c
1 #define _GNU_SOURCE
2 #include "../gdk_imlib/gdk_imlib.h"
3 #include "../gdk_imlib/gdk_imlib_private.h"
4
5 /* uncomment this to compile imlib's cahce with pixmap accounting output */
6 /*#define PIXMAP_ACCOUNTING */
7
8 void
9 gdirty_pixmaps(GdkImlibImage * im)
10 {
11 struct pixmap_cache *ptr;
12
13 ptr = id->cache.pixmap;
14 while (ptr)
15 {
16 if ((ptr->im == im) && ((!ptr->file) || (!strcmp(im->filename, ptr->file))))
17 ptr->dirty = 1;
18 ptr = ptr->next;
19 }
20 }
21
22 void
23 gdirty_images(GdkImlibImage * im)
24 {
25 struct image_cache *ptr;
26
27 ptr = id->cache.image;
28 while (ptr)
29 {
30 if ((!strcmp(im->filename, ptr->file)) && (im == ptr->im))
31 {
32 ptr->dirty = 1;
33 return;
34 }
35 ptr = ptr->next;
36 }
37 }
38
39 void
40 gfind_pixmap(GdkImlibImage * im, int width, int height, GdkPixmap ** pmap, GdkBitmap ** mask)
41 {
42 struct pixmap_cache *ptr;
43
44 ptr = id->cache.pixmap;
45 while (ptr)
46 {
47 if ((ptr->im == im) && (ptr->width == width) && (ptr->height == height) &&
48 ((!ptr->file) || (!strcmp(im->filename, ptr->file))) &&
49 (!ptr->dirty))
50 {
51 if (ptr->refnum > 0)
52 ptr->refnum++;
53 else
54 {
55 ptr->refnum++;
56 id->cache.num_pixmap++;
57 if (ptr->pmap)
58 id->cache.used_pixmap -= width * height * id->x.depth;
59 if (ptr->shape_mask)
60 id->cache.used_pixmap -= width * height;
61 if (id->cache.used_pixmap < 0)
62 {
63 id->cache.used_pixmap = 0;
64 fprintf(stderr, "IMLIB: uhoh.. caching problems.... meep meep\n");
65 }
66 }
67 if (ptr->prev)
68 {
69 ptr->prev->next = ptr->next;
70 if (ptr->next)
71 ptr->next->prev = ptr->prev;
72 ptr->next = id->cache.pixmap;
73 ptr->next->prev = ptr;
74 id->cache.pixmap = ptr;
75 ptr->prev = NULL;
76 }
77 *pmap = ptr->pmap;
78 *mask = ptr->shape_mask;
79 return;
80 }
81 ptr = ptr->next;
82 }
83 *pmap = NULL;
84 *mask = NULL;
85 }
86
87 GdkImlibImage *
88 gfind_image(char *file)
89 {
90 struct image_cache *ptr;
91
92 ptr = id->cache.image;
93 while (ptr)
94 {
95 if ((!strcmp(file, ptr->file)) && (!ptr->dirty))
96 {
97 if (ptr->refnum)
98 ptr->refnum++;
99 else
100 {
101 ptr->refnum++;
102 id->cache.num_image++;
103 id->cache.used_image -= ptr->im->rgb_width * ptr->im->rgb_height * 3;
104 if (id->cache.used_image < 0)
105 {
106 id->cache.used_image = 0;
107 fprintf(stderr, "IMLIB: uhoh.. caching problems.... meep meep\n");
108 }
109 }
110 if (ptr->prev)
111 {
112 ptr->prev->next = ptr->next;
113 if (ptr->next)
114 ptr->next->prev = ptr->prev;
115 ptr->next = id->cache.image;
116 ptr->next->prev = ptr;
117 id->cache.image = ptr;
118 ptr->prev = NULL;
119 }
120 return ptr->im;
121 }
122 ptr = ptr->next;
123 }
124 return NULL;
125 }
126
127 void
128 gfree_pixmappmap(GdkPixmap * pmap)
129 {
130 struct pixmap_cache *ptr;
131
132 ptr = id->cache.pixmap;
133 while (ptr)
134 {
135 if ((ptr->pmap == pmap) || (ptr->shape_mask == pmap))
136 {
137 if (ptr->shape_mask == pmap)
138 return;
139 if (ptr->refnum > 0)
140 {
141 ptr->refnum--;
142 if (ptr->refnum == 0)
143 {
144 id->cache.num_pixmap--;
145 if (ptr->pmap)
146 id->cache.used_pixmap += ptr->width * ptr->height * id->x.depth;
147 if (ptr->shape_mask)
148 id->cache.used_pixmap += ptr->width * ptr->height;
149 }
150 }
151 return;
152 }
153 ptr = ptr->next;
154 }
155 gdk_pixmap_unref(pmap);
156 }
157
158 void
159 gfree_image(GdkImlibImage * im)
160 {
161 struct image_cache *ptr;
162
163 ptr = id->cache.image;
164 while (ptr)
165 {
166 if (im == ptr->im)
167 {
168 if (ptr->refnum)
169 {
170 ptr->refnum--;
171 if (!ptr->refnum)
172 {
173 id->cache.num_image--;
174 id->cache.used_image += ptr->im->rgb_width * ptr->im->rgb_height * 3;
175 }
176 }
177 return;
178 }
179 ptr = ptr->next;
180 }
181 gnullify_image(im);
182 }
183
184 void
185 gflush_image(GdkImlibImage * im)
186 {
187 if (im)
188 im->cache = 0;
189 }
190
191 void
192 gadd_image(GdkImlibImage * im, char *file)
193 {
194 struct image_cache *ptr;
195 struct image_cache *n;
196
197 if ((!im) || (!file))
198 return;
199 ptr = id->cache.image;
200 n = malloc(sizeof(struct image_cache));
201
202 if (!n)
203 return;
204 n->prev = NULL;
205 n->next = ptr;
206 n->file = malloc(strlen(file) + 1);
207 if (!n->file)
208 {
209 free(n);
210 return;
211 }
212 strcpy(n->file, file);
213 n->im = im;
214 n->refnum = 1;
215 n->dirty = 0;
216 if (n->next)
217 n->next->prev = n;
218 id->cache.image = n;
219 id->cache.num_image++;
220 }
221
222 void
223 gadd_pixmap(GdkImlibImage * im, int width, int height, XImage * xim, XImage * sxim)
224 {
225 struct pixmap_cache *ptr;
226 struct pixmap_cache *n;
227
228 if (!im)
229 return;
230 ptr = id->cache.pixmap;
231 n = malloc(sizeof(struct pixmap_cache));
232
233 if (!n)
234 return;
235 n->prev = NULL;
236 n->next = ptr;
237 n->im = im;
238 if (im->filename)
239 {
240 n->file = malloc(strlen(im->filename) + 1);
241 if (n->file)
242 strcpy(n->file, im->filename);
243 }
244 else
245 n->file = NULL;
246 n->refnum = 1;
247 n->dirty = 0;
248 n->width = width;
249 n->height = height;
250 n->pmap = im->pixmap;
251 n->shape_mask = im->shape_mask;
252 n->xim = xim;
253 n->sxim = sxim;
254 if (n->next)
255 n->next->prev = n;
256 id->cache.pixmap = n;
257 id->cache.num_pixmap++;
258 }
259
260 void
261 gclean_caches()
262 {
263 {
264 struct image_cache *ptr = NULL;
265 struct image_cache *pptr = NULL;
266 struct image_cache *last = NULL;
267 int newlast;
268
269 /* find the back of the list */
270 ptr = id->cache.image;
271 while (ptr)
272 {
273 last = ptr;
274 ptr = ptr->next;
275 }
276 newlast = 0;
277 ptr = last;
278 /* remove all images that are tagged non-cachable, and have 0 */
279 /* references , even if the cache has spare room. */
280 while (ptr)
281 {
282 if (!ptr->refnum)
283 {
284 if (!ptr->im->cache)
285 {
286 if (ptr == last)
287 newlast = 1;
288 id->cache.used_image -= ptr->im->rgb_width * ptr->im->rgb_height * 3;
289 gnullify_image(ptr->im);
290 if (pptr)
291 ptr = pptr->prev;
292 if (ptr->prev)
293 ptr->prev->next = ptr->next;
294 else
295 id->cache.image = ptr->next;
296 if (ptr->next)
297 ptr->next->prev = ptr->prev;
298 if (ptr->file)
299 free(ptr->file);
300 free(ptr);
301 ptr = NULL;
302 }
303 }
304 if (ptr)
305 ptr = ptr->prev;
306 if (newlast)
307 {
308 last = NULL;
309 ptr = id->cache.image;
310 while (ptr)
311 {
312 last = ptr;
313 ptr = ptr->next;
314 }
315 newlast = 0;
316 ptr = last;
317 }
318 }
319 /* find the back of the list */
320 ptr = id->cache.image;
321 last = NULL;
322 while (ptr)
323 {
324 last = ptr;
325 ptr = ptr->next;
326 }
327 newlast = 0;
328 ptr = last;
329 /* while the amount of data in the cache is greater than the set */
330 /* amount, delete the last entry (last used) from the unreferenced */
331 /* cached 24-bit images */
332 while (id->cache.used_image > id->cache.size_image)
333 {
334 while (ptr)
335 {
336 if (ptr->refnum < 1)
337 {
338 if (ptr == last)
339 newlast = 1;
340 id->cache.used_image -= ptr->im->rgb_width * ptr->im->rgb_height * 3;
341 gnullify_image(ptr->im);
342 if (ptr->prev)
343 ptr->prev->next = ptr->next;
344 else
345 id->cache.image = ptr->next;
346 if (ptr->next)
347 ptr->next->prev = ptr->prev;
348 if (ptr->file)
349 free(ptr->file);
350 free(ptr);
351 ptr = NULL;
352 break;
353 }
354 if (ptr)
355 ptr = ptr->prev;
356 }
357 if (newlast)
358 {
359 last = NULL;
360 ptr = id->cache.image;
361 while (ptr)
362 {
363 last = ptr;
364 ptr = ptr->next;
365 }
366 newlast = 0;
367 ptr = last;
368 }
369 if (!ptr)
370 break;
371 }
372 }
373 {
374 struct pixmap_cache *ptr;
375 struct pixmap_cache *last;
376 int newlast;
377
378 #ifdef PIXMAP_ACCOUNTING
379 int total, total2, num, num2;
380
381 printf("--------- Pixmap cashe zise %i / %i with %i pixmaps referenced\n",
382 id->cache.used_pixmap, id->cache.size_pixmap,
383 id->cache.num_pixmap);
384 ptr = id->cache.pixmap;
385 total = 0;
386 total2 = 0;
387 num = 0;
388 num2 = 0;
389 while (ptr)
390 {
391 printf("Pmap for file %s REFNUM %3i SIZE %4ix%4i PMAP %8x MASK %8x\n",
392 ptr->file, ptr->refnum, ptr->width, ptr->height, ptr->pmap,
393 ptr->shape_mask);
394 if (ptr->refnum > 0)
395 {
396 total += (ptr->width * ptr->height * id->x.depth);
397 if (ptr->shape_mask)
398 total += (ptr->width * ptr->height);
399 num++;
400 }
401 else
402 {
403 total2 += (ptr->width * ptr->height * id->x.depth);
404 if (ptr->shape_mask)
405 total2 += (ptr->width * ptr->height);
406 num2++;
407 }
408 ptr = ptr->next;
409 }
410 printf("Accounting Data:\n");
411 printf("*** total pixmap's in cache %i with %i pixmaps\n",
412 total, num);
413 printf("*** total unreffed pixmap's in cache %i with %i pixmaps\n\n",
414 total2, num2);
415 #endif
416 /* find the back of the list */
417 ptr = id->cache.pixmap;
418 last = NULL;
419 while (ptr)
420 {
421 last = ptr;
422 ptr = ptr->next;
423 }
424 newlast = 0;
425 ptr = last;
426 /* while the amount of data in the cache is greater than the set */
427 /* amount, delete the last entry (last used) from the unreferenced */
428 /* cached pixmaps */
429 while (id->cache.used_pixmap > id->cache.size_pixmap)
430 {
431 while (ptr)
432 {
433 if (ptr->refnum < 1)
434 {
435 if (ptr == last)
436 newlast = 1;
437 if (ptr->pmap)
438 id->cache.used_pixmap -= ptr->width * ptr->height * id->x.depth;
439 if (ptr->shape_mask)
440 id->cache.used_pixmap -= ptr->width * ptr->height;
441 if (ptr->pmap)
442 gdk_pixmap_unref(ptr->pmap);
443 if (ptr->shape_mask)
444 gdk_pixmap_unref(ptr->shape_mask);
445 if (ptr->xim)
446 XDestroyImage(ptr->xim);
447 if (ptr->sxim)
448 XDestroyImage(ptr->sxim);
449 if (ptr->prev)
450 ptr->prev->next = ptr->next;
451 else
452 id->cache.pixmap = ptr->next;
453 if (ptr->next)
454 ptr->next->prev = ptr->prev;
455 if (ptr->file)
456 free(ptr->file);
457 free(ptr);
458 ptr = NULL;
459 break;
460 }
461 if (ptr)
462 ptr = ptr->prev;
463 }
464 if (newlast)
465 {
466 last = NULL;
467 ptr = id->cache.pixmap;
468 while (ptr)
469 {
470 last = ptr;
471 ptr = ptr->next;
472 }
473 newlast = 0;
474 ptr = last;
475 }
476 if (!ptr)
477 break;
478 }
479 }
480 }
481
482 void
483 gnullify_image(GdkImlibImage * im)
484 {
485 if (!im)
486 return;
487 if (im->rgb_data)
488 free(im->rgb_data);
489 if (im->alpha_data)
490 free(im->alpha_data);
491 if (im->pixmap)
492 gfree_pixmappmap(im->pixmap);
493 if (im->filename)
494 free(im->filename);
495 free(im);
496 }