Scale down native resolution setting

This commit is contained in:
Flyinghead 2019-02-19 00:49:24 +01:00
parent e2c839dde3
commit 810182c4fe
10 changed files with 180 additions and 161 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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<Vertex> 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<dfa;i++)
glDrawArrays(GL_TRIANGLE_STRIP,osd_base+i*4,4);
for (int i = 0; i < dfa; i++)
glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
}
#endif
if (settings.rend.ShowFPS)
@ -1503,9 +1474,6 @@ bool RenderFrame()
bool is_rtt=pvrrc.isRTT;
if (!is_rtt)
OSD_HOOK();
//if (FrameCount&7) return;
//Setup the matrix
@ -1669,14 +1637,16 @@ bool RenderFrame()
/*
Handle Dc to screen scaling
*/
float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f;
float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0);
float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0) / 2);
dc2s_scale_h *= screen_scaling;
float ds2s_offs_x = is_rtt ? 0 : (((screen_width * screen_scaling) - dc2s_scale_h * 640.0) / 2);
//-1 -> 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;
}

View File

@ -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 pixel_type> class PixelBuffer;
typedef void TexConvFP(PixelBuffer<u16>* pb,u8* p_in,u32 Width,u32 Height);

View File

@ -481,18 +481,13 @@ typedef map<u64,TextureCacheData>::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();
}

View File

@ -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");

View File

@ -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