This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via 5e2e627e16c613ffee331d5ac32071caca27a369 (commit) via 43ae478827afcbdb94f4ce3d46a0881c6e2f9c01 (commit) via 5073ef02014ec1f3d2ca23e50951a6db7785c23e (commit) via cdf48d7342a48c7a5225403bfc371ba0ec7e74d5 (commit) via 7831f900a2f1ad24e66b999a6ddb7d664236d0d7 (commit) via ea3d8a3b3ff7deca52c6320bcbc30f3115f5aa32 (commit) via f027b0f012e6ea1e694dd0618be0d9c18c840dc5 (commit) from b45098c71ca5dab7345e2b2f704ae6452a7b52cb (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/5e2e627e16c613ffee331d5ac32071caca27a...
commit 5e2e627e16c613ffee331d5ac32071caca27a369 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 20:21:18 2012 +0200
spiv: Temporarily fix the bussy loop.
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 28ae50d..ec5a656 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -416,6 +416,7 @@ static int wait_for_event(int sleep_msec)
if (sleep_msec < 0) { GP_BackendPoll(backend); + usleep(10000); return 0; }
http://repo.or.cz/w/gfxprim.git/commit/43ae478827afcbdb94f4ce3d46a0881c6e2f9...
commit 43ae478827afcbdb94f4ce3d46a0881c6e2f9c01 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 20:12:06 2012 +0200
spiv: image_cache: Add elevator count, drop cache on d.
diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index 3f26474..4a8c2b7 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -30,6 +30,9 @@ struct image { struct image *prev; struct image *next;
+ /* number of elevated get calls */ + unsigned int elevated; + /* this identifies an image */ long cookie1; long cookie2; @@ -172,6 +175,8 @@ GP_Context *image_cache_get(struct image_cache *self, const char *path, remove_img(self, i, size); add_img(self, i, size); + + i->elevated++; }
return i->ctx; @@ -184,8 +189,8 @@ void image_cache_print(struct image_cache *self) printf("Image cache size %u used %un", self->max_size, self->cur_size);
for (i = self->root; i != NULL; i = i->next) - printf(" Image '%s:%10li:%10li' size %zun", i->path, - i->cookie1, i->cookie2, image_size(i)); + printf(" Image '%s:%10li:%10li' size %10zu elevated %un", i->path, + i->cookie1, i->cookie2, image_size(i), i->elevated); }
static int assert_size(struct image_cache *self, size_t size) @@ -227,6 +232,7 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, img->ctx = ctx; img->cookie1 = cookie1; img->cookie2 = cookie2; + img->elevated = 0; strcpy(img->path, path);
add_img(self, img, size); @@ -234,6 +240,16 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, return 0; }
+void image_cache_drop(struct image_cache *self) +{ + GP_DEBUG(1, "Dropping images in cache"); + + while (self->end != NULL) + remove_img_free(self, self->end, 0); + + self->cur_size = sizeof(struct image_cache); +} + void image_cache_destroy(struct image_cache *self) { GP_DEBUG(1, "Destroying image cache"); diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h index 38efb0d..e946709 100644 --- a/demos/spiv/image_cache.h +++ b/demos/spiv/image_cache.h @@ -55,6 +55,11 @@ int image_cache_put(struct image_cache *self, GP_Context *img, const char *path, long cookie1, long cookie2);
/* + * Drop all image in cache. + */ +void image_cache_drop(struct image_cache *self); + +/* * Destroys image cache and all it's images. */ void image_cache_destroy(struct image_cache *self); diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index e4a6747..28ae50d 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -596,6 +596,9 @@ int main(int argc, char *argv[]) params.show_progress_once = 1; show_image(¶ms, NULL); break; + case GP_KEY_D: + image_cache_drop(params.image_cache); + break; case GP_KEY_ESC: case GP_KEY_ENTER: case GP_KEY_Q:
http://repo.or.cz/w/gfxprim.git/commit/5073ef02014ec1f3d2ca23e50951a6db7785c...
commit 5073ef02014ec1f3d2ca23e50951a6db7785c23e Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 20:00:36 2012 +0200
spiv: image_cache: Add elevate parameter to get function.
diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index 759febc..3f26474 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -148,8 +148,8 @@ static void add_img(struct image_cache *self, struct image *img, size_t size) self->end = img; }
-GP_Context *image_cache_get(struct image_cache *self, - const char *path, long cookie1, long cookie2) +GP_Context *image_cache_get(struct image_cache *self, const char *path, + long cookie1, long cookie2, int elevate) { struct image *i;
@@ -164,12 +164,15 @@ GP_Context *image_cache_get(struct image_cache *self, return NULL;
/* Push the image to the root of the list */ - size_t size = image_size(i); + if (elevate) { + size_t size = image_size(i);
- GP_DEBUG(2, "Refreshing image '%s:%10li:%10li", path, cookie1, cookie2); + GP_DEBUG(2, "Refreshing image '%s:%10li:%10li", + path, cookie1, cookie2); - remove_img(self, i, size); - add_img(self, i, size); + remove_img(self, i, size); + add_img(self, i, size); + }
return i->ctx; } diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h index d2e3019..38efb0d 100644 --- a/demos/spiv/image_cache.h +++ b/demos/spiv/image_cache.h @@ -42,11 +42,11 @@ struct image_cache *image_cache_create(unsigned int max_size); /* * Returns cached image, or NULL. * - * Also image, if found, is rotated to the top, so recently touched images have - * lesser chance of being freed. + * If elevate set and image is found, the image is elevated to the top so + * it has lesser chance of being freed. */ -GP_Context *image_cache_get(struct image_cache *self, - const char *path, long cookie1, long cookie2); +GP_Context *image_cache_get(struct image_cache *self, const char *path, + long cookie1, long cookie2, int elevate);
/* * Puts an image into a cache. diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 93c066f..e4a6747 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -126,7 +126,7 @@ static void set_caption(const char *path, float rat) /* * Loads image */ -GP_Context *load_image(struct loader_params *params) +GP_Context *load_image(struct loader_params *params, int elevate) { struct cpu_timer timer; GP_Context *img, *context = backend->context; @@ -134,7 +134,7 @@ GP_Context *load_image(struct loader_params *params) GP_ProgressCallback callback = {.callback = image_loader_callback, .priv = "Loading image"};
- img = image_cache_get(params->image_cache, params->img_path, 0, 0); + img = image_cache_get(params->image_cache, params->img_path, 0, 0, elevate);
/* Image not cached, load it */ if (img == NULL) { @@ -176,13 +176,13 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size GP_ProgressCallback callback = {.callback = image_loader_callback};
/* Try to get resized cached image */ - img = image_cache_get(params->image_cache, params->img_path, cookie, resampling_method); + img = image_cache_get(params->image_cache, params->img_path, cookie, resampling_method, 1);
if (img != NULL) return img; /* Otherwise load image and resize it */ - if ((img = load_image(params)) == NULL) + if ((img = load_image(params, 1)) == NULL) return NULL;
/* Do low pass filter */ @@ -222,7 +222,7 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size */ static int resize_backend_and_blit(struct loader_params *params) { - GP_Context *img = load_image(params); + GP_Context *img = load_image(params, 1); if (GP_BackendResize(backend, img->w, img->h)) return 1; @@ -260,7 +260,7 @@ static void *image_loader(void *ptr) break; }
- if ((img = load_image(params)) == NULL) + if ((img = load_image(params, 0)) == NULL) return NULL;
float rat = calc_img_size(img->w, img->h, w, h);
http://repo.or.cz/w/gfxprim.git/commit/cdf48d7342a48c7a5225403bfc371ba0ec7e7...
commit cdf48d7342a48c7a5225403bfc371ba0ec7e74d5 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 19:50:50 2012 +0200
spiv: image_cache: Count image size more properly.
diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index 7ff0c56..759febc 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -67,6 +67,20 @@ static size_t read_total_memory(void) return ret * 1024 / 10; }
+/* + * Reports correct image record size. + */ +static size_t image_size2(GP_Context *ctx, const char *path) +{ + return ctx->bytes_per_row * ctx->h + sizeof(GP_Context) + + sizeof(struct image) + strlen(path) + 1; +} + +static size_t image_size(struct image *img) +{ + return image_size2(img->ctx, img->path); +} + struct image_cache *image_cache_create(unsigned int max_size) { struct image_cache *self; @@ -77,7 +91,7 @@ struct image_cache *image_cache_create(unsigned int max_size) return NULL;
self->max_size = max_size ? max_size : read_total_memory(); - self->cur_size = 0; + self->cur_size = sizeof(struct image_cache);
self->root = NULL; self->end = NULL; @@ -87,10 +101,8 @@ struct image_cache *image_cache_create(unsigned int max_size) return self; }
-static void remove_img(struct image_cache *self, struct image *img) +static void remove_img(struct image_cache *self, struct image *img, size_t size) { - size_t size = img->ctx->bytes_per_row * img->ctx->h; - if (img == self->end) self->end = img->prev;
@@ -106,13 +118,13 @@ static void remove_img(struct image_cache *self, struct image *img) self->cur_size -= size; }
-static void remove_img_free(struct image_cache *self, struct image *img) +static void remove_img_free(struct image_cache *self, + struct image *img, size_t size) { - GP_DEBUG(2, "Freeing image '%s:%10li:%10li' size %u", - img->path, img->cookie1, img->cookie2, - img->ctx->bytes_per_row * img->ctx->h); + GP_DEBUG(2, "Freeing image '%s:%10li:%10li' size %zu", + img->path, img->cookie1, img->cookie2, size); - remove_img(self, img); + remove_img(self, img, size); GP_ContextFree(img->ctx); free(img); } @@ -120,10 +132,8 @@ static void remove_img_free(struct image_cache *self, struct image *img) /* * Adds image to the start of the double linked list */ -static void add_img(struct image_cache *self, struct image *img) +static void add_img(struct image_cache *self, struct image *img, size_t size) { - size_t size = img->ctx->bytes_per_row * img->ctx->h; - img->next = self->root; if (img->next) @@ -154,9 +164,12 @@ GP_Context *image_cache_get(struct image_cache *self, return NULL;
/* Push the image to the root of the list */ + size_t size = image_size(i); + GP_DEBUG(2, "Refreshing image '%s:%10li:%10li", path, cookie1, cookie2); - remove_img(self, i); - add_img(self, i); + + remove_img(self, i, size); + add_img(self, i, size);
return i->ctx; } @@ -168,8 +181,8 @@ void image_cache_print(struct image_cache *self) printf("Image cache size %u used %un", self->max_size, self->cur_size);
for (i = self->root; i != NULL; i = i->next) - printf(" Image '%s:%10li:%10li' size %un", i->path, i->cookie1, i->cookie2, - i->ctx->bytes_per_row * i->ctx->h); + printf(" Image '%s:%10li:%10li' size %zun", i->path, + i->cookie1, i->cookie2, image_size(i)); }
static int assert_size(struct image_cache *self, size_t size) @@ -184,7 +197,7 @@ static int assert_size(struct image_cache *self, size_t size) return 1; }
- remove_img_free(self, self->end); + remove_img_free(self, self->end, image_size(self->end)); }
return 0; @@ -193,7 +206,7 @@ static int assert_size(struct image_cache *self, size_t size) int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, long cookie1, long cookie2) { - size_t size = ctx->bytes_per_row * ctx->h; + size_t size = image_size2(ctx, path);
if (assert_size(self, size)) return 1; @@ -213,7 +226,8 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, img->cookie2 = cookie2; strcpy(img->path, path);
- add_img(self, img); + add_img(self, img, size); + return 0; }
@@ -222,7 +236,7 @@ void image_cache_destroy(struct image_cache *self) GP_DEBUG(1, "Destroying image cache"); while (self->end != NULL) - remove_img_free(self, self->end); + remove_img_free(self, self->end, 0); free(self); } diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h index fc008ed..d2e3019 100644 --- a/demos/spiv/image_cache.h +++ b/demos/spiv/image_cache.h @@ -34,13 +34,16 @@ struct image_cache; /* * Creates an image cache with maximal memory size. * - * When memory size is set to zero, the size is read from /proc/meminfo - * as 10% of total memory. + * When memory size is set to zero it's set to 10% of total machine memory + * (as reported by /proc/meminfo). */ struct image_cache *image_cache_create(unsigned int max_size);
/* * Returns cached image, or NULL. + * + * Also image, if found, is rotated to the top, so recently touched images have + * lesser chance of being freed. */ GP_Context *image_cache_get(struct image_cache *self, const char *path, long cookie1, long cookie2);
http://repo.or.cz/w/gfxprim.git/commit/7831f900a2f1ad24e66b999a6ddb7d664236d...
commit 7831f900a2f1ad24e66b999a6ddb7d664236d0d7 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 19:30:58 2012 +0200
spiv: Fix low pass filtering, edhance cache.
diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index f252013..7ff0c56 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -26,11 +26,13 @@
struct image { GP_Context *ctx; - int cookie;
struct image *prev; struct image *next;
+ /* this identifies an image */ + long cookie1; + long cookie2; char path[]; };
@@ -106,8 +108,8 @@ static void remove_img(struct image_cache *self, struct image *img)
static void remove_img_free(struct image_cache *self, struct image *img) { - GP_DEBUG(2, "Freeing image '%s:%i' size %u", - img->path, img->cookie, + GP_DEBUG(2, "Freeing image '%s:%10li:%10li' size %u", + img->path, img->cookie1, img->cookie2, img->ctx->bytes_per_row * img->ctx->h); remove_img(self, img); @@ -137,21 +139,22 @@ static void add_img(struct image_cache *self, struct image *img) }
GP_Context *image_cache_get(struct image_cache *self, - const char *path, int cookie) + const char *path, long cookie1, long cookie2) { struct image *i;
- GP_DEBUG(2, "Looking for image '%s:%i'", path, cookie); + GP_DEBUG(2, "Looking for image '%s:%10li:%10li'", path, cookie1, cookie2);
for (i = self->root; i != NULL; i = i->next) - if (!strcmp(path, i->path) && i->cookie == cookie) + if (!strcmp(path, i->path) && + i->cookie1 == cookie1 && i->cookie2 == cookie2) break; if (i == NULL) return NULL;
/* Push the image to the root of the list */ - GP_DEBUG(2, "Refreshing image '%s:%i", path, cookie); + GP_DEBUG(2, "Refreshing image '%s:%10li:%10li", path, cookie1, cookie2); remove_img(self, i); add_img(self, i);
@@ -165,7 +168,7 @@ void image_cache_print(struct image_cache *self) printf("Image cache size %u used %un", self->max_size, self->cur_size);
for (i = self->root; i != NULL; i = i->next) - printf(" Image '%s:%i' size %un", i->path, i->cookie, + printf(" Image '%s:%10li:%10li' size %un", i->path, i->cookie1, i->cookie2, i->ctx->bytes_per_row * i->ctx->h); }
@@ -187,8 +190,8 @@ static int assert_size(struct image_cache *self, size_t size) return 0; }
-int image_cache_put(struct image_cache *self, - GP_Context *ctx, const char *path, int cookie) +int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, + long cookie1, long cookie2) { size_t size = ctx->bytes_per_row * ctx->h;
@@ -202,11 +205,12 @@ int image_cache_put(struct image_cache *self, return 1; } - GP_DEBUG(2, "Adding image '%s:%i' size %zu", - img->path, img->cookie, size); + GP_DEBUG(2, "Adding image '%s:%10li:%10li' size %zu", + img->path, img->cookie1, img->cookie2, size);
img->ctx = ctx; - img->cookie = cookie; + img->cookie1 = cookie1; + img->cookie2 = cookie2; strcpy(img->path, path);
add_img(self, img); diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h index ad3ecdd..fc008ed 100644 --- a/demos/spiv/image_cache.h +++ b/demos/spiv/image_cache.h @@ -43,13 +43,13 @@ struct image_cache *image_cache_create(unsigned int max_size); * Returns cached image, or NULL. */ GP_Context *image_cache_get(struct image_cache *self, - const char *path, int cookie); + const char *path, long cookie1, long cookie2);
/* * Puts an image into a cache. */ -int image_cache_put(struct image_cache *self, - GP_Context *img, const char *path, int cookie); +int image_cache_put(struct image_cache *self, GP_Context *img, + const char *path, long cookie1, long cookie2);
/* * Destroys image cache and all it's images. diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index c1ec6d2..93c066f 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -134,7 +134,7 @@ GP_Context *load_image(struct loader_params *params) GP_ProgressCallback callback = {.callback = image_loader_callback, .priv = "Loading image"};
- img = image_cache_get(params->image_cache, params->img_path, 0); + img = image_cache_get(params->image_cache, params->img_path, 0, 0);
/* Image not cached, load it */ if (img == NULL) { @@ -160,7 +160,7 @@ GP_Context *load_image(struct loader_params *params) img = tmp; } - image_cache_put(params->image_cache, img, params->img_path, 0); + image_cache_put(params->image_cache, img, params->img_path, 0, 0); cpu_timer_stop(&timer); } @@ -171,33 +171,33 @@ GP_Context *load_image(struct loader_params *params) GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size h, float rat) { long cookie = (w & 0xffff) | (h & 0xffff)<<16; - GP_Context *img; + GP_Context *img, *res = NULL; struct cpu_timer timer; GP_ProgressCallback callback = {.callback = image_loader_callback};
/* Try to get resized cached image */ - img = image_cache_get(params->image_cache, params->img_path, cookie); + img = image_cache_get(params->image_cache, params->img_path, cookie, resampling_method);
if (img != NULL) return img; /* Otherwise load image and resize it */ - img = load_image(params); - - if (img == NULL) + if ((img = load_image(params)) == NULL) return NULL;
/* Do low pass filter */ - if (resampling_method != GP_INTERP_LINEAR_LF_INT) { - if (rat < 1) { - cpu_timer_start(&timer, "Blur"); - callback.priv = "Blurring Image"; - //TODO: We can't blur saved image! - if (GP_FilterGaussianBlur(img, img, 0.4/rat, 0.4/rat, - &callback) == NULL) - return NULL; - cpu_timer_stop(&timer); - } + if (resampling_method != GP_INTERP_LINEAR_LF_INT && rat < 1) { + cpu_timer_start(&timer, "Blur"); + callback.priv = "Blurring Image"; + + res = GP_FilterGaussianBlur(img, NULL, 0.4/rat, 0.4/rat, &callback); + + if (res == NULL) + return NULL; + + img = res; + + cpu_timer_stop(&timer); }
cpu_timer_start(&timer, "Resampling"); @@ -205,11 +205,14 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size img = GP_FilterResize(img, NULL, resampling_method, w, h, &callback); cpu_timer_stop(&timer);
+ /* Free low passed context if needed */ + GP_ContextFree(res); + if (img == NULL) return NULL;
- image_cache_put(params->image_cache, img, params->img_path, cookie); - + image_cache_put(params->image_cache, img, params->img_path, cookie, resampling_method); + return img; }
@@ -270,6 +273,8 @@ static void *image_loader(void *ptr) if (img == NULL) return NULL;
+ image_cache_print(params->image_cache); + switch (rotate) { case 0: break;
http://repo.or.cz/w/gfxprim.git/commit/ea3d8a3b3ff7deca52c6320bcbc30f3115f5a...
commit ea3d8a3b3ff7deca52c6320bcbc30f3115f5aa32 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 18:59:27 2012 +0200
spiv: Cache resized images too, not optimal yet though.
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 26eb45b..c1ec6d2 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -168,6 +168,51 @@ GP_Context *load_image(struct loader_params *params) return img; }
+GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size h, float rat) +{ + long cookie = (w & 0xffff) | (h & 0xffff)<<16; + GP_Context *img; + struct cpu_timer timer; + GP_ProgressCallback callback = {.callback = image_loader_callback}; + + /* Try to get resized cached image */ + img = image_cache_get(params->image_cache, params->img_path, cookie); + + if (img != NULL) + return img; + + /* Otherwise load image and resize it */ + img = load_image(params); + + if (img == NULL) + return NULL; + + /* Do low pass filter */ + if (resampling_method != GP_INTERP_LINEAR_LF_INT) { + if (rat < 1) { + cpu_timer_start(&timer, "Blur"); + callback.priv = "Blurring Image"; + //TODO: We can't blur saved image! + if (GP_FilterGaussianBlur(img, img, 0.4/rat, 0.4/rat, + &callback) == NULL) + return NULL; + cpu_timer_stop(&timer); + } + } + + cpu_timer_start(&timer, "Resampling"); + callback.priv = "Resampling Image"; + img = GP_FilterResize(img, NULL, resampling_method, w, h, &callback); + cpu_timer_stop(&timer); + + if (img == NULL) + return NULL; + + image_cache_put(params->image_cache, img, params->img_path, cookie); + + return img; +} + /* * This function tries to resize spiv window * and if succedes blits the image directly to the screen. @@ -189,26 +234,12 @@ static int resize_backend_and_blit(struct loader_params *params) static void *image_loader(void *ptr) { struct loader_params *params = ptr; - struct cpu_timer timer; - struct cpu_timer sum_timer; + struct cpu_timer timer, sum_timer; GP_Context *img, *context = backend->context; GP_ProgressCallback callback = {.callback = image_loader_callback};
cpu_timer_start(&sum_timer, "sum");
- /* Load Image */ - img = load_image(params); - - if (img == NULL) - return NULL; - - /* - if (img->w < 320 && img->h < 240) { - if (!resize_backend_and_blit(img, params)) - return NULL; - } - */ - /* Figure out rotation */ GP_Size w, h;
@@ -226,32 +257,17 @@ static void *image_loader(void *ptr) break; }
+ if ((img = load_image(params)) == NULL) + return NULL; + float rat = calc_img_size(img->w, img->h, w, h);
w = img->w; h = img->h;
- GP_Context *ret; - - /* Do low pass filter */ - if (resampling_method != GP_INTERP_LINEAR_LF_INT) { - if (rat < 1) { - cpu_timer_start(&timer, "Blur"); - callback.priv = "Blurring Image"; - //TODO: We can't blur saved image! - if (GP_FilterGaussianBlur(img, img, 0.4/rat, 0.4/rat, - &callback) == NULL) - return NULL; - cpu_timer_stop(&timer); - } - } - - cpu_timer_start(&timer, "Resampling"); - callback.priv = "Resampling Image"; - ret = GP_FilterResize(img, NULL, resampling_method, img->w * rat, img->h * rat, &callback); - cpu_timer_stop(&timer); + img = load_resized_image(params, img->w * rat + 0.5, img->h * rat + 0.5, rat);
- if (ret == NULL) + if (img == NULL) return NULL;
switch (rotate) { @@ -259,28 +275,23 @@ static void *image_loader(void *ptr) break; case 90: callback.priv = "Rotating image (90)"; - img = GP_FilterRotate90_Alloc(ret, &callback); + img = GP_FilterRotate90_Alloc(img, &callback); break; case 180: callback.priv = "Rotating image (180)"; - img = GP_FilterRotate180_Alloc(ret, &callback); + img = GP_FilterRotate180_Alloc(img, &callback); break; case 270: callback.priv = "Rotating image (270)"; - img = GP_FilterRotate270_Alloc(ret, &callback); + img = GP_FilterRotate270_Alloc(img, &callback); break; } - - if (rotate) { - GP_ContextFree(ret); - ret = img; - } - + if (img == NULL) return NULL;
- uint32_t cx = (context->w - ret->w)/2; - uint32_t cy = (context->h - ret->h)/2; + uint32_t cx = (context->w - img->w)/2; + uint32_t cy = (context->h - img->h)/2;
GP_Context sub_display;
@@ -288,21 +299,23 @@ static void *image_loader(void *ptr) if (dithering) { callback.priv = "Dithering"; - GP_ContextSubContext(context, &sub_display, cx, cy, ret->w, ret->h); + GP_ContextSubContext(context, &sub_display, cx, cy, img->w, img->h); // GP_FilterFloydSteinberg_RGB888(ret, &sub_display, NULL); - GP_FilterHilbertPeano_RGB888(ret, &sub_display, NULL); + GP_FilterHilbertPeano_RGB888(img, &sub_display, NULL); } else { - GP_Blit_Raw(ret, 0, 0, ret->w, ret->h, context, cx, cy); + GP_Blit_Raw(img, 0, 0, img->w, img->h, context, cx, cy); } cpu_timer_stop(&timer); - GP_ContextFree(ret); + + if (rotate) + GP_ContextFree(img);
/* clean up the rest of the display */ GP_FillRectXYWH(context, 0, 0, cx, context->h, black_pixel); GP_FillRectXYWH(context, 0, 0, context->w, cy, black_pixel); - GP_FillRectXYWH(context, ret->w+cx, 0, context->w - ret->w - cx, context->h, black_pixel); - GP_FillRectXYWH(context, 0, ret->h+cy, context->w, context->h - ret->h - cy, black_pixel); + GP_FillRectXYWH(context, img->w + cx, 0, context->w - img->w - cx, context->h, black_pixel); + GP_FillRectXYWH(context, 0, img->h + cy, context->w, context->h - img->h - cy, black_pixel);
cpu_timer_stop(&sum_timer);
http://repo.or.cz/w/gfxprim.git/commit/f027b0f012e6ea1e694dd0618be0d9c18c840...
commit f027b0f012e6ea1e694dd0618be0d9c18c840dc5 Author: Cyril Hrubis metan@ucw.cz Date: Fri Jun 8 18:40:43 2012 +0200
spiv: Add image cache.
diff --git a/demos/spiv/Makefile b/demos/spiv/Makefile index 13b416c..431e6ce 100644 --- a/demos/spiv/Makefile +++ b/demos/spiv/Makefile @@ -9,7 +9,7 @@ LDLIBS+=-lGP -lGP_backends -lSDL -L$(TOPDIR)/build/
APPS=spiv
-spiv: cpu_timer.o +spiv: cpu_timer.o image_cache.o
include $(TOPDIR)/pre.mk include $(TOPDIR)/app.mk diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c new file mode 100644 index 0000000..f252013 --- /dev/null +++ b/demos/spiv/image_cache.c @@ -0,0 +1,224 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include <string.h> +#include <GP.h> +#include "image_cache.h" + +struct image { + GP_Context *ctx; + int cookie; + + struct image *prev; + struct image *next; + + char path[]; +}; + +struct image_cache { + unsigned int max_size; + unsigned int cur_size; + + struct image *root; + struct image *end; +}; + +static size_t read_total_memory(void) +{ + FILE *f; + size_t ret; + + f = fopen("/proc/meminfo", "r"); + + if (f == NULL) { + GP_WARN("Failed to read /proc/meminfo"); + return 0; + } + + if (fscanf(f, "MemTotal: %zu", &ret) != 1) { + fclose(f); + GP_WARN("Failed to read /proc/meminfo"); + return 0; + } + + fclose(f); + + return ret * 1024 / 10; +} + +struct image_cache *image_cache_create(unsigned int max_size) +{ + struct image_cache *self; + + self = malloc(sizeof(struct image_cache)); + + if (self == NULL) + return NULL; + + self->max_size = max_size ? max_size : read_total_memory(); + self->cur_size = 0; + + self->root = NULL; + self->end = NULL; + + GP_DEBUG(1, "Created image cache size %u bytes", self->max_size); + + return self; +} + +static void remove_img(struct image_cache *self, struct image *img) +{ + size_t size = img->ctx->bytes_per_row * img->ctx->h; + + if (img == self->end) + self->end = img->prev; + + if (img->prev) + img->prev->next = img->next; + + if (img->next) + img->next->prev = img->prev; + + if (img == self->root) + self->root = img->next; + + self->cur_size -= size; +} + +static void remove_img_free(struct image_cache *self, struct image *img) +{ + GP_DEBUG(2, "Freeing image '%s:%i' size %u", + img->path, img->cookie, + img->ctx->bytes_per_row * img->ctx->h); + + remove_img(self, img); + GP_ContextFree(img->ctx); + free(img); +} + +/* + * Adds image to the start of the double linked list + */ +static void add_img(struct image_cache *self, struct image *img) +{ + size_t size = img->ctx->bytes_per_row * img->ctx->h; + + img->next = self->root; + + if (img->next) + img->next->prev = img; + + img->prev = NULL; + + self->root = img; + self->cur_size += size; + + if (self->end == NULL) + self->end = img; +} + +GP_Context *image_cache_get(struct image_cache *self, + const char *path, int cookie) +{ + struct image *i; + + GP_DEBUG(2, "Looking for image '%s:%i'", path, cookie); + + for (i = self->root; i != NULL; i = i->next) + if (!strcmp(path, i->path) && i->cookie == cookie) + break; + + if (i == NULL) + return NULL; + + /* Push the image to the root of the list */ + GP_DEBUG(2, "Refreshing image '%s:%i", path, cookie); + remove_img(self, i); + add_img(self, i); + + return i->ctx; +} + +void image_cache_print(struct image_cache *self) +{ + struct image *i; + + printf("Image cache size %u used %un", self->max_size, self->cur_size); + + for (i = self->root; i != NULL; i = i->next) + printf(" Image '%s:%i' size %un", i->path, i->cookie, + i->ctx->bytes_per_row * i->ctx->h); +} + +static int assert_size(struct image_cache *self, size_t size) +{ + if (self->cur_size + size < self->max_size) + return 0; + + while (self->cur_size + size > self->max_size) { + + if (self->end == NULL) { + GP_WARN("Cache too small for image size %zu", size); + return 1; + } + + remove_img_free(self, self->end); + } + + return 0; +} + +int image_cache_put(struct image_cache *self, + GP_Context *ctx, const char *path, int cookie) +{ + size_t size = ctx->bytes_per_row * ctx->h; + + if (assert_size(self, size)) + return 1; + + struct image *img = malloc(sizeof(struct image) + strlen(path) + 1); + + if (img == NULL) { + GP_WARN("Malloc failed :("); + return 1; + } + + GP_DEBUG(2, "Adding image '%s:%i' size %zu", + img->path, img->cookie, size); + + img->ctx = ctx; + img->cookie = cookie; + strcpy(img->path, path); + + add_img(self, img); + return 0; +} + +void image_cache_destroy(struct image_cache *self) +{ + GP_DEBUG(1, "Destroying image cache"); + + while (self->end != NULL) + remove_img_free(self, self->end); + + free(self); +} diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h new file mode 100644 index 0000000..ad3ecdd --- /dev/null +++ b/demos/spiv/image_cache.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + Image loader chache. + + */ + +#ifndef __IMAGE_CACHE_H__ +#define __IMAGE_CACHE_H__ + +struct image_cache; + +/* + * Creates an image cache with maximal memory size. + * + * When memory size is set to zero, the size is read from /proc/meminfo + * as 10% of total memory. + */ +struct image_cache *image_cache_create(unsigned int max_size); + +/* + * Returns cached image, or NULL. + */ +GP_Context *image_cache_get(struct image_cache *self, + const char *path, int cookie); + +/* + * Puts an image into a cache. + */ +int image_cache_put(struct image_cache *self, + GP_Context *img, const char *path, int cookie); + +/* + * Destroys image cache and all it's images. + */ +void image_cache_destroy(struct image_cache *self); + +/* + * Print the image cache content. + */ +void image_cache_print(struct image_cache *self); + +#endif /* __IMAGE_CACHE_H__ */ diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 6e03531..26eb45b 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -36,6 +36,7 @@ #include <backends/GP_Backends.h> #include <input/GP_InputDriverLinux.h>
+#include "image_cache.h" #include "cpu_timer.h"
static GP_Pixel black_pixel; @@ -88,8 +89,8 @@ struct loader_params { int show_progress_once; int show_info;
- /* cached loaded image */ - GP_Context *img; + /* cached loaded images */ + struct image_cache *image_cache; };
static float calc_img_size(uint32_t img_w, uint32_t img_h, @@ -125,46 +126,46 @@ static void set_caption(const char *path, float rat) /* * Loads image */ -int load_image(struct loader_params *params) +GP_Context *load_image(struct loader_params *params) { struct cpu_timer timer; GP_Context *img, *context = backend->context; - - if (params->img != NULL) { - fprintf(stderr, "Image cached!n"); - return 0; - } GP_ProgressCallback callback = {.callback = image_loader_callback, .priv = "Loading image"}; - - show_progress = params->show_progress || params->show_progress_once; - params->show_progress_once = 0;
- fprintf(stderr, "Loading '%s'n", params->img_path); + img = image_cache_get(params->image_cache, params->img_path, 0);
- cpu_timer_start(&timer, "Loading"); - if ((img = GP_LoadImage(params->img_path, &callback)) == NULL) { - GP_Fill(context, black_pixel); - GP_Print(context, NULL, context->w/2, context->h/2, - GP_ALIGN_CENTER|GP_VALIGN_CENTER, white_pixel, black_pixel, - "Failed to load image :( (%s)", strerror(errno)); - GP_BackendFlip(backend); - return 1; - } + /* Image not cached, load it */ + if (img == NULL) { + show_progress = params->show_progress || params->show_progress_once; + params->show_progress_once = 0; + + fprintf(stderr, "Loading '%s'n", params->img_path); + + cpu_timer_start(&timer, "Loading"); + if ((img = GP_LoadImage(params->img_path, &callback)) == NULL) { + GP_Fill(context, black_pixel); + GP_Print(context, NULL, context->w/2, context->h/2, + GP_ALIGN_CENTER|GP_VALIGN_CENTER, white_pixel, black_pixel, + "Failed to load image :( (%s)", strerror(errno)); + GP_BackendFlip(backend); + return NULL; + } + + /* Workaround */ + if (img->pixel_type != GP_PIXEL_RGB888) { + GP_Context *tmp = GP_ContextConvert(img, GP_PIXEL_RGB888); + GP_ContextFree(img); + img = tmp; + } - /* Workaround */ - if (img->pixel_type != GP_PIXEL_RGB888) { - GP_Context *tmp = GP_ContextConvert(img, GP_PIXEL_RGB888); - GP_ContextFree(img); - img = tmp; + image_cache_put(params->image_cache, img, params->img_path, 0); + + cpu_timer_stop(&timer); } - - cpu_timer_stop(&timer); - - params->img = img;
- return 0; + return img; }
/* @@ -173,7 +174,7 @@ int load_image(struct loader_params *params) */ static int resize_backend_and_blit(struct loader_params *params) { - GP_Context *img = params->img; + GP_Context *img = load_image(params); if (GP_BackendResize(backend, img->w, img->h)) return 1; @@ -196,10 +197,10 @@ static void *image_loader(void *ptr) cpu_timer_start(&sum_timer, "sum");
/* Load Image */ - if (load_image(params)) - return NULL; + img = load_image(params);
- img = params->img; + if (img == NULL) + return NULL;
/* if (img->w < 320 && img->h < 240) { @@ -351,13 +352,8 @@ static void show_image(struct loader_params *params, const char *path) abort_flag = 0; } - /* invalidate cached image if path has changed */ - if (params->img_path == NULL || - (path != NULL && strcmp(params->img_path, path))) { - GP_ContextFree(params->img); - params->img = NULL; + if (path != NULL) params->img_path = path; - }
ret = pthread_create(&loader_thread, NULL, image_loader, (void*)params);
@@ -465,10 +461,12 @@ int main(int argc, char *argv[]) GP_Context *context = NULL; const char *backend_opts = "X11"; int sleep_sec = -1; - struct loader_params params = {NULL, 0, 0, 0, .img = NULL}; + struct loader_params params = {NULL, 0, 0, 0, NULL}; int opt, debug_level = 0; GP_PixelType emul_type = GP_PIXEL_UNKNOWN;
+ params.image_cache = image_cache_create(0); + while ((opt = getopt(argc, argv, "b:cd:e:fIPs:r:")) != -1) { switch (opt) { case 'I':
-----------------------------------------------------------------------
Summary of changes: demos/spiv/Makefile | 2 +- demos/spiv/image_cache.c | 261 ++++++++++++++++++++ .../loaders/GP_JPG.h => demos/spiv/image_cache.h | 49 ++-- demos/spiv/spiv.c | 196 ++++++++------- 4 files changed, 398 insertions(+), 110 deletions(-) create mode 100644 demos/spiv/image_cache.c copy include/loaders/GP_JPG.h => demos/spiv/image_cache.h (61%)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.