diff --git a/libretro-common/include/queues/task_queue.h b/libretro-common/include/queues/task_queue.h index 4b438acbb0..aedd8456c3 100644 --- a/libretro-common/include/queues/task_queue.h +++ b/libretro-common/include/queues/task_queue.h @@ -123,6 +123,10 @@ struct retro_task /* always called from the main loop */ retro_task_callback_t callback; + /* task cleanup handler to free allocated resources, will + * be called immediately after running the main callback */ + retro_task_handler_t cleanup; + /* set to true by the handler to signal * the task has finished executing. */ bool finished; diff --git a/libretro-common/queues/task_queue.c b/libretro-common/queues/task_queue.c index a52c7d6105..a21c0b9a69 100644 --- a/libretro-common/queues/task_queue.c +++ b/libretro-common/queues/task_queue.c @@ -126,6 +126,9 @@ static void retro_task_internal_gather(void) if (task->callback) task->callback(task->task_data, task->user_data, task->error); + if (task->cleanup) + task->cleanup(task); + if (task->error) free(task->error); diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 87f6c71758..8960720be4 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -728,48 +728,6 @@ static void xmb_update_thumbnail_path(void *data, unsigned i) #endif } -static void xmb_context_bg_destroy(xmb_handle_t *xmb) -{ - if (!xmb) - return; - video_driver_texture_unload(&xmb->textures.bg); - video_driver_texture_unload(&menu_display_white_texture); -} - -static bool xmb_load_image(void *userdata, void *data, enum menu_image_type type) -{ - xmb_handle_t *xmb = (xmb_handle_t*)userdata; - - if (!xmb || !data) - return false; - - switch (type) - { - case MENU_IMAGE_NONE: - break; - case MENU_IMAGE_WALLPAPER: - xmb_context_bg_destroy(xmb); - video_driver_texture_unload(&xmb->textures.bg); - video_driver_texture_load(data, - TEXTURE_FILTER_MIPMAP_LINEAR, - &xmb->textures.bg); - menu_display_allocate_white_texture(); - break; - case MENU_IMAGE_THUMBNAIL: - { - struct texture_image *img = (struct texture_image*)data; - xmb->thumbnail_height = xmb->thumbnail_width - * (float)img->height / (float)img->width; - video_driver_texture_unload(&xmb->thumbnail); - video_driver_texture_load(data, - TEXTURE_FILTER_MIPMAP_LINEAR, &xmb->thumbnail); - } - break; - } - - return true; -} - static void xmb_update_thumbnail_image(void *data) { xmb_handle_t *xmb = (xmb_handle_t*)data; @@ -777,12 +735,8 @@ static void xmb_update_thumbnail_image(void *data) return; if (path_file_exists(xmb->thumbnail_file_path)) - { - struct texture_image ti = {0}; - image_texture_load(&ti, xmb->thumbnail_file_path); - xmb_load_image(xmb, &ti, MENU_IMAGE_THUMBNAIL); - image_texture_free(&ti); - } + rarch_task_push_image_load(xmb->thumbnail_file_path, "cb_menu_thumbnail", + menu_display_handle_thumbnail_upload, NULL); else if (xmb->depth == 1) xmb->thumbnail = 0; } @@ -2662,6 +2616,48 @@ static void xmb_free(void *data) } +static void xmb_context_bg_destroy(xmb_handle_t *xmb) +{ + if (!xmb) + return; + video_driver_texture_unload(&xmb->textures.bg); + video_driver_texture_unload(&menu_display_white_texture); +} + +static bool xmb_load_image(void *userdata, void *data, enum menu_image_type type) +{ + xmb_handle_t *xmb = (xmb_handle_t*)userdata; + + if (!xmb || !data) + return false; + + switch (type) + { + case MENU_IMAGE_NONE: + break; + case MENU_IMAGE_WALLPAPER: + xmb_context_bg_destroy(xmb); + video_driver_texture_unload(&xmb->textures.bg); + video_driver_texture_load(data, + TEXTURE_FILTER_MIPMAP_LINEAR, + &xmb->textures.bg); + menu_display_allocate_white_texture(); + break; + case MENU_IMAGE_THUMBNAIL: + { + struct texture_image *img = (struct texture_image*)data; + xmb->thumbnail_height = xmb->thumbnail_width + * (float)img->height / (float)img->width; + video_driver_texture_unload(&xmb->thumbnail); + video_driver_texture_load(data, + TEXTURE_FILTER_MIPMAP_LINEAR, &xmb->thumbnail); + } + break; + } + + return true; +} + static const char *xmb_texture_path(unsigned id) { switch (id) diff --git a/tasks/task_file_transfer.c b/tasks/task_file_transfer.c index b3909a5325..a2acbfd52e 100644 --- a/tasks/task_file_transfer.c +++ b/tasks/task_file_transfer.c @@ -90,27 +90,17 @@ void rarch_task_file_load_handler(retro_task_t *task) case IMAGE_TYPE_TGA: case IMAGE_TYPE_BMP: if (!rarch_task_image_load_handler(task)) - goto task_finished; + task->finished = true; break; case 0: if (nbio->is_finished) - goto task_finished; + task->finished = true; break; } if (task->cancelled) { task->error = strdup("Task canceled."); - goto task_finished; + task->finished = true; } - - return; - -task_finished: - task->finished = true; - - nbio_free(nbio->handle); - nbio->handle = NULL; - nbio->is_finished = false; - free(nbio); } diff --git a/tasks/task_image.c b/tasks/task_image.c index fc340af8d6..a5877c2ca9 100644 --- a/tasks/task_image.c +++ b/tasks/task_image.c @@ -210,14 +210,14 @@ static void rarch_task_image_load_free_internal(nbio_handle_t *nbio) { nbio_image_handle_t *image = (nbio_image_handle_t*)nbio->data; - if (image) + if (image) { + image_transfer_free(image->handle, nbio->image_type); + + image->handle = NULL; + image->cb = NULL; + free(image); - - image_transfer_free(image->handle, nbio->image_type); - image_texture_free(&image->ti); - - image->handle = NULL; - image->cb = NULL; + } } static int cb_nbio_generic(nbio_handle_t *nbio, size_t *len) @@ -331,7 +331,7 @@ bool rarch_task_push_image_load(const char *fullpath, nbio_handle_t *nbio = NULL; retro_task_t *t = NULL; uint32_t cb_type_hash = djb2_calculate(type); - struct nbio_t *handle = nbio_open(fullpath, NBIO_READ); + struct nbio_t *handle = NULL; nbio_image_handle_t *image = NULL; switch (cb_type_hash) @@ -340,26 +340,30 @@ bool rarch_task_push_image_load(const char *fullpath, case CB_MENU_THUMBNAIL: break; default: - goto error; + goto error_msg; } - if (!handle) - goto error; + t = (retro_task_t*)calloc(1, sizeof(*t)); + if (!t) + goto error_msg; nbio = (nbio_handle_t*)calloc(1, sizeof(*nbio)); - if (!nbio) goto error; - image = (nbio_image_handle_t*)calloc(1, sizeof(*image)); - + handle = nbio_open(fullpath, NBIO_READ); + if (!handle) + goto error; + + nbio->handle = handle; + + image = (nbio_image_handle_t*)calloc(1, sizeof(*image)); if (!image) goto error; image->status = IMAGE_STATUS_TRANSFER; nbio->data = (nbio_image_handle_t*)image; - nbio->handle = handle; nbio->is_finished = false; nbio->cb = &cb_nbio_image_menu_thumbnail; nbio->status = NBIO_STATUS_TRANSFER; @@ -373,16 +377,11 @@ bool rarch_task_push_image_load(const char *fullpath, else if (strstr(fullpath, ".tga")) nbio->image_type = IMAGE_TYPE_TGA; - nbio_begin_read(handle); - t = (retro_task_t*)calloc(1, sizeof(*t)); - - if (!t) - goto error; - t->state = nbio; t->handler = rarch_task_file_load_handler; + t->cleanup = rarch_task_image_load_free; t->callback = cb; t->user_data = user_data; @@ -392,20 +391,23 @@ bool rarch_task_push_image_load(const char *fullpath, error: rarch_task_image_load_free(t); - nbio_free(handle); - if (nbio) - free(nbio); + free(t); +error_msg: RARCH_ERR("[image load] Failed to open '%s': %s.\n", fullpath, strerror(errno)); + return false; } void rarch_task_image_load_free(retro_task_t *task) { nbio_handle_t *nbio = task ? (nbio_handle_t*)task->state : NULL; - if (!nbio) - return; - rarch_task_image_load_free_internal(nbio); -} + if (nbio) { + rarch_task_image_load_free_internal(nbio); + nbio_free(nbio->handle); + nbio->handle = NULL; + free(nbio); + } +}