From a0d2bb4c7cb3a47d8f40f15a98b2691be4e2c188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Mon, 23 Nov 2015 14:15:19 -0300 Subject: [PATCH] Reimplement overlay loading with tasks --- command_event.c | 6 +- input/input_overlay.c | 847 ++---------------------------------------- input/input_overlay.h | 109 +++++- runloop_data.c | 150 +------- tasks/task_overlay.c | 735 ++++++++++++++++++++++++++++++++++-- tasks/tasks.c | 6 +- tasks/tasks.h | 3 +- 7 files changed, 851 insertions(+), 1005 deletions(-) diff --git a/command_event.c b/command_event.c index dc2f9b32ee..db67b3c680 100644 --- a/command_event.c +++ b/command_event.c @@ -1338,14 +1338,14 @@ bool event_command(enum event_command cmd) break; case EVENT_CMD_OVERLAY_DEINIT: #ifdef HAVE_OVERLAY - input_overlay_free_ptr(); + input_overlay_free(); #endif break; case EVENT_CMD_OVERLAY_INIT: event_command(EVENT_CMD_OVERLAY_DEINIT); #ifdef HAVE_OVERLAY - if (input_overlay_new_ptr() == -1) - RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_OVERLAY)); + input_overlay_init(); + //RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_OVERLAY)); #endif break; case EVENT_CMD_OVERLAY_NEXT: diff --git a/input/input_overlay.c b/input/input_overlay.c index b2c5581f04..0040a2d492 100644 --- a/input/input_overlay.c +++ b/input/input_overlay.c @@ -33,95 +33,9 @@ #include "../configuration.h" #include "../verbosity.h" +#include "../tasks/tasks.h" #include "input_common.h" -#define BOX_RADIAL 0x18df06d2U -#define BOX_RECT 0x7c9d4d93U - -#define KEY_ANALOG_LEFT 0x56b92e81U -#define KEY_ANALOG_RIGHT 0x2e4dc654U - -struct overlay -{ - struct overlay_desc *descs; - size_t size; - size_t pos; - unsigned pos_increment; - - struct texture_image image; - - bool block_scale; - float mod_x, mod_y, mod_w, mod_h; - float x, y, w, h; - float scale; - float center_x, center_y; - - bool full_screen; - - char name[64]; - - struct - { - struct - { - char key[64]; - char path[PATH_MAX_LENGTH]; - } paths; - - struct - { - char key[64]; - } names; - - struct - { - char array[256]; - char key[64]; - } rect; - - struct - { - char key[64]; - unsigned size; - } descs; - - bool normalized; - float alpha_mod; - float range_mod; - } config; - - struct texture_image *load_images; - unsigned load_images_size; -}; - -struct overlay_desc -{ - float x; - float y; - - enum overlay_hitbox hitbox; - float range_x, range_y; - float range_x_mod, range_y_mod; - float mod_x, mod_y, mod_w, mod_h; - float delta_x, delta_y; - - enum overlay_type type; - uint64_t key_mask; - float analog_saturate_pct; - - unsigned next_index; - char next_index_name[64]; - - struct texture_image image; - unsigned image_index; - - float alpha_mod; - float range_mod; - - bool updated; - bool movable; -}; - struct input_overlay { void *iface_data; @@ -321,313 +235,6 @@ static void input_overlay_free_overlays(void) ol->overlays = NULL; } -static bool input_overlay_load_texture_image(struct overlay *overlay, - struct texture_image *image, const char *path) -{ - if (!image) - return false; - if (!texture_image_load(image, path)) - return false; - - overlay->load_images[overlay->load_images_size++] = *image; - - return true; -} - -static bool input_overlay_load_desc_image( - struct overlay_desc *desc, - struct overlay *input_overlay, - unsigned ol_idx, unsigned desc_idx) -{ - char overlay_desc_image_key[64] = {0}; - char image_path[PATH_MAX_LENGTH] = {0}; - input_overlay_t *ol = overlay_ptr; - config_file_t *conf = ol ? config_file_new(ol->overlay_path) : NULL; - - if (!ol || !conf) - return false; - - snprintf(overlay_desc_image_key, sizeof(overlay_desc_image_key), - "overlay%u_desc%u_overlay", ol_idx, desc_idx); - - if (config_get_path(conf, overlay_desc_image_key, - image_path, sizeof(image_path))) - { - char path[PATH_MAX_LENGTH] = {0}; - fill_pathname_resolve_relative(path, ol->overlay_path, - image_path, sizeof(path)); - - if (input_overlay_load_texture_image(input_overlay, &desc->image, path)) - desc->image_index = input_overlay->load_images_size - 1; - } - - input_overlay->pos ++; - - config_file_free(conf); - - return true; -} - -static bool input_overlay_load_desc( - struct overlay_desc *desc, - struct overlay *input_overlay, - unsigned ol_idx, unsigned desc_idx, - unsigned width, unsigned height, - bool normalized, float alpha_mod, float range_mod) -{ - float width_mod, height_mod; - uint32_t box_hash, key_hash; - bool ret = true; - bool by_pixel = false; - char overlay_desc_key[64] = {0}; - char conf_key[64] = {0}; - char overlay_desc_normalized_key[64] = {0}; - char overlay[256] = {0}; - char *save = NULL; - char *key = NULL; - struct string_list *list = NULL; - const char *x = NULL; - const char *y = NULL; - const char *box = NULL; - input_overlay_t *ol = overlay_ptr; - config_file_t *conf = ol ? config_file_new(ol->overlay_path) : NULL; - - if (!ol || !conf) - return false; - - snprintf(overlay_desc_key, sizeof(overlay_desc_key), - "overlay%u_desc%u", ol_idx, desc_idx); - - snprintf(overlay_desc_normalized_key, sizeof(overlay_desc_normalized_key), - "overlay%u_desc%u_normalized", ol_idx, desc_idx); - config_get_bool(conf, overlay_desc_normalized_key, &normalized); - - by_pixel = !normalized; - - if (by_pixel && (width == 0 || height == 0)) - { - RARCH_ERR("[Overlay]: Base overlay is not set and not using normalized coordinates.\n"); - goto error; - } - - if (!config_get_array(conf, overlay_desc_key, overlay, sizeof(overlay))) - { - RARCH_ERR("[Overlay]: Didn't find key: %s.\n", overlay_desc_key); - goto error; - } - - list = string_split(overlay, ", "); - - if (!list) - { - RARCH_ERR("[Overlay]: Failed to split overlay desc.\n"); - goto error; - } - - if (list->size < 6) - { - RARCH_ERR("[Overlay]: Overlay desc is invalid. Requires at least 6 tokens.\n"); - goto error; - } - - key = list->elems[0].data; - x = list->elems[1].data; - y = list->elems[2].data; - box = list->elems[3].data; - - box_hash = djb2_calculate(box); - key_hash = djb2_calculate(key); - - desc->key_mask = 0; - - switch (key_hash) - { - case KEY_ANALOG_LEFT: - desc->type = OVERLAY_TYPE_ANALOG_LEFT; - break; - case KEY_ANALOG_RIGHT: - desc->type = OVERLAY_TYPE_ANALOG_RIGHT; - break; - default: - if (strstr(key, "retrok_") == key) - { - desc->type = OVERLAY_TYPE_KEYBOARD; - desc->key_mask = input_translate_str_to_rk(key + 7); - } - else - { - const char *tmp = NULL; - - desc->type = OVERLAY_TYPE_BUTTONS; - for (tmp = strtok_r(key, "|", &save); tmp; tmp = strtok_r(NULL, "|", &save)) - { - if (strcmp(tmp, "nul") != 0) - desc->key_mask |= UINT64_C(1) << input_translate_str_to_bind_id(tmp); - } - - if (desc->key_mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) - { - char overlay_target_key[64] = {0}; - - snprintf(overlay_target_key, sizeof(overlay_target_key), - "overlay%u_desc%u_next_target", ol_idx, desc_idx); - config_get_array(conf, overlay_target_key, - desc->next_index_name, sizeof(desc->next_index_name)); - } - } - break; - } - - width_mod = 1.0f; - height_mod = 1.0f; - - if (by_pixel) - { - width_mod /= width; - height_mod /= height; - } - - desc->x = (float)strtod(x, NULL) * width_mod; - desc->y = (float)strtod(y, NULL) * height_mod; - - switch (box_hash) - { - case BOX_RADIAL: - desc->hitbox = OVERLAY_HITBOX_RADIAL; - break; - case BOX_RECT: - desc->hitbox = OVERLAY_HITBOX_RECT; - break; - default: - RARCH_ERR("[Overlay]: Hitbox type (%s) is invalid. Use \"radial\" or \"rect\".\n", box); - ret = false; - goto end; - } - - switch (desc->type) - { - case OVERLAY_TYPE_ANALOG_LEFT: - case OVERLAY_TYPE_ANALOG_RIGHT: - { - char overlay_analog_saturate_key[64] = {0}; - - if (desc->hitbox != OVERLAY_HITBOX_RADIAL) - { - RARCH_ERR("[Overlay]: Analog hitbox type must be \"radial\".\n"); - ret = false; - goto end; - } - - snprintf(overlay_analog_saturate_key, sizeof(overlay_analog_saturate_key), - "overlay%u_desc%u_saturate_pct", ol_idx, desc_idx); - if (!config_get_float(conf, overlay_analog_saturate_key, - &desc->analog_saturate_pct)) - desc->analog_saturate_pct = 1.0f; - } - break; - default: - /* OVERLAY_TYPE_BUTTONS - unhandled */ - /* OVERLAY_TYPE_KEYBOARD - unhandled */ - break; - } - - desc->range_x = (float)strtod(list->elems[4].data, NULL) * width_mod; - desc->range_y = (float)strtod(list->elems[5].data, NULL) * height_mod; - - desc->mod_x = desc->x - desc->range_x; - desc->mod_w = 2.0f * desc->range_x; - desc->mod_y = desc->y - desc->range_y; - desc->mod_h = 2.0f * desc->range_y; - - snprintf(conf_key, sizeof(conf_key), - "overlay%u_desc%u_alpha_mod", ol_idx, desc_idx); - desc->alpha_mod = alpha_mod; - config_get_float(conf, conf_key, &desc->alpha_mod); - - snprintf(conf_key, sizeof(conf_key), - "overlay%u_desc%u_range_mod", ol_idx, desc_idx); - desc->range_mod = range_mod; - config_get_float(conf, conf_key, &desc->range_mod); - - snprintf(conf_key, sizeof(conf_key), - "overlay%u_desc%u_movable", ol_idx, desc_idx); - desc->movable = false; - desc->delta_x = 0.0f; - desc->delta_y = 0.0f; - config_get_bool(conf, conf_key, &desc->movable); - - desc->range_x_mod = desc->range_x; - desc->range_y_mod = desc->range_y; - - input_overlay->pos ++; - -end: - if (list) - string_list_free(list); - if (conf) - config_file_free(conf); - return ret; - -error: - if (list) - string_list_free(list); - if (conf) - config_file_free(conf); - return false; -} - -static ssize_t input_overlay_find_index(const struct overlay *ol, - const char *name, size_t size) -{ - size_t i; - - if (!ol) - return -1; - - for (i = 0; i < size; i++) - { - if (!strcmp(ol[i].name, name)) - return i; - } - - return -1; -} - -static bool input_overlay_resolve_targets(struct overlay *ol, - size_t idx, size_t size) -{ - size_t i; - struct overlay *current = NULL; - - if (!ol) - return false; - - current = (struct overlay*)&ol[idx]; - - for (i = 0; i < current->size; i++) - { - const char *next = current->descs[i].next_index_name; - - if (*next) - { - ssize_t next_idx = input_overlay_find_index(ol, next, size); - - if (next_idx < 0) - { - RARCH_ERR("[Overlay]: Couldn't find overlay called: \"%s\".\n", - next); - return false; - } - - current->descs[i].next_index = next_idx; - } - else - current->descs[i].next_index = (idx + 1) % size; - } - - return true; -} - static void input_overlay_load_active(float opacity) { input_overlay_t *ol = overlay_ptr; @@ -662,310 +269,6 @@ static void input_overlay_enable(bool enable) ol->iface->enable(ol->iface_data, enable); } -bool input_overlay_load_overlays_resolve_iterate(void) -{ - input_overlay_t *ol = overlay_ptr; - bool not_done = true; - - if (!ol) - return false; - - not_done = ol->resolve_pos < ol->size; - - if (!not_done) - { - ol->state = OVERLAY_STATUS_DEFERRED_DONE; - return true; - } - - if (!input_overlay_resolve_targets(ol->overlays, ol->resolve_pos, ol->size)) - { - RARCH_ERR("[Overlay]: Failed to resolve next targets.\n"); - goto error; - } - - if (ol->resolve_pos == 0) - { - ol->active = &ol->overlays[0]; - - input_overlay_load_active(ol->deferred.opacity); - input_overlay_enable(ol->deferred.enable); - } - - ol->resolve_pos += 1; - - return true; -error: - ol->state = OVERLAY_STATUS_DEFERRED_ERROR; - - return false; -} - - -static bool input_overlay_load_overlay_image_done(struct overlay *overlay) -{ - overlay->pos = 0; - /* Divide iteration steps by half of total descs if size is even, - * otherwise default to 8 (arbitrary value for now to speed things up). */ - overlay->pos_increment = (overlay->size / 2) ? (overlay->size / 2) : 8; - -#if 0 - RARCH_LOG("pos increment: %u\n", overlay->pos_increment); -#endif - - return true; -} - -bool input_overlay_load_overlays_iterate(void) -{ - size_t i = 0; - bool not_done = true; - struct overlay *overlay = NULL; - input_overlay_t *ol = overlay_ptr; - - if (!ol) - return false; - - overlay = &ol->overlays[ol->pos]; - - not_done = ol->pos < ol->size; - - if (!not_done) - { - ol->state = OVERLAY_STATUS_DEFERRED_LOADING_RESOLVE; - return true; - } - - switch (ol->loading_status) - { - case OVERLAY_IMAGE_TRANSFER_NONE: - case OVERLAY_IMAGE_TRANSFER_BUSY: - ol->loading_status = OVERLAY_IMAGE_TRANSFER_DONE; - break; - case OVERLAY_IMAGE_TRANSFER_DONE: - input_overlay_load_overlay_image_done(&ol->overlays[ol->pos]); - ol->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_IMAGE_ITERATE; - ol->overlays[ol->pos].pos = 0; - break; - case OVERLAY_IMAGE_TRANSFER_DESC_IMAGE_ITERATE: - for (i = 0; i < overlay->pos_increment; i++) - { - if (overlay->pos < overlay->size) - { - input_overlay_load_desc_image( - &overlay->descs[overlay->pos], overlay, - ol->pos, overlay->pos); - } - else - { - overlay->pos = 0; - ol->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_ITERATE; - break; - } - - } - break; - case OVERLAY_IMAGE_TRANSFER_DESC_ITERATE: - for (i = 0; i < overlay->pos_increment; i++) - { - if (overlay->pos < overlay->size) - { - if (!input_overlay_load_desc(&overlay->descs[overlay->pos], overlay, - ol->pos, overlay->pos, - overlay->image.width, overlay->image.height, - overlay->config.normalized, - overlay->config.alpha_mod, overlay->config.range_mod)) - { - RARCH_ERR("[Overlay]: Failed to load overlay descs for overlay #%u.\n", - (unsigned)overlay->pos); - goto error; - } - - } - else - { - overlay->pos = 0; - ol->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_DONE; - break; - } - - } - break; - case OVERLAY_IMAGE_TRANSFER_DESC_DONE: - if (ol->pos == 0) - input_overlay_load_overlays_resolve_iterate(); - ol->pos += 1; - ol->loading_status = OVERLAY_IMAGE_TRANSFER_NONE; - break; - case OVERLAY_IMAGE_TRANSFER_ERROR: - goto error; - } - - return true; - -error: - ol->state = OVERLAY_STATUS_DEFERRED_ERROR; - - return false; -} - - -bool input_overlay_load_overlays(void) -{ - unsigned i; - input_overlay_t *ol = overlay_ptr; - config_file_t *conf = config_file_new(ol->overlay_path); - - if (!ol || !conf) - return false; - - for (i = 0; i < ol->pos_increment; i++, ol->pos++) - { - char conf_key[64] = {0}; - char overlay_full_screen_key[64] = {0}; - struct overlay *overlay = NULL; - bool to_cont = ol->pos < ol->size; - - if (!to_cont) - { - ol->pos = 0; - ol->state = OVERLAY_STATUS_DEFERRED_LOADING; - break; - } - - overlay = &ol->overlays[ol->pos]; - - if (!overlay) - continue; - - snprintf(overlay->config.descs.key, - sizeof(overlay->config.descs.key), "overlay%u_descs", ol->pos); - - if (!config_get_uint(conf, overlay->config.descs.key, &overlay->config.descs.size)) - { - RARCH_ERR("[Overlay]: Failed to read number of descs from config key: %s.\n", - overlay->config.descs.key); - goto error; - } - - overlay->descs = (struct overlay_desc*) - calloc(overlay->config.descs.size, sizeof(*overlay->descs)); - - if (!overlay->descs) - { - RARCH_ERR("[Overlay]: Failed to allocate descs.\n"); - goto error; - } - - overlay->size = overlay->config.descs.size; - - snprintf(overlay_full_screen_key, sizeof(overlay_full_screen_key), - "overlay%u_full_screen", ol->pos); - overlay->full_screen = false; - config_get_bool(conf, overlay_full_screen_key, &overlay->full_screen); - - overlay->config.normalized = false; - overlay->config.alpha_mod = 1.0f; - overlay->config.range_mod = 1.0f; - - snprintf(conf_key, sizeof(conf_key), - "overlay%u_normalized", ol->pos); - config_get_bool(conf, conf_key, &overlay->config.normalized); - - snprintf(conf_key, sizeof(conf_key), "overlay%u_alpha_mod", ol->pos); - config_get_float(conf, conf_key, &overlay->config.alpha_mod); - - snprintf(conf_key, sizeof(conf_key), "overlay%u_range_mod", ol->pos); - config_get_float(conf, conf_key, &overlay->config.range_mod); - - /* Precache load image array for simplicity. */ - overlay->load_images = (struct texture_image*) - calloc(1 + overlay->size, sizeof(struct texture_image)); - - if (!overlay->load_images) - { - RARCH_ERR("[Overlay]: Failed to allocate load_images.\n"); - goto error; - } - - snprintf(overlay->config.paths.key, sizeof(overlay->config.paths.key), - "overlay%u_overlay", ol->pos); - - config_get_path(conf, overlay->config.paths.key, - overlay->config.paths.path, sizeof(overlay->config.paths.path)); - - if (overlay->config.paths.path[0] != '\0') - { - char overlay_resolved_path[PATH_MAX_LENGTH] = {0}; - - fill_pathname_resolve_relative(overlay_resolved_path, ol->overlay_path, - overlay->config.paths.path, sizeof(overlay_resolved_path)); - - if (!input_overlay_load_texture_image(overlay, &overlay->image, overlay_resolved_path)) - { - RARCH_ERR("[Overlay]: Failed to load image: %s.\n", - overlay_resolved_path); - ol->loading_status = OVERLAY_IMAGE_TRANSFER_ERROR; - goto error; - } - - } - - snprintf(overlay->config.names.key, sizeof(overlay->config.names.key), - "overlay%u_name", ol->pos); - config_get_array(conf, overlay->config.names.key, - overlay->name, sizeof(overlay->name)); - - /* By default, we stretch the overlay out in full. */ - overlay->x = overlay->y = 0.0f; - overlay->w = overlay->h = 1.0f; - - snprintf(overlay->config.rect.key, sizeof(overlay->config.rect.key), - "overlay%u_rect", ol->pos); - - if (config_get_array(conf, overlay->config.rect.key, - overlay->config.rect.array, sizeof(overlay->config.rect.array))) - { - struct string_list *list = string_split(overlay->config.rect.array, ", "); - - if (!list || list->size < 4) - { - RARCH_ERR("[Overlay]: Failed to split rect \"%s\" into at least four tokens.\n", - overlay->config.rect.array); - string_list_free(list); - goto error; - } - - overlay->x = (float)strtod(list->elems[0].data, NULL); - overlay->y = (float)strtod(list->elems[1].data, NULL); - overlay->w = (float)strtod(list->elems[2].data, NULL); - overlay->h = (float)strtod(list->elems[3].data, NULL); - string_list_free(list); - } - - /* Assume for now that scaling center is in the middle. - * TODO: Make this configurable. */ - overlay->block_scale = false; - overlay->center_x = overlay->x + 0.5f * overlay->w; - overlay->center_y = overlay->y + 0.5f * overlay->h; - } - - if (conf) - config_file_free(conf); - - return true; - -error: - ol->pos = 0; - ol->state = OVERLAY_STATUS_DEFERRED_ERROR; - - if (conf) - config_file_free(conf); - - return false; -} - - bool input_overlay_new_done(void) { input_overlay_t *ol = overlay_ptr; @@ -982,96 +285,6 @@ bool input_overlay_new_done(void) return true; } -static bool input_overlay_load_overlays_init(input_overlay_t *ol) -{ - config_file_t *conf = config_file_new(ol->overlay_path); - - if (!conf) - return false; - - if (!config_get_uint(conf, "overlays", &ol->config.overlays.size)) - { - RARCH_ERR("overlays variable not defined in config.\n"); - goto error; - } - - if (!ol->config.overlays.size) - goto error; - - ol->overlays = (struct overlay*)calloc( - ol->config.overlays.size, sizeof(*ol->overlays)); - if (!ol->overlays) - goto error; - - ol->size = ol->config.overlays.size; - ol->pos = 0; - ol->resolve_pos = 0; - ol->pos_increment = (ol->size / 4) ? (ol->size / 4) : 4; - - config_file_free(conf); - - return true; - -error: - ol->state = OVERLAY_STATUS_DEFERRED_ERROR; - - if (conf) - config_file_free(conf); - - return false; -} - -/** - * input_overlay_new: - * @path : Path to overlay file. - * @enable : Enable the overlay after initializing it? - * - * Creates and initializes an overlay handle. - * - * Returns: Overlay handle on success, otherwise NULL. - **/ -input_overlay_t *input_overlay_new(const char *path, bool enable, - float opacity, float scale_factor) -{ - input_overlay_t *ol = (input_overlay_t*)calloc(1, sizeof(*ol)); - - if (!ol) - goto error; - - ol->overlay_path = strdup(path); - if (!ol->overlay_path) - { - free(ol); - return NULL; - } - - if (!video_driver_overlay_interface(&ol->iface)) - { - RARCH_ERR("Overlay interface is not present in video driver.\n"); - goto error; - } - - ol->iface_data = video_driver_get_ptr(true); - - if (!ol->iface) - goto error; - - ol->state = OVERLAY_STATUS_DEFERRED_LOAD; - ol->deferred.enable = enable; - ol->deferred.opacity = opacity; - ol->deferred.scale_factor = scale_factor; - ol->pos = 0; - - input_overlay_load_overlays_init(ol); - - return ol; - -error: - input_overlay_free(); - return NULL; -} - - /** * inside_hitbox: * @desc : Overlay descriptor handle. @@ -1367,44 +580,46 @@ void input_overlay_free(void) free(ol->overlay_path); ol->overlay_path = NULL; free(ol); -} - -void input_overlay_free_ptr(void) -{ - input_overlay_free(); overlay_ptr = NULL; - - memset(&overlay_st_ptr, 0, sizeof(overlay_st_ptr)); } -int input_overlay_new_ptr(void) +/* task_data = overlay_array_t* */ +static void input_overlay_loaded(void *task_data, void *user_data, const char *err) { - driver_t *driver = driver_get_ptr(); - settings_t *settings = config_get_ptr(); + overlay_task_data_t *data = (overlay_task_data_t*)task_data; + settings_t *settings = config_get_ptr(); + input_overlay_t *ol = (input_overlay_t*)calloc(1, sizeof(*ol)); + ol->overlays = data->overlays; + ol->size = data->size; + ol->active = data->active; - if (driver->osk_enable) + if (!video_driver_overlay_interface(&ol->iface)) { - if (!*settings->osk.overlay) - return 1; - } - else - { - if (!*settings->input.overlay) - return 1; + RARCH_ERR("Overlay interface is not present in video driver.\n"); + goto error; } - overlay_ptr = input_overlay_new( - driver->osk_enable ? - settings->osk.overlay : settings->input.overlay, - driver->osk_enable ? - settings->osk.enable : settings->input.overlay_enable, - settings->input.overlay_opacity, - settings->input.overlay_scale); + ol->iface_data = video_driver_get_ptr(true); - if (!overlay_ptr) - return -1; + if (!ol->iface) + goto error; - return 0; + overlay_ptr = ol; + + input_overlay_load_active(settings->input.overlay_opacity); + input_overlay_enable(settings->input.overlay_scale); + + + RARCH_LOG("%u overlays loaded.\n", (unsigned)data->size); + + return; +error: + input_overlay_free(); +} + +void input_overlay_init(void) +{ + rarch_task_push_overlay_load_default(input_overlay_loaded, NULL); } /** diff --git a/input/input_overlay.h b/input/input_overlay.h index ce616a8acb..5df92aec44 100644 --- a/input/input_overlay.h +++ b/input/input_overlay.h @@ -21,12 +21,19 @@ #include #include +#include #include "../libretro.h" #ifdef __cplusplus extern "C" { #endif +#define BOX_RADIAL 0x18df06d2U +#define BOX_RECT 0x7c9d4d93U + +#define KEY_ANALOG_LEFT 0x56b92e81U +#define KEY_ANALOG_RIGHT 0x2e4dc654U + #define OVERLAY_GET_KEY(state, key) (((state)->keys[(key) / 32] >> ((key) % 32)) & 1) #define OVERLAY_SET_KEY(state, key) (state)->keys[(key) / 32] |= 1 << ((key) % 32) #define OVERLAY_CLEAR_KEY(state, key) (state)->keys[(key) / 32] &= ~(1 << ((key) % 32)) @@ -91,10 +98,99 @@ enum overlay_image_transfer_status OVERLAY_IMAGE_TRANSFER_ERROR }; + +struct overlay +{ + struct overlay_desc *descs; + size_t size; + size_t pos; + unsigned pos_increment; + + struct texture_image image; + + bool block_scale; + float mod_x, mod_y, mod_w, mod_h; + float x, y, w, h; + float scale; + float center_x, center_y; + + bool full_screen; + + char name[64]; + + struct + { + struct + { + char key[64]; + char path[PATH_MAX_LENGTH]; + } paths; + + struct + { + char key[64]; + } names; + + struct + { + char array[256]; + char key[64]; + } rect; + + struct + { + char key[64]; + unsigned size; + } descs; + + bool normalized; + float alpha_mod; + float range_mod; + } config; + + struct texture_image *load_images; + unsigned load_images_size; +}; + +struct overlay_desc +{ + float x; + float y; + + enum overlay_hitbox hitbox; + float range_x, range_y; + float range_x_mod, range_y_mod; + float mod_x, mod_y, mod_w, mod_h; + float delta_x, delta_y; + + enum overlay_type type; + uint64_t key_mask; + float analog_saturate_pct; + + unsigned next_index; + char next_index_name[64]; + + struct texture_image image; + unsigned image_index; + + float alpha_mod; + float range_mod; + + bool updated; + bool movable; +}; + typedef struct overlay_desc overlay_desc_t; typedef struct input_overlay input_overlay_t; +typedef struct +{ + struct overlay *overlays; + struct overlay *active; + size_t size; +} overlay_task_data_t; + /** * input_overlay_new: * @path : Path to overlay file. @@ -122,6 +218,13 @@ bool input_overlay_new_done(void); **/ void input_overlay_free(void); + +/** + * input_overlay_init + * + * Initializes the overlay system. + */ +void input_overlay_init(void); /** * input_overlay_set_alpha_mod: * @mod : New modulating factor to apply. @@ -147,12 +250,6 @@ void input_overlay_set_scale_factor(float scale); **/ void input_overlay_next(float opacity); -bool input_overlay_data_is_active(void); - -void input_overlay_free_ptr(void); - -int input_overlay_new_ptr(void); - enum overlay_status input_overlay_status(void); /* diff --git a/runloop_data.c b/runloop_data.c index 4a9e537091..fd73fab6d5 100644 --- a/runloop_data.c +++ b/runloop_data.c @@ -23,61 +23,23 @@ #include "verbosity.h" #include "tasks/tasks.h" -#include "input/input_overlay.h" #ifdef HAVE_MENU #include "menu/menu.h" #endif +#undef HAVE_THREADS typedef struct data_runloop { bool inited; - -#ifdef HAVE_THREADS - bool thread_sleeping; - bool thread_inited; - bool alive; - - slock_t *lock; - slock_t *cond_lock; - scond_t *cond; - sthread_t *thread; -#endif } data_runloop_t; static char data_runloop_msg[PATH_MAX_LENGTH]; static data_runloop_t g_data_runloop; -#ifdef HAVE_THREADS -static void data_runloop_thread_deinit(void) -{ - if (!g_data_runloop.thread_inited) - { - slock_lock(g_data_runloop.cond_lock); - g_data_runloop.alive = false; - scond_signal(g_data_runloop.cond); - slock_unlock(g_data_runloop.cond_lock); - sthread_join(g_data_runloop.thread); - - slock_free(g_data_runloop.lock); - slock_free(g_data_runloop.cond_lock); - scond_free(g_data_runloop.cond); - } -} -#endif - void rarch_main_data_deinit(void) { -#ifdef HAVE_THREADS - if (g_data_runloop.thread_inited) - { - data_runloop_thread_deinit(); - - g_data_runloop.thread_inited = false; - } -#endif - g_data_runloop.inited = false; rarch_task_deinit(); @@ -88,86 +50,11 @@ void rarch_main_data_free(void) memset(&g_data_runloop, 0, sizeof(g_data_runloop)); } -static void data_runloop_iterate(bool is_thread) -{ -} - - bool rarch_main_data_active(void) { -#ifdef HAVE_OVERLAY - if (input_overlay_data_is_active()) - return true; -#endif - return false; } -#ifdef HAVE_THREADS -static void data_thread_loop(void *data) -{ - data_runloop_t *runloop = (data_runloop_t*)data; - - RARCH_LOG("[Data Thread]: Initializing data thread.\n"); - - slock_lock(runloop->lock); - while (!runloop->thread_inited) - scond_wait(runloop->cond, runloop->lock); - slock_unlock(runloop->lock); - - RARCH_LOG("[Data Thread]: Starting data thread.\n"); - - while (runloop->alive) - { - slock_lock(runloop->lock); - - if (!runloop->alive) - break; - - data_runloop_iterate(true); - - if (!rarch_main_data_active()) - { - runloop->thread_sleeping = true; - while(runloop->thread_sleeping) - scond_wait(runloop->cond, runloop->lock); - } - - slock_unlock(runloop->lock); - - } - - RARCH_LOG("[Data Thread]: Stopping data thread.\n"); -} -#endif - -#ifdef HAVE_THREADS -static void rarch_main_data_thread_init(void) -{ - if (g_data_runloop.thread_inited) - return; - - g_data_runloop.lock = slock_new(); - g_data_runloop.cond_lock = slock_new(); - g_data_runloop.cond = scond_new(); - - g_data_runloop.thread = sthread_create(data_thread_loop, &g_data_runloop); - - if (!g_data_runloop.thread) - goto error; - - slock_lock(g_data_runloop.lock); - g_data_runloop.thread_inited = true; - g_data_runloop.alive = true; - slock_unlock(g_data_runloop.lock); - - return; - -error: - data_runloop_thread_deinit(); -} -#endif - #ifdef HAVE_MENU static void rarch_main_data_menu_iterate(void) { @@ -177,28 +64,6 @@ static void rarch_main_data_menu_iterate(void) void rarch_main_data_iterate(void) { - settings_t *settings = config_get_ptr(); - - (void)settings; -#ifdef HAVE_THREADS - if (settings->threaded_data_runloop_enable) - { - if (!g_data_runloop.thread_inited) - rarch_main_data_thread_init(); - else if (g_data_runloop.thread_sleeping) - { - slock_lock(g_data_runloop.cond_lock); - g_data_runloop.thread_sleeping = false; - scond_signal(g_data_runloop.cond); - slock_unlock(g_data_runloop.cond_lock); - } - } -#endif - -#ifdef HAVE_OVERLAY - rarch_main_data_overlay_iterate(); -#endif - #ifdef HAVE_MENU rarch_main_data_menu_iterate(); #endif @@ -210,22 +75,10 @@ void rarch_main_data_iterate(void) } rarch_task_check(); - -#ifdef HAVE_THREADS - if (settings->threaded_data_runloop_enable && g_data_runloop.alive) - return; -#endif - - data_runloop_iterate(false); } static void rarch_main_data_init(void) { -#ifdef HAVE_THREADS - g_data_runloop.thread_inited = false; - g_data_runloop.alive = false; -#endif - g_data_runloop.inited = true; rarch_task_init(); @@ -268,7 +121,6 @@ void rarch_main_data_msg_queue_push(unsigned type, #endif #ifdef HAVE_OVERLAY case DATA_TYPE_OVERLAY: - fill_pathname_join_delim(new_msg, msg, msg2, '|', sizeof(new_msg)); break; #endif case DATA_TYPE_DB: diff --git a/tasks/task_overlay.c b/tasks/task_overlay.c index a664ae63fa..e567187d7c 100644 --- a/tasks/task_overlay.c +++ b/tasks/task_overlay.c @@ -13,35 +13,716 @@ * If not, see . */ +#include #include - +#include +#include +#include +#include #include "tasks.h" -#include "../input/input_overlay.h" -void rarch_main_data_overlay_iterate(void) +#include "../input/input_common.h" +#include "../input/input_overlay.h" +#include "../configuration.h" +#include "../verbosity.h" + +typedef struct { + enum overlay_status state; + enum overlay_image_transfer_status loading_status; + config_file_t *conf; + char *overlay_path; + unsigned size; + unsigned pos; + unsigned pos_increment; + struct overlay *overlays; + struct overlay *active; + size_t resolve_pos; + +} overlay_loader_t; + +static void rarch_task_overlay_resolve_iterate(overlay_loader_t *loader); + +static void rarch_task_overlay_image_done(struct overlay *overlay) { - while (input_overlay_status() != OVERLAY_STATUS_NONE) - { - switch (input_overlay_status()) - { - case OVERLAY_STATUS_DEFERRED_LOADING: - input_overlay_load_overlays_iterate(); - break; - case OVERLAY_STATUS_DEFERRED_LOAD: - input_overlay_load_overlays(); - break; - case OVERLAY_STATUS_DEFERRED_LOADING_RESOLVE: - input_overlay_load_overlays_resolve_iterate(); - break; - case OVERLAY_STATUS_DEFERRED_DONE: - input_overlay_new_done(); - break; - case OVERLAY_STATUS_DEFERRED_ERROR: - input_overlay_free(); - break; - default: - case OVERLAY_STATUS_NONE: - break; - } - } + overlay->pos = 0; + /* Divide iteration steps by half of total descs if size is even, + * otherwise default to 8 (arbitrary value for now to speed things up). */ + overlay->pos_increment = (overlay->size / 2) ? (overlay->size / 2) : 8; +} + +static bool rarch_task_overlay_load_texture_image(struct overlay *overlay, + struct texture_image *image, const char *path) +{ + if (!image) + return false; + if (!texture_image_load(image, path)) /* possibly unsafe on XBOX */ + return false; + + overlay->load_images[overlay->load_images_size++] = *image; + + return true; +} + + +static void rarch_task_overlay_load_desc_image( + overlay_loader_t *loader, + struct overlay_desc *desc, + struct overlay *input_overlay, + unsigned ol_idx, unsigned desc_idx) +{ + char overlay_desc_image_key[64] = {0}; + char image_path[PATH_MAX_LENGTH] = {0}; + config_file_t *conf = loader->conf; + + snprintf(overlay_desc_image_key, sizeof(overlay_desc_image_key), + "overlay%u_desc%u_overlay", ol_idx, desc_idx); + + if (config_get_path(conf, overlay_desc_image_key, + image_path, sizeof(image_path))) + { + char path[PATH_MAX_LENGTH] = {0}; + fill_pathname_resolve_relative(path, loader->overlay_path, + image_path, sizeof(path)); + + if (rarch_task_overlay_load_texture_image(input_overlay, &desc->image, path)) + desc->image_index = input_overlay->load_images_size - 1; + } + + input_overlay->pos ++; +} + +static bool rarch_task_overlay_load_desc( + overlay_loader_t *loader, + struct overlay_desc *desc, + struct overlay *input_overlay, + unsigned ol_idx, unsigned desc_idx, + unsigned width, unsigned height, + bool normalized, float alpha_mod, float range_mod) +{ + float width_mod, height_mod; + uint32_t box_hash, key_hash; + bool ret = true; + bool by_pixel = false; + char overlay_desc_key[64] = {0}; + char conf_key[64] = {0}; + char overlay_desc_normalized_key[64] = {0}; + char overlay[256] = {0}; + char *save = NULL; + char *key = NULL; + struct string_list *list = NULL; + const char *x = NULL; + const char *y = NULL; + const char *box = NULL; + config_file_t *conf = loader->conf; + + snprintf(overlay_desc_key, sizeof(overlay_desc_key), + "overlay%u_desc%u", ol_idx, desc_idx); + + snprintf(overlay_desc_normalized_key, sizeof(overlay_desc_normalized_key), + "overlay%u_desc%u_normalized", ol_idx, desc_idx); + config_get_bool(conf, overlay_desc_normalized_key, &normalized); + + by_pixel = !normalized; + + if (by_pixel && (width == 0 || height == 0)) + { + RARCH_ERR("[Overlay]: Base overlay is not set and not using normalized coordinates.\n"); + goto error; + } + + if (!config_get_array(conf, overlay_desc_key, overlay, sizeof(overlay))) + { + RARCH_ERR("[Overlay]: Didn't find key: %s.\n", overlay_desc_key); + goto error; + } + + list = string_split(overlay, ", "); + + if (!list) + { + RARCH_ERR("[Overlay]: Failed to split overlay desc.\n"); + goto error; + } + + if (list->size < 6) + { + RARCH_ERR("[Overlay]: Overlay desc is invalid. Requires at least 6 tokens.\n"); + goto error; + } + + key = list->elems[0].data; + x = list->elems[1].data; + y = list->elems[2].data; + box = list->elems[3].data; + + box_hash = djb2_calculate(box); + key_hash = djb2_calculate(key); + + desc->key_mask = 0; + + switch (key_hash) + { + case KEY_ANALOG_LEFT: + desc->type = OVERLAY_TYPE_ANALOG_LEFT; + break; + case KEY_ANALOG_RIGHT: + desc->type = OVERLAY_TYPE_ANALOG_RIGHT; + break; + default: + if (strstr(key, "retrok_") == key) + { + desc->type = OVERLAY_TYPE_KEYBOARD; + desc->key_mask = input_translate_str_to_rk(key + 7); + } + else + { + const char *tmp = NULL; + + desc->type = OVERLAY_TYPE_BUTTONS; + for (tmp = strtok_r(key, "|", &save); tmp; tmp = strtok_r(NULL, "|", &save)) + { + if (strcmp(tmp, "nul") != 0) + desc->key_mask |= UINT64_C(1) << input_translate_str_to_bind_id(tmp); + } + + if (desc->key_mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) + { + char overlay_target_key[64] = {0}; + + snprintf(overlay_target_key, sizeof(overlay_target_key), + "overlay%u_desc%u_next_target", ol_idx, desc_idx); + config_get_array(conf, overlay_target_key, + desc->next_index_name, sizeof(desc->next_index_name)); + } + } + break; + } + + width_mod = 1.0f; + height_mod = 1.0f; + + if (by_pixel) + { + width_mod /= width; + height_mod /= height; + } + + desc->x = (float)strtod(x, NULL) * width_mod; + desc->y = (float)strtod(y, NULL) * height_mod; + + switch (box_hash) + { + case BOX_RADIAL: + desc->hitbox = OVERLAY_HITBOX_RADIAL; + break; + case BOX_RECT: + desc->hitbox = OVERLAY_HITBOX_RECT; + break; + default: + RARCH_ERR("[Overlay]: Hitbox type (%s) is invalid. Use \"radial\" or \"rect\".\n", box); + ret = false; + goto end; + } + + switch (desc->type) + { + case OVERLAY_TYPE_ANALOG_LEFT: + case OVERLAY_TYPE_ANALOG_RIGHT: + { + char overlay_analog_saturate_key[64] = {0}; + + if (desc->hitbox != OVERLAY_HITBOX_RADIAL) + { + RARCH_ERR("[Overlay]: Analog hitbox type must be \"radial\".\n"); + ret = false; + goto end; + } + + snprintf(overlay_analog_saturate_key, sizeof(overlay_analog_saturate_key), + "overlay%u_desc%u_saturate_pct", ol_idx, desc_idx); + if (!config_get_float(conf, overlay_analog_saturate_key, + &desc->analog_saturate_pct)) + desc->analog_saturate_pct = 1.0f; + } + break; + default: + /* OVERLAY_TYPE_BUTTONS - unhandled */ + /* OVERLAY_TYPE_KEYBOARD - unhandled */ + break; + } + + desc->range_x = (float)strtod(list->elems[4].data, NULL) * width_mod; + desc->range_y = (float)strtod(list->elems[5].data, NULL) * height_mod; + + desc->mod_x = desc->x - desc->range_x; + desc->mod_w = 2.0f * desc->range_x; + desc->mod_y = desc->y - desc->range_y; + desc->mod_h = 2.0f * desc->range_y; + + snprintf(conf_key, sizeof(conf_key), + "overlay%u_desc%u_alpha_mod", ol_idx, desc_idx); + desc->alpha_mod = alpha_mod; + config_get_float(conf, conf_key, &desc->alpha_mod); + + snprintf(conf_key, sizeof(conf_key), + "overlay%u_desc%u_range_mod", ol_idx, desc_idx); + desc->range_mod = range_mod; + config_get_float(conf, conf_key, &desc->range_mod); + + snprintf(conf_key, sizeof(conf_key), + "overlay%u_desc%u_movable", ol_idx, desc_idx); + desc->movable = false; + desc->delta_x = 0.0f; + desc->delta_y = 0.0f; + config_get_bool(conf, conf_key, &desc->movable); + + desc->range_x_mod = desc->range_x; + desc->range_y_mod = desc->range_y; + + input_overlay->pos ++; + +end: + if (list) + string_list_free(list); + return ret; + +error: + if (list) + string_list_free(list); + return false; +} + +static void rarch_task_overlay_deferred_loading(overlay_loader_t *loader) +{ + size_t i = 0; + bool not_done = true; + struct overlay *overlay = NULL; + + overlay = &loader->overlays[loader->pos]; + not_done = loader->pos < loader->size; + + if (!not_done) + { + loader->state = OVERLAY_STATUS_DEFERRED_LOADING_RESOLVE; + return; + } + + switch (loader->loading_status) + { + case OVERLAY_IMAGE_TRANSFER_NONE: + case OVERLAY_IMAGE_TRANSFER_BUSY: + loader->loading_status = OVERLAY_IMAGE_TRANSFER_DONE; + //break; + case OVERLAY_IMAGE_TRANSFER_DONE: + rarch_task_overlay_image_done(&loader->overlays[loader->pos]); + loader->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_IMAGE_ITERATE; + loader->overlays[loader->pos].pos = 0; + break; + case OVERLAY_IMAGE_TRANSFER_DESC_IMAGE_ITERATE: + for (i = 0; i < overlay->pos_increment; i++) + { + if (overlay->pos < overlay->size) + { + rarch_task_overlay_load_desc_image(loader, + &overlay->descs[overlay->pos], overlay, + loader->pos, overlay->pos); + } + else + { + overlay->pos = 0; + loader->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_ITERATE; + break; + } + + } + break; + case OVERLAY_IMAGE_TRANSFER_DESC_ITERATE: + for (i = 0; i < overlay->pos_increment; i++) + { + if (overlay->pos < overlay->size) + { + if (!rarch_task_overlay_load_desc(loader, + &overlay->descs[overlay->pos], overlay, + loader->pos, overlay->pos, + overlay->image.width, overlay->image.height, + overlay->config.normalized, + overlay->config.alpha_mod, overlay->config.range_mod)) + { + RARCH_ERR("[Overlay]: Failed to load overlay descs for overlay #%u.\n", + (unsigned)overlay->pos); + goto error; + } + + } + else + { + overlay->pos = 0; + loader->loading_status = OVERLAY_IMAGE_TRANSFER_DESC_DONE; + break; + } + + } + break; + case OVERLAY_IMAGE_TRANSFER_DESC_DONE: + if (loader->pos == 0) + rarch_task_overlay_resolve_iterate(loader); + + loader->pos += 1; + loader->loading_status = OVERLAY_IMAGE_TRANSFER_NONE; + break; + case OVERLAY_IMAGE_TRANSFER_ERROR: + goto error; + } + + return; + +error: + loader->state = OVERLAY_STATUS_DEFERRED_ERROR; +} + +static void rarch_task_overlay_deferred_load(overlay_loader_t *loader) +{ + unsigned i; + config_file_t *conf = loader->conf; + + for (i = 0; i < loader->pos_increment; i++, loader->pos++) + { + char conf_key[64] = {0}; + char overlay_full_screen_key[64] = {0}; + struct overlay *overlay = NULL; + bool to_cont = loader->pos < loader->size; + + if (!to_cont) + { + loader->pos = 0; + loader->state = OVERLAY_STATUS_DEFERRED_LOADING; + break; + } + + overlay = &loader->overlays[loader->pos]; + + if (!overlay) + continue; + + snprintf(overlay->config.descs.key, + sizeof(overlay->config.descs.key), "overlay%u_descs", loader->pos); + + if (!config_get_uint(conf, overlay->config.descs.key, &overlay->config.descs.size)) + { + RARCH_ERR("[Overlay]: Failed to read number of descs from config key: %s.\n", + overlay->config.descs.key); + goto error; + } + + overlay->descs = (struct overlay_desc*) + calloc(overlay->config.descs.size, sizeof(*overlay->descs)); + + if (!overlay->descs) + { + RARCH_ERR("[Overlay]: Failed to allocate descs.\n"); + goto error; + } + + overlay->size = overlay->config.descs.size; + + snprintf(overlay_full_screen_key, sizeof(overlay_full_screen_key), + "overlay%u_full_screen", loader->pos); + overlay->full_screen = false; + config_get_bool(conf, overlay_full_screen_key, &overlay->full_screen); + + overlay->config.normalized = false; + overlay->config.alpha_mod = 1.0f; + overlay->config.range_mod = 1.0f; + + snprintf(conf_key, sizeof(conf_key), + "overlay%u_normalized", loader->pos); + config_get_bool(conf, conf_key, &overlay->config.normalized); + + snprintf(conf_key, sizeof(conf_key), "overlay%u_alpha_mod", loader->pos); + config_get_float(conf, conf_key, &overlay->config.alpha_mod); + + snprintf(conf_key, sizeof(conf_key), "overlay%u_range_mod", loader->pos); + config_get_float(conf, conf_key, &overlay->config.range_mod); + + /* Precache load image array for simplicity. */ + overlay->load_images = (struct texture_image*) + calloc(1 + overlay->size, sizeof(struct texture_image)); + + if (!overlay->load_images) + { + RARCH_ERR("[Overlay]: Failed to allocate load_images.\n"); + goto error; + } + + snprintf(overlay->config.paths.key, sizeof(overlay->config.paths.key), + "overlay%u_overlay", loader->pos); + + config_get_path(conf, overlay->config.paths.key, + overlay->config.paths.path, sizeof(overlay->config.paths.path)); + + if (overlay->config.paths.path[0] != '\0') + { + char overlay_resolved_path[PATH_MAX_LENGTH] = {0}; + + fill_pathname_resolve_relative(overlay_resolved_path, loader->overlay_path, + overlay->config.paths.path, sizeof(overlay_resolved_path)); + + if (!rarch_task_overlay_load_texture_image(overlay, &overlay->image, overlay_resolved_path)) + { + RARCH_ERR("[Overlay]: Failed to load image: %s.\n", + overlay_resolved_path); + loader->loading_status = OVERLAY_IMAGE_TRANSFER_ERROR; + goto error; + } + + } + + snprintf(overlay->config.names.key, sizeof(overlay->config.names.key), + "overlay%u_name", loader->pos); + config_get_array(conf, overlay->config.names.key, + overlay->name, sizeof(overlay->name)); + + /* By default, we stretch the overlay out in full. */ + overlay->x = overlay->y = 0.0f; + overlay->w = overlay->h = 1.0f; + + snprintf(overlay->config.rect.key, sizeof(overlay->config.rect.key), + "overlay%u_rect", loader->pos); + + if (config_get_array(conf, overlay->config.rect.key, + overlay->config.rect.array, sizeof(overlay->config.rect.array))) + { + struct string_list *list = string_split(overlay->config.rect.array, ", "); + + if (!list || list->size < 4) + { + RARCH_ERR("[Overlay]: Failed to split rect \"%s\" into at least four tokens.\n", + overlay->config.rect.array); + string_list_free(list); + goto error; + } + + overlay->x = (float)strtod(list->elems[0].data, NULL); + overlay->y = (float)strtod(list->elems[1].data, NULL); + overlay->w = (float)strtod(list->elems[2].data, NULL); + overlay->h = (float)strtod(list->elems[3].data, NULL); + string_list_free(list); + } + + /* Assume for now that scaling center is in the middle. + * TODO: Make this configurable. */ + overlay->block_scale = false; + overlay->center_x = overlay->x + 0.5f * overlay->w; + overlay->center_y = overlay->y + 0.5f * overlay->h; + } + + return; + +error: + loader->pos = 0; + loader->state = OVERLAY_STATUS_DEFERRED_ERROR; +} + +static ssize_t rarch_task_overlay_find_index(const struct overlay *ol, + const char *name, size_t size) +{ + size_t i; + + if (!ol) + return -1; + + for (i = 0; i < size; i++) + { + if (!strcmp(ol[i].name, name)) + return i; + } + + return -1; +} + +static bool rarch_task_overlay_resolve_targets(struct overlay *ol, + size_t idx, size_t size) +{ + size_t i; + struct overlay *current = NULL; + + current = (struct overlay*)&ol[idx]; + + for (i = 0; i < current->size; i++) + { + const char *next = current->descs[i].next_index_name; + + if (*next) + { + ssize_t next_idx = rarch_task_overlay_find_index(ol, next, size); + + if (next_idx < 0) + { + RARCH_ERR("[Overlay]: Couldn't find overlay called: \"%s\".\n", + next); + return false; + } + + current->descs[i].next_index = next_idx; + } + else + current->descs[i].next_index = (idx + 1) % size; + } + return true; +} + +static void rarch_task_overlay_resolve_iterate(overlay_loader_t *loader) +{ + bool not_done = true; + + not_done = loader->resolve_pos < loader->size; + + if (!not_done) + { + loader->state = OVERLAY_STATUS_DEFERRED_DONE; + return; + } + + if (!rarch_task_overlay_resolve_targets(loader->overlays, loader->resolve_pos, loader->size)) + { + RARCH_ERR("[Overlay]: Failed to resolve next targets.\n"); + goto error; + } + + if (loader->resolve_pos == 0) + { + loader->active = &loader->overlays[0]; + + /* TODO: MOVE TO MAIN THREAD / CALLBACK */ +// input_overlay_load_active(loader->deferred.opacity); +// input_overlay_enable(loader->deferred.enable); + } + + loader->resolve_pos += 1; + + return; +error: + loader->state = OVERLAY_STATUS_DEFERRED_ERROR; +} + +static void rarch_task_overlay_handler(rarch_task_t *task) +{ + overlay_loader_t *loader = (overlay_loader_t*)task->state; + overlay_task_data_t *data; + + switch (loader->state) + { + case OVERLAY_STATUS_DEFERRED_LOADING: + rarch_task_overlay_deferred_loading(loader); + break; + case OVERLAY_STATUS_DEFERRED_LOAD: + rarch_task_overlay_deferred_load(loader); + break; + case OVERLAY_STATUS_DEFERRED_LOADING_RESOLVE: + rarch_task_overlay_resolve_iterate(loader); + break; + case OVERLAY_STATUS_DEFERRED_DONE: +// input_overlay_new_done(); +// break; + case OVERLAY_STATUS_DEFERRED_ERROR: +// input_overlay_free(); +// break; + + default: + case OVERLAY_STATUS_NONE: + goto task_finished; + break; + } + + return; +task_finished: + task->finished = true; + + data = (overlay_task_data_t*)calloc(1, sizeof(*data)); + + data->overlays = loader->overlays; + data->size = loader->size; + data->active = loader->active; + + task->task_data = data; + + if (loader->overlay_path) + free(loader->overlay_path); + + if (loader->conf) + config_file_free(loader->conf); + + free(loader); +} + + + +static bool rarch_task_push_overlay_load(const char *overlay_path, + rarch_task_callback_t cb, void *user_data) +{ + rarch_task_t *t; + overlay_loader_t *loader = (overlay_loader_t*)calloc(1, sizeof(*loader)); + config_file_t *conf = config_file_new(overlay_path); + + if (!conf || !loader) + goto error; + + if (!config_get_uint(conf, "overlays", &loader->size)) + { + RARCH_ERR("overlays variable not defined in config.\n"); + goto error; + } + + loader->overlays = (struct overlay*)calloc(loader->size, sizeof(*loader->overlays)); + if (!loader->overlays) + goto error; + + loader->overlay_path = strdup(overlay_path); + loader->conf = conf; + loader->state = OVERLAY_STATUS_DEFERRED_LOAD; + loader->pos_increment = (loader->size / 4) ? (loader->size / 4) : 4; + + t = (rarch_task_t*)calloc(1, sizeof(*t)); + t->handler = rarch_task_overlay_handler; + t->state = loader; + t->callback = cb; + t->user_data = user_data; + + rarch_task_push(t); + + return true; +error: + if (conf) + config_file_free(conf); + + if (loader) + { + if (loader->overlays) + free(loader->overlays); + free(loader); + } + + return false; +} + +bool rarch_task_push_overlay_load_default( + rarch_task_callback_t cb, void *user_data) +{ + driver_t *driver = driver_get_ptr(); + settings_t *settings = config_get_ptr(); + + if (driver->osk_enable) + { + if (!*settings->osk.overlay) + return 1; + } + else + { + if (!*settings->input.overlay) + return 1; + } + + return rarch_task_push_overlay_load( + driver->osk_enable ? settings->osk.overlay : settings->input.overlay, + cb, user_data); } diff --git a/tasks/tasks.c b/tasks/tasks.c index 3ba08ce34f..e56ecd9577 100644 --- a/tasks/tasks.c +++ b/tasks/tasks.c @@ -161,6 +161,7 @@ static void threaded_worker(void *userdata) { rarch_task_t *queue = NULL; rarch_task_t *task = NULL; + rarch_task_t *next = NULL; /* pop all into a local queue to avoid trouble with rarch_task_push(), * tasks are in the reverse order here. */ @@ -184,10 +185,9 @@ static void threaded_worker(void *userdata) slock_unlock(running_lock); - - - for (task = queue; task; task = task->next) + for (task = queue; task; task = next) { + next = task->next; task->handler(task); if (task->finished) diff --git a/tasks/tasks.h b/tasks/tasks.h index 77de198844..2cac6ff4a0 100644 --- a/tasks/tasks.h +++ b/tasks/tasks.h @@ -82,7 +82,8 @@ bool rarch_task_push_dbscan(const char *fullpath, bool directory, rarch_task_cal #endif #ifdef HAVE_OVERLAY -void rarch_main_data_overlay_iterate(void); +bool rarch_task_push_overlay_load_default( + rarch_task_callback_t cb, void *user_data); #endif void rarch_main_data_nbio_iterate(bool is_thread);