Reimplement 'fix ozone issues on mali400 gpu. as a bonus, fixes #5378'

by BringerethOfLight
This commit is contained in:
twinaphex 2019-05-24 04:13:55 +02:00
parent 320d22f5b8
commit 5dc11fcd31
2 changed files with 136 additions and 2 deletions

View File

@ -26,6 +26,48 @@
#include "../menu_driver.h"
#if defined(__arm__) || defined(__aarch64__)
static int scx0, scx1, scy0, scy1;
/* This array contains problematic GPU drivers
* that have problems when we draw outside the
* bounds of the framebuffer */
static const struct {
const char *str;
int len;
} scissor_device_strings[] = {
{ "ARM Mali-4xx", 10 },
{ 0, 0 }
};
static void scissor_set_rectangle(
int x0, int x1, int y0, int y1, int sc)
{
const int dx = sc ? 10 : 2;
const int dy = dx;
scx0 = x0 + dx;
scx1 = x1 - dx;
scy0 = y0 + dy;
scy1 = y1 - dy;
}
static bool scissor_is_outside_rectangle(
int x0, int x1, int y0, int y1)
{
if (x1 < scx0)
return true;
if (scx1 < x0)
return true;
if (y1 < scy0)
return true;
if (scy1 < y0)
return true;
return false;
}
#define MALI_BUG
#endif
static const GLfloat gl_vertexes[] = {
0, 0,
1, 0,
@ -100,6 +142,63 @@ static void menu_display_gl_viewport(menu_display_ctx_draw_t *draw,
glViewport(draw->x, draw->y, draw->width, draw->height);
}
#ifdef MALI_BUG
static bool
menu_display_gl_discard_draw_rectangle(menu_display_ctx_draw_t *draw,
video_frame_info_t *video_info
)
{
static bool mali_4xx_detected = false;
static bool scissor_inited = false;
if (!scissor_inited)
{
unsigned i;
const char *gpu_device_string = NULL;
scissor_inited = true;
if ((scx0 + scx1 + scy0 + scy1) == 0)
scissor_set_rectangle(0,
video_info->width - 1,
0,
video_info->height - 1,
0);
/* TODO/FIXME - This might be thread unsafe in the long run -
* preferably call this once outside of the menu display driver
* and then just pass this string as a parameter */
gpu_device_string = video_driver_get_gpu_device_string();
if (gpu_device_string)
{
for (i = 0; scissor_device_strings[i].len; ++i)
{
if (strncmp(gpu_device_string,
scissor_device_strings[i].str,
scissor_device_strings[i].len) == 0)
{
mali_4xx_detected = true;
break;
}
}
}
}
/* discards not only out-of-bounds scissoring,
* but also out-of-view draws.
*
* This is intentional.
*/
if (mali_4xx_detected &&
scissor_is_outside_rectangle(
draw->x, draw->x + draw->width - 1,
draw->y, draw->y + draw->height - 1))
return true;
return false;
}
#endif
static void menu_display_gl_draw(menu_display_ctx_draw_t *draw,
video_frame_info_t *video_info)
{
@ -108,6 +207,15 @@ static void menu_display_gl_draw(menu_display_ctx_draw_t *draw,
if (!gl || !draw)
return;
#ifdef MALI_BUG
if (menu_display_gl_discard_draw_rectangle(draw, video_info))
{
/*RARCH_WARN("[Menu]: discarded draw rect: %.4i %.4i %.4i %.4i\n",
(int)draw->x, (int)draw->y, (int)draw->width, (int)draw->height);*/
return;
}
#endif
if (!draw->coords->vertex)
draw->coords->vertex = menu_display_gl_get_default_vertices();
if (!draw->coords->tex_coord)
@ -243,12 +351,18 @@ static void menu_display_gl_scissor_begin(
{
glScissor(x, video_info->height - y - height, width, height);
glEnable(GL_SCISSOR_TEST);
#ifdef MALI_BUG
scissor_set_rectangle(x, x + width - 1, y, y + height - 1, 1);
#endif
}
static void menu_display_gl_scissor_end(video_frame_info_t *video_info)
{
glScissor(0, 0, video_info->width, video_info->height);
glDisable(GL_SCISSOR_TEST);
#ifdef MALI_BUG
scissor_set_rectangle(0, video_info->width - 1, 0, video_info->height - 1, 0);
#endif
}
menu_display_ctx_driver_t menu_display_ctx_gl = {

View File

@ -504,7 +504,26 @@ void menu_display_blend_end(video_frame_info_t *video_info)
void menu_display_scissor_begin(video_frame_info_t *video_info, int x, int y, unsigned width, unsigned height)
{
if (menu_disp && menu_disp->scissor_begin)
{
if (y < 0)
y = 0;
if (x < 0)
x = 0;
if (y >= menu_display_framebuf_height)
return;
if (x >= menu_display_framebuf_width)
return;
if ((y + height) > menu_display_framebuf_height)
height = menu_display_framebuf_height - y;
if ((x + width) > menu_display_framebuf_width)
width = menu_display_framebuf_width - x;
if (height <= 0)
return;
if (width <= 0)
return;
menu_disp->scissor_begin(video_info, x, y, width, height);
}
}
/* End scissoring operation */
@ -790,9 +809,10 @@ void menu_display_draw(menu_display_ctx_draw_t *draw,
if (!menu_disp || !draw || !menu_disp->draw)
return;
/* TODO - edge case */
if (draw->height <= 0)
draw->height = 1;
return;
if (draw->width <= 0)
return;
menu_disp->draw(draw, video_info);
}