Remove unprotected access to cmd_data and rewrite message passing mechanism

This commit is contained in:
Higor Eurípedes 2015-05-20 16:58:22 -03:00
parent b363060262
commit bb2f181386
4 changed files with 276 additions and 241 deletions

View File

@ -91,6 +91,7 @@ unsigned video_texture_load(void *data,
{ {
driver_t *driver = driver_get_ptr(); driver_t *driver = driver_get_ptr();
thread_video_t *thr = (thread_video_t*)driver->video_data; thread_video_t *thr = (thread_video_t*)driver->video_data;
thread_packet_t pkt = { CMD_CUSTOM_COMMAND };
if (!thr) if (!thr)
return 0; return 0;
@ -100,22 +101,21 @@ unsigned video_texture_load(void *data,
case TEXTURE_BACKEND_OPENGL: case TEXTURE_BACKEND_OPENGL:
if (filter_type == TEXTURE_FILTER_MIPMAP_LINEAR || if (filter_type == TEXTURE_FILTER_MIPMAP_LINEAR ||
filter_type == TEXTURE_FILTER_MIPMAP_NEAREST) filter_type == TEXTURE_FILTER_MIPMAP_NEAREST)
thr->cmd_data.custom_command.method = video_texture_png_load_wrap_gl_mipmap; pkt.data.custom_command.method = video_texture_png_load_wrap_gl_mipmap;
else else
thr->cmd_data.custom_command.method = video_texture_png_load_wrap_gl; pkt.data.custom_command.method = video_texture_png_load_wrap_gl;
break; break;
case TEXTURE_BACKEND_DEFAULT: case TEXTURE_BACKEND_DEFAULT:
default: default:
thr->cmd_data.custom_command.method = video_texture_png_load_wrap; pkt.data.custom_command.method = video_texture_png_load_wrap;
break; break;
} }
thr->cmd_data.custom_command.data = (void*)data; pkt.data.custom_command.data = (void*)data;
thr->send_cmd_func(thr, CMD_CUSTOM_COMMAND); thr->send_and_wait(thr, &pkt);
thr->wait_reply_func(thr, CMD_CUSTOM_COMMAND);
return thr->cmd_data.custom_command.return_value; return pkt.data.custom_command.return_value;
} }
return video_texture_png_load(data, type, filter_type); return video_texture_png_load(data, type, filter_type);

View File

