From a483c9c6f1e6674eb2b5dcf01e21a7ab4c77e24f Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 8 Sep 2011 12:38:21 +0000 Subject: Use buflib for skin images. Allows much more images to be loaded git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30478 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_display.c | 20 +++++++---- apps/gui/skin_engine/skin_engine.h | 10 +----- apps/gui/skin_engine/skin_parser.c | 69 +++++++++++++++++++++++++++++------- apps/gui/skin_engine/wps_internals.h | 1 + 4 files changed, 73 insertions(+), 27 deletions(-) diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c index 49f9f86133..f7a0888afc 100644 --- a/apps/gui/skin_engine/skin_display.c +++ b/apps/gui/skin_engine/skin_display.c @@ -22,6 +22,7 @@ #include "config.h" #include #include "string-extra.h" +#include "core_alloc.h" #include "misc.h" #include "font.h" #include "system.h" @@ -247,15 +248,16 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) if (pb->backdrop) { struct gui_img *img = pb->backdrop; + char *img_data = core_get_data(img->buflib_handle); #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif - display->mono_bitmap_part(img->bm.data, + display->mono_bitmap_part(img_data, 0, 0, img->bm.width, x, y, width, height); #if LCD_DEPTH > 1 } else { - display->transparent_bitmap_part((fb_data *)img->bm.data, + display->transparent_bitmap_part((fb_data *)img_data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), @@ -268,9 +270,13 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) if (!pb->nobar) { if (pb->image) + { + char *img_data = core_get_data(pb->image->buflib_handle); + pb->image->bm.data = img_data; gui_bitmap_scrollbar_draw(display, &pb->image->bm, x, y, width, height, length, 0, end, flags); + } else gui_scrollbar_draw(display, x, y, width, height, length, 0, end, flags); @@ -281,6 +287,7 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) int xoff = 0, yoff = 0; int w = width, h = height; struct gui_img *img = pb->slider; + char *img_data = core_get_data(img->buflib_handle); if (flags&HORIZONTAL) { @@ -301,12 +308,12 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif - display->mono_bitmap_part(img->bm.data, + display->mono_bitmap_part(img_data, 0, 0, img->bm.width, x + xoff, y + yoff, w, h); #if LCD_DEPTH > 1 } else { - display->transparent_bitmap_part((fb_data *)img->bm.data, + display->transparent_bitmap_part((fb_data *)img_data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), @@ -350,6 +357,7 @@ void clear_image_pos(struct gui_wps *gwps, struct gui_img *img) void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage) { struct screen *display = gwps->display; + char *img_data = core_get_data(img->buflib_handle); if(img->always_display) display->set_drawmode(DRMODE_FG); else @@ -358,14 +366,14 @@ void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage) #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif - display->mono_bitmap_part(img->bm.data, + display->mono_bitmap_part(img_data, 0, img->subimage_height * subimage, img->bm.width, img->x, img->y, img->bm.width, img->subimage_height); #if LCD_DEPTH > 1 } else { - display->transparent_bitmap_part((fb_data *)img->bm.data, + display->transparent_bitmap_part((fb_data *)img_data, 0, img->subimage_height * subimage, STRIDE(display->screen_type, img->bm.width, img->bm.height), diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h index 52ec19d5f9..c8104f9304 100644 --- a/apps/gui/skin_engine/skin_engine.h +++ b/apps/gui/skin_engine/skin_engine.h @@ -43,16 +43,8 @@ enum skinnable_screens { #ifdef HAVE_LCD_BITMAP -#define MAIN_BUFFER (2*LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) -#if (NB_SCREENS > 1) -#define REMOTE_BUFFER (2*(LCD_REMOTE_HEIGHT*LCD_REMOTE_WIDTH*LCD_REMOTE_DEPTH/8)) -#else -#define REMOTE_BUFFER 0 -#endif - - -#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER + SKIN_FONT_SIZE) + \ +#define SKIN_BUFFER_SIZE (2048 + SKIN_FONT_SIZE) + \ (WPS_MAX_TOKENS * \ (sizeof(struct wps_token) + (sizeof(struct skin_element)))) #endif diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 373309ff51..a866101c1c 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -24,6 +24,7 @@ #include #include #include "config.h" +#include "core_alloc.h" #include "file.h" #include "misc.h" #include "plugin.h" @@ -364,6 +365,7 @@ static int parse_image_load(struct skin_element *element, img->always_display = false; img->display = -1; img->using_preloaded_icons = false; + img->buflib_handle = -1; /* save current viewport */ img->vp = &curr_vp->vp; @@ -885,6 +887,7 @@ static int parse_progressbar_tag(struct skin_element* element, img->always_display = false; img->display = -1; img->using_preloaded_icons = false; + img->buflib_handle = -1; img->vp = &curr_vp->vp; struct skin_token_list *item = (struct skin_token_list *)new_skin_token_list_item(NULL, img); @@ -1389,10 +1392,20 @@ static bool check_feature_tag(const int type) **/ static void skin_data_reset(struct wps_data *wps_data) { - wps_data->tree = NULL; #ifdef HAVE_LCD_BITMAP +#ifndef __PCTOOL__ + struct skin_token_list *list = wps_data->images; + while (list) + { + struct gui_img *img = (struct gui_img*)list->token->value.data; + if (img->buflib_handle > 0) + core_free(img->buflib_handle); + list = list->next; + } +#endif wps_data->images = NULL; #endif + wps_data->tree = NULL; #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 if (wps_data->backdrop_id >= 0) skin_backdrop_unload(wps_data->backdrop_id); @@ -1430,11 +1443,33 @@ static void skin_data_reset(struct wps_data *wps_data) } #ifdef HAVE_LCD_BITMAP -static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir) +#ifndef __PCTOOL__ +static int currently_loading_handle = -1; +static int buflib_move_callback(int handle, void* current, void* new) +{ + (void)current; + (void)new; + if (handle == currently_loading_handle) + return BUFLIB_CB_CANNOT_MOVE; + return BUFLIB_CB_OK; +} +static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL}; +static void lock_handle(int handle) +{ + currently_loading_handle = handle; +} +static void unlock_handle(void) +{ + currently_loading_handle = -1; +} +#endif + +static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir) { (void)wps_data; /* only needed for remote targets */ char img_path[MAX_PATH]; int fd; + int handle; get_image_filename(bitmap->data, bmpdir, img_path, sizeof(img_path)); @@ -1451,35 +1486,44 @@ static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char if (fd < 0) { DEBUGF("Couldn't open %s\n", img_path); - return false; + return fd; } +#ifndef __PCTOOL__ size_t buf_size = read_bmp_fd(fd, bitmap, 0, - format|FORMAT_RETURN_SIZE, NULL); - char* imgbuf = (char*)skin_buffer_alloc(buf_size); - if (!imgbuf) + format|FORMAT_RETURN_SIZE, NULL); + handle = core_alloc_ex(bitmap->data, buf_size, &buflib_ops); + if (handle < 0) { #ifndef APPLICATION DEBUGF("Not enough skin buffer: need %zd more.\n", buf_size - skin_buffer_freespace()); #endif close(fd); - return NULL; + return handle; } lseek(fd, 0, SEEK_SET); - bitmap->data = imgbuf; + lock_handle(handle); + bitmap->data = core_get_data(handle); int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL); - + bitmap->data = NULL; /* do this to force a crash later if the + caller doesnt call core_get_data() */ + unlock_handle(); close(fd); if (ret > 0) { - return true; + return handle; } else { /* Abort if we can't load an image */ DEBUGF("Couldn't load '%s'\n", img_path); - return false; + core_free(handle); + return -1; } +#else /* !__PCTOOL__ */ + close(fd); + return 1; +#endif } static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) @@ -1501,7 +1545,8 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) } else { - img->loaded = load_skin_bmp(wps_data, &img->bm, bmpdir); + img->buflib_handle = load_skin_bmp(wps_data, &img->bm, bmpdir); + img->loaded = img->buflib_handle >= 0; if (img->loaded) img->subimage_height = img->bm.height / img->num_subimages; else diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index 136ec2921a..e996c96613 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -77,6 +77,7 @@ struct gui_img { short int num_subimages; /* number of sub-images */ short int subimage_height; /* height of each sub-image */ struct bitmap bm; + int buflib_handle; const char *label; bool loaded; /* load state */ bool always_display; /* not using the preload/display mechanism */ -- cgit v1.2.3