Merge pull request #551 from ggdrt/gl-height-pad

Implement framebuffer height padding for GL renderer
This commit is contained in:
Twinaphex 2019-10-26 09:49:36 +02:00 committed by GitHub
commit a82b3a71f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 9 deletions

View File

@ -541,9 +541,17 @@ static void UpdateDisplayMode(void)
uint16_t yres = GPU.VertEnd - GPU.VertStart; uint16_t yres = GPU.VertEnd - GPU.VertStart;
bool is_pal_mode = false;
if((GPU.DisplayMode & DISP_PAL) == DISP_PAL)
is_pal_mode = true;
// Both 2nd bit and 5th bit have to be enabled to use interlacing properly. // Both 2nd bit and 5th bit have to be enabled to use interlacing properly.
bool is_480i_mode = false;
if((GPU.DisplayMode & (DISP_INTERLACED | DISP_VERT480)) == (DISP_INTERLACED | DISP_VERT480)) if((GPU.DisplayMode & (DISP_INTERLACED | DISP_VERT480)) == (DISP_INTERLACED | DISP_VERT480))
{
yres *= 2; yres *= 2;
is_480i_mode = true;
}
unsigned pixelclock_divider; unsigned pixelclock_divider;
@ -588,7 +596,9 @@ static void UpdateDisplayMode(void)
GPU.DisplayFB_XStart, GPU.DisplayFB_XStart,
GPU.DisplayFB_YStart, GPU.DisplayFB_YStart,
xres, yres, xres, yres,
depth_24bpp); depth_24bpp,
is_pal_mode,
is_480i_mode);
} }
/* Forward decls */ /* Forward decls */
@ -1112,6 +1122,7 @@ void GPU_Write(const int32_t timestamp, uint32_t A, uint32_t V)
GPU_SoftReset(); GPU_SoftReset();
rsx_intf_set_draw_area(GPU.ClipX0, GPU.ClipY0, rsx_intf_set_draw_area(GPU.ClipX0, GPU.ClipY0,
GPU.ClipX1, GPU.ClipY1); GPU.ClipX1, GPU.ClipY1);
rsx_intf_set_display_range(GPU.VertStart, GPU.VertEnd); //0x10, 0x100 set by GPU_SoftReset()
UpdateDisplayMode(); UpdateDisplayMode();
break; break;
@ -1150,6 +1161,7 @@ void GPU_Write(const int32_t timestamp, uint32_t A, uint32_t V)
case 0x07: case 0x07:
GPU.VertStart = V & 0x3FF; GPU.VertStart = V & 0x3FF;
GPU.VertEnd = (V >> 10) & 0x3FF; GPU.VertEnd = (V >> 10) & 0x3FF;
rsx_intf_set_display_range(GPU.VertStart, GPU.VertEnd);
break; break;
case 0x08: case 0x08:
@ -1854,6 +1866,8 @@ void GPU_RestoreStateP3(void)
1024, 512, 1024, 512,
GPU.vram, false, false); GPU.vram, false, false);
rsx_intf_set_display_range(GPU.VertStart, GPU.VertEnd);
UpdateDisplayMode(); UpdateDisplayMode();
} }

View File

