summaryrefslogtreecommitdiff
path: root/riscos
diff options
context:
space:
mode:
authorRichard Wilson <rjw@netsurf-browser.org>2006-02-22 01:58:19 +0000
committerRichard Wilson <rjw@netsurf-browser.org>2006-02-22 01:58:19 +0000
commit3d9a1198db571973e2760d6f27c771cbe31c844b (patch)
tree5a306a7fdf135f63fa1bd031924fb18edc5ecc2b /riscos
parent01cc7987c7af26c70269c81e9d344fd2e91a8793 (diff)
downloadnetsurf-3d9a1198db571973e2760d6f27c771cbe31c844b.tar.gz
netsurf-3d9a1198db571973e2760d6f27c771cbe31c844b.tar.bz2
[project @ 2006-02-22 01:58:19 by rjw]
Reduce constant bitmap overhead per reference by moving to a flag word. Allow bitmaps to be reduced back to their raw data to free extra memory in a highly efficient manner. svn path=/import/netsurf/; revision=2089
Diffstat (limited to 'riscos')
-rw-r--r--riscos/bitmap.c124
-rw-r--r--riscos/bitmap.h9
-rw-r--r--riscos/history.c4
-rw-r--r--riscos/plotters.c4
-rw-r--r--riscos/save.c9
-rw-r--r--riscos/thumbnail.c2
6 files changed, 86 insertions, 66 deletions
diff --git a/riscos/bitmap.c b/riscos/bitmap.c
index 505b27ee5..f9c66bb34 100644
--- a/riscos/bitmap.c
+++ b/riscos/bitmap.c
@@ -13,8 +13,6 @@
* sprites.
*/
-#define NDEBUG
-
#include <assert.h>
#include <stdbool.h>
#include <string.h>
@@ -61,6 +59,14 @@ unsigned int bitmap_compressed_size;
*/
unsigned int bitmap_compressed_used = 0;
+/** Total number of suspendable bitmaps
+*/
+unsigned int bitmap_suspendable = 0;
+
+/** Total number of suspended bitmaps
+*/
+unsigned int bitmap_suspended = 0;
+
/** Compressed data header
*/
struct bitmap_compressed_header {
@@ -145,7 +151,8 @@ void bitmap_quit(void)
struct bitmap *bitmap;
for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next)
- if ((bitmap->persistent) && ((bitmap->modified) ||
+ if ((bitmap->state & BITMAP_PERSISTENT) &&
+ ((bitmap->state & BITMAP_MODIFIED) ||
(bitmap->filename[0] == '\0')))
bitmap_save_file(bitmap);
}
@@ -160,7 +167,7 @@ void bitmap_quit(void)
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-struct bitmap *bitmap_create(int width, int height, bitmap_state state)
+struct bitmap *bitmap_create(int width, int height, unsigned int state)
{
struct bitmap *bitmap;
@@ -172,17 +179,7 @@ struct bitmap *bitmap_create(int width, int height, bitmap_state state)
return NULL;
bitmap->width = width;
bitmap->height = height;
- bitmap->opaque = false;
- switch (state) {
- case BITMAP_CLEAR_MEMORY:
- case BITMAP_ALLOCATE_MEMORY:
- bitmap->state = state;
- break;
- default:
- LOG(("Invalid bitmap state"));
- assert(false);
- return false;
- }
+ bitmap->state = state;
/* link into our list of bitmaps at the head */
if (bitmap_head) {
@@ -212,9 +209,7 @@ struct bitmap *bitmap_create_file(char *file)
bitmap = calloc(1, sizeof(struct bitmap));
if (!bitmap)
return NULL;
- bitmap->opaque = true;
- bitmap->persistent = true;
- bitmap->state = BITMAP_READY;
+ bitmap->state = BITMAP_OPAQUE | BITMAP_PERSISTENT | BITMAP_READY;
strcpy(bitmap->filename, file);
/* link in at the head */
@@ -243,21 +238,14 @@ bool bitmap_initialise(struct bitmap *bitmap)
assert(!bitmap->sprite_area);
area_size = 16 + 44 + bitmap->width * bitmap->height * 4;
- switch (bitmap->state) {
- case BITMAP_CLEAR_MEMORY:
- bitmap->sprite_area = calloc(1, area_size);
- break;
- case BITMAP_ALLOCATE_MEMORY:
- bitmap->sprite_area = malloc(area_size);
- break;
- default:
- LOG(("Invalid bitmap state"));
- assert(false);
- return false;
- }
+ if (bitmap->state & BITMAP_CLEAR_MEMORY)
+ bitmap->sprite_area = calloc(1, area_size);
+ else
+ bitmap->sprite_area = malloc(area_size);
+
if (!bitmap->sprite_area)
return false;
- bitmap->state = BITMAP_READY;
+ bitmap->state |= BITMAP_READY;
bitmap_direct_used += area_size;
/* area control block */
@@ -295,7 +283,11 @@ bool bitmap_initialise(struct bitmap *bitmap)
void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
{
assert(bitmap);
- bitmap->opaque = opaque;
+
+ if (opaque)
+ bitmap->state |= BITMAP_OPAQUE;
+ else
+ bitmap->state &= ~BITMAP_OPAQUE;
}
@@ -345,7 +337,7 @@ bool bitmap_test_opaque(struct bitmap *bitmap)
bool bitmap_get_opaque(struct bitmap *bitmap)
{
assert(bitmap);
- return (bitmap->opaque);
+ return (bitmap->state & BITMAP_OPAQUE);
}
@@ -374,18 +366,17 @@ char *bitmap_get_buffer(struct bitmap *bitmap)
bitmap->previous = NULL;
bitmap_head = bitmap;
}
-
+
/* dynamically create the buffer */
- switch (bitmap->state) {
- case BITMAP_ALLOCATE_MEMORY:
- case BITMAP_CLEAR_MEMORY:
- if (!bitmap_initialise(bitmap))
- return NULL;
- break;
- default:
- break;
+ if (!(bitmap->state & BITMAP_READY)) {
+ if (!bitmap_initialise(bitmap))
+ return NULL;
}
+ /* reset our suspended flag */
+ if (bitmap->state & BITMAP_SUSPENDED)
+ bitmap->state &= ~BITMAP_SUSPENDED;
+
/* image is already decompressed, no change to image states */
if (bitmap->sprite_area)
return ((char *) (bitmap->sprite_area)) + 16 + 44;
@@ -493,17 +484,33 @@ bool bitmap_save(struct bitmap *bitmap, const char *path)
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_modified(struct bitmap *bitmap) {
- bitmap->modified = true;
+ bitmap->state |= BITMAP_MODIFIED;
}
/**
+ * The bitmap image can be suspended.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param private_word a private word to be returned later
+ * \param invalidate the function to be called upon suspension
+ */
+void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
+ void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
+ bitmap->private_word = private_word;
+ bitmap->invalidate = invalidate;
+ bitmap_suspendable++;
+}
+
+
+/**
* Performs routine maintenance.
*/
void bitmap_maintain(void)
{
unsigned int memory = 0;
unsigned int compressed_memory = 0;
+ unsigned int suspended = 0;
struct bitmap *bitmap = bitmap_head;
struct bitmap_compressed_header *header;
unsigned int maintain_direct_size;
@@ -535,7 +542,8 @@ void bitmap_maintain(void)
bitmap->compressed;
compressed_memory += header->input_size +
sizeof(struct bitmap_compressed_header);
- }
+ } else if (bitmap->state & BITMAP_SUSPENDED)
+ suspended++;
}
if (!bitmap) {
@@ -543,6 +551,25 @@ void bitmap_maintain(void)
bitmap_maintenance_priority = false;
return;
}
+
+ /* the fastest and easiest way to release memory is by suspending
+ * images. as such, we try to do this first for as many images as
+ * possible, potentially freeing up large amounts of memory */
+ if (suspended <= (bitmap_suspendable - bitmap_suspended)) {
+ for (; bitmap; bitmap = bitmap->next) {
+ if (bitmap->invalidate) {
+ bitmap->invalidate(bitmap, bitmap->private_word);
+ free(bitmap->sprite_area);
+ bitmap->sprite_area = NULL;
+ bitmap->state |= BITMAP_SUSPENDED;
+ bitmap->state &= ~BITMAP_READY;
+ bitmap_direct_used -= 16 + 44 +
+ bitmap->width * bitmap->height * 4;
+ bitmap_suspended++;
+ }
+ }
+ return;
+ }
/* under heavy loads, we ignore compression */
if (!bitmap_maintenance_priority) {
@@ -608,7 +635,6 @@ void bitmap_decompress(struct bitmap *bitmap)
}
/* create the image memory/header to decompress to */
- bitmap->state = BITMAP_ALLOCATE_MEMORY;
if (!bitmap_initialise(bitmap))
return;
@@ -654,7 +680,7 @@ void bitmap_compress(struct bitmap *bitmap)
return;
/* compress the data */
- if (bitmap->opaque)
+ if (bitmap->state & BITMAP_OPAQUE)
flags |= tinct_OPAQUE_IMAGE;
error = _swix(Tinct_Compress, _IN(0) | _IN(2) | _IN(7) | _OUT(0),
(char *)(bitmap->sprite_area + 1),
@@ -754,7 +780,7 @@ void bitmap_load_file(struct bitmap *bitmap)
bitmap->compressed = NULL;
return;
}
- if (bitmap->modified)
+ if (bitmap->state & BITMAP_MODIFIED)
bitmap_delete_file(bitmap);
}
@@ -769,7 +795,7 @@ void bitmap_save_file(struct bitmap *bitmap)
assert(bitmap->compressed || bitmap->sprite_area);
/* unmodified bitmaps will still have their file available */
- if (!bitmap->modified && bitmap->filename[0]) {
+ if ((!(bitmap->state & BITMAP_MODIFIED)) && bitmap->filename[0]) {
if (bitmap->sprite_area)
free(bitmap->sprite_area);
bitmap->sprite_area = NULL;
@@ -814,7 +840,7 @@ void bitmap_save_file(struct bitmap *bitmap)
free(bitmap->compressed);
}
bitmap->compressed = NULL;
- bitmap->modified = false;
+ bitmap->state &= ~BITMAP_MODIFIED;
LOG(("Saved file to disk"));
}
}
diff --git a/riscos/bitmap.h b/riscos/bitmap.h
index 910c201bb..a113d9b1b 100644
--- a/riscos/bitmap.h
+++ b/riscos/bitmap.h
@@ -16,10 +16,11 @@ struct osspriteop_area;
struct bitmap {
int width;
int height;
- bool opaque;
- bool modified;
- bool persistent;
- bitmap_state state;
+
+ unsigned int state;
+
+ void *private_word;
+ void (*invalidate)(struct bitmap *bitmap, void *private_word);
osspriteop_area *sprite_area; /** Uncompressed data, or NULL */
char *compressed; /** Compressed data, or NULL */
diff --git a/riscos/history.c b/riscos/history.c
index 46ef458bf..8b9beaa12 100644
--- a/riscos/history.c
+++ b/riscos/history.c
@@ -179,12 +179,12 @@ void history_add(struct history *history, struct content *content, char *frag_id
bitmap = url_store_get_thumbnail(url);
if (!bitmap) {
bitmap = bitmap_create(WIDTH / 2, HEIGHT / 2,
- BITMAP_ALLOCATE_MEMORY);
+ BITMAP_NEW | BITMAP_CLEAR_MEMORY |
+ BITMAP_OPAQUE | BITMAP_PERSISTENT);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
return;
}
- bitmap_set_opaque(bitmap, true);
thumbnail_create(content, bitmap, url);
}
entry->bitmap = bitmap;
diff --git a/riscos/plotters.c b/riscos/plotters.c
index d59883075..dcce28c38 100644
--- a/riscos/plotters.c
+++ b/riscos/plotters.c
@@ -326,7 +326,7 @@ bool ro_plot_bitmap(int x, int y, int width, int height,
bitmap->height,
bg,
false, false, false,
- bitmap->opaque ? IMAGE_PLOT_TINCT_OPAQUE :
+ bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
IMAGE_PLOT_TINCT_ALPHA);
}
@@ -344,7 +344,7 @@ bool ro_plot_bitmap_tile(int x, int y, int width, int height,
bitmap->height,
bg,
repeat_x, repeat_y, true,
- bitmap->opaque ? IMAGE_PLOT_TINCT_OPAQUE :
+ bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
IMAGE_PLOT_TINCT_ALPHA);
}
diff --git a/riscos/save.c b/riscos/save.c
index 7792e6ccc..e288150a6 100644
--- a/riscos/save.c
+++ b/riscos/save.c
@@ -801,12 +801,8 @@ void ro_gui_save_object_native(struct content *c, char *path)
bitmap_save(c->bitmap, path);
break;
#endif
-#ifdef WITH_PNG
- case CONTENT_PNG:
-/* error = xosspriteop_save_sprite_file(osspriteop_USER_AREA, c->data.png.sprite_area, path);
- break;*/
-#endif
#ifdef WITH_MNG
+ case CONTENT_PNG:
case CONTENT_JNG:
case CONTENT_MNG:
bitmap_save(c->bitmap, path);
@@ -1007,12 +1003,11 @@ bool ro_gui_save_create_thumbnail(struct content *c, const char *name)
struct bitmap *bitmap;
osspriteop_area *area;
- bitmap = bitmap_create(34, 34, BITMAP_CLEAR_MEMORY);
+ bitmap = bitmap_create(34, 34, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
return false;
}
- bitmap_set_opaque(bitmap, true);
thumbnail_create(c, bitmap, NULL);
area = thumbnail_convert_8bpp(bitmap);
bitmap_destroy(bitmap);
diff --git a/riscos/thumbnail.c b/riscos/thumbnail.c
index e1231cd2d..8c5351cac 100644
--- a/riscos/thumbnail.c
+++ b/riscos/thumbnail.c
@@ -139,9 +139,7 @@ bool thumbnail_create(struct content *content, struct bitmap *bitmap,
/* register the thumbnail with the URL */
if (url)
url_store_add_thumbnail(url, bitmap);
-
bitmap_modified(bitmap);
- bitmap->persistent = true;
return true;
}