diff options
Diffstat (limited to 'riscos/bitmap.c')
-rw-r--r-- | riscos/bitmap.c | 527 |
1 files changed, 2 insertions, 525 deletions
diff --git a/riscos/bitmap.c b/riscos/bitmap.c index 0f54003a9..60b0345d0 100644 --- a/riscos/bitmap.c +++ b/riscos/bitmap.c @@ -50,222 +50,9 @@ /** Colour in the overlay sprite that allows the bitmap to show through */ #define OVERLAY_INDEX 0xfe -#define MAINTENANCE_THRESHOLD 32 - /** Size of buffer used when constructing mask data to be saved */ #define SAVE_CHUNK_SIZE 4096 -/** The head of the bitmap list -*/ -struct bitmap *bitmap_head = NULL; - -/** Whether maintenance of the pool states is needed -*/ -bool bitmap_maintenance = false; - -/** Whether maintenance of the pool is high priority -*/ -bool bitmap_maintenance_priority = false; - -/** Maximum amount of memory for direct images -*/ -unsigned int bitmap_direct_size; - -/** Current amount of memory for direct images -*/ -unsigned int bitmap_direct_used = 0; - -/** Total size of compressed area -*/ -unsigned int bitmap_compressed_size; - -/** Total size of compressed area -*/ -unsigned int bitmap_compressed_used = 0; - -/** Compressed data header -*/ -struct bitmap_compressed_header { - int width; - int height; - char name[12]; - unsigned int flags; - unsigned int input_size; -}; - -char bitmap_unixname[256]; -char bitmap_filename[256]; - - - -static void bitmap_delete_file(struct bitmap *bitmap) -{ - assert(bitmap->filename[0]); - filename_release(bitmap->filename); - bitmap->filename[0] = 0; -} - - -static void bitmap_load_file(struct bitmap *bitmap) -{ - int len; - fileswitch_object_type obj_type; - os_error *error; - char *r; - struct bitmap_compressed_header *bitmap_compressed; - osspriteop_header *bitmap_direct; - int *data; - - assert(bitmap->filename); - - sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, - bitmap->filename); - r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, - bitmap_filename, 256, 0); - if (r == 0) { - LOG(("__riscosify failed")); - return; - } - error = xosfile_read_stamped_no_path(bitmap_filename, - &obj_type, 0, 0, &len, 0, 0); - if ((error) || (obj_type != fileswitch_IS_FILE)) - return; - - bitmap->compressed = malloc(len); - if (!bitmap->compressed) - return; - - error = xosfile_load_stamped_no_path(bitmap_filename, - (byte *) bitmap->compressed, 0, 0, 0, 0, 0); - if (error) { - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - - data = (void *) bitmap->compressed; - - LOG(("Loaded file from disk")); - /* Sanity check the file we've just loaded: - * If it's an uncompressed buffer, then it's a raw sprite area, - * including the total size word at the start. Therefore, we check - * that: - * a) The declared total area size == file length - * b) The offset to the first free word == file length - * c) There is only 1 sprite in the area - * d) The name of the sprite in the area is "bitmap" - * - * If it's a compressed buffer, then we check that: - * a) The declared input size + header size == file length - * b) The name of the buffer is "bitmap" - * - * If it's neither of these, we fail. - */ - if (*data == len && *(data + 3) == len && *(data + 1) == 1 && - strncmp(bitmap->compressed + 20, "bitmap", 6) == 0) { - bitmap->sprite_area = (void *) bitmap->compressed; - bitmap->compressed = NULL; - bitmap_direct = (osspriteop_header *)(bitmap->sprite_area + 1); - bitmap->width = bitmap_direct->width + 1; - bitmap->height = bitmap_direct->height + 1; - bitmap_direct_used += 16 + 44 + - bitmap->width * bitmap->height * 4; - } else if ((int) (*(data + 6) + - sizeof(struct bitmap_compressed_header)) == len && - strncmp(bitmap->compressed + 8, "bitmap", 6) == 0) { - bitmap_compressed = (void *) bitmap->compressed; - bitmap_compressed_used -= bitmap_compressed->input_size + - sizeof(struct bitmap_compressed_header); - bitmap->width = bitmap_compressed->width; - bitmap->height = bitmap_compressed->height; - } else { - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - if (bitmap->state & BITMAP_MODIFIED) - bitmap_delete_file(bitmap); -} - - -static void bitmap_save_file(struct bitmap *bitmap) -{ - unsigned int area_size; - const char *filename; - char *r; - os_error *error; - struct bitmap_compressed_header *header; - - assert(bitmap); - - if (!bitmap->compressed && !bitmap->sprite_area) { - LOG(("bitmap has no data")); - return; - } - - /* unmodified bitmaps will still have their file available */ - if ((!(bitmap->state & BITMAP_MODIFIED)) && bitmap->filename[0]) { - if (bitmap->sprite_area) - free(bitmap->sprite_area); - bitmap->sprite_area = NULL; - if (bitmap->compressed) - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - - /* dump the data (compressed or otherwise) to disk */ - filename = filename_request(); - if (!filename) { - LOG(("filename_request failed")); - return; - } - - strcpy(bitmap->filename, filename); - sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, - bitmap->filename); - r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, - bitmap_filename, 256, 0); - if (r == 0) { - LOG(("__riscosify failed")); - return; - } - if (bitmap->compressed) { - header = (void *) bitmap->compressed; - area_size = header->input_size + - sizeof(struct bitmap_compressed_header); - error = xosfile_save_stamped(bitmap_filename, 0xffd, - (byte *) bitmap->compressed, - (byte *) bitmap->compressed + area_size); - } else { - area_size = bitmap->width * bitmap->height * 4 + - sizeof(osspriteop_header) + - sizeof(osspriteop_area); - error = xosfile_save_stamped(bitmap_filename, 0xffd, - (byte *) bitmap->sprite_area, - ((byte *) bitmap->sprite_area) + area_size); - } - - if (error) { - LOG(("xosfile_save_stamped: 0x%x: %s", - error->errnum, error->errmess)); - bitmap->filename[0] = 0; - } else { - if (bitmap->sprite_area) { - bitmap_direct_used -= area_size; - free(bitmap->sprite_area); - } - bitmap->sprite_area = NULL; - if (bitmap->compressed) { - bitmap_compressed_used -= area_size; - free(bitmap->compressed); - } - bitmap->compressed = NULL; - bitmap->state &= ~BITMAP_MODIFIED; - LOG(("Saved file to disk")); - } -} - /** * Initialise a bitmaps sprite area. @@ -291,7 +78,6 @@ static bool bitmap_initialise(struct bitmap *bitmap) if (!bitmap->sprite_area) return false; bitmap->state |= BITMAP_READY; - bitmap_direct_used += area_size; /* area control block */ sprite_area = bitmap->sprite_area; @@ -312,177 +98,10 @@ static bool bitmap_initialise(struct bitmap *bitmap) sprite->image = sprite->mask = 44; sprite->mode = tinct_SPRITE_MODE; - bitmap_maintenance = true; - bitmap_maintenance_priority |= - (bitmap_direct_used > bitmap_direct_size * 0.9); return true; } -static void bitmap_decompress(struct bitmap *bitmap) -{ - unsigned int area_size; - _kernel_oserror *error; - int output_size; - struct bitmap_compressed_header *header; - - assert(bitmap->compressed); - - /* ensure the width/height is correct */ - header = (void *)bitmap->compressed; - if ((header->width != bitmap->width) || - (header->height != bitmap->height)) { - LOG(("Warning: Mismatch between bitmap and compressed sizes")); - return; - } - - /* create the image memory/header to decompress to */ - if (!bitmap_initialise(bitmap)) - return; - - /* decompress the data */ - output_size = bitmap->width * bitmap->height * 4 + - sizeof(struct osspriteop_header); - error = _swix(Tinct_Decompress, _IN(0) | _IN(2) | _IN(3) | _IN(7), - bitmap->compressed, - (char *)(bitmap->sprite_area + 1), - output_size, - 0); - if (error) { - LOG(("Decompression error")); - free(bitmap->sprite_area); - bitmap->sprite_area = NULL; - } else { - LOG(("Decompressed")); - area_size = header->input_size + - sizeof(struct bitmap_compressed_header); - bitmap_compressed_used -= area_size; - free(bitmap->compressed); - bitmap->compressed = NULL; - area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used += area_size; - } -} - - -static void bitmap_compress(struct bitmap *bitmap) -{ - unsigned int area_size; - _kernel_oserror *error; - char *output; - unsigned int output_size, new_size; - unsigned int flags = 0; - float calc; - - /* get the maximum output size (33/32 * size) */ - output_size = ((bitmap->width * bitmap->height * 4 * 33) >> 5) + - sizeof(struct bitmap_compressed_header); - output = malloc(output_size); - if (!output) - return; - - /* compress the data */ - 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), - output, - flags, - &new_size); - if (error) { - LOG(("Compression error")); - free(output); - } else { - bitmap->compressed = realloc(output, new_size); - if (!bitmap->compressed) { - free(output); - } else { - bitmap_compressed_used += new_size; - if (bitmap->sprite_area) { - area_size = 16 + 44 + bitmap->width * - bitmap->height * 4; - bitmap_direct_used -= area_size; - free(bitmap->sprite_area); - } - bitmap->sprite_area = NULL; - calc = (100 / (float)output_size) * new_size; - LOG(("Compression: %i->%i, %.3f%%", - output_size, new_size, calc)); - } - } -} - - -/** - * Initialise the bitmap memory pool. - */ - -void bitmap_initialise_memory(void) -{ - int available_memory, direct_size, compressed_size; - int free_slot; - os_error *error; - - /* calculate how much memory is currently free - (Note that the free_slot returned by wimp_slot_size - includes the next_slot; the value displayed by the - TaskManager has been adjusted to make it more logical - for the user). - */ - error = xwimp_slot_size(-1, -1, NULL, NULL, &free_slot); - if (error) { - LOG(("xwimp_slot_size: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - available_memory = free_slot; - - /* calculate our memory block sizes */ - if (nsoption_int(image_memory_direct) == -1) { - /* claim 25% of free memory - min 256KB, max 32768KB */ - direct_size = available_memory / 4; - if (direct_size < (256 << 10)) - direct_size = (256 << 10); - if (direct_size > (32768 << 10)) - direct_size = (32768 << 10); - } else { - direct_size = (nsoption_int(image_memory_direct) << 10); - } - if (nsoption_int(image_memory_compressed) == -1) { - /* claim 10% of free memory - min 256KB, max 4192KB */ - compressed_size = available_memory / 10; - if (compressed_size < (256 << 10)) - compressed_size = 0; - if (compressed_size > (4192 << 10)) - compressed_size = (4192 << 10); - } else { - compressed_size = (nsoption_int(image_memory_compressed) << 10); - } - - /* set our values. No fixed buffers here, ho hum. */ - bitmap_direct_size = direct_size; - bitmap_compressed_size = compressed_size; - bitmap_maintenance = bitmap_maintenance_priority = true; -} - - -/** - * Prepare for the end of a session. - */ - -void bitmap_quit(void) -{ - struct bitmap *bitmap; - - for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next) - if ((bitmap->state & BITMAP_PERSISTENT) && - ((bitmap->state & BITMAP_MODIFIED) || - (bitmap->filename[0] == '\0'))) - bitmap_save_file(bitmap); -} - - /** * Create a bitmap. * @@ -506,12 +125,6 @@ void *bitmap_create(int width, int height, unsigned int state) bitmap->height = height; bitmap->state = state; - /* link into our list of bitmaps at the head */ - if (bitmap_head) { - bitmap->next = bitmap_head; - bitmap_head->previous = bitmap; - } - bitmap_head = bitmap; return bitmap; } @@ -700,38 +313,13 @@ unsigned char *bitmap_get_buffer(void *vbitmap) struct bitmap *bitmap = (struct bitmap *) vbitmap; assert(bitmap); - /* move to the head of the list */ - if (bitmap_head != bitmap) { - if (bitmap->previous) - bitmap->previous->next = bitmap->next; - if (bitmap->next) - bitmap->next->previous = bitmap->previous; - bitmap->next = bitmap_head; - bitmap_head->previous = bitmap; - bitmap->previous = NULL; - bitmap_head = bitmap; - } - /* dynamically create the buffer */ if (!(bitmap->state & BITMAP_READY)) { if (!bitmap_initialise(bitmap)) return NULL; } - /* image is already decompressed, no change to image states */ - if (bitmap->sprite_area) - return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44; - - /* load and/or decompress the image */ - if (bitmap->filename[0]) - bitmap_load_file(bitmap); - if (bitmap->compressed) - bitmap_decompress(bitmap); - - bitmap_maintenance = true; - bitmap_maintenance_priority |= - (bitmap_direct_used > bitmap_direct_size * 0.9); - + /* image data area should exist */ if (bitmap->sprite_area) return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44; @@ -762,34 +350,14 @@ size_t bitmap_get_rowstride(void *vbitmap) void bitmap_destroy(void *vbitmap) { struct bitmap *bitmap = (struct bitmap *) vbitmap; - struct bitmap_compressed_header *header; - unsigned int area_size; assert(bitmap); - /* delink from list */ - bitmap_maintenance = true; - if (bitmap_head == bitmap) - bitmap_head = bitmap->next; - if (bitmap->previous) - bitmap->previous->next = bitmap->next; - if (bitmap->next) - bitmap->next->previous = bitmap->previous; - /* destroy bitmap */ if (bitmap->sprite_area) { - area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used -= area_size; free(bitmap->sprite_area); } - if (bitmap->compressed) { - header = (void *) bitmap->compressed; - bitmap_compressed_used -= header->input_size + - sizeof(struct bitmap_compressed_header); - free(bitmap->compressed); - } - if (bitmap->filename[0]) - bitmap_delete_file(bitmap); + free(bitmap); } @@ -978,97 +546,6 @@ void bitmap_modified(void *vbitmap) { } -/** - * Performs routine maintenance. - */ -void bitmap_maintain(void) -{ - unsigned int memory = 0; - unsigned int compressed_memory = 0; - struct bitmap *bitmap = bitmap_head; - struct bitmap_compressed_header *header; - unsigned int maintain_direct_size; - - LOG(("Performing maintenance.")); - - /* under heavy loads allow an extra 30% to work with */ - maintain_direct_size = bitmap_direct_size; - if (!bitmap_maintenance_priority) - maintain_direct_size = maintain_direct_size * 0.7; - - if ((!bitmap) || ((bitmap_direct_used < maintain_direct_size) && - (bitmap_compressed_used < bitmap_compressed_size))) { - bitmap_maintenance = bitmap_maintenance_priority; - bitmap_maintenance_priority = false; - return; - } - - /* we don't change the first bitmap_MEMORY entries as they - * will automatically be loaded/decompressed from whatever state - * they are in when neeeded. */ - for (; bitmap && (memory < maintain_direct_size); - bitmap = bitmap->next) { - if (bitmap->sprite_area) - memory += bitmap->width * bitmap->height * 4; - else if ((bitmap->compressed) && - (!bitmap_maintenance_priority)) { - header = (void *) bitmap->compressed; - compressed_memory += header->input_size + - sizeof(struct bitmap_compressed_header); - } - } - - if (!bitmap) { - bitmap_maintenance = bitmap_maintenance_priority; - bitmap_maintenance_priority = false; - return; - } - - /* under heavy loads, we ignore compression */ - if (!bitmap_maintenance_priority) { - /* for the next section, up until bitmap_COMPRESSED we - * forcibly compress the data if it's currently held directly - * in memory */ - for (; bitmap && (compressed_memory < bitmap_compressed_size); - bitmap = bitmap->next) { - if (bitmap->sprite_area) { - if ((bitmap->width * bitmap->height) <= - (512 * 512)) - bitmap_compress(bitmap); - else - bitmap_save_file(bitmap); - return; - } - if (bitmap->compressed) { - header = (void *) bitmap->compressed; - compressed_memory += header->input_size + - sizeof(struct bitmap_compressed_header); - } - } - if (!bitmap) { - bitmap_maintenance = false; - return; - } - } - - /* for the remaining entries we dump to disk */ - for (; bitmap; bitmap = bitmap->next) { - if ((bitmap->sprite_area) || (bitmap->compressed)) { - if (bitmap_maintenance_priority) { - if (bitmap->sprite_area) - bitmap_save_file(bitmap); - - } else { - bitmap_save_file(bitmap); - return; - } - } - } - bitmap_maintenance = bitmap_maintenance_priority; - bitmap_maintenance_priority = false; -} - - int bitmap_get_width(void *vbitmap) { struct bitmap *bitmap = (struct bitmap *) vbitmap; |