From 810182c4fec1a71aa5742538f60a274b5fa36aac Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 19 Feb 2019 00:49:24 +0100 Subject: [PATCH] Scale down native resolution setting --- core/hw/pvr/Renderer_if.cpp | 4 +- core/nullDC.cpp | 4 ++ core/rend/gl4/gles.cpp | 3 - core/rend/gl4/gltex.cpp | 20 +++--- core/rend/gles/gldraw.cpp | 34 ++-------- core/rend/gles/gles.cpp | 127 +++++++++++++++--------------------- core/rend/gles/gles.h | 33 ++++++---- core/rend/gles/gltex.cpp | 112 +++++++++++++++++++++++-------- core/rend/gui.cpp | 3 + core/types.h | 1 + 10 files changed, 180 insertions(+), 161 deletions(-) diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 2117f6248..e9cfc1da1 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -98,7 +98,7 @@ bool fb_dirty; TA_context* _pvrrc; void SetREP(TA_context* cntx); void killtex(); -bool render_last_frame(); +bool render_output_framebuffer(); void dump_frame(const char* file, TA_context* ctx, u8* vram, u8* vram_ref = NULL) { FILE* fw = fopen(file, "wb"); @@ -282,7 +282,7 @@ bool rend_single_frame() } else { - render_last_frame(); + render_output_framebuffer(); #if defined(_ANDROID) if (!rs.Wait(100)) return false; diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 8f86c8e26..8e9c3cc50 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -528,6 +528,7 @@ void InitSettings() settings.rend.ExtraDepthScale = 1.f; settings.rend.CustomTextures = false; settings.rend.DumpTextures = false; + settings.rend.ScreenScaling = 100; settings.pvr.ta_skip = 0; settings.pvr.rend = 0; @@ -605,6 +606,8 @@ void LoadSettings(bool game_specific) } settings.rend.CustomTextures = cfgLoadBool(config_section, "rend.CustomTextures", settings.rend.CustomTextures); 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.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip); settings.pvr.rend = cfgLoadInt(config_section, "pvr.rend", settings.pvr.rend); @@ -705,6 +708,7 @@ void SaveSettings() cfgSaveInt("config", "rend.MaxFilteredTextureSize", settings.rend.MaxFilteredTextureSize); cfgSaveBool("config", "rend.CustomTextures", settings.rend.CustomTextures); cfgSaveBool("config", "rend.DumpTextures", settings.rend.DumpTextures); + cfgSaveInt("config", "rend.ScreenScaling", settings.rend.ScreenScaling); cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip); cfgSaveInt("config", "pvr.rend", settings.pvr.rend); diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index cb792ef50..d2e69d82e 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -686,9 +686,6 @@ static bool RenderFrame() //printf("scale: %f, %f, %f, %f\n",gl4ShaderUniforms.scale_coefs[0],gl4ShaderUniforms.scale_coefs[1],gl4ShaderUniforms.scale_coefs[2],gl4ShaderUniforms.scale_coefs[3]); - if (!is_rtt) - OSD_HOOK(); - //VERT and RAM fog color constants u8* fog_colvert_bgra=(u8*)&FOG_COL_VERT; u8* fog_colram_bgra=(u8*)&FOG_COL_RAM; diff --git a/core/rend/gl4/gltex.cpp b/core/rend/gl4/gltex.cpp index 40f986e14..85a0b9430 100644 --- a/core/rend/gl4/gltex.cpp +++ b/core/rend/gl4/gltex.cpp @@ -3,12 +3,10 @@ GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) { - FBT& rv=fb_rtt; + if (gl.rtt.fbo) glDeleteFramebuffers(1,&gl.rtt.fbo); + if (gl.rtt.tex) glcache.DeleteTextures(1,&gl.rtt.tex); - if (rv.fbo) glDeleteFramebuffers(1,&rv.fbo); - if (rv.tex) glcache.DeleteTextures(1,&rv.tex); - - rv.TexAddr=addy>>3; + gl.rtt.TexAddr=addy>>3; // Find the smallest power of two texture that fits the viewport int fbh2 = 2; @@ -29,17 +27,17 @@ GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) //glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo); // Create a texture for rendering to - rv.tex = glcache.GenTexture(); - glcache.BindTexture(GL_TEXTURE_2D, rv.tex); + gl.rtt.tex = glcache.GenTexture(); + glcache.BindTexture(GL_TEXTURE_2D, gl.rtt.tex); glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw2, fbh2, 0, channels, fmt, 0); // Create the object that will allow us to render to the aforementioned texture - glGenFramebuffers(1, &rv.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo); + glGenFramebuffers(1, &gl.rtt.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, gl.rtt.fbo); // Attach the texture to the FBO - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rv.tex, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.rtt.tex, 0); // Check that our FBO creation was successful GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -48,5 +46,5 @@ GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) glViewport(0, 0, fbw, fbh); // TODO CLIP_X/Y min? - return rv.fbo; + return gl.rtt.fbo; } diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 76efabad7..c740dedbe 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -1150,41 +1150,17 @@ void DrawFramebuffer(float w, float h) fbTextureId = 0; } -void save_current_frame() +void render_output_framebuffer() { -#ifndef GLES - glReadBuffer(GL_FRONT); -#endif - // (Re-)create the texture and reserve space for it - if (g_previous_frame_tex != 0) - glcache.DeleteTextures(1, &g_previous_frame_tex); - glGenTextures(1, &g_previous_frame_tex); - glBindTexture(GL_TEXTURE_2D, g_previous_frame_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen_width, screen_height, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)NULL); - - // Copy the current framebuffer into it - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_width, screen_height); - glCheck(); -} - -bool render_last_frame() -{ - if (g_previous_frame_tex == 0) - return false; - #if HOST_OS != OS_DARWIN //Fix this in a proper way - glBindFramebuffer(GL_FRAMEBUFFER,0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif glViewport(0, 0, screen_width, screen_height); + if (gl.ofbo.tex == 0) + return; float scl = 480.f / screen_height; float tx = (screen_width * scl - 640.f) / 2; - DrawQuad(g_previous_frame_tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0); - - return true; + DrawQuad(gl.ofbo.tex, -tx, 0, 640.f + tx * 2, 480.f, 0, 1, 1, 0); } diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 10be6aab9..c99853032 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -751,7 +751,7 @@ void gl_term() memset(gl.pogram_table, 0, sizeof(gl.pogram_table)); -#if HOST_OS==OS_WINDOWS + #if HOST_OS==OS_WINDOWS ReleaseDC((HWND)gl.setup.native_wind,(HDC)gl.setup.native_disp); #elif defined(TARGET_PANDORA) || defined(_ANDROID) eglMakeCurrent(gl.setup.display, NULL, NULL, EGL_NO_CONTEXT); @@ -1247,10 +1247,6 @@ extern u8 rt[4],lt[4]; #define key_CONT_DPAD2_LEFT (1 << 14) #define key_CONT_DPAD2_RIGHT (1 << 15) -u32 osd_base; -u32 osd_count; - - #if defined(_ANDROID) extern float vjoy_pos[14][8]; #else @@ -1278,7 +1274,10 @@ float vjoy_pos[14][8]= }; #endif // !_ANDROID -float vjoy_sz[2][14] = { +static List osd_vertices; +static bool osd_vertices_overrun; + +static const float vjoy_sz[2][14] = { { 64,64,64,64, 64,64,64,64, 64, 90,90, 128, 64 }, { 64,64,64,64, 64,64,64,64, 64, 64,64, 128, 64 }, }; @@ -1312,63 +1311,48 @@ static void DrawButton(float* xy, u32 state) vtx.x=x; vtx.y=y; vtx.u=xy[4]; vtx.v=xy[5]; - *pvrrc.verts.Append()=vtx; + *osd_vertices.Append() = vtx; vtx.x=x+w; vtx.y=y; vtx.u=xy[6]; vtx.v=xy[5]; - *pvrrc.verts.Append()=vtx; + *osd_vertices.Append() = vtx; vtx.x=x; vtx.y=y+h; vtx.u=xy[4]; vtx.v=xy[7]; - *pvrrc.verts.Append()=vtx; + *osd_vertices.Append() = vtx; vtx.x=x+w; vtx.y=y+h; vtx.u=xy[6]; vtx.v=xy[7]; - *pvrrc.verts.Append()=vtx; - - osd_count+=4; + *osd_vertices.Append() = vtx; } -static void ClearBG() -{ - -} - - -void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); } +static void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); } static float LastFPSTime; static int lastFrameCount = 0; static float fps = -1; -void OSD_HOOK() +static void osd_gen_vertices() { - osd_base=pvrrc.verts.used(); - osd_count=0; + osd_vertices.Init(ARRAY_SIZE(vjoy_pos) * 4, &osd_vertices_overrun, "OSD vertices"); + DrawButton2(vjoy_pos[0],kcode[0]&key_CONT_DPAD_LEFT); + DrawButton2(vjoy_pos[1],kcode[0]&key_CONT_DPAD_UP); + DrawButton2(vjoy_pos[2],kcode[0]&key_CONT_DPAD_RIGHT); + DrawButton2(vjoy_pos[3],kcode[0]&key_CONT_DPAD_DOWN); - #ifndef TARGET_PANDORA - if (osd_tex) - { - DrawButton2(vjoy_pos[0],kcode[0]&key_CONT_DPAD_LEFT); - DrawButton2(vjoy_pos[1],kcode[0]&key_CONT_DPAD_UP); - DrawButton2(vjoy_pos[2],kcode[0]&key_CONT_DPAD_RIGHT); - DrawButton2(vjoy_pos[3],kcode[0]&key_CONT_DPAD_DOWN); + DrawButton2(vjoy_pos[4],kcode[0]&key_CONT_X); + DrawButton2(vjoy_pos[5],kcode[0]&key_CONT_Y); + DrawButton2(vjoy_pos[6],kcode[0]&key_CONT_B); + DrawButton2(vjoy_pos[7],kcode[0]&key_CONT_A); - DrawButton2(vjoy_pos[4],kcode[0]&key_CONT_X); - DrawButton2(vjoy_pos[5],kcode[0]&key_CONT_Y); - DrawButton2(vjoy_pos[6],kcode[0]&key_CONT_B); - DrawButton2(vjoy_pos[7],kcode[0]&key_CONT_A); + DrawButton2(vjoy_pos[8],kcode[0]&key_CONT_START); - DrawButton2(vjoy_pos[8],kcode[0]&key_CONT_START); + DrawButton(vjoy_pos[9],lt[0]); - DrawButton(vjoy_pos[9],lt[0]); + DrawButton(vjoy_pos[10],rt[0]); - DrawButton(vjoy_pos[10],rt[0]); - - DrawButton2(vjoy_pos[11],1); - DrawButton2(vjoy_pos[12],0); - } - #endif + DrawButton2(vjoy_pos[11],1); + DrawButton2(vjoy_pos[12],0); } #define OSD_TEX_W 512 @@ -1376,9 +1360,11 @@ void OSD_HOOK() void OSD_DRAW(GLuint shader_program) { - #ifndef TARGET_PANDORA +#ifndef TARGET_PANDORA if (osd_tex) { + osd_gen_vertices(); + float u=0; float v=0; @@ -1405,22 +1391,7 @@ void OSD_DRAW(GLuint shader_program) glcache.BindTexture(GL_TEXTURE_2D, osd_tex); glcache.UseProgram(shader_program); - //reset rendering scale -/* - float dc_width=640; - float dc_height=480; - - float dc2s_scale_h=screen_height/480.0f; - float ds2s_offs_x=(screen_width-dc2s_scale_h*640)/2; - - //-1 -> too much to left - ShaderUniforms.scale_coefs[0]=2.0f/(screen_width/dc2s_scale_h); - ShaderUniforms.scale_coefs[1]=-2/dc_height; - ShaderUniforms.scale_coefs[2]=1-2*ds2s_offs_x/(screen_width); - ShaderUniforms.scale_coefs[3]=-1; - - glUniform4fv( gl.OSD_SHADER.scale, 1, ShaderUniforms.scale_coefs); -*/ + glBufferData(GL_ARRAY_BUFFER, osd_vertices.bytes(), osd_vertices.head(), GL_STREAM_DRAW); glcache.Enable(GL_BLEND); glcache.Disable(GL_DEPTH_TEST); @@ -1432,10 +1403,10 @@ void OSD_DRAW(GLuint shader_program) glcache.Disable(GL_CULL_FACE); glcache.Disable(GL_SCISSOR_TEST); - int dfa=osd_count/4; + int dfa = osd_vertices.used() / 4; - for (int i=0;i too much to left - ShaderUniforms.scale_coefs[0]=2.0f/(screen_width/dc2s_scale_h*scale_x); - 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); - ShaderUniforms.scale_coefs[3]=(is_rtt?1:-1); + ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width * screen_scaling / dc2s_scale_h * scale_x); + 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[3]= (is_rtt ? 1 : -1); ShaderUniforms.depth_coefs[0]=2/(vtx_max_fZ-vtx_min_fZ); @@ -1789,11 +1759,18 @@ bool RenderFrame() } else { + if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved) + { + init_output_framebuffer(screen_width * settings.rend.ScreenScaling / 100, screen_height * settings.rend.ScreenScaling / 100); + } + else + { #if HOST_OS != OS_DARWIN - //Fix this in a proper way - glBindFramebuffer(GL_FRAMEBUFFER,0); + //Fix this in a proper way + glBindFramebuffer(GL_FRAMEBUFFER,0); #endif - glViewport(0, 0, screen_width, screen_height); + glViewport(0, 0, screen_width, screen_height); + } } bool wide_screen_on = !is_rtt && settings.rend.WideScreen @@ -1892,8 +1869,6 @@ bool RenderFrame() { glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT); - glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.geometry); glCheck(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl.vbo.idxs); glCheck(); DrawFramebuffer(dc_width, dc_height); glBufferData(GL_ARRAY_BUFFER, pvrrc.verts.bytes(), pvrrc.verts.head(), GL_STREAM_DRAW); upload_vertex_indices(); @@ -1908,8 +1883,8 @@ bool RenderFrame() if (is_rtt) ReadRTTBuffer(); - else if (gl.swap_buffer_not_preserved) - save_current_frame(); + else if (settings.rend.ScreenScaling != 100 || gl.swap_buffer_not_preserved) + render_output_framebuffer(); return !is_rtt; } diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index ab33ffa6c..5204cf414 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -116,6 +116,23 @@ struct gl_ctx #endif } vbo; + struct + { + u32 TexAddr; + GLuint depthb; + GLuint tex; + GLuint fbo; + } rtt; + + struct + { + GLuint depthb; + GLuint tex; + GLuint fbo; + int width; + int height; + } ofbo; + const char *gl_version; const char *glsl_version_header; int gl_major; @@ -148,8 +165,6 @@ void gl_free_osd_resources(); void gl_swap(); bool ProcessFrame(TA_context* ctx); void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format); -void save_current_frame(); -bool render_last_frame(); text_info raw_GetTexture(TSP tsp, TCW tcw); void killtex(); @@ -164,9 +179,10 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt); void ReadRTTBuffer(); void RenderFramebuffer(); void DrawFramebuffer(float w, float h); +void init_output_framebuffer(int width, int height); +void render_output_framebuffer(); void HideOSD(); -void OSD_HOOK(); void OSD_DRAW(GLuint shader_program); int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode, u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, @@ -226,17 +242,6 @@ extern struct ShaderUniforms_t } ShaderUniforms; -// Render to texture -struct FBT -{ - u32 TexAddr; - GLuint depthb,stencilb; - GLuint tex; - GLuint fbo; -}; - -extern FBT fb_rtt; - struct PvrTexInfo; template class PixelBuffer; typedef void TexConvFP(PixelBuffer* pb,u8* p_in,u32 Width,u32 Height); diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index 6e676b5c4..0e0af9607 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -481,18 +481,13 @@ typedef map::iterator TexCacheIter; TextureCacheData *getTextureCacheData(TSP tsp, TCW tcw); -FBT fb_rtt; - void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) { - FBT& rv=fb_rtt; + if (gl.rtt.fbo) glDeleteFramebuffers(1,&gl.rtt.fbo); + if (gl.rtt.tex) glcache.DeleteTextures(1,&gl.rtt.tex); + if (gl.rtt.depthb) glDeleteRenderbuffers(1,&gl.rtt.depthb); - if (rv.fbo) glDeleteFramebuffers(1,&rv.fbo); - if (rv.tex) glcache.DeleteTextures(1,&rv.tex); - if (rv.depthb) glDeleteRenderbuffers(1,&rv.depthb); - if (rv.stencilb) glDeleteRenderbuffers(1,&rv.stencilb); - - rv.TexAddr=addy>>3; + gl.rtt.TexAddr=addy>>3; // Find the smallest power of two texture that fits into the viewport int fbh2 = 2; @@ -513,8 +508,8 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) //glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo); // Generate and bind a render buffer which will become a depth buffer shared between our two FBOs - glGenRenderbuffers(1, &rv.depthb); - glBindRenderbuffer(GL_RENDERBUFFER, rv.depthb); + glGenRenderbuffers(1, &gl.rtt.depthb); + glBindRenderbuffer(GL_RENDERBUFFER, gl.rtt.depthb); /* Currently it is unknown to GL that we want our new render buffer to be a depth buffer. @@ -534,8 +529,8 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) #endif // Create a texture for rendering to - rv.tex = glcache.GenTexture(); - glcache.BindTexture(GL_TEXTURE_2D, rv.tex); + gl.rtt.tex = glcache.GenTexture(); + glcache.BindTexture(GL_TEXTURE_2D, gl.rtt.tex); glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw2, fbh2, 0, channels, fmt, 0); glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -543,19 +538,19 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) 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); // Create the object that will allow us to render to the aforementioned texture - glGenFramebuffers(1, &rv.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo); + glGenFramebuffers(1, &gl.rtt.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, gl.rtt.fbo); // Attach the texture to the FBO - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rv.tex, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl.rtt.tex, 0); // Attach the depth buffer we created earlier to our FBO. - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rv.depthb); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl.rtt.depthb); #ifdef GLES if (gl.GL_OES_packed_depth_stencil_supported) #endif - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rv.depthb); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl.rtt.depthb); // Check that our FBO creation was successful GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -582,7 +577,7 @@ void ReadRTTBuffer() { if (settings.rend.RenderToTextureBuffer) { - u32 tex_addr = fb_rtt.TexAddr << 3; + u32 tex_addr = gl.rtt.TexAddr << 3; // Manually mark textures as dirty and remove all vram locks before calling glReadPixels // (deadlock on rpi) @@ -673,12 +668,12 @@ void ReadRTTBuffer() { //dumpRtTexture(fb_rtt.TexAddr, w, h); if (w > 1024 || h > 1024 || settings.rend.RenderToTextureBuffer) { - glcache.DeleteTextures(1, &fb_rtt.tex); + glcache.DeleteTextures(1, &gl.rtt.tex); } else { // TexAddr : fb_rtt.TexAddr, Reserved : 0, StrideSel : 0, ScanOrder : 1 - TCW tcw = { { fb_rtt.TexAddr, 0, 0, 1 } }; + TCW tcw = { { gl.rtt.TexAddr, 0, 0, 1 } }; switch (fb_packmode) { case 0: case 3: @@ -700,16 +695,15 @@ void ReadRTTBuffer() { glcache.DeleteTextures(1, &texture_data->texID); else texture_data->Create(false); - texture_data->texID = fb_rtt.tex; + texture_data->texID = gl.rtt.tex; texture_data->dirty = 0; if (texture_data->lock_block == NULL) texture_data->lock_block = libCore_vramlock_Lock(texture_data->sa_tex, texture_data->sa + texture_data->size - 1, texture_data); } - fb_rtt.tex = 0; + gl.rtt.tex = 0; - if (fb_rtt.fbo) { glDeleteFramebuffers(1,&fb_rtt.fbo); fb_rtt.fbo = 0; } - if (fb_rtt.depthb) { glDeleteRenderbuffers(1,&fb_rtt.depthb); fb_rtt.depthb = 0; } - if (fb_rtt.stencilb) { glDeleteRenderbuffers(1,&fb_rtt.stencilb); fb_rtt.stencilb = 0; } + if (gl.rtt.fbo) { glDeleteFramebuffers(1,&gl.rtt.fbo); gl.rtt.fbo = 0; } + if (gl.rtt.depthb) { glDeleteRenderbuffers(1,&gl.rtt.depthb); gl.rtt.depthb = 0; } } @@ -1012,3 +1006,69 @@ void RenderFramebuffer() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pb.data()); } +void 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); + } + gl.ofbo.width = width; + gl.ofbo.height = height; + } + if (gl.ofbo.fbo == 0) + { + // Create the depth+stencil renderbuffer + glGenRenderbuffers(1, &gl.ofbo.depthb); + glBindRenderbuffer(GL_RENDERBUFFER, gl.ofbo.depthb); + +#ifdef GLES + if (gl.GL_OES_packed_depth_stencil_supported) + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + else if (gl.GL_OES_depth24_supported) + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height); + else + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); +#else + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); +#endif + // 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); + + // Create the framebuffer + glGenFramebuffers(1, &gl.ofbo.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.fbo); + + // Attach the depth buffer to our FBO. + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl.ofbo.depthb); + +#ifdef GLES + if (gl.GL_OES_packed_depth_stencil_supported) +#endif + 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); + + // Check that our FBO creation was successful + GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + verify(uStatus == GL_FRAMEBUFFER_COMPLETE); + } + else + glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.fbo); + + glViewport(0, 0, width, height); + glCheck(); +} diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 99e914897..4308fd972 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -799,6 +799,9 @@ static void gui_display_settings() ImGui::Checkbox("Show FPS Counter", &settings.rend.ShowFPS); ImGui::SameLine(); ShowHelpMarker("Show on-screen frame/sec counter"); + ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100); + ImGui::SameLine(); + ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better"); ImGui::SliderInt("Frame Skipping", (int *)&settings.pvr.ta_skip, 0, 6); ImGui::SameLine(); ShowHelpMarker("Number of frames to skip between two actually rendered frames"); diff --git a/core/types.h b/core/types.h index f8b2c04ae..fb627d819 100644 --- a/core/types.h +++ b/core/types.h @@ -726,6 +726,7 @@ struct settings_t f32 ExtraDepthScale; bool CustomTextures; bool DumpTextures; + int ScreenScaling; // in percent. 50 means half the native resolution } rend; struct