Add horizontal screen stretching option
fix scissor test when scaling/stretching fix infiniloop when starting a game fails
This commit is contained in:
parent
408d16b299
commit
47bb509f02
|
@ -313,7 +313,9 @@ int dc_start_game(const char *path)
|
|||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (!settings.bios.UseReios)
|
||||
#endif
|
||||
LoadRomFiles(get_readonly_data_path(DATA_PATH));
|
||||
if (!LoadRomFiles(get_readonly_data_path(DATA_PATH)))
|
||||
return -5;
|
||||
|
||||
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
||||
if (path == NULL)
|
||||
{
|
||||
|
@ -513,6 +515,7 @@ void InitSettings()
|
|||
settings.rend.CustomTextures = false;
|
||||
settings.rend.DumpTextures = false;
|
||||
settings.rend.ScreenScaling = 100;
|
||||
settings.rend.ScreenStretching = 100;
|
||||
settings.rend.Fog = true;
|
||||
|
||||
settings.pvr.ta_skip = 0;
|
||||
|
@ -596,6 +599,7 @@ void LoadSettings(bool game_specific)
|
|||
settings.rend.DumpTextures = cfgLoadBool(config_section, "rend.DumpTextures", settings.rend.DumpTextures);
|
||||
settings.rend.ScreenScaling = cfgLoadInt(config_section, "rend.ScreenScaling", settings.rend.ScreenScaling);
|
||||
settings.rend.ScreenScaling = min(max(1, settings.rend.ScreenScaling), 100);
|
||||
settings.rend.ScreenStretching = cfgLoadInt(config_section, "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
settings.rend.Fog = cfgLoadBool(config_section, "rend.Fog", settings.rend.Fog);
|
||||
|
||||
settings.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip);
|
||||
|
@ -720,6 +724,7 @@ void SaveSettings()
|
|||
cfgSaveBool("config", "rend.CustomTextures", settings.rend.CustomTextures);
|
||||
cfgSaveBool("config", "rend.DumpTextures", settings.rend.DumpTextures);
|
||||
cfgSaveInt("config", "rend.ScreenScaling", settings.rend.ScreenScaling);
|
||||
cfgSaveInt("config", "rend.ScreenStretching", settings.rend.ScreenStretching);
|
||||
cfgSaveBool("config", "rend.Fog", settings.rend.Fog);
|
||||
cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip);
|
||||
cfgSaveInt("config", "pvr.rend", settings.pvr.rend);
|
||||
|
|
|
@ -697,11 +697,15 @@ void gl4DrawFramebuffer(float w, float h)
|
|||
|
||||
bool gl4_render_output_framebuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
if (gl.ofbo.fbo == 0)
|
||||
return false;
|
||||
|
||||
gl4_draw_quad_texture(gl.ofbo.tex, true);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, gl.ofbo.width, gl.ofbo.height,
|
||||
0, 0, screen_width, screen_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -662,14 +662,15 @@ static bool RenderFrame()
|
|||
Handle Dc to screen scaling
|
||||
*/
|
||||
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
dc2s_scale_h *= screen_scaling;
|
||||
float ds2s_offs_x = is_rtt ? 0 : (((screen_width * screen_scaling) - dc2s_scale_h * 640.0) / 2);
|
||||
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2);
|
||||
|
||||
//-1 -> too much to left
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width * screen_scaling / dc2s_scale_h * scale_x);
|
||||
gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
gl4ShaderUniforms.scale_coefs[1] = (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / (screen_width * screen_scaling);
|
||||
gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width;
|
||||
gl4ShaderUniforms.scale_coefs[3] = (is_rtt ? 1 : -1);
|
||||
|
||||
gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale;
|
||||
|
@ -763,7 +764,7 @@ static bool RenderFrame()
|
|||
{
|
||||
if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved)
|
||||
{
|
||||
output_fbo = init_output_framebuffer(screen_width * screen_scaling, screen_height * screen_scaling);
|
||||
output_fbo = init_output_framebuffer(screen_width * screen_scaling + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -826,21 +827,21 @@ static bool RenderFrame()
|
|||
if (!is_rtt)
|
||||
{
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h + ds2s_offs_x;
|
||||
min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = screen_height * screen_scaling - (min_y + height) * dc2s_scale_h;
|
||||
width *= dc2s_scale_h;
|
||||
height *= dc2s_scale_h;
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_scaling * screen_stretching;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
{
|
||||
float rounded_offs_x = ds2s_offs_x + 0.5f;
|
||||
float scaled_offs_x = ds2s_offs_x * screen_scaling;
|
||||
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, rounded_offs_x, screen_height);
|
||||
glScissor(0, 0, scaled_offs_x + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glScissor(screen_width - rounded_offs_x, 0, rounded_offs_x, screen_height);
|
||||
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1141,17 +1141,27 @@ void DrawFramebuffer(float w, float h)
|
|||
|
||||
bool render_output_framebuffer()
|
||||
{
|
||||
#if HOST_OS != OS_DARWIN
|
||||
//Fix this in a proper way
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
return false;
|
||||
|
||||
float scl = 480.f / screen_height;
|
||||
float tx = (screen_width * scl - 640.f) / 2;
|
||||
DrawQuad(gl.ofbo.tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0);
|
||||
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
if (gl.gl_major < 3)
|
||||
{
|
||||
glViewport(0, 0, screen_width, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
float scl = 480.f / screen_height;
|
||||
float tx = (screen_width * scl - 640.f) / 2;
|
||||
DrawQuad(gl.ofbo.tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gl.ofbo.fbo == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, gl.ofbo.width, gl.ofbo.height,
|
||||
0, 0, screen_width, screen_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1678,15 +1678,16 @@ bool RenderFrame()
|
|||
/*
|
||||
Handle Dc to screen scaling
|
||||
*/
|
||||
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
|
||||
float screen_stretching = settings.rend.ScreenStretching / 100.f;
|
||||
float screen_scaling = settings.rend.ScreenScaling / 100.f;
|
||||
|
||||
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
|
||||
dc2s_scale_h *= screen_scaling;
|
||||
float ds2s_offs_x = is_rtt ? 0 : (((screen_width * screen_scaling) - dc2s_scale_h * 640.0) / 2);
|
||||
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2);
|
||||
|
||||
//-1 -> too much to left
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width * screen_scaling / dc2s_scale_h * scale_x);
|
||||
ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching;
|
||||
ShaderUniforms.scale_coefs[1]= (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512
|
||||
ShaderUniforms.scale_coefs[2]= 1 - 2 * ds2s_offs_x / (screen_width * screen_scaling);
|
||||
ShaderUniforms.scale_coefs[2]= 1 - 2 * ds2s_offs_x / screen_width;
|
||||
ShaderUniforms.scale_coefs[3]= (is_rtt ? 1 : -1);
|
||||
|
||||
|
||||
|
@ -1791,7 +1792,7 @@ bool RenderFrame()
|
|||
{
|
||||
if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved)
|
||||
{
|
||||
init_output_framebuffer(screen_width * screen_scaling, screen_height * screen_scaling);
|
||||
init_output_framebuffer(screen_width * screen_scaling + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1857,21 +1858,21 @@ bool RenderFrame()
|
|||
if (!is_rtt)
|
||||
{
|
||||
// Add x offset for aspect ratio > 4/3
|
||||
min_x = min_x * dc2s_scale_h + ds2s_offs_x;
|
||||
min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling;
|
||||
// Invert y coordinates when rendering to screen
|
||||
min_y = screen_height * screen_scaling - (min_y + height) * dc2s_scale_h;
|
||||
width *= dc2s_scale_h;
|
||||
height *= dc2s_scale_h;
|
||||
min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling;
|
||||
width *= dc2s_scale_h * screen_scaling * screen_stretching;
|
||||
height *= dc2s_scale_h * screen_scaling;
|
||||
|
||||
if (ds2s_offs_x > 0)
|
||||
{
|
||||
float rounded_offs_x = ds2s_offs_x + 0.5f;
|
||||
float scaled_offs_x = ds2s_offs_x * screen_scaling;
|
||||
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, rounded_offs_x, screen_height);
|
||||
glScissor(0, 0, scaled_offs_x + 0.5f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glScissor(screen_width - rounded_offs_x, 0, rounded_offs_x, screen_height);
|
||||
glScissor(screen_width * screen_scaling - scaled_offs_x + 0.5f, 0, scaled_offs_x + 1.f, screen_height * screen_scaling + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ struct gl_ctx
|
|||
struct
|
||||
{
|
||||
GLuint depthb;
|
||||
GLuint colorb;
|
||||
GLuint tex;
|
||||
GLuint fbo;
|
||||
int width;
|
||||
|
|
|
@ -996,13 +996,7 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
{
|
||||
if (width != gl.ofbo.width || height != gl.ofbo.height)
|
||||
{
|
||||
if (gl.ofbo.fbo != 0)
|
||||
{
|
||||
glDeleteFramebuffers(1, &gl.ofbo.fbo);
|
||||
gl.ofbo.fbo = 0;
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.depthb);
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
}
|
||||
free_output_framebuffer();
|
||||
gl.ofbo.width = width;
|
||||
gl.ofbo.height = height;
|
||||
}
|
||||
|
@ -1026,15 +1020,25 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
else
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
|
||||
// Create a texture for rendering to
|
||||
gl.ofbo.tex = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gl.ofbo.tex);
|
||||
if (gl.gl_major < 3)
|
||||
{
|
||||
// Create a texture for rendering to
|
||||
gl.ofbo.tex = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gl.ofbo.tex);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a renderbuffer and glBlitFramebuffer
|
||||
glGenRenderbuffers(1, &gl.ofbo.colorb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, gl.ofbo.colorb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
|
||||
}
|
||||
|
||||
// Create the framebuffer
|
||||
glGenFramebuffers(1, &gl.ofbo.fbo);
|
||||
|
@ -1046,13 +1050,20 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
if (!gl.is_gles || gl.GL_OES_packed_depth_stencil_supported)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl.ofbo.depthb);
|
||||
|
||||
// Attach the texture to the FBO
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.ofbo.tex, 0);
|
||||
// Attach the texture/renderbuffer to the FBO
|
||||
if (gl.gl_major < 3)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.ofbo.tex, 0);
|
||||
else
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, gl.ofbo.colorb);
|
||||
|
||||
// Check that our FBO creation was successful
|
||||
GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
verify(uStatus == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
|
@ -1071,7 +1082,15 @@ void free_output_framebuffer()
|
|||
gl.ofbo.fbo = 0;
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.depthb);
|
||||
gl.ofbo.depthb = 0;
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
gl.ofbo.tex = 0;
|
||||
if (gl.ofbo.tex != 0)
|
||||
{
|
||||
glcache.DeleteTextures(1, &gl.ofbo.tex);
|
||||
gl.ofbo.tex = 0;
|
||||
}
|
||||
if (gl.ofbo.colorb != 0)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &gl.ofbo.colorb);
|
||||
gl.ofbo.colorb = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -952,6 +952,9 @@ static void gui_display_settings()
|
|||
ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better");
|
||||
ImGui::SliderInt("Horizontal Stretching", (int *)&settings.rend.ScreenStretching, 100, 150);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Stretch the screen horizontally");
|
||||
ImGui::SliderInt("Frame Skipping", (int *)&settings.pvr.ta_skip, 0, 6);
|
||||
ImGui::SameLine();
|
||||
ShowHelpMarker("Number of frames to skip between two actually rendered frames");
|
||||
|
@ -1251,6 +1254,7 @@ static void gui_start_game(const std::string& path)
|
|||
{
|
||||
gui_state = Main;
|
||||
game_started = false;
|
||||
cfgSetVirtual("config", "image", "");
|
||||
switch (rc) {
|
||||
case -3:
|
||||
error_msg = "Audio/video initialization failed";
|
||||
|
|
|
@ -632,7 +632,8 @@ struct settings_t
|
|||
f32 ExtraDepthScale;
|
||||
bool CustomTextures;
|
||||
bool DumpTextures;
|
||||
int ScreenScaling; // in percent. 50 means half the native resolution
|
||||
int ScreenScaling; // in percent. 50 means half the native resolution
|
||||
int ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3
|
||||
bool Fog;
|
||||
} rend;
|
||||
|
||||
|
|
Loading…
Reference in New Issue