mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-04 08:16:25 +00:00
Fix GPU screenshots with GL + threaded driver.
This commit is contained in:
parent
ffed705b4c
commit
28d1e77a36
@ -144,6 +144,7 @@ typedef struct thread_video
|
||||
unsigned height;
|
||||
unsigned pitch;
|
||||
bool updated;
|
||||
bool within_thread;
|
||||
char msg[1024];
|
||||
} frame;
|
||||
|
||||
@ -170,6 +171,41 @@ static void thread_reply(thread_video_t *thr, enum thread_cmd cmd)
|
||||
slock_unlock(thr->lock);
|
||||
}
|
||||
|
||||
static void thread_update_driver_state(thread_video_t *thr)
|
||||
{
|
||||
#if defined(HAVE_MENU)
|
||||
if (thr->texture.frame_updated)
|
||||
{
|
||||
thr->poke->set_texture_frame(thr->driver_data,
|
||||
thr->texture.frame, thr->texture.rgb32,
|
||||
thr->texture.width, thr->texture.height,
|
||||
thr->texture.alpha);
|
||||
thr->texture.frame_updated = false;
|
||||
}
|
||||
|
||||
if (thr->poke && thr->poke->set_texture_enable)
|
||||
thr->poke->set_texture_enable(thr->driver_data, thr->texture.enable, thr->texture.full_screen);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OVERLAY)
|
||||
slock_lock(thr->alpha_lock);
|
||||
if (thr->alpha_update)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < thr->alpha_mods; i++)
|
||||
thr->overlay->set_alpha(thr->driver_data, i, thr->alpha_mod[i]);
|
||||
thr->alpha_update = false;
|
||||
}
|
||||
slock_unlock(thr->alpha_lock);
|
||||
#endif
|
||||
|
||||
if (thr->apply_state_changes)
|
||||
{
|
||||
thr->poke->apply_state_changes(thr->driver_data);
|
||||
thr->apply_state_changes = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_loop(void *data)
|
||||
{
|
||||
thread_video_t *thr = (thread_video_t*)data;
|
||||
@ -214,7 +250,12 @@ static void thread_loop(void *data)
|
||||
thr->driver->viewport_info(thr->driver_data, &vp);
|
||||
if (memcmp(&vp, &thr->read_vp, sizeof(vp)) == 0) // We can read safely
|
||||
{
|
||||
// read_viewport() in GL driver calls rarch_render_cached_frame() to be able to read from back buffer.
|
||||
// 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.
|
||||
thr->frame.within_thread = true;
|
||||
thr->cmd_data.b = thr->driver->read_viewport(thr->driver_data, (uint8_t*)thr->cmd_data.v);
|
||||
thr->frame.within_thread = false;
|
||||
thread_reply(thr, CMD_READ_VIEWPORT);
|
||||
}
|
||||
else // Viewport dimensions changed right after main thread read the async value. Cannot read safely.
|
||||
@ -309,41 +350,11 @@ static void thread_loop(void *data)
|
||||
{
|
||||
slock_lock(thr->frame.lock);
|
||||
|
||||
#if defined(HAVE_MENU)
|
||||
if (thr->texture.frame_updated)
|
||||
{
|
||||
thr->poke->set_texture_frame(thr->driver_data,
|
||||
thr->texture.frame, thr->texture.rgb32,
|
||||
thr->texture.width, thr->texture.height,
|
||||
thr->texture.alpha);
|
||||
thr->texture.frame_updated = false;
|
||||
}
|
||||
|
||||
if (thr->poke && thr->poke->set_texture_enable)
|
||||
thr->poke->set_texture_enable(thr->driver_data, thr->texture.enable, thr->texture.full_screen);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OVERLAY)
|
||||
slock_lock(thr->alpha_lock);
|
||||
if (thr->alpha_update)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < thr->alpha_mods; i++)
|
||||
thr->overlay->set_alpha(thr->driver_data, i, thr->alpha_mod[i]);
|
||||
thr->alpha_update = false;
|
||||
}
|
||||
slock_unlock(thr->alpha_lock);
|
||||
#endif
|
||||
|
||||
if (thr->apply_state_changes)
|
||||
{
|
||||
thr->poke->apply_state_changes(thr->driver_data);
|
||||
thr->apply_state_changes = false;
|
||||
}
|
||||
|
||||
thread_update_driver_state(thr);
|
||||
bool ret = thr->driver->frame(thr->driver_data,
|
||||
thr->frame.buffer, thr->frame.width, thr->frame.height,
|
||||
thr->frame.pitch, *thr->frame.msg ? thr->frame.msg : NULL);
|
||||
|
||||
slock_unlock(thr->frame.lock);
|
||||
|
||||
bool alive = ret && thr->driver->alive(thr->driver_data);
|
||||
@ -410,10 +421,18 @@ static bool thread_focus(void *data)
|
||||
static bool thread_frame(void *data, const void *frame_,
|
||||
unsigned width, unsigned height, unsigned pitch, const char *msg)
|
||||
{
|
||||
thread_video_t *thr = (thread_video_t*)data;
|
||||
|
||||
// If called from within read_viewport, we're actually in the driver thread, so just render directly.
|
||||
if (thr->frame.within_thread)
|
||||
{
|
||||
thread_update_driver_state(thr);
|
||||
return thr->driver->frame(thr->driver_data, frame_, width, height, pitch, msg);
|
||||
}
|
||||
|
||||
RARCH_PERFORMANCE_INIT(thread_frame);
|
||||
RARCH_PERFORMANCE_START(thread_frame);
|
||||
|
||||
thread_video_t *thr = (thread_video_t*)data;
|
||||
unsigned copy_stride = width * (thr->info.rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
|
||||
const uint8_t *src = (const uint8_t*)frame_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user