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();
thread_video_t *thr = (thread_video_t*)driver->video_data;
thread_packet_t pkt = { CMD_CUSTOM_COMMAND };
if (!thr)
return 0;
@ -100,22 +101,21 @@ unsigned video_texture_load(void *data,
case TEXTURE_BACKEND_OPENGL:
if (filter_type == TEXTURE_FILTER_MIPMAP_LINEAR ||
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
thr->cmd_data.custom_command.method = video_texture_png_load_wrap_gl;
pkt.data.custom_command.method = video_texture_png_load_wrap_gl;
break;
case TEXTURE_BACKEND_DEFAULT:
default:
thr->cmd_data.custom_command.method = video_texture_png_load_wrap;
pkt.data.custom_command.method = video_texture_png_load_wrap;
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->wait_reply_func(thr, CMD_CUSTOM_COMMAND);
thr->send_and_wait(thr, &pkt);
return thr->cmd_data.custom_command.return_value;
return pkt.data.custom_command.return_value;
}
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;
}
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);
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);
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)
{
#if defined(HAVE_MENU)
@ -90,6 +130,7 @@ static void thread_loop(void *data)
for (;;)
{
thread_packet_t pkt;
enum thread_cmd send_cmd;
bool ret = false;
bool updated = false;
@ -102,8 +143,9 @@ static void thread_loop(void *data)
/* To avoid race condition where send_cmd is updated
* right after the switch is checked. */
send_cmd = thr->send_cmd;
pkt = thr->cmd_data;
slock_unlock(thr->lock);
switch (send_cmd)
@ -111,9 +153,9 @@ static void thread_loop(void *data)
case CMD_INIT:
thr->driver_data = thr->driver->init(&thr->info,
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);
thread_reply(thr, CMD_INIT);
thread_reply(thr, &pkt);
break;
case CMD_FREE:
@ -123,13 +165,13 @@ static void thread_loop(void *data)
thr->driver->free(thr->driver_data);
}
thr->driver_data = NULL;
thread_reply(thr, CMD_FREE);
thread_reply(thr, &pkt);
return;
case CMD_SET_ROTATION:
if (thr->driver && thr->driver->set_rotation)
thr->driver->set_rotation(thr->driver_data, thr->cmd_data.i);
thread_reply(thr, CMD_SET_ROTATION);
thr->driver->set_rotation(thr->driver_data, pkt.data.i);
thread_reply(thr, &pkt);
break;
case CMD_READ_VIEWPORT:
@ -156,55 +198,55 @@ static void thread_loop(void *data)
if (thr->driver && thr->driver->read_viewport)
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;
}
else
{
/* Viewport dimensions changed right after main
* 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;
}
case CMD_SET_SHADER:
if (thr->driver && thr->driver->set_shader)
ret = thr->driver->set_shader(thr->driver_data,
thr->cmd_data.set_shader.type,
thr->cmd_data.set_shader.path);
pkt.data.set_shader.type,
pkt.data.set_shader.path);
thr->cmd_data.b = ret;
thread_reply(thr, CMD_SET_SHADER);
pkt.data.b = ret;
thread_reply(thr, &pkt);
break;
case CMD_ALIVE:
if (thr->driver && thr->driver->alive)
ret = thr->driver->alive(thr->driver_data);
thr->cmd_data.b = ret;
thread_reply(thr, CMD_ALIVE);
pkt.data.b = ret;
thread_reply(thr, &pkt);
break;
#ifdef HAVE_OVERLAY
case CMD_OVERLAY_ENABLE:
if (thr->overlay && thr->overlay->enable)
thr->overlay->enable(thr->driver_data, thr->cmd_data.b);
thread_reply(thr, CMD_OVERLAY_ENABLE);
thr->overlay->enable(thr->driver_data, pkt.data.b);
thread_reply(thr, &pkt);
break;
case CMD_OVERLAY_LOAD:
if (thr->overlay && thr->overlay->load)
ret = thr->overlay->load(thr->driver_data,
thr->cmd_data.image.data,
thr->cmd_data.image.num);
pkt.data.image.data,
pkt.data.image.num);
thr->cmd_data.b = ret;
thr->alpha_mods = thr->cmd_data.image.num;
pkt.data.b = ret;
thr->alpha_mods = pkt.data.image.num;
thr->alpha_mod = (float*)realloc(thr->alpha_mod,
thr->alpha_mods * sizeof(float));
@ -213,118 +255,117 @@ static void thread_loop(void *data)
/* Avoid temporary garbage data. */
thr->alpha_mod[i] = 1.0f;
}
thread_reply(thr, CMD_OVERLAY_LOAD);
thread_reply(thr, &pkt);
break;
case CMD_OVERLAY_TEX_GEOM:
if (thr->overlay && thr->overlay->tex_geom)
thr->overlay->tex_geom(thr->driver_data,
thr->cmd_data.rect.index,
thr->cmd_data.rect.x,
thr->cmd_data.rect.y,
thr->cmd_data.rect.w,
thr->cmd_data.rect.h);
thread_reply(thr, CMD_OVERLAY_TEX_GEOM);
pkt.data.rect.index,
pkt.data.rect.x,
pkt.data.rect.y,
pkt.data.rect.w,
pkt.data.rect.h);
thread_reply(thr, &pkt);
break;
case CMD_OVERLAY_VERTEX_GEOM:
if (thr->overlay && thr->overlay->vertex_geom)
thr->overlay->vertex_geom(thr->driver_data,
thr->cmd_data.rect.index,
thr->cmd_data.rect.x,
thr->cmd_data.rect.y,
thr->cmd_data.rect.w,
thr->cmd_data.rect.h);
thread_reply(thr, CMD_OVERLAY_VERTEX_GEOM);
pkt.data.rect.index,
pkt.data.rect.x,
pkt.data.rect.y,
pkt.data.rect.w,
pkt.data.rect.h);
thread_reply(thr, &pkt);
break;
case CMD_OVERLAY_FULL_SCREEN:
if (thr->overlay && thr->overlay->full_screen)
thr->overlay->full_screen(thr->driver_data,
thr->cmd_data.b);
thread_reply(thr, CMD_OVERLAY_FULL_SCREEN);
pkt.data.b);
thread_reply(thr, &pkt);
break;
#endif
case CMD_POKE_SET_VIDEO_MODE:
if (thr->poke && thr->poke->set_video_mode)
thr->poke->set_video_mode(thr->driver_data,
thr->cmd_data.new_mode.width,
thr->cmd_data.new_mode.height,
thr->cmd_data.new_mode.fullscreen);
thread_reply(thr, CMD_POKE_SET_VIDEO_MODE);
pkt.data.new_mode.width,
pkt.data.new_mode.height,
pkt.data.new_mode.fullscreen);
thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_FILTERING:
if (thr->poke && thr->poke->set_filtering)
thr->poke->set_filtering(thr->driver_data,
thr->cmd_data.filtering.index,
thr->cmd_data.filtering.smooth);
thread_reply(thr, CMD_POKE_SET_FILTERING);
pkt.data.filtering.index,
pkt.data.filtering.smooth);
thread_reply(thr, &pkt);
break;
case CMD_POKE_GET_VIDEO_OUTPUT_SIZE:
if (thr->poke && thr->poke->get_video_output_size)
thr->poke->get_video_output_size(thr->driver_data,
&thr->cmd_data.output.width,
&thr->cmd_data.output.height);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE);
&pkt.data.output.width,
&pkt.data.output.height);
thread_reply(thr, &pkt);
break;
case CMD_POKE_GET_VIDEO_OUTPUT_PREV:
if (thr->poke && thr->poke->get_video_output_prev)
thr->poke->get_video_output_prev(thr->driver_data);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV);
thread_reply(thr, &pkt);
break;
case CMD_POKE_GET_VIDEO_OUTPUT_NEXT:
if (thr->poke && thr->poke->get_video_output_next)
thr->poke->get_video_output_next(thr->driver_data);
thread_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT);
thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_ASPECT_RATIO:
thr->poke->set_aspect_ratio(thr->driver_data,
thr->cmd_data.i);
thread_reply(thr, CMD_POKE_SET_ASPECT_RATIO);
pkt.data.i);
thread_reply(thr, &pkt);
break;
case CMD_POKE_SET_OSD_MSG:
if (thr->poke && thr->poke->set_osd_msg)
thr->poke->set_osd_msg(thr->driver_data,
thr->cmd_data.osd_message.msg,
&thr->cmd_data.osd_message.params, NULL);
thread_reply(thr, CMD_POKE_SET_OSD_MSG);
pkt.data.osd_message.msg,
&pkt.data.osd_message.params, NULL);
thread_reply(thr, &pkt);
break;
case CMD_FONT_INIT:
if (thr->cmd_data.font_init.method)
thr->cmd_data.font_init.return_value =
thr->cmd_data.font_init.method
(thr->cmd_data.font_init.font_driver,
thr->cmd_data.font_init.font_handle,
thr->cmd_data.font_init.video_data,
thr->cmd_data.font_init.font_path,
thr->cmd_data.font_init.font_size,
thr->cmd_data.font_init.api);
thread_reply(thr, CMD_FONT_INIT);
if (pkt.data.font_init.method)
pkt.data.font_init.return_value =
pkt.data.font_init.method
(pkt.data.font_init.font_driver,
pkt.data.font_init.font_handle,
pkt.data.font_init.video_data,
pkt.data.font_init.font_path,
pkt.data.font_init.font_size,
pkt.data.font_init.api);
thread_reply(thr, &pkt);
break;
case CMD_CUSTOM_COMMAND:
if (thr->cmd_data.custom_command.method)
thr->cmd_data.custom_command.return_value =
thr->cmd_data.custom_command.method
(thr->cmd_data.custom_command.data);
thread_reply(thr, CMD_CUSTOM_COMMAND);
if (pkt.data.custom_command.method)
pkt.data.custom_command.return_value =
pkt.data.custom_command.method
(pkt.data.custom_command.data);
thread_reply(thr, &pkt);
break;
case CMD_NONE:
/* Never reply on no command. Possible deadlock if
* thread sends command right after frame update. */
break;
default:
thread_reply(thr, send_cmd);
thread_reply(thr, &pkt);
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)
{
@ -396,9 +423,9 @@ static bool thread_alive(void *data)
if (runloop->is_paused)
{
thread_send_cmd(thr, CMD_ALIVE);
thread_wait_reply(thr, CMD_ALIVE);
return thr->cmd_data.b;
thread_packet_t pkt = { CMD_ALIVE };
thread_send_and_wait(thr, &pkt);
return pkt.data.b;
}
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)
{
size_t max_size;
thread_packet_t pkt = {CMD_INIT};
thr->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)
return false;
thread_send_cmd(thr, CMD_INIT);
thread_wait_reply(thr, CMD_INIT);
thread_send_and_wait(thr, &pkt);
thr->send_cmd_func = thread_send_cmd;
thr->wait_reply_func = thread_wait_reply;
// thr->send_cmd_func = thread_send_cmd;
// 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,
enum rarch_shader_type type, const char *path)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = {CMD_SET_SHADER};
if (!thr)
return false;
thr->cmd_data.set_shader.type = type;
thr->cmd_data.set_shader.path = path;
thread_send_cmd(thr, CMD_SET_SHADER);
thread_wait_reply(thr, CMD_SET_SHADER);
pkt.data.set_shader.type = type;
pkt.data.set_shader.path = path;
thread_send_and_wait(thr, &pkt);
return thr->cmd_data.b;
return pkt.data.b;
}
static void thread_set_viewport(void *data, unsigned width,
unsigned height, bool force_full, bool allow_rotate)
{
thread_video_t *thr = (thread_video_t*)data;
if (!thr)
return;
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)
thr->driver->set_viewport(thr->driver_data,
thr->cmd_data.set_viewport.width,
thr->cmd_data.set_viewport.height,
thr->cmd_data.set_viewport.force_full,
thr->cmd_data.set_viewport.allow_rotate);
thr->driver->set_viewport(thr->driver_data, width, height,
force_full, allow_rotate);
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)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_SET_ROTATION };
if (!thr)
return;
thr->cmd_data.i = rotation;
thread_send_cmd(thr, CMD_SET_ROTATION);
thread_wait_reply(thr, CMD_SET_ROTATION);
pkt.data.i = rotation;
thread_send_and_wait(thr, &pkt);
}
/* 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)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_READ_VIEWPORT };
if (!thr)
return false;
thr->cmd_data.v = buffer;
thread_send_cmd(thr, CMD_READ_VIEWPORT);
thread_wait_reply(thr, CMD_READ_VIEWPORT);
pkt.data.v = buffer;
thread_send_and_wait(thr, &pkt);
return thr->cmd_data.b;
return pkt.data.b;
}
static void thread_free(void *data)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_FREE };
if (!thr)
return;
thread_send_cmd(thr, CMD_FREE);
thread_wait_reply(thr, CMD_FREE);
thread_send_and_wait(thr, &pkt);
sthread_join(thr->thread);
#if defined(HAVE_MENU)
@ -707,69 +728,73 @@ static void thread_free(void *data)
static void thread_overlay_enable(void *data, bool state)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_ENABLE };
if (!thr)
return;
thr->cmd_data.b = state;
thread_send_cmd(thr, CMD_OVERLAY_ENABLE);
thread_wait_reply(thr, CMD_OVERLAY_ENABLE);
pkt.data.b = state;
thread_send_and_wait(thr, &pkt);
}
static bool thread_overlay_load(void *data,
const struct texture_image *images, unsigned num_images)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_LOAD };
if (!thr)
return false;
thr->cmd_data.image.data = images;
thr->cmd_data.image.num = num_images;
thread_send_cmd(thr, CMD_OVERLAY_LOAD);
thread_wait_reply(thr, CMD_OVERLAY_LOAD);
pkt.data.image.data = images;
pkt.data.image.num = num_images;
thread_send_and_wait(thr, &pkt);
return thr->cmd_data.b;
return pkt.data.b;
}
static void thread_overlay_tex_geom(void *data,
unsigned idx, float x, float y, float w, float h)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_TEX_GEOM };
if (!thr)
return;
thr->cmd_data.rect.index = idx;
thr->cmd_data.rect.x = x;
thr->cmd_data.rect.y = y;
thr->cmd_data.rect.w = w;
thr->cmd_data.rect.h = h;
thread_send_cmd(thr, CMD_OVERLAY_TEX_GEOM);
thread_wait_reply(thr, CMD_OVERLAY_TEX_GEOM);
pkt.data.rect.index = idx;
pkt.data.rect.x = x;
pkt.data.rect.y = y;
pkt.data.rect.w = w;
pkt.data.rect.h = h;
thread_send_and_wait(thr, &pkt);
}
static void thread_overlay_vertex_geom(void *data,
unsigned idx, float x, float y, float w, float h)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_VERTEX_GEOM };
if (!thr)
return;
thr->cmd_data.rect.index = idx;
thr->cmd_data.rect.x = x;
thr->cmd_data.rect.y = y;
thr->cmd_data.rect.w = w;
thr->cmd_data.rect.h = h;
thread_send_cmd(thr, CMD_OVERLAY_VERTEX_GEOM);
thread_wait_reply(thr, CMD_OVERLAY_VERTEX_GEOM);
pkt.data.rect.index = idx;
pkt.data.rect.x = x;
pkt.data.rect.y = y;
pkt.data.rect.w = w;
pkt.data.rect.h = h;
thread_send_and_wait(thr, &pkt);
}
static void thread_overlay_full_screen(void *data, bool enable)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_OVERLAY_FULL_SCREEN };
thr->cmd_data.b = enable;
thread_send_cmd(thr, CMD_OVERLAY_FULL_SCREEN);
thread_wait_reply(thr, CMD_OVERLAY_FULL_SCREEN);
pkt.data.b = enable;
thread_send_and_wait(thr, &pkt);
}
/* 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)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_VIDEO_MODE };
if (!thr)
return;
thr->cmd_data.new_mode.width = width;
thr->cmd_data.new_mode.height = height;
thr->cmd_data.new_mode.fullscreen = fullscreen;
thread_send_cmd(thr, CMD_POKE_SET_VIDEO_MODE);
thread_wait_reply(thr, CMD_POKE_SET_VIDEO_MODE);
pkt.data.new_mode.width = width;
pkt.data.new_mode.height = height;
pkt.data.new_mode.fullscreen = fullscreen;
thread_send_and_wait(thr, &pkt);
}
static void thread_set_filtering(void *data, unsigned idx, bool smooth)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_FILTERING };
if (!thr)
return;
thr->cmd_data.filtering.index = idx;
thr->cmd_data.filtering.smooth = smooth;
thread_send_cmd(thr, CMD_POKE_SET_FILTERING);
thread_wait_reply(thr, CMD_POKE_SET_FILTERING);
pkt.data.filtering.index = idx;
pkt.data.filtering.smooth = smooth;
thread_send_and_wait(thr, &pkt);
}
static void thread_get_video_output_size(void *data,
unsigned *width, unsigned *height)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_SIZE };
if (!thr)
return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_SIZE);
*width = thr->cmd_data.output.width;
*height = thr->cmd_data.output.height;
thread_send_and_wait(thr, &pkt);
*width = pkt.data.output.width;
*height = pkt.data.output.height;
}
static void thread_get_video_output_prev(void *data)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_PREV };
if (!thr)
return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_PREV);
thread_send_and_wait(thr, &pkt);
}
static void thread_get_video_output_next(void *data)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_GET_VIDEO_OUTPUT_NEXT };
if (!thr)
return;
thread_send_cmd(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT);
thread_wait_reply(thr, CMD_POKE_GET_VIDEO_OUTPUT_NEXT);
thread_send_and_wait(thr, &pkt);
}
static void thread_set_aspect_ratio(void *data, unsigned aspectratio_idx)
{
thread_video_t *thr = (thread_video_t*)data;
thread_packet_t pkt = { CMD_POKE_SET_ASPECT_RATIO };
if (!thr)
return;
thr->cmd_data.i = aspectratio_idx;
thread_send_cmd(thr, CMD_POKE_SET_ASPECT_RATIO);
thread_wait_reply(thr, CMD_POKE_SET_ASPECT_RATIO);
pkt.data.i = aspectratio_idx;
thread_send_and_wait(thr, &pkt);
}
#if defined(HAVE_MENU)

View File

@ -59,60 +59,9 @@ enum thread_cmd
CMD_DUMMY = INT_MAX
};
typedef struct thread_video
typedef struct
{
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);
enum thread_cmd send_cmd;
enum thread_cmd reply_cmd;
enum thread_cmd type;
union
{
bool b;
@ -182,8 +131,8 @@ typedef struct thread_video
struct
{
bool (*method)(const void **font_driver,
void **font_handle, void *video_data, const char *font_path,
float font_size, enum font_driver_render_api api);
void **font_handle, void *video_data, const char *font_path,
float font_size, enum font_driver_render_api api);
const void **font_driver;
void **font_handle;
void *video_data;
@ -192,8 +141,65 @@ typedef struct thread_video
bool return_value;
enum font_driver_render_api api;
} 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 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();
thread_video_t *thr = (thread_video_t*)driver->video_data;
thread_packet_t pkt;
if (!thr)
return false;
thr->cmd_data.font_init.method = font_init_first;
thr->cmd_data.font_init.font_driver = (const void**)font_driver;
thr->cmd_data.font_init.font_handle = font_handle;
thr->cmd_data.font_init.video_data = video_data;
thr->cmd_data.font_init.font_path = font_path;
thr->cmd_data.font_init.font_size = font_size;
thr->cmd_data.font_init.api = FONT_DRIVER_RENDER_OPENGL_API;
pkt.type = CMD_FONT_INIT;
pkt.data.font_init.method = font_init_first;
pkt.data.font_init.font_driver = (const void**)font_driver;
pkt.data.font_init.font_handle = font_handle;
pkt.data.font_init.video_data = video_data;
pkt.data.font_init.font_path = font_path;
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->wait_reply_func(thr, CMD_FONT_INIT);
thr->send_and_wait(thr, &pkt);
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,