video_thread_wrapper.c - make code safer - prevent more null pointer

dereferences
This commit is contained in:
twinaphex 2014-08-14 16:39:35 +02:00
parent ea178216cc
commit 9bb044a79b

View File

@ -175,10 +175,11 @@ static void thread_update_driver_state(thread_video_t *thr)
#if defined(HAVE_MENU) #if defined(HAVE_MENU)
if (thr->texture.frame_updated) if (thr->texture.frame_updated)
{ {
thr->poke->set_texture_frame(thr->driver_data, if (thr->poke && thr->poke->set_texture_frame)
thr->texture.frame, thr->texture.rgb32, thr->poke->set_texture_frame(thr->driver_data,
thr->texture.width, thr->texture.height, thr->texture.frame, thr->texture.rgb32,
thr->texture.alpha); thr->texture.width, thr->texture.height,
thr->texture.alpha);
thr->texture.frame_updated = false; thr->texture.frame_updated = false;
} }
@ -192,7 +193,10 @@ static void thread_update_driver_state(thread_video_t *thr)
{ {
unsigned i; unsigned i;
for (i = 0; i < thr->alpha_mods; i++) for (i = 0; i < thr->alpha_mods; i++)
thr->overlay->set_alpha(thr->driver_data, i, thr->alpha_mod[i]); {
if (thr->overlay && thr->overlay->set_alpha)
thr->overlay->set_alpha(thr->driver_data, i, thr->alpha_mod[i]);
}
thr->alpha_update = false; thr->alpha_update = false;
} }
slock_unlock(thr->alpha_lock); slock_unlock(thr->alpha_lock);
@ -200,7 +204,8 @@ static void thread_update_driver_state(thread_video_t *thr)
if (thr->apply_state_changes) if (thr->apply_state_changes)
{ {
thr->poke->apply_state_changes(thr->driver_data); if (thr->poke && thr->poke->apply_state_changes)
thr->poke->apply_state_changes(thr->driver_data);
thr->apply_state_changes = false; thr->apply_state_changes = false;
} }
} }
@ -213,6 +218,7 @@ static void thread_loop(void *data)
for (;;) for (;;)
{ {
bool ret = false;
bool updated = false; bool updated = false;
slock_lock(thr->lock); slock_lock(thr->lock);
while (thr->send_cmd == CMD_NONE && !thr->frame.updated) while (thr->send_cmd == CMD_NONE && !thr->frame.updated)
@ -233,13 +239,17 @@ static void thread_loop(void *data)
case CMD_FREE: case CMD_FREE:
if (thr->driver_data) if (thr->driver_data)
thr->driver->free(thr->driver_data); {
if (thr->driver && thr->driver->free)
thr->driver->free(thr->driver_data);
}
thr->driver_data = NULL; thr->driver_data = NULL;
thread_reply(thr, CMD_FREE); thread_reply(thr, CMD_FREE);
return; return;
case CMD_SET_ROTATION: case CMD_SET_ROTATION:
thr->driver->set_rotation(thr->driver_data, thr->cmd_data.i); if (thr->driver && thr->driver->set_rotation)
thr->driver->set_rotation(thr->driver_data, thr->cmd_data.i);
thread_reply(thr, CMD_SET_ROTATION); thread_reply(thr, CMD_SET_ROTATION);
break; break;
@ -253,7 +263,11 @@ static void thread_loop(void *data)
// This means frame() callback in threaded wrapper will be called from this thread, causing a timeout, and no frame to be rendered. // This means frame() callback in threaded wrapper will be called from this thread, causing a timeout, and no frame to be rendered.
// To avoid this, set a flag so wrapper can see if it's called in this "special" way. // To avoid this, set a flag so wrapper can see if it's called in this "special" way.
thr->frame.within_thread = true; thr->frame.within_thread = true;
thr->cmd_data.b = thr->driver->read_viewport(thr->driver_data, (uint8_t*)thr->cmd_data.v);
if (thr->driver && thr->driver->read_viewport)
ret = thr->driver->read_viewport(thr->driver_data, (uint8_t*)thr->cmd_data.v);
thr->cmd_data.b = ret;
thr->frame.within_thread = false; thr->frame.within_thread = false;
thread_reply(thr, CMD_READ_VIEWPORT); thread_reply(thr, CMD_READ_VIEWPORT);
} }
@ -266,10 +280,7 @@ static void thread_loop(void *data)
} }
case CMD_SET_SHADER: case CMD_SET_SHADER:
{ if (thr->driver && thr->driver->set_shader)
bool ret = false;
if (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, thr->cmd_data.set_shader.type,
thr->cmd_data.set_shader.path); thr->cmd_data.set_shader.path);
@ -277,58 +288,69 @@ static void thread_loop(void *data)
thr->cmd_data.b = ret; thr->cmd_data.b = ret;
thread_reply(thr, CMD_SET_SHADER); thread_reply(thr, CMD_SET_SHADER);
break; break;
}
case CMD_ALIVE: case CMD_ALIVE:
thr->cmd_data.b = thr->driver->alive(thr->driver_data); if (thr->driver && thr->driver->alive)
ret = thr->driver->alive(thr->driver_data);
thr->cmd_data.b = ret;
thread_reply(thr, CMD_ALIVE); thread_reply(thr, CMD_ALIVE);
break; break;
#ifdef HAVE_OVERLAY #ifdef HAVE_OVERLAY
case CMD_OVERLAY_ENABLE: case CMD_OVERLAY_ENABLE:
thr->overlay->enable(thr->driver_data, thr->cmd_data.b); if (thr->overlay && thr->overlay->enable)
thr->overlay->enable(thr->driver_data, thr->cmd_data.b);
thread_reply(thr, CMD_OVERLAY_ENABLE); thread_reply(thr, CMD_OVERLAY_ENABLE);
break; break;
case CMD_OVERLAY_LOAD: case CMD_OVERLAY_LOAD:
thr->cmd_data.b = thr->overlay->load(thr->driver_data,
thr->cmd_data.image.data, if (thr->overlay && thr->overlay->load)
thr->cmd_data.image.num); ret = thr->overlay->load(thr->driver_data,
thr->cmd_data.image.data,
thr->cmd_data.image.num);
thr->cmd_data.b = ret;
thr->alpha_mods = thr->cmd_data.image.num; thr->alpha_mods = thr->cmd_data.image.num;
thr->alpha_mod = (float*)realloc(thr->alpha_mod, thr->alpha_mods * sizeof(float)); thr->alpha_mod = (float*)realloc(thr->alpha_mod, thr->alpha_mods * sizeof(float));
for (i = 0; i < thr->alpha_mods; i++) // Avoid temporary garbage data. for (i = 0; i < thr->alpha_mods; i++) // 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, CMD_OVERLAY_LOAD);
break; break;
case CMD_OVERLAY_TEX_GEOM: case CMD_OVERLAY_TEX_GEOM:
thr->overlay->tex_geom(thr->driver_data, if (thr->overlay && thr->overlay->tex_geom)
thr->cmd_data.rect.index, thr->overlay->tex_geom(thr->driver_data,
thr->cmd_data.rect.x, thr->cmd_data.rect.index,
thr->cmd_data.rect.y, thr->cmd_data.rect.x,
thr->cmd_data.rect.w, thr->cmd_data.rect.y,
thr->cmd_data.rect.h); thr->cmd_data.rect.w,
thr->cmd_data.rect.h);
thread_reply(thr, CMD_OVERLAY_TEX_GEOM); thread_reply(thr, CMD_OVERLAY_TEX_GEOM);
break; break;
case CMD_OVERLAY_VERTEX_GEOM: case CMD_OVERLAY_VERTEX_GEOM:
thr->overlay->vertex_geom(thr->driver_data, if (thr->overlay && thr->overlay->vertex_geom)
thr->cmd_data.rect.index, thr->overlay->vertex_geom(thr->driver_data,
thr->cmd_data.rect.x, thr->cmd_data.rect.index,
thr->cmd_data.rect.y, thr->cmd_data.rect.x,
thr->cmd_data.rect.w, thr->cmd_data.rect.y,
thr->cmd_data.rect.h); thr->cmd_data.rect.w,
thr->cmd_data.rect.h);
thread_reply(thr, CMD_OVERLAY_VERTEX_GEOM); thread_reply(thr, CMD_OVERLAY_VERTEX_GEOM);
break; break;
case CMD_OVERLAY_FULL_SCREEN: case CMD_OVERLAY_FULL_SCREEN:
thr->overlay->full_screen(thr->driver_data, thr->cmd_data.b); 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); thread_reply(thr, CMD_OVERLAY_FULL_SCREEN);
break; break;
#endif #endif
case CMD_POKE_SET_FILTERING: case CMD_POKE_SET_FILTERING:
if (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, thr->cmd_data.filtering.index,
thr->cmd_data.filtering.smooth); thr->cmd_data.filtering.smooth);
@ -355,17 +377,26 @@ static void thread_loop(void *data)
slock_lock(thr->frame.lock); slock_lock(thr->frame.lock);
thread_update_driver_state(thr); thread_update_driver_state(thr);
bool ret = thr->driver->frame(thr->driver_data, bool ret = false;
bool alive = false;
bool focus = false;
struct rarch_viewport vp = {0};
if (thr->driver && thr->driver->frame)
ret = thr->driver->frame(thr->driver_data,
thr->frame.buffer, thr->frame.width, thr->frame.height, thr->frame.buffer, thr->frame.width, thr->frame.height,
thr->frame.pitch, *thr->frame.msg ? thr->frame.msg : NULL); thr->frame.pitch, *thr->frame.msg ? thr->frame.msg : NULL);
slock_unlock(thr->frame.lock); slock_unlock(thr->frame.lock);
bool alive = ret && thr->driver->alive(thr->driver_data); if (thr->driver && thr->driver->alive)
bool focus = ret && thr->driver->focus(thr->driver_data); alive = ret && thr->driver->alive(thr->driver_data);
struct rarch_viewport vp = {0}; if (thr->driver && thr->driver->focus)
thr->driver->viewport_info(thr->driver_data, &vp); focus = ret && thr->driver->focus(thr->driver_data);
if (thr->driver && thr->driver->viewport_info)
thr->driver->viewport_info(thr->driver_data, &vp);
slock_lock(thr->lock); slock_lock(thr->lock);
thr->alive = alive; thr->alive = alive;
@ -431,7 +462,10 @@ static bool thread_frame(void *data, const void *frame_,
if (thr->frame.within_thread) if (thr->frame.within_thread)
{ {
thread_update_driver_state(thr); thread_update_driver_state(thr);
return thr->driver->frame(thr->driver_data, frame_, width, height, pitch, msg);
if (thr->driver && thr->driver->frame)
return thr->driver->frame(thr->driver_data, frame_, width, height, pitch, msg);
return false;
} }
RARCH_PERFORMANCE_INIT(thread_frame); RARCH_PERFORMANCE_INIT(thread_frame);
@ -444,8 +478,6 @@ static bool thread_frame(void *data, const void *frame_,
slock_lock(thr->lock); slock_lock(thr->lock);
// scond_wait_timeout cannot be implemented on consoles.
#ifndef RARCH_CONSOLE
if (!thr->nonblock) if (!thr->nonblock)
{ {
retro_time_t target_frame_time = (retro_time_t)roundf(1000000LL / g_settings.video.refresh_rate); retro_time_t target_frame_time = (retro_time_t)roundf(1000000LL / g_settings.video.refresh_rate);
@ -463,7 +495,6 @@ static bool thread_frame(void *data, const void *frame_,
break; break;
} }
} }
#endif
// Drop frame if updated flag is still set, as thread is still working on last frame. // Drop frame if updated flag is still set, as thread is still working on last frame.
if (!thr->frame.updated) if (!thr->frame.updated)