@ -130,7 +130,15 @@ void rsx_dump_set_draw_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
write_u32(y1); write_u32(y1);
} }
void rsx_dump_set_display_mode(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool depth_24bpp) void rsx_dump_set_display_range(uint16_t y1, uint16_t y2)
{
if (!file)
return;
write_u32(y1);
write_u32(y2);
}
void rsx_dump_set_display_mode(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool depth_24bpp, bool is_pal, bool is_480i)
{ {
if (!file) if (!file)
return; return;
@ -140,6 +148,8 @@ void rsx_dump_set_display_mode(uint16_t x, uint16_t y, uint16_t w, uint16_t h, b
write_u32(w); write_u32(w);
write_u32(h); write_u32(h);
write_u32(depth_24bpp); write_u32(depth_24bpp);
write_u32(is_pal);
write_u32(is_480i);
} }
void rsx_dump_triangle(const struct rsx_dump_vertex *vertices, const struct rsx_render_state *state) void rsx_dump_triangle(const struct rsx_dump_vertex *vertices, const struct rsx_render_state *state)

View File

@ -16,7 +16,8 @@ void rsx_dump_finalize_frame(void);
void rsx_dump_set_tex_window(uint8_t tww, uint8_t twh, uint8_t twx, uint8_t twy); void rsx_dump_set_tex_window(uint8_t tww, uint8_t twh, uint8_t twx, uint8_t twy);
void rsx_dump_set_draw_offset(int16_t x, int16_t y); void rsx_dump_set_draw_offset(int16_t x, int16_t y);
void rsx_dump_set_draw_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void rsx_dump_set_draw_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void rsx_dump_set_display_mode(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool depth_24bpp); void rsx_dump_set_display_range(uint16_t y1, uint16_t y2);
void rsx_dump_set_display_mode(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool depth_24bpp, bool is_pal, bool is_480i);
struct rsx_dump_vertex struct rsx_dump_vertex
{ {

View File

@ -224,6 +224,9 @@ struct DrawConfig
int16_t draw_offset[2]; int16_t draw_offset[2];
uint16_t draw_area_top_left[2]; uint16_t draw_area_top_left[2];
uint16_t draw_area_bot_right[2]; uint16_t draw_area_bot_right[2];
uint16_t display_area_yrange[2];
bool is_pal;
bool is_480i;
}; };
struct Texture struct Texture
@ -344,6 +347,9 @@ static DrawConfig persistent_config = {
{0, 0}, /* draw_area_top_left */ {0, 0}, /* draw_area_top_left */
{0, 0}, /* draw_area_dimensions */ {0, 0}, /* draw_area_dimensions */
{0, 0}, /* draw_offset */ {0, 0}, /* draw_offset */
{0x10, 0x100}, /* display_area_yrange (hardware reset values)*/
false, /* is_pal */
false, /* is_480i */
}; };
static RetroGl static_renderer; static RetroGl static_renderer;
@ -1457,6 +1463,11 @@ static void bind_libretro_framebuffer(GlRenderer *renderer)
float aspect_ratio = widescreen_hack ? 16.0 / 9.0 : float aspect_ratio = widescreen_hack ? 16.0 / 9.0 :
MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO; MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO;
/* Padding vars */
uint32_t unpadded_h;
uint32_t top_pad = 0;
uint32_t bottom_pad = 0;
if (renderer->display_vram) if (renderer->display_vram)
{ {
_w = VRAM_WIDTH_PIXELS; _w = VRAM_WIDTH_PIXELS;
@ -1464,10 +1475,42 @@ static void bind_libretro_framebuffer(GlRenderer *renderer)
/* Is this accurate? */ /* Is this accurate? */
aspect_ratio = 2.0 / 1.0; aspect_ratio = 2.0 / 1.0;
} }
else
{
/* Height padding for non-standard framebuffer heights
*
* We check the config.is_pal set by UpdateDisplayMode
* instead of querying content_is_pal since config.is_pal
* is a runtime GPU value while content_is_pal is only set
* at load time */
uint16_t first_line = renderer->config.is_pal ? 20 : 16;
uint16_t last_line = renderer->config.is_pal ? 308 : 256; //non-inclusive bound
if (renderer->config.display_area_yrange[0] > first_line) //check bounds
top_pad = (uint32_t) (renderer->config.display_area_yrange[0] - first_line);
if (renderer->config.display_area_yrange[1] < last_line)
bottom_pad = (uint32_t) (last_line - renderer->config.display_area_yrange[1]);
if (renderer->config.is_480i) //double padding if 480-line mode
{
top_pad *= 2;
bottom_pad *= 2;
}
}
w = (uint32_t) _w * upscale; w = (uint32_t) _w * upscale;
h = (uint32_t) _h * upscale; h = (uint32_t) _h * upscale;
//printf("VertStart = %3u, VertEnd = %3u\n", renderer->config.display_area_yrange[0], renderer->config.display_area_yrange[1]);
//printf("_w = %3u, _h = %3u, top_pad = %3u, bottom_pad = %3u\n", _w, _h, top_pad, bottom_pad);
/* Scale pad heights up and add to scaled height */
unpadded_h = h;
top_pad *= upscale;
bottom_pad *= upscale;
h += (top_pad + bottom_pad);
if (w != f_w || h != f_h) if (w != f_w || h != f_h)
{ {
/* We need to change the frontend's resolution */ /* We need to change the frontend's resolution */
@ -1490,7 +1533,7 @@ static void bind_libretro_framebuffer(GlRenderer *renderer)
/* Bind the output framebuffer provided by the frontend */ /* Bind the output framebuffer provided by the frontend */
fbo = glsm_get_current_framebuffer(); fbo = glsm_get_current_framebuffer();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glViewport(0, 0, (GLsizei) w, (GLsizei) h); glViewport(0, (GLsizei) bottom_pad, (GLsizei) w, (GLsizei) unpadded_h);
} }
static bool retro_refresh_variables(GlRenderer *renderer) static bool retro_refresh_variables(GlRenderer *renderer)
@ -2145,6 +2188,12 @@ static void rsx_gl_finalize_frame(const void *fb, unsigned width,
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND); glDisable(GL_BLEND);
/* Clear the screen no matter what: prevents possible leftover
pixels from previous frame when loading save state for any
games not using standard framebuffer heights */
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* If the display is off, just clear the screen */ /* If the display is off, just clear the screen */
if (renderer->config.display_off && !renderer->display_vram) if (renderer->config.display_off && !renderer->display_vram)
{ {
@ -3733,12 +3782,44 @@ void rsx_intf_set_draw_area(uint16_t x0, uint16_t y0,
} }
} }
void rsx_intf_set_display_mode(uint16_t x, uint16_t y, void rsx_intf_set_display_range(uint16_t y1, uint16_t y2)
uint16_t w, uint16_t h,
bool depth_24bpp)
{ {
#ifdef RSX_DUMP #ifdef RSX_DUMP
rsx_dump_set_display_mode(x, y, w, h, depth_24bpp); rsx_dump_set_display_range(y1, y2);
#endif
switch (rsx_type)
{
case RSX_SOFTWARE:
break;
case RSX_OPENGL:
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
{
GlRenderer *renderer = static_renderer.state_data;
if (static_renderer.state != GlState_Invalid
&& renderer)
{
renderer->config.display_area_yrange[0] = y1;
renderer->config.display_area_yrange[1] = y2;
}
}
#endif
break;
case RSX_VULKAN:
//implement me for Vulkan and set HAVE_VULKAN define check
break;
}
}
void rsx_intf_set_display_mode(uint16_t x, uint16_t y,
uint16_t w, uint16_t h,
bool depth_24bpp,
bool is_pal,
bool is_480i)
{
#ifdef RSX_DUMP
rsx_dump_set_display_mode(x, y, w, h, depth_24bpp, is_pal, is_480i);
#endif #endif
switch (rsx_type) switch (rsx_type)
@ -3758,6 +3839,9 @@ void rsx_intf_set_display_mode(uint16_t x, uint16_t y,
renderer->config.display_resolution[0] = w; renderer->config.display_resolution[0] = w;
renderer->config.display_resolution[1] = h; renderer->config.display_resolution[1] = h;
renderer->config.display_24bpp = depth_24bpp; renderer->config.display_24bpp = depth_24bpp;
renderer->config.is_pal = is_pal;
renderer->config.is_480i = is_480i;
} }
} }
#endif #endif

View File

@ -45,9 +45,12 @@ void rsx_intf_set_mask_setting(uint32_t mask_set_or, uint32_t mask_eval_and);
void rsx_intf_set_draw_offset(int16_t x, int16_t y); void rsx_intf_set_draw_offset(int16_t x, int16_t y);
void rsx_intf_set_draw_area(uint16_t x0, uint16_t y0, void rsx_intf_set_draw_area(uint16_t x0, uint16_t y0,
uint16_t x1, uint16_t y1); uint16_t x1, uint16_t y1);
void rsx_intf_set_display_range(uint16_t y1, uint16_t y2);
void rsx_intf_set_display_mode(uint16_t x, uint16_t y, void rsx_intf_set_display_mode(uint16_t x, uint16_t y,
uint16_t w, uint16_t h, uint16_t w, uint16_t h,
bool depth_24bpp); bool depth_24bpp,
bool is_pal,
bool is_480i);
void rsx_intf_push_triangle(float p0x, float p0y, float p0w, void rsx_intf_push_triangle(float p0x, float p0y, float p0w,
float p1x, float p1y, float p1w, float p1x, float p1y, float p1w,