@ -32,15 +32,55 @@ static void *thread_init_never_call(const video_info_t *video,
return NULL; return NULL;
} }
static void thread_reply(thread_video_t *thr, enum thread_cmd cmd) /* thread -> user */
static void thread_reply(thread_video_t *thr, const thread_packet_t *pkt)
{ {
slock_lock(thr->lock); slock_lock(thr->lock);
thr->reply_cmd = cmd;
thr->send_cmd = CMD_NONE; thr->cmd_data = *pkt;
thr->reply_cmd = pkt->type;
thr->send_cmd = CMD_NONE;
scond_signal(thr->cond_cmd); scond_signal(thr->cond_cmd);
slock_unlock(thr->lock); slock_unlock(thr->lock);
} }
/* user -> thread */
static void thread_send_packet(thread_video_t *thr, const thread_packet_t *pkt)
{
slock_lock(thr->lock);
thr->cmd_data = *pkt;
thr->send_cmd = pkt->type;
thr->reply_cmd = CMD_NONE;
scond_signal(thr->cond_thread);
slock_unlock(thr->lock);
}
/* user -> thread */
static void thread_wait_reply(thread_video_t *thr, thread_packet_t *pkt)
{
slock_lock(thr->lock);
while (pkt->type != thr->reply_cmd)
scond_wait(thr->cond_cmd, thr->lock);
*pkt = thr->cmd_data;
slock_unlock(thr->lock);
}
/* user -> thread */
static void thread_send_and_wait(thread_video_t *thr, thread_packet_t *pkt)
{
thread_send_packet(thr, pkt);
thread_wait_reply(thr, pkt);
}
static void thread_update_driver_state(thread_video_t *thr) static void thread_update_driver_state(thread_video_t *thr)
{ {
#if defined(HAVE_MENU) #if defined(HAVE_MENU)
@ -90,6 +130,7 @@ static void thread_loop(void *data)
for (;;) for (;;)
{ {
thread_packet_t pkt;
enum thread_cmd send_cmd; enum thread_cmd send_cmd;
bool ret = false; bool ret = false;
bool updated = false; bool updated = false;
@ -102,8 +143,9 @@ static void thread_loop(void *data)
/* To avoid race condition where send_cmd is updated /* To avoid race condition where send_cmd is updated
* right after the switch is checked. */ * right after the switch is checked. */
send_cmd = thr->send_cmd; send_cmd = thr->send_cmd;
pkt = thr->cmd_data;
slock_unlock(thr->lock); slock_unlock(thr->lock);
switch (send_cmd) switch (send_cmd)
@ -111,9 +153,9 @@ static void thread_loop(void *data)
case CMD_INIT: case CMD_INIT:
thr->driver_data = thr->driver->init(&thr->info, thr->driver_data = thr->driver->init(&thr->info,
thr->input, thr->input_data); thr->input, thr->input_data);
thr->cmd_data.b = thr->driver_data; pkt.data.b = thr->driver_data;
thr->driver->viewport_info(thr->driver_data, &thr->vp); thr->driver->viewport_info(thr->driver_data, &thr->vp);
thread_reply(thr, CMD_INIT); thread_reply(thr, &pkt);
break; break;
case CMD_FREE: case CMD_FREE:
@ -123,13 +165,13 @@ static void thread_loop(void *data)
thr->driver->free(thr->driver_data); thr->driver->free(thr->driver_data);
} }
thr->driver_data = NULL; thr->driver_data = NULL;
thread_reply(thr, CMD_FREE); thread_reply(thr, &pkt);
return; return;
case CMD_SET_ROTATION: case CMD_SET_ROTATION:
if (thr->driver && thr->driver->set_rotation) if (thr->driver && thr->driver->set_rotation)
thr->driver->set_rotation(thr->driver_data, thr->cmd_data.i); thr->driver->set_rotation(thr->driver_data, pkt.data.i);
thread_reply(thr, CMD_SET_ROTATION); thread_reply(thr, &pkt);
break; break;
case CMD_READ_VIEWPORT: case CMD_READ_VIEWPORT:
@ -156,55 +198,55 @@ static void thread_loop(void *data)
if (thr->driver && thr->driver->read_viewport) if (thr->driver && thr->driver->read_viewport)
ret = thr->driver->read_viewport(thr->driver_data, ret = thr->driver->read_viewport(thr->driver_data,
(uint8_t*)thr->cmd_data.v); (uint8_t*)pkt.data.v);
thr->cmd_data.b = ret; pkt.data.b = ret;
thr->frame.within_thread = false; thr->frame.within_thread = false;
} }
else else
{ {
/* Viewport dimensions changed right after main /* Viewport dimensions changed right after main
* thread read the async value. Cannot read safely. */ * thread read the async value. Cannot read safely. */
thr->cmd_data.b = false; pkt.data.b = false;
} }
thread_reply(thr, CMD_READ_VIEWPORT); thread_reply(thr, &pkt);
break; break;
} }
case CMD_SET_SHADER: case CMD_SET_SHADER:
if (thr->driver && thr->driver->set_shader) if (thr->driver && thr->driver->set_shader)
ret = thr->driver->set_shader(thr->driver_data, ret = thr->driver->set_shader(thr->driver_data,
thr->cmd_data.set_shader.type, pkt.data.set_shader.type,
thr->cmd_data.set_shader.path); pkt.data.set_shader.path);
thr->cmd_data.b = ret; pkt.data.b = ret;
thread_reply(thr, CMD_SET_SHADER); thread_reply(thr, &pkt);
break; break;
case CMD_ALIVE: case CMD_ALIVE:
if (thr->driver && thr->driver->alive) if (thr->driver && thr->driver->alive)
ret = thr->driver->alive(thr->driver_data); ret = thr->driver->alive(thr->driver_data);
thr->cmd_data.b = ret; pkt.data.b = ret;
thread_reply(thr, CMD_ALIVE); thread_reply(thr, &pkt);
break; break;
#ifdef HAVE_OVERLAY #ifdef HAVE_OVERLAY
case CMD_OVERLAY_ENABLE: case CMD_OVERLAY_ENABLE:
if (thr->overlay && thr->overlay->enable) if (thr->overlay && thr->overlay->enable)
thr->overlay->enable(thr->driver_data, thr->cmd_data.b); thr->overlay->enable(thr->driver_data, pkt.data.b);
thread_reply(thr, CMD_OVERLAY_ENABLE); thread_reply(thr, &pkt);
break; break;
case CMD_OVERLAY_LOAD: case CMD_OVERLAY_LOAD:
if (thr->overlay && thr->overlay->load) if (thr->overlay && thr->overlay->load)
ret = thr->overlay->load(thr->driver_data, ret = thr->overlay->load(thr->driver_data,
thr->cmd_data.image.data, pkt.data.image.data,
thr->cmd_data.image.num); pkt.data.image.num);
thr->cmd_data.b = ret; pkt.data.b = ret;
thr->alpha_mods = thr->cmd_data.image.num; thr->alpha_mods = pkt.data.image.num;
thr->alpha_mod = (float*)realloc(thr->alpha_mod, thr->alpha_mod = (float*)realloc(thr->alpha_mod,
thr->alpha_mods * sizeof(float)); thr->alpha_mods * sizeof(float));
@ -213,118 +255,117 @@ static void thread_loop(void *data)
/* Avoid temporary garbage data. */ /* Avoid temporary garbage data. */
thr->alpha_mod[i] = 1.0f; thr->alpha_mod[i] = 1.0f;
} }
thread_reply(thr, CMD_OVERLAY_LOAD);
thread_reply(thr, &pkt);
break; break;
case CMD_OVERLAY_TEX_GEOM: case CMD_OVERLAY_TEX_GEOM:
if (thr->overlay && thr->overlay->tex_geom) if (thr->overlay && thr->overlay->tex_geom)
thr->overlay->tex_geom(thr->driver_data, thr->overlay->tex_geom(thr->driver_data,
thr->cmd_data.rect.index, pkt.data.rect.index,
thr->cmd_data.rect.x, pkt.data.rect.x,
thr->cmd_data.rect.y, pkt.data.rect.y,
thr->cmd_data.rect.w, pkt.data.rect.w,
thr->cmd_data.rect.h); pkt.data.rect.h);
thread_reply(thr, CMD_OVERLAY_TEX_GEOM); thread_reply(thr, &pkt);
break; break;
case CMD_OVERLAY_VERTEX_GEOM: case CMD_OVERLAY_VERTEX_GEOM:
if (thr->overlay && thr->overlay->vertex_geom) if (thr->overlay && thr->overlay->vertex_geom)
thr->overlay->vertex_geom(thr->driver_data, thr->overlay->vertex_geom(thr->driver_data,
thr->cmd_data.rect.index, pkt.data.rect.index,
thr->cmd_data.rect.x, pkt.data.rect.x,
thr->cmd_data.rect.y, pkt.data.rect.y,
thr->cmd_data.rect.w, pkt.data.rect.w,
thr->cmd_data.rect.h); pkt.data.rect.h);
thread_reply(thr, CMD_OVERLAY_VERTEX_GEOM); thread_reply(thr, &pkt);
break; break;
case CMD_OVERLAY_FULL_SCREEN: case CMD_OVERLAY_FULL_SCREEN:
if (thr->overlay && thr->overlay->full_screen) if (thr->overlay && thr->overlay->full_screen)
thr->overlay->full_screen(thr->driver_data, thr->overlay->full_screen(thr->driver_data,
thr->cmd_data.b); pkt.data.b);
thread_reply(thr, CMD_OVERLAY_FULL_SCREEN); thread_reply(thr, &pkt);
break; break;
#endif #endif
case CMD_POKE_SET_VIDEO_MODE: case CMD_POKE_SET_VIDEO_MODE:
if (thr->poke && thr->poke->set_video_mode) if (thr->poke && thr->poke->set_video_mode)
thr->poke->set_video_mode(thr->driver_data, thr->poke->set_video_mode(thr->driver_data,
thr->cmd_data.new_mode.width, pkt.data.new_mode.width,
thr->cmd_data.new_mode.height, pkt.data.new_mode.height,
thr->cmd_data.new_mode.fullscreen); pkt.data.new_mode.fullscreen);
thread_reply(thr, CMD_POKE_SET_VIDEO_MODE); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_SET_FILTERING: case CMD_POKE_SET_FILTERING:
if (thr->poke && thr->poke->set_filtering) if (thr->poke && thr->poke->set_filtering)
thr->poke->set_filtering(thr->driver_data, thr->poke->set_filtering(thr->driver_data,
thr->cmd_data.filtering.index, pkt.data.filtering.index,
thr->cmd_data.filtering.smooth); pkt.data.filtering.smooth);
thread_reply(thr, CMD_POKE_SET_FILTERING); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_GET_VIDEO_OUTPUT_SIZE: case CMD_POKE_GET_VIDEO_OUTPUT_SIZE:
if (thr->poke && thr->poke->get_video_output_size) if (thr->poke && thr->poke->get_video_output_size)
thr->poke->get_video_output_size(thr->driver_data, thr->poke->get_video_output_size(thr->driver_data,
&thr->cmd_data.output.width, &pkt.data.output.width,
&thr->cmd_data.output.height); &pkt.data.output.height);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_GET_VIDEO_OUTPUT_PREV: case CMD_POKE_GET_VIDEO_OUTPUT_PREV:
if (thr->poke && thr->poke->get_video_output_prev) if (thr->poke && thr->poke->get_video_output_prev)
thr->poke->get_video_output_prev(thr->driver_data); thr->poke->get_video_output_prev(thr->driver_data);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_GET_VIDEO_OUTPUT_NEXT: case CMD_POKE_GET_VIDEO_OUTPUT_NEXT:
if (thr->poke && thr->poke->get_video_output_next) if (thr->poke && thr->poke->get_video_output_next)
thr->poke->get_video_output_next(thr->driver_data); thr->poke->get_video_output_next(thr->driver_data);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_SET_ASPECT_RATIO: case CMD_POKE_SET_ASPECT_RATIO:
thr->poke->set_aspect_ratio(thr->driver_data, thr->poke->set_aspect_ratio(thr->driver_data,
thr->cmd_data.i); pkt.data.i);
thread_reply(thr, CMD_POKE_SET_ASPECT_RATIO); thread_reply(thr, &pkt);
break; break;
case CMD_POKE_SET_OSD_MSG: case CMD_POKE_SET_OSD_MSG:
if (thr->poke && thr->poke->set_osd_msg) if (thr->poke && thr->poke->set_osd_msg)
thr->poke->set_osd_msg(thr->driver_data, thr->poke->set_osd_msg(thr->driver_data,
thr->cmd_data.osd_message.msg, pkt.data.osd_message.msg,
&thr->cmd_data.osd_message.params, NULL); &pkt.data.osd_message.params, NULL);
thread_reply(thr, CMD_POKE_SET_OSD_MSG); thread_reply(thr, &pkt);
break; break;
case CMD_FONT_INIT: case CMD_FONT_INIT:
if (thr->cmd_data.font_init.method) if (pkt.data.font_init.method)
thr->cmd_data.font_init.return_value = pkt.data.font_init.return_value =
thr->cmd_data.font_init.method pkt.data.font_init.method
(thr->cmd_data.font_init.font_driver, (pkt.data.font_init.font_driver,
thr->cmd_data.font_init.font_handle, pkt.data.font_init.font_handle,
thr->cmd_data.font_init.video_data, pkt.data.font_init.video_data,
thr->cmd_data.font_init.font_path, pkt.data.font_init.font_path,
thr->cmd_data.font_init.font_size, pkt.data.font_init.font_size,
thr->cmd_data.font_init.api); pkt.data.font_init.api);
thread_reply(thr, CMD_FONT_INIT); thread_reply(thr, &pkt);
break; break;
case CMD_CUSTOM_COMMAND: case CMD_CUSTOM_COMMAND:
if (thr->cmd_data.custom_command.method) if (pkt.data.custom_command.method)
thr->cmd_data.custom_command.return_value = pkt.data.custom_command.return_value =
thr->cmd_data.custom_command.method pkt.data.custom_command.method
(thr->cmd_data.custom_command.data); (pkt.data.custom_command.data);
thread_reply(thr, CMD_CUSTOM_COMMAND); thread_reply(thr, &pkt);
break; break;
case CMD_NONE: case CMD_NONE:
/* Never reply on no command. Possible deadlock if /* Never reply on no command. Possible deadlock if
* thread sends command right after frame update. */ * thread sends command right after frame update. */
break; break;
default: default:
thread_reply(thr, send_cmd); thread_reply(thr, &pkt);
break; break;
} }
@ -371,22 +412,8 @@ static void thread_loop(void *data)
} }
} }
static void thread_send_cmd(thread_video_t *thr, enum thread_cmd cmd)
{
slock_lock(thr->lock);
thr->send_cmd = cmd;
thr->reply_cmd = CMD_NONE;
scond_signal(thr->cond_thread);
slock_unlock(thr->lock);
}
static void thread_wait_reply(thread_video_t *thr, enum thread_cmd cmd)
{
slock_lock(thr->lock);
while (cmd != thr->reply_cmd)
scond_wait(thr->cond_cmd, thr->lock);
slock_unlock(thr->lock);
}
static bool thread_alive(void *data) static bool thread_alive(void *data)
{ {
@ -396,9 +423,9 @@ static bool thread_alive(void *data)
if (runloop->is_paused) if (runloop->is_paused)
{ {
thread_send_cmd(thr, CMD_ALIVE); thread_packet_t pkt = { CMD_ALIVE };
thread_wait_reply(thr, CMD_ALIVE); thread_send_and_wait(thr, &pkt);
return thr->cmd_data.b; return pkt.data.b;
} }
slock_lock(thr->lock); slock_lock(thr->lock);
@ -551,6 +578,7 @@ static bool thread_init(thread_video_t *thr, const video_info_t *info,
const input_driver_t **input, void **input_data) const input_driver_t **input, void **input_data)
{ {
size_t max_size; size_t max_size;
thread_packet_t pkt = {CMD_INIT};
thr->lock = slock_new(); thr->lock = slock_new();
thr->alpha_lock = slock_new(); thr->alpha_lock = slock_new();
@ -580,52 +608,42 @@ static bool thread_init(thread_video_t *thr, const video_info_t *info,
if (!thr->thread) if (!thr->thread)
return false; return false;
thread_send_cmd(thr, CMD_INIT); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_INIT);
thr->send_cmd_func = thread_send_cmd; // thr->send_cmd_func = thread_send_cmd;
thr->wait_reply_func = thread_wait_reply; // thr->wait_reply_func = thread_wait_reply;
return thr->cmd_data.b; thr->send_and_wait = thread_send_and_wait;
return pkt.data.b;
} }
static bool thread_set_shader(void *data, static bool thread_set_shader(void *data,
enum rarch_shader_type type, const char *path) enum rarch_shader_type type, const char *path)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = {CMD_SET_SHADER};
if (!thr) if (!thr)
return false; return false;
thr->cmd_data.set_shader.type = type; pkt.data.set_shader.type = type;
thr->cmd_data.set_shader.path = path; pkt.data.set_shader.path = path;
thread_send_cmd(thr, CMD_SET_SHADER); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_SET_SHADER);
return thr->cmd_data.b; return pkt.data.b;
} }
static void thread_set_viewport(void *data, unsigned width, static void thread_set_viewport(void *data, unsigned width,
unsigned height, bool force_full, bool allow_rotate) unsigned height, bool force_full, bool allow_rotate)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
if (!thr) if (!thr)
return; return;
slock_lock(thr->lock); slock_lock(thr->lock);
thr->cmd_data.set_viewport.width = width;
thr->cmd_data.set_viewport.height = height;
thr->cmd_data.set_viewport.force_full = force_full;
thr->cmd_data.set_viewport.allow_rotate = allow_rotate;
if (thr->driver && thr->driver->set_viewport) if (thr->driver && thr->driver->set_viewport)
thr->driver->set_viewport(thr->driver_data, thr->driver->set_viewport(thr->driver_data, width, height,
thr->cmd_data.set_viewport.width, force_full, allow_rotate);
thr->cmd_data.set_viewport.height,
thr->cmd_data.set_viewport.force_full,
thr->cmd_data.set_viewport.allow_rotate);
slock_unlock(thr->lock); slock_unlock(thr->lock);
} }
@ -633,13 +651,13 @@ static void thread_set_viewport(void *data, unsigned width,
static void thread_set_rotation(void *data, unsigned rotation) static void thread_set_rotation(void *data, unsigned rotation)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_SET_ROTATION };
if (!thr) if (!thr)
return; return;
thr->cmd_data.i = rotation; pkt.data.i = rotation;
thread_send_cmd(thr, CMD_SET_ROTATION); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_SET_ROTATION);
} }
/* This value is set async as stalling on the video driver for /* This value is set async as stalling on the video driver for
@ -665,24 +683,27 @@ static void thread_viewport_info(void *data, struct video_viewport *vp)
static bool thread_read_viewport(void *data, uint8_t *buffer) static bool thread_read_viewport(void *data, uint8_t *buffer)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_READ_VIEWPORT };
if (!thr) if (!thr)
return false; return false;
thr->cmd_data.v = buffer; pkt.data.v = buffer;
thread_send_cmd(thr, CMD_READ_VIEWPORT); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_READ_VIEWPORT);
return thr->cmd_data.b; return pkt.data.b;
} }
static void thread_free(void *data) static void thread_free(void *data)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_FREE };
if (!thr) if (!thr)
return; return;
thread_send_cmd(thr, CMD_FREE); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_FREE);
sthread_join(thr->thread); sthread_join(thr->thread);
#if defined(HAVE_MENU) #if defined(HAVE_MENU)
@ -707,69 +728,73 @@ static void thread_free(void *data)
static void thread_overlay_enable(void *data, bool state) static void thread_overlay_enable(void *data, bool state)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_ENABLE };
if (!thr) if (!thr)
return; return;
thr->cmd_data.b = state;
thread_send_cmd(thr, CMD_OVERLAY_ENABLE); pkt.data.b = state;
thread_wait_reply(thr, CMD_OVERLAY_ENABLE); thread_send_and_wait(thr, &pkt);
} }
static bool thread_overlay_load(void *data, static bool thread_overlay_load(void *data,
const struct texture_image *images, unsigned num_images) const struct texture_image *images, unsigned num_images)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_LOAD };
if (!thr) if (!thr)
return false; return false;
thr->cmd_data.image.data = images; pkt.data.image.data = images;
thr->cmd_data.image.num = num_images; pkt.data.image.num = num_images;
thread_send_cmd(thr, CMD_OVERLAY_LOAD); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_OVERLAY_LOAD);
return thr->cmd_data.b; return pkt.data.b;
} }
static void thread_overlay_tex_geom(void *data, static void thread_overlay_tex_geom(void *data,
unsigned idx, float x, float y, float w, float h) unsigned idx, float x, float y, float w, float h)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_TEX_GEOM };
if (!thr) if (!thr)
return; return;
thr->cmd_data.rect.index = idx; pkt.data.rect.index = idx;
thr->cmd_data.rect.x = x; pkt.data.rect.x = x;
thr->cmd_data.rect.y = y; pkt.data.rect.y = y;
thr->cmd_data.rect.w = w; pkt.data.rect.w = w;
thr->cmd_data.rect.h = h; pkt.data.rect.h = h;
thread_send_cmd(thr, CMD_OVERLAY_TEX_GEOM);
thread_wait_reply(thr, CMD_OVERLAY_TEX_GEOM); thread_send_and_wait(thr, &pkt);
} }
static void thread_overlay_vertex_geom(void *data, static void thread_overlay_vertex_geom(void *data,
unsigned idx, float x, float y, float w, float h) unsigned idx, float x, float y, float w, float h)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_VERTEX_GEOM };
if (!thr) if (!thr)
return; return;
thr->cmd_data.rect.index = idx;
thr->cmd_data.rect.x = x; pkt.data.rect.index = idx;
thr->cmd_data.rect.y = y; pkt.data.rect.x = x;
thr->cmd_data.rect.w = w; pkt.data.rect.y = y;
thr->cmd_data.rect.h = h; pkt.data.rect.w = w;
thread_send_cmd(thr, CMD_OVERLAY_VERTEX_GEOM); pkt.data.rect.h = h;
thread_wait_reply(thr, CMD_OVERLAY_VERTEX_GEOM);
thread_send_and_wait(thr, &pkt);
} }
static void thread_overlay_full_screen(void *data, bool enable) static void thread_overlay_full_screen(void *data, bool enable)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_FULL_SCREEN };
thr->cmd_data.b = enable; pkt.data.b = enable;
thread_send_cmd(thr, CMD_OVERLAY_FULL_SCREEN); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_OVERLAY_FULL_SCREEN);
} }
/* We cannot wait for this to complete. Totally blocks the main thread. */ /* We cannot wait for this to complete. Totally blocks the main thread. */
@ -809,70 +834,73 @@ static void thread_set_video_mode(void *data, unsigned width, unsigned height,
bool fullscreen) bool fullscreen)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_VIDEO_MODE };
if (!thr) if (!thr)
return; return;
thr->cmd_data.new_mode.width = width;
thr->cmd_data.new_mode.height = height; pkt.data.new_mode.width = width;
thr->cmd_data.new_mode.fullscreen = fullscreen; pkt.data.new_mode.height = height;
thread_send_cmd(thr, CMD_POKE_SET_VIDEO_MODE); pkt.data.new_mode.fullscreen = fullscreen;
thread_wait_reply(thr, CMD_POKE_SET_VIDEO_MODE); thread_send_and_wait(thr, &pkt);
} }
static void thread_set_filtering(void *data, unsigned idx, bool smooth) static void thread_set_filtering(void *data, unsigned idx, bool smooth)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_FILTERING };
if (!thr) if (!thr)
return; return;
thr->cmd_data.filtering.index = idx; pkt.data.filtering.index = idx;
thr->cmd_data.filtering.smooth = smooth; pkt.data.filtering.smooth = smooth;
thread_send_cmd(thr, CMD_POKE_SET_FILTERING); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_POKE_SET_FILTERING);
} }
static void thread_get_video_output_size(void *data, static void thread_get_video_output_size(void *data,
unsigned *width, unsigned *height) unsigned *width, unsigned *height)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_SIZE };
if (!thr) if (!thr)
return; return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE); thread_send_and_wait(thr, &pkt);
*width = thr->cmd_data.output.width;
*height = thr->cmd_data.output.height; *width = pkt.data.output.width;
*height = pkt.data.output.height;
} }
static void thread_get_video_output_prev(void *data) static void thread_get_video_output_prev(void *data)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_PREV };
if (!thr) if (!thr)
return; return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV);
} }
static void thread_get_video_output_next(void *data) static void thread_get_video_output_next(void *data)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_NEXT };
if (!thr) if (!thr)
return; return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT);
} }
static void thread_set_aspect_ratio(void *data, unsigned aspectratio_idx) static void thread_set_aspect_ratio(void *data, unsigned aspectratio_idx)
{ {
thread_video_t *thr = (thread_video_t*)data; thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_ASPECT_RATIO };
if (!thr) if (!thr)
return; return;
thr->cmd_data.i = aspectratio_idx; pkt.data.i = aspectratio_idx;
thread_send_cmd(thr, CMD_POKE_SET_ASPECT_RATIO); thread_send_and_wait(thr, &pkt);
thread_wait_reply(thr, CMD_POKE_SET_ASPECT_RATIO);
} }
#if defined(HAVE_MENU) #if defined(HAVE_MENU)

View File

@ -59,60 +59,9 @@ enum thread_cmd
CMD_DUMMY = INT_MAX CMD_DUMMY = INT_MAX
}; };
typedef struct thread_video typedef struct
{ {
slock_t *lock; enum thread_cmd type;
scond_t *cond_cmd;
scond_t *cond_thread;
sthread_t *thread;
video_info_t info;
const video_driver_t *driver;
#ifdef HAVE_OVERLAY
const video_overlay_interface_t *overlay;
#endif
const video_poke_interface_t *poke;
void *driver_data;
const input_driver_t **input;
void **input_data;
#if defined(HAVE_MENU)
struct
{
void *frame;
size_t frame_cap;
unsigned width;
unsigned height;
float alpha;
bool frame_updated;
bool rgb32;
bool enable;
bool full_screen;
} texture;
#endif
bool apply_state_changes;
bool alive;
bool focus;
bool suppress_screensaver;
bool has_windowed;
bool nonblock;
retro_time_t last_time;
unsigned hit_count;
unsigned miss_count;
float *alpha_mod;
unsigned alpha_mods;
bool alpha_update;
slock_t *alpha_lock;
void (*send_cmd_func)(struct thread_video *, enum thread_cmd);
void (*wait_reply_func)(struct thread_video *, enum thread_cmd);
enum thread_cmd send_cmd;
enum thread_cmd reply_cmd;
union union
{ {
bool b; bool b;
@ -182,8 +131,8 @@ typedef struct thread_video
struct struct
{ {
bool (*method)(const void **font_driver, bool (*method)(const void **font_driver,
void **font_handle, void *video_data, const char *font_path, void **font_handle, void *video_data, const char *font_path,
float font_size, enum font_driver_render_api api); float font_size, enum font_driver_render_api api);
const void **font_driver; const void **font_driver;
void **font_handle; void **font_handle;
void *video_data; void *video_data;
@ -192,8 +141,65 @@ typedef struct thread_video
bool return_value; bool return_value;
enum font_driver_render_api api; enum font_driver_render_api api;
} font_init; } font_init;
} data;
} thread_packet_t;
} cmd_data; typedef struct thread_video
{
slock_t *lock;
scond_t *cond_cmd;
scond_t *cond_thread;
sthread_t *thread;
video_info_t info;
const video_driver_t *driver;
#ifdef HAVE_OVERLAY
const video_overlay_interface_t *overlay;
#endif
const video_poke_interface_t *poke;
void *driver_data;
const input_driver_t **input;
void **input_data;
#if defined(HAVE_MENU)
struct
{
void *frame;
size_t frame_cap;
unsigned width;
unsigned height;
float alpha;
bool frame_updated;
bool rgb32;
bool enable;
bool full_screen;
} texture;
#endif
bool apply_state_changes;
bool alive;
bool focus;
bool suppress_screensaver;
bool has_windowed;
bool nonblock;
retro_time_t last_time;
unsigned hit_count;
unsigned miss_count;
float *alpha_mod;
unsigned alpha_mods;
bool alpha_update;
slock_t *alpha_lock;
// void (*send_cmd_func)(struct thread_video *, enum thread_cmd);
// void (*wait_reply_func)(struct thread_video *, enum thread_cmd);
void (*send_and_wait)(struct thread_video *, thread_packet_t*);
enum thread_cmd send_cmd;
enum thread_cmd reply_cmd;
thread_packet_t cmd_data;
struct video_viewport vp; struct video_viewport vp;
struct video_viewport read_vp; /* Last viewport reported to caller. */ struct video_viewport read_vp; /* Last viewport reported to caller. */

View File

@ -141,22 +141,23 @@ bool menu_display_font_init_first(const void **font_driver,
{ {
driver_t *driver = driver_get_ptr(); driver_t *driver = driver_get_ptr();
thread_video_t *thr = (thread_video_t*)driver->video_data; thread_video_t *thr = (thread_video_t*)driver->video_data;
thread_packet_t pkt;
if (!thr) if (!thr)
return false; return false;
thr->cmd_data.font_init.method = font_init_first; pkt.type = CMD_FONT_INIT;
thr->cmd_data.font_init.font_driver = (const void**)font_driver; pkt.data.font_init.method = font_init_first;
thr->cmd_data.font_init.font_handle = font_handle; pkt.data.font_init.font_driver = (const void**)font_driver;
thr->cmd_data.font_init.video_data = video_data; pkt.data.font_init.font_handle = font_handle;
thr->cmd_data.font_init.font_path = font_path; pkt.data.font_init.video_data = video_data;
thr->cmd_data.font_init.font_size = font_size; pkt.data.font_init.font_path = font_path;
thr->cmd_data.font_init.api = FONT_DRIVER_RENDER_OPENGL_API; pkt.data.font_init.font_size = font_size;
pkt.data.font_init.api = FONT_DRIVER_RENDER_OPENGL_API;
thr->send_cmd_func(thr, CMD_FONT_INIT); thr->send_and_wait(thr, &pkt);
thr->wait_reply_func(thr, CMD_FONT_INIT);
return thr->cmd_data.font_init.return_value; return pkt.data.font_init.return_value;
} }
return font_init_first(font_driver, font_handle, video_data, return font_init_first(font_driver, font_handle, video_data,