mirror of https://github.com/PCSX2/pcsx2.git
gsdx mipmap:ogl: plug trilinear/mipmap2 option
mipmap option 3. Actually maybe a separate tri-linear option will be better m_mipmap == 2 => use manual PS2 trilinear/mipmap Otherwise m_filter == 3 => always use full automatic trilinear interpolation m_filter == 4 => use automatic trilinear interpolation when PS2 uses mipmap m_filter == 5 => like 4 but force bilinear interpolation inside layer
This commit is contained in:
parent
c2777ff989
commit
5ced9c1f19
|
@ -75,6 +75,7 @@ GSDeviceOGL::GSDeviceOGL()
|
||||||
GLState::Clear();
|
GLState::Clear();
|
||||||
|
|
||||||
m_mipmap = theApp.GetConfigI("mipmap");
|
m_mipmap = theApp.GetConfigI("mipmap");
|
||||||
|
m_filter = theApp.GetConfigI("filter");
|
||||||
|
|
||||||
// Reset the debug file
|
// Reset the debug file
|
||||||
#ifdef ENABLE_OGL_DEBUG
|
#ifdef ENABLE_OGL_DEBUG
|
||||||
|
@ -229,7 +230,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt
|
||||||
|
|
||||||
// A wrapper to call GSTextureOGL, with the different kind of parameter
|
// A wrapper to call GSTextureOGL, with the different kind of parameter
|
||||||
GSTextureOGL* t = NULL;
|
GSTextureOGL* t = NULL;
|
||||||
t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1);
|
t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || m_filter > 2);
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
throw GSDXErrorOOM();
|
throw GSDXErrorOOM();
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,6 +405,7 @@ public:
|
||||||
uint32 m_msaa; // Level of Msaa
|
uint32 m_msaa; // Level of Msaa
|
||||||
int m_force_texture_clear;
|
int m_force_texture_clear;
|
||||||
int m_mipmap;
|
int m_mipmap;
|
||||||
|
int m_filter;
|
||||||
|
|
||||||
static bool m_debug_gl_call;
|
static bool m_debug_gl_call;
|
||||||
static FILE* m_debug_gl_file;
|
static FILE* m_debug_gl_file;
|
||||||
|
|
|
@ -478,7 +478,7 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc
|
||||||
// After the conversion the texture will be RGBA8 (aka 32 bits) hence the 0 below
|
// After the conversion the texture will be RGBA8 (aka 32 bits) hence the 0 below
|
||||||
int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0;
|
int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0;
|
||||||
|
|
||||||
bool bilinear = m_filter == 2 ? m_vt.IsLinear() : m_filter != 0;
|
bool bilinear = m_filter == 2 || m_filter == 4 ? m_vt.IsLinear() : m_filter != 0;
|
||||||
bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 2 && m_context->CLAMP.WMT < 2;
|
bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 2 && m_context->CLAMP.WMT < 2;
|
||||||
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
||||||
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
||||||
|
|
|
@ -571,7 +571,7 @@ void GSRendererHW::Draw()
|
||||||
tex = tex_psm.depth ? m_tc->LookupDepthSource(TEX0, env.TEXA, r) : m_tc->LookupSource(TEX0, env.TEXA, r);
|
tex = tex_psm.depth ? m_tc->LookupDepthSource(TEX0, env.TEXA, r) : m_tc->LookupSource(TEX0, env.TEXA, r);
|
||||||
|
|
||||||
// Round 2
|
// Round 2
|
||||||
if (IsMipMapActive() && m_mipmap > 1 && !tex_psm.depth) {
|
if (IsMipMapActive() && m_mipmap == 2 && !tex_psm.depth) {
|
||||||
// Upload remaining texture layers
|
// Upload remaining texture layers
|
||||||
GSVector4 tmin = m_vt.m_min.t;
|
GSVector4 tmin = m_vt.m_min.t;
|
||||||
GSVector4 tmax = m_vt.m_max.t;
|
GSVector4 tmax = m_vt.m_max.t;
|
||||||
|
|
|
@ -747,9 +747,45 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||||
const uint8 wmt = m_context->CLAMP.WMT;
|
const uint8 wmt = m_context->CLAMP.WMT;
|
||||||
bool complex_wms_wmt = !!((wms | wmt) & 2);
|
bool complex_wms_wmt = !!((wms | wmt) & 2);
|
||||||
|
|
||||||
bool mipmap = m_mipmap > 1 && m_context->TEX1.MMIN > 1;
|
bool need_mipmap = IsMipMapDraw();
|
||||||
bool bilinear = m_filter == 2 ? m_vt.IsLinear() : m_filter != 0;
|
|
||||||
bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth;
|
bool shader_emulated_sampler = tex->m_palette || cpsm.fmt != 0 || complex_wms_wmt || psm.depth;
|
||||||
|
bool trilinear_manual = need_mipmap && m_mipmap == 2;
|
||||||
|
|
||||||
|
bool bilinear = false;
|
||||||
|
int trilinear = 0;
|
||||||
|
bool trilinear_auto = false;
|
||||||
|
switch (m_filter) {
|
||||||
|
case 0: // Nearest
|
||||||
|
bilinear = false;
|
||||||
|
break;
|
||||||
|
case 1: // Forced Bilinear
|
||||||
|
bilinear = true;
|
||||||
|
break;
|
||||||
|
case 2: // Bilinear PS2
|
||||||
|
bilinear = m_vt.IsLinear();
|
||||||
|
break;
|
||||||
|
case 3: // Trilinear Forced
|
||||||
|
bilinear = true;
|
||||||
|
trilinear = static_cast<uint8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
|
||||||
|
trilinear_auto = m_mipmap != 2;
|
||||||
|
break;
|
||||||
|
case 4: // Trilinear
|
||||||
|
bilinear = m_vt.IsLinear();
|
||||||
|
if (need_mipmap && m_mipmap != 2) {
|
||||||
|
trilinear = m_context->TEX1.MMIN;
|
||||||
|
trilinear_auto = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5: // Trilinear (forced on linear)
|
||||||
|
bilinear = true;
|
||||||
|
if (need_mipmap && m_mipmap != 2) {
|
||||||
|
trilinear = (m_context->TEX1.MMIN | 4) & 0x5;
|
||||||
|
trilinear_auto = true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
// Don't force extra filtering on sprite (it creates various upscaling issue)
|
||||||
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());
|
||||||
|
|
||||||
|
@ -875,12 +911,14 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||||
if (complex_wms_wmt) {
|
if (complex_wms_wmt) {
|
||||||
ps_cb.MskFix = GSVector4i(m_context->CLAMP.MINU, m_context->CLAMP.MINV, m_context->CLAMP.MAXU, m_context->CLAMP.MAXV);
|
ps_cb.MskFix = GSVector4i(m_context->CLAMP.MINU, m_context->CLAMP.MINV, m_context->CLAMP.MAXU, m_context->CLAMP.MAXV);
|
||||||
ps_cb.MinMax = GSVector4(ps_cb.MskFix) / WH.xyxy();
|
ps_cb.MinMax = GSVector4(ps_cb.MskFix) / WH.xyxy();
|
||||||
} else if (mipmap) {
|
} else if (trilinear_manual) {
|
||||||
// Reuse MinMax for mipmap parameter to avoid an extension of the UBO
|
// Reuse MinMax for mipmap parameter to avoid an extension of the UBO
|
||||||
ps_cb.MinMax.x = (float)m_context->TEX1.K / 16.0f;
|
ps_cb.MinMax.x = (float)m_context->TEX1.K / 16.0f;
|
||||||
ps_cb.MinMax.y = float(1 << m_context->TEX1.L);
|
ps_cb.MinMax.y = float(1 << m_context->TEX1.L);
|
||||||
ps_cb.MinMax.z = float(m_lod.x); // Offset because first layer is m_lod, dunno if we can do better
|
ps_cb.MinMax.z = float(m_lod.x); // Offset because first layer is m_lod, dunno if we can do better
|
||||||
ps_cb.MinMax.w = float(m_lod.y);
|
ps_cb.MinMax.w = float(m_lod.y);
|
||||||
|
} else if (trilinear_auto) {
|
||||||
|
tex->m_texture->GenerateMipmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TC Offset Hack
|
// TC Offset Hack
|
||||||
|
@ -898,11 +936,11 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||||
} else {
|
} else {
|
||||||
m_ps_ssel.biln = bilinear;
|
m_ps_ssel.biln = bilinear;
|
||||||
m_ps_ssel.aniso = 1;
|
m_ps_ssel.aniso = 1;
|
||||||
if (mipmap) {
|
m_ps_ssel.triln = trilinear;
|
||||||
m_ps_ssel.triln = m_context->TEX1.MMIN;
|
if (trilinear_manual) {
|
||||||
m_ps_sel.manual_lod = 1;
|
m_ps_sel.manual_lod = 1;
|
||||||
} else {
|
} else if (trilinear_auto) {
|
||||||
m_ps_ssel.triln = m_context->TEX1.MMIN & 1;
|
m_ps_sel.automatic_lod = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue