From ff297e72e78a99cad6218e0f4192353798011903 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Tue, 28 May 2019 12:55:31 +0100 Subject: [PATCH] (task_image) Make image loading/processing non-blocking on non-threaded systems --- libretro-common/formats/image_transfer.c | 3 -- libretro-common/formats/png/rpng.c | 16 ++++----- tasks/task_image.c | 45 ++++++++++++++---------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/libretro-common/formats/image_transfer.c b/libretro-common/formats/image_transfer.c index 4d5e58d6cc..c47a308818 100644 --- a/libretro-common/formats/image_transfer.c +++ b/libretro-common/formats/image_transfer.c @@ -217,9 +217,6 @@ int image_transfer_process( { case IMAGE_TYPE_PNG: #ifdef HAVE_RPNG - if (!rpng_is_valid((rpng_t*)data)) - return IMAGE_PROCESS_ERROR; - return rpng_process_image( (rpng_t*)data, (void**)buf, len, width, height); diff --git a/libretro-common/formats/png/rpng.c b/libretro-common/formats/png/rpng.c index 90f8c3fec9..da3bd7f82b 100644 --- a/libretro-common/formats/png/rpng.c +++ b/libretro-common/formats/png/rpng.c @@ -774,8 +774,7 @@ static int png_reverse_filter_iterate(rpng_t *rpng, uint32_t **data) return png_reverse_filter_regular_iterate(data, &rpng->ihdr, rpng->process); } -static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height) +static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, uint32_t **data) { bool zstatus; enum trans_stream_error terror; @@ -803,8 +802,6 @@ end: process->stream_backend->stream_free(process->stream); process->stream = NULL; - *width = rpng->ihdr.width; - *height = rpng->ihdr.height; #ifdef GEKKO /* we often use these in textures, make sure they're 32-byte aligned */ *data = (uint32_t*)memalign(32, rpng->ihdr.width * @@ -870,7 +867,7 @@ bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf) return true; } -static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, unsigned *height) +static struct rpng_process *rpng_process_init(rpng_t *rpng) { uint8_t *inflate_buf = NULL; struct rpng_process *process = (struct rpng_process*)calloc(1, sizeof(*process)); @@ -1114,8 +1111,7 @@ int rpng_process_image(rpng_t *rpng, if (!rpng->process) { - struct rpng_process *process = rpng_process_init( - rpng, width, height); + struct rpng_process *process = rpng_process_init(rpng); if (!process) goto error; @@ -1126,12 +1122,14 @@ int rpng_process_image(rpng_t *rpng, if (!rpng->process->inflate_initialized) { - if (rpng_load_image_argb_process_inflate_init(rpng, data, - width, height) == -1) + if (rpng_load_image_argb_process_inflate_init(rpng, data) == -1) goto error; return IMAGE_PROCESS_NEXT; } + *width = rpng->ihdr.width; + *height = rpng->ihdr.height; + return png_reverse_filter_iterate(rpng, data); error: diff --git a/tasks/task_image.c b/tasks/task_image.c index d3f46d96f1..cd190fdb22 100644 --- a/tasks/task_image.c +++ b/tasks/task_image.c @@ -23,13 +23,17 @@ #include #include #include +#include #include "task_file_transfer.h" #include "tasks_internal.h" +#include "../dynamic.h" + enum image_status_enum { - IMAGE_STATUS_TRANSFER = 0, + IMAGE_STATUS_WAIT = 0, + IMAGE_STATUS_TRANSFER, IMAGE_STATUS_TRANSFER_PARSE, IMAGE_STATUS_PROCESS_TRANSFER, IMAGE_STATUS_PROCESS_TRANSFER_PARSE @@ -43,8 +47,7 @@ struct nbio_image_handle bool is_blocking_on_processing; bool is_finished; int processing_final_state; - unsigned processing_pos_increment; - unsigned pos_increment; + unsigned frame_duration; size_t size; void *handle; transfer_cb_t cb; @@ -129,18 +132,19 @@ static int cb_image_thumbnail(void *data, size_t len) static int task_image_iterate_process_transfer(struct nbio_image_handle *image) { - unsigned i; int retval = 0; unsigned width = 0; unsigned height = 0; + retro_time_t start_time = cpu_features_get_time_usec(); - for (i = 0; i < image->processing_pos_increment; i++) + do { retval = task_image_process(image, &width, &height); if (retval != IMAGE_PROCESS_NEXT) break; } + while (cpu_features_get_time_usec() - start_time < image->frame_duration); if (retval == IMAGE_PROCESS_NEXT) return 0; @@ -185,13 +189,14 @@ static int cb_nbio_image_thumbnail(void *data, size_t len) { void *ptr = NULL; nbio_handle_t *nbio = (nbio_handle_t*)data; - struct nbio_image_handle *image = nbio ? - (struct nbio_image_handle*)nbio->data : NULL; - void *handle = image ? image_transfer_new(image->type) : NULL; + struct nbio_image_handle *image = nbio ? (struct nbio_image_handle*)nbio->data : NULL; + void *handle = image ? image_transfer_new(image->type) : NULL; + float refresh_rate; if (!handle) return -1; + image->status = IMAGE_STATUS_TRANSFER; image->handle = handle; image->size = len; image->cb = &cb_image_thumbnail; @@ -200,11 +205,11 @@ static int cb_nbio_image_thumbnail(void *data, size_t len) image_transfer_set_buffer_ptr(image->handle, image->type, ptr, len); - image->size = len; - image->pos_increment = (len / 2) ? - ((unsigned)(len / 2)) : 1; - image->processing_pos_increment = (len / 4) ? - ((unsigned)(len / 4)) : 1; + /* Set task iteration duration */ + rarch_environment_cb(RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE, &refresh_rate); + if (refresh_rate == 0.0f) + refresh_rate = 60.0f; + image->frame_duration = (unsigned)((1.0 / refresh_rate) * 1000000.0f); if (!image_transfer_start(image->handle, image->type)) { @@ -221,7 +226,6 @@ static int cb_nbio_image_thumbnail(void *data, size_t len) bool task_image_load_handler(retro_task_t *task) { - unsigned i; nbio_handle_t *nbio = (nbio_handle_t*)task->state; struct nbio_image_handle *image = (struct nbio_image_handle*)nbio->data; @@ -229,8 +233,10 @@ bool task_image_load_handler(retro_task_t *task) { switch (image->status) { + case IMAGE_STATUS_WAIT: + return true; case IMAGE_STATUS_PROCESS_TRANSFER: - if (image && task_image_iterate_process_transfer(image) == -1) + if (task_image_iterate_process_transfer(image) == -1) image->status = IMAGE_STATUS_PROCESS_TRANSFER_PARSE; break; case IMAGE_STATUS_TRANSFER_PARSE: @@ -246,7 +252,8 @@ bool task_image_load_handler(retro_task_t *task) case IMAGE_STATUS_TRANSFER: if (!image->is_blocking && !image->is_finished) { - for (i = 0; i < image->pos_increment; i++) + retro_time_t start_time = cpu_features_get_time_usec(); + do { if (!image_transfer_iterate(image->handle, image->type)) { @@ -254,6 +261,7 @@ bool task_image_load_handler(retro_task_t *task) break; } } + while (cpu_features_get_time_usec() - start_time < image->frame_duration); } break; case IMAGE_STATUS_PROCESS_TRANSFER_PARSE: @@ -333,13 +341,12 @@ bool task_push_image_load(const char *fullpath, nbio->path = strdup(fullpath); image->type = IMAGE_TYPE_NONE; - image->status = IMAGE_STATUS_TRANSFER; + image->status = IMAGE_STATUS_WAIT; image->is_blocking = false; image->is_blocking_on_processing = false; image->is_finished = false; image->processing_final_state = 0; - image->processing_pos_increment = 0; - image->pos_increment = 0; + image->frame_duration = 0; image->size = 0; image->handle = NULL;