1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-05 17:58:41 +00:00

mali_fbdev fix for fps drop after egl_destroy (#13494)

Currently each time a screen resolution or setting change occurs, fbdev_destroy, fbdev_init and fbdev_set_mode are called in sequence, trying to destroy context and surface (though context pointer seems to remain unchanged) and create again both of them.
However it seems something is wrong with egl_destroy, as after the call fps drops from 60 to 33fps in GUI with huge performance impact, at least with libmali.
Philosophy is changed with this commit to avoid destroying and creating context and surface each time (creation only occurs in fbdev_init and egl_destroy is called only if retroarch is shutting down).
As a minor modification, framebuffer is resetted to 0 on retroarch shutdown to avoid any chance of freezed screen effect.
This commit is contained in:
Giovanni Cascione 2022-01-14 15:30:04 +01:00 committed by GitHub
parent aca2b9675f
commit f93548ab56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -53,35 +53,102 @@ typedef struct
float refresh_rate;
} mali_ctx_data_t;
mali_ctx_data_t *mali=NULL;
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;
if (!mali || ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
goto error;
/*Workaround to reset yoffset when returned >0 from driver */
if (vinfo.yoffset != 0)
{
vinfo.yoffset = 0;
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo))
{
RARCH_ERR("Error resetting yoffset to 0.\n");
}
}
close(fd);
fd = -1;
mali->width = vinfo.xres;
mali->height = vinfo.yres;
mali->native_window.width = vinfo.xres;
mali->native_window.height = vinfo.yres;
if (vinfo.pixclock)
{
mali->refresh_rate = 1000000.0f / vinfo.pixclock * 1000000.0f /
(vinfo.yres + vinfo.upper_margin + vinfo.lower_margin + vinfo.vsync_len) /
(vinfo.xres + vinfo.left_margin + vinfo.right_margin + vinfo.hsync_len);
}else{
mali->refresh_rate = 60;
}
return 0;
error:
if (fd >= 0)
close(fd);
return 1;
}
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_ctx_data_t *mali = (mali_ctx_data_t*)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
egl_destroy(&mali->egl);
if (mali)
egl_destroy(&mali->egl);
#endif
mali->resize = false;
free(mali);
}
gfx_ctx_mali_fbdev_clear_screen();
/* Clear framebuffer and set cursor on again */
if (!system(NULL) && !system("which setterm > /dev/null 2>&1"))
{
int fd = open("/dev/tty", O_RDWR);
ioctl(fd, VT_ACTIVATE, 5);
ioctl(fd, VT_ACTIVATE, 1);
close(fd);
system("setterm -cursor on");
{
int fd = open("/dev/tty", O_RDWR);
ioctl(fd, VT_ACTIVATE, 5);
ioctl(fd, VT_ACTIVATE, 1);
close(fd);
system("setterm -cursor on");
}
}
}
static void gfx_ctx_mali_fbdev_get_video_size(void *data,
unsigned *width, unsigned *height)
{
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
mali = (mali_ctx_data_t*)data;
*width = mali->width;
*height = mali->height;
@ -89,11 +156,14 @@ 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;
#ifdef HAVE_EGL
EGLint n;
EGLint major, minor;
EGLint format;
static const EGLint attribs[] = {
static const EGLint attribs_init[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
@ -102,20 +172,28 @@ static void *gfx_ctx_mali_fbdev_init(void *video_driver)
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
static const EGLint attribs_create[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
#endif
mali_ctx_data_t *mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali));
mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali));
if (!mali)
return NULL;
if (gfx_ctx_mali_fbdev_get_vinfo(mali))
goto error;
#ifdef HAVE_EGL
frontend_driver_install_signal_handler();
#endif
#ifdef HAVE_EGL
if (!egl_init_context(&mali->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
&major, &minor, &n, attribs, NULL))
&major, &minor, &n, attribs_init, NULL) ||
!egl_create_context(&mali->egl, attribs_create) ||
!egl_create_surface(&mali->egl, &mali->native_window))
goto error;
#endif
@ -148,66 +226,17 @@ static bool gfx_ctx_mali_fbdev_set_video_mode(void *data,
unsigned width, unsigned height,
bool fullscreen)
{
struct fb_var_screeninfo vinfo;
static const EGLint attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2, /* Use version 2, even for GLES3. */
EGL_NONE
};
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
int fd = open("/dev/fb0", O_RDWR);
mali = (mali_ctx_data_t*)data;
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
{
RARCH_ERR("Error obtaining framebuffer info.\n");
goto error;
}
/*Workaround to reset yoffset when returned >0 from driver */
if (vinfo.yoffset != 0)
{
vinfo.yoffset = 0;
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo))
{
RARCH_ERR("Error resetting yoffset to 0.\n");
}
}
if (gfx_ctx_mali_fbdev_get_vinfo(mali))
goto error;
close(fd);
fd = -1;
width = vinfo.xres;
height = vinfo.yres;
mali->width = width;
mali->height = height;
mali->native_window.width = vinfo.xres;
mali->native_window.height = vinfo.yres;
if (vinfo.pixclock)
{
mali->refresh_rate = 1000000.0f / vinfo.pixclock * 1000000.0f /
(vinfo.yres + vinfo.upper_margin + vinfo.lower_margin + vinfo.vsync_len) /
(vinfo.xres + vinfo.left_margin + vinfo.right_margin + vinfo.hsync_len);
}else{
mali->refresh_rate = 60;
}
#ifdef HAVE_EGL
if (!egl_create_context(&mali->egl, attribs))
goto error;
#endif
#ifdef HAVE_EGL
if (!egl_create_surface(&mali->egl, &mali->native_window))
goto error;
#endif
width = mali->width;
height = mali->height;
return true;
error:
if (fd >= 0)
close(fd);
egl_report_error();
gfx_ctx_mali_fbdev_destroy(data);
return false;
}
@ -240,7 +269,7 @@ 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_ctx_data_t *mali = (mali_ctx_data_t*)data;
mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_set_swap_interval(&mali->egl, swap_interval);
@ -249,7 +278,7 @@ static void gfx_ctx_mali_fbdev_set_swap_interval(void *data,
static void gfx_ctx_mali_fbdev_swap_buffers(void *data)
{
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_swap_buffers(&mali->egl);
@ -258,7 +287,7 @@ static void gfx_ctx_mali_fbdev_swap_buffers(void *data)
static void gfx_ctx_mali_fbdev_bind_hw_render(void *data, bool enable)
{
mali_ctx_data_t *mali = (mali_ctx_data_t*)data;
mali = (mali_ctx_data_t*)data;
#ifdef HAVE_EGL
egl_bind_hw_render(&mali->egl, enable);
@ -278,7 +307,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_ctx_data_t *mali = (mali_ctx_data_t*)data;
mali = (mali_ctx_data_t*)data;
return mali->refresh_rate;
}