fbdev: fix segfault on video thread switch and exit from hw_ctx cores (#13571)

pull/13575/head
Giovanni Cascione 2022-01-30 09:24:33 +01:00 committed by GitHub
parent 84052ee7e1
commit ffbbdbd256
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 62 additions and 41 deletions

View File

@ -53,14 +53,17 @@ typedef struct
float refresh_rate;
} mali_ctx_data_t;
mali_ctx_data_t *mali=NULL;
mali_ctx_data_t *gfx_ctx_mali_fbdev_global=NULL;
bool gfx_ctx_mali_fbdev_was_threaded=false;
bool gfx_ctx_mali_fbdev_hw_ctx_trigger=false;
bool gfx_ctx_mali_fbdev_restart_pending=false;
static int gfx_ctx_mali_fbdev_get_vinfo(void *data)
{
struct fb_var_screeninfo vinfo;
int fd = open("/dev/fb0", O_RDWR);
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
if (!mali || ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
goto error;
@ -106,32 +109,12 @@ static void gfx_ctx_mali_fbdev_clear_screen(void)
struct fb_var_screeninfo vinfo;
void *buffer = NULL;
int fd = open("/dev/fb0", O_RDWR);
ioctl (fd, FBIOGET_VSCREENINFO, &vinfo);
long buffer_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
buffer = calloc(1, buffer_size);
write(fd,buffer,buffer_size);
free(buffer);
close(fd);
}
static void gfx_ctx_mali_fbdev_destroy(void *data)
{
mali = (mali_ctx_data_t*)data;
if (mali)
mali->resize = false;
runloop_state_t *runloop_st = runloop_state_get_ptr();
if (runloop_st->shutdown_initiated) {
#ifdef HAVE_EGL
if (mali)
egl_destroy(&mali->egl);
#endif
gfx_ctx_mali_fbdev_clear_screen();
/* Clear framebuffer and set cursor on again */
if (!system(NULL) && !system("which setterm > /dev/null 2>&1"))
@ -142,13 +125,49 @@ static void gfx_ctx_mali_fbdev_destroy(void *data)
close(fd);
system("setterm -cursor on");
}
}
/*TODO FIXME
As egl_destroy does not work properly with libmali (big fps drop after destroy and initialization/creation of new context/surface), it is not used.
A global pointers is initialized at startup in gfx_ctx_mali_fbdev_init, and returned each time gfx_ctx_mali_fbdev_init is called.
Originally gfx_ctx_mali_fbdev_init initialized a new pointer each time (destroyed each time with egl_destroy), and context/surface creation occurred in gfx_ctx_mali_fbdev_set_video_mode.
With this workaround it's all created once in gfx_ctx_mali_fbdev_init and never destroyed.
Additional workarounds (RA restart) are applied in gfx_ctx_mali_fbdev_destroy in order to avoid segmentation fault when video threaded switch is activated or on exit from cores requesting gfx_ctx_mali_fbdev_hw_ctx_trigger.
All these workarounds should be reverted when and if egl_destroy issues in libmali blobs are fixed.
*/
static void gfx_ctx_mali_fbdev_destroy(void *data)
{
/* mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
if (mali)
{
#ifdef HAVE_EGL
egl_destroy(&mali->egl);
#endif
mali->resize = false;
free(mali);
}
*/
runloop_state_t *runloop_st = runloop_state_get_ptr();
if (runloop_st->shutdown_initiated && gfx_ctx_mali_fbdev_was_threaded==*video_driver_get_threaded() && !gfx_ctx_mali_fbdev_hw_ctx_trigger)
{
gfx_ctx_mali_fbdev_clear_screen();
}else if (gfx_ctx_mali_fbdev_hw_ctx_trigger)
{
video_context_driver_reset();
gfx_ctx_mali_fbdev_global=NULL;
gfx_ctx_mali_fbdev_restart_pending=true;
}else if (gfx_ctx_mali_fbdev_was_threaded!=*video_driver_get_threaded()){
command_event(CMD_EVENT_RESTART_RETROARCH,NULL);
}
}
static void gfx_ctx_mali_fbdev_get_video_size(void *data,
unsigned *width, unsigned *height)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
*width = mali->width;
*height = mali->height;
@ -156,8 +175,8 @@ static void gfx_ctx_mali_fbdev_get_video_size(void *data,
static void *gfx_ctx_mali_fbdev_init(void *video_driver)
{
if (mali)
return mali;
if (gfx_ctx_mali_fbdev_global)
return gfx_ctx_mali_fbdev_global;
#ifdef HAVE_EGL
EGLint n;
@ -174,13 +193,13 @@ static void *gfx_ctx_mali_fbdev_init(void *video_driver)
};
static const EGLint attribs_create[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
#endif
mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali));
mali_ctx_data_t *mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali));
if (!mali)
return NULL;
@ -189,7 +208,7 @@ static void *gfx_ctx_mali_fbdev_init(void *video_driver)
#ifdef HAVE_EGL
frontend_driver_install_signal_handler();
mali->egl.use_hw_ctx=true;
if (!egl_init_context(&mali->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
&major, &minor, &n, attribs_init, NULL) ||
!egl_create_context(&mali->egl, attribs_create) ||
@ -197,11 +216,13 @@ static void *gfx_ctx_mali_fbdev_init(void *video_driver)
goto error;
#endif
gfx_ctx_mali_fbdev_global=mali;
gfx_ctx_mali_fbdev_was_threaded=*video_driver_get_threaded();
return mali;
error:
egl_report_error();
gfx_ctx_mali_fbdev_destroy(video_driver);
gfx_ctx_mali_fbdev_destroy(mali);
return NULL;
}
@ -220,16 +241,22 @@ static void gfx_ctx_mali_fbdev_check_window(void *data, bool *quit,
}
*quit = (bool)frontend_driver_get_signal_handler_state();
if (gfx_ctx_mali_fbdev_restart_pending)
command_event(CMD_EVENT_RESTART_RETROARCH,NULL);
}
static bool gfx_ctx_mali_fbdev_set_video_mode(void *data,
unsigned width, unsigned height,
bool fullscreen)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
if (video_driver_is_hw_context())
gfx_ctx_mali_fbdev_hw_ctx_trigger=true;
if (gfx_ctx_mali_fbdev_get_vinfo(mali))
goto error;
goto error;
width = mali->width;
height = mali->height;
@ -269,26 +296,21 @@ static bool gfx_ctx_mali_fbdev_suppress_screensaver(void *data, bool enable) { r
static void gfx_ctx_mali_fbdev_set_swap_interval(void *data,
int swap_interval)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_set_swap_interval(&mali->egl, swap_interval);
#endif
}
static void gfx_ctx_mali_fbdev_swap_buffers(void *data)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_swap_buffers(&mali->egl);
#endif
}
static void gfx_ctx_mali_fbdev_bind_hw_render(void *data, bool enable)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_bind_hw_render(&mali->egl, enable);
#endif
@ -297,7 +319,6 @@ static void gfx_ctx_mali_fbdev_bind_hw_render(void *data, bool enable)
static uint32_t gfx_ctx_mali_fbdev_get_flags(void *data)
{
uint32_t flags = 0;
BIT32_SET(flags, GFX_CTX_FLAGS_SHADERS_GLSL);
return flags;
@ -307,7 +328,7 @@ static void gfx_ctx_mali_fbdev_set_flags(void *data, uint32_t flags) { }
static float gfx_ctx_mali_fbdev_get_refresh_rate(void *data)
{
mali = (mali_ctx_data_t*)data;
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
return mali->refresh_rate;
}