From 5ced9c1f19b3bc65d07fb01ae8d71c58a295a742 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 2 Oct 2016 10:51:29 +0200 Subject: [PATCH] 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 --- plugins/GSdx/GSDeviceOGL.cpp | 3 +- plugins/GSdx/GSDeviceOGL.h | 1 + plugins/GSdx/GSRendererDX.cpp | 2 +- plugins/GSdx/GSRendererHW.cpp | 2 +- plugins/GSdx/GSRendererOGL.cpp | 52 +++++++++++++++++++++++++++++----- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index a43874fa37..1b47fc8c3a 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -75,6 +75,7 @@ GSDeviceOGL::GSDeviceOGL() GLState::Clear(); m_mipmap = theApp.GetConfigI("mipmap"); + m_filter = theApp.GetConfigI("filter"); // Reset the debug file #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 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) { throw GSDXErrorOOM(); } diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 0d9d8ed687..2a0f8b1023 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -405,6 +405,7 @@ public: uint32 m_msaa; // Level of Msaa int m_force_texture_clear; int m_mipmap; + int m_filter; static bool m_debug_gl_call; static FILE* m_debug_gl_file; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index 52f2f43ee0..42cef3a04c 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -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 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; // 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()); diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index fb87c9a531..1cbffeca37 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -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); // Round 2 - if (IsMipMapActive() && m_mipmap > 1 && !tex_psm.depth) { + if (IsMipMapActive() && m_mipmap == 2 && !tex_psm.depth) { // Upload remaining texture layers GSVector4 tmin = m_vt.m_min.t; GSVector4 tmax = m_vt.m_max.t; diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index ea79807918..8c18f1d95b 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -747,9 +747,45 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) const uint8 wmt = m_context->CLAMP.WMT; bool complex_wms_wmt = !!((wms | wmt) & 2); - bool mipmap = m_mipmap > 1 && m_context->TEX1.MMIN > 1; - bool bilinear = m_filter == 2 ? m_vt.IsLinear() : m_filter != 0; + bool need_mipmap = IsMipMapDraw(); 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(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) 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) { 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(); - } else if (mipmap) { + } else if (trilinear_manual) { // 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.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.w = float(m_lod.y); + } else if (trilinear_auto) { + tex->m_texture->GenerateMipmap(); } // TC Offset Hack @@ -898,11 +936,11 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) } else { m_ps_ssel.biln = bilinear; m_ps_ssel.aniso = 1; - if (mipmap) { - m_ps_ssel.triln = m_context->TEX1.MMIN; + m_ps_ssel.triln = trilinear; + if (trilinear_manual) { m_ps_sel.manual_lod = 1; - } else { - m_ps_ssel.triln = m_context->TEX1.MMIN & 1; + } else if (trilinear_auto) { + m_ps_sel.automatic_lod = 1; } }