diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h index eba2a0ac6ace2..3673aa2a381d2 100644 --- a/plugins/GSdx/GS.h +++ b/plugins/GSdx/GS.h @@ -1416,14 +1416,19 @@ enum class GSVideoMode : uint8 DTV_1080I }; -enum class Filtering : uint8 +enum class BiFiltering : uint8 { Nearest, - Bilinear_Forced, - Bilinear_PS2, - Trilinear, - Trilinear_Bilinear_Forced, - Trilinear_Always + PS2, + Forced_But_Sprite, + Forced, +}; + +enum class TriFiltering : uint8 +{ + None, + PS2, + Forced, }; enum class CRCHackLevel : uint8 diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index f86b52c7ea0e6..baff080ed6818 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -76,7 +76,9 @@ GSDeviceOGL::GSDeviceOGL() GLState::Clear(); m_mipmap = theApp.GetConfigI("mipmap"); - m_filter = static_cast(theApp.GetConfigI("filter")); + m_filter = static_cast(theApp.GetConfigI("UserHacks_TriFilter")); + if (!theApp.GetConfigB("UserHacks")) + m_filter = TriFiltering::None; // Reset the debug file #ifdef ENABLE_OGL_DEBUG @@ -234,9 +236,8 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt { GL_PUSH("Create surface"); - bool trilinear = m_filter == Filtering::Trilinear || m_filter == Filtering::Trilinear_Bilinear_Forced || m_filter == Filtering::Trilinear_Always; // A wrapper to call GSTextureOGL, with the different kind of parameter - GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || trilinear); + GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || m_filter != TriFiltering::None); // NOTE: I'm not sure RenderTarget always need to be cleared. It could be costly for big upscale. // FIXME: it will be more logical to do it in FetchSurface. This code is only called at first creation diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 7f8f14243df44..49b8fe81247bb 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -411,7 +411,7 @@ class GSDeviceOGL final : public GSDevice uint32 m_msaa; // Level of Msaa int m_force_texture_clear; int m_mipmap; - Filtering m_filter; + TriFiltering m_filter; static bool m_debug_gl_call; static FILE* m_debug_gl_file; diff --git a/plugins/GSdx/GSLinuxDialog.cpp b/plugins/GSdx/GSLinuxDialog.cpp index 66d09a2de49ae..163c697d83414 100644 --- a/plugins/GSdx/GSLinuxDialog.cpp +++ b/plugins/GSdx/GSLinuxDialog.cpp @@ -219,9 +219,6 @@ GtkWidget* CreateTableInBox(GtkWidget* parent_box, const char* frame_title, int void populate_hw_table(GtkWidget* hw_table) { - GtkWidget* filter_label = left_label("Texture Filtering:"); - GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_filter, "filter"); - GtkWidget* fsaa_label = left_label("Internal Resolution:"); GtkWidget* fsaa_combo_box = CreateComboBoxFromVector(theApp.m_gs_upscale_multiplier, "upscale_multiplier"); @@ -249,7 +246,6 @@ void populate_hw_table(GtkWidget* hw_table) AddTooltip(large_fb_check, IDC_LARGE_FB); AddTooltip(crc_label, crc_combo_box, IDC_CRC_LEVEL); AddTooltip(acc_bld_label, acc_bld_combo_box, IDC_ACCURATE_BLEND_UNIT); - AddTooltip(filter_label, filter_combo_box, IDC_FILTER); AddTooltip(af_label, af_combo_box, IDC_AFCOMBO); gtk_widget_set_tooltip_text(hack_enable_check, "Enable the HW hack option panel"); AddTooltip(mipmap_label, IDC_MIPMAP_HW); @@ -259,7 +255,6 @@ void populate_hw_table(GtkWidget* hw_table) InsertWidgetInTable(hw_table , paltex_check , acc_date_check); InsertWidgetInTable(hw_table , large_fb_check, hack_enable_check); InsertWidgetInTable(hw_table , fsaa_label , fsaa_combo_box); - InsertWidgetInTable(hw_table , filter_label , filter_combo_box); InsertWidgetInTable(hw_table , af_label , af_combo_box); InsertWidgetInTable(hw_table , acc_bld_label , acc_bld_combo_box); InsertWidgetInTable(hw_table , crc_label , crc_combo_box); @@ -359,6 +354,8 @@ void populate_hack_table(GtkWidget* hack_table) GtkWidget* hack_sprite_label = left_label("Alpha-Sprite Hack:"); GtkWidget* stretch_hack_box = CreateComboBoxFromVector(theApp.m_gs_hack, "UserHacks_round_sprite_offset"); GtkWidget* stretch_hack_label = left_label("Align Sprite Texture:"); + GtkWidget* trilinear_box = CreateComboBoxFromVector(theApp.m_gs_trifilter, "UserHacks_TriFilter"); + GtkWidget* trilinear_label = left_label("Trilinear Filtering:"); // Reuse windows helper string :) AddTooltip(hack_offset_label, IDC_OFFSETHACK); @@ -376,6 +373,8 @@ void populate_hack_table(GtkWidget* hack_table) AddTooltip(hack_depth_check, IDC_TC_DEPTH); AddTooltip(hack_auto_flush, IDC_AUTO_FLUSH); AddTooltip(hack_unscale_prim, IDC_UNSCALE_POINT_LINE); + AddTooltip(trilinear_box, IDC_TRI_FILTER); + AddTooltip(trilinear_label, IDC_TRI_FILTER); s_table_line = 0; @@ -390,6 +389,7 @@ void populate_hack_table(GtkWidget* hack_table) InsertWidgetInTable(hack_table , stretch_hack_label , stretch_hack_box ); InsertWidgetInTable(hack_table , hack_skipdraw_label , hack_skipdraw_spin); InsertWidgetInTable(hack_table , hack_tco_label , hack_tco_entry); + InsertWidgetInTable(hack_table , trilinear_label , trilinear_box); } void populate_main_table(GtkWidget* main_table) @@ -398,11 +398,15 @@ void populate_main_table(GtkWidget* main_table) GtkWidget* render_combo_box = CreateComboBoxFromVector(theApp.m_gs_renderers, "Renderer"); GtkWidget* interlace_label = left_label("Interlacing (F5):"); GtkWidget* interlace_combo_box = CreateComboBoxFromVector(theApp.m_gs_interlace, "interlace"); + GtkWidget* filter_label = left_label("Texture Filtering:"); + GtkWidget* filter_combo_box = CreateComboBoxFromVector(theApp.m_gs_bifilter, "filter"); + AddTooltip(filter_label, filter_combo_box, IDC_FILTER); s_table_line = 0; InsertWidgetInTable(main_table, render_label, render_combo_box); InsertWidgetInTable(main_table, interlace_label, interlace_combo_box); + InsertWidgetInTable(main_table, filter_label , filter_combo_box); } void populate_debug_table(GtkWidget* debug_table) diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index cac0fef5a2c08..ac2524ddc807c 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -45,7 +45,6 @@ GSRenderer::GSRenderer() m_interlace = theApp.GetConfigI("interlace") % s_interlace_nb; m_aspectratio = theApp.GetConfigI("AspectRatio") % s_aspect_ratio_nb; m_shader = theApp.GetConfigI("TVShader") % s_post_shader_nb; - m_filter = static_cast(theApp.GetConfigI("filter")); m_vsync = theApp.GetConfigB("vsync"); m_aa1 = theApp.GetConfigB("aa1"); m_fxaa = theApp.GetConfigB("fxaa"); diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index 273f7c526bbf5..9e91ee07fdb6f 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -48,7 +48,6 @@ class GSRenderer : public GSState bool m_fxaa; bool m_shadeboost; bool m_texture_shuffle; - Filtering m_filter; GSVector2i m_real_size; virtual GSTexture* GetOutput(int i, int& y_offset) = 0; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index f14a1321829e4..1bb35224db912 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -478,10 +478,8 @@ 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 == Filtering::Bilinear_PS2 || m_filter == Filtering::Trilinear ? m_vt.IsLinear() : m_filter != Filtering::Nearest; + bool bilinear = m_vt.IsLinear(); 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()); ps_sel.wms = m_context->CLAMP.WMS; ps_sel.wmt = m_context->CLAMP.WMT; diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 043d52bf9754e..08d94553e5730 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -40,6 +40,7 @@ GSRendererOGL::GSRendererOGL() UserHacks_merge_sprite = theApp.GetConfigB("UserHacks_merge_pp_sprite"); UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line"); UserHacks_HPO = theApp.GetConfigI("UserHacks_HalfPixelOffset"); + UserHacks_tri_filter = static_cast(theApp.GetConfigI("UserHacks_TriFilter")); m_prim_overlap = PRIM_OVERLAP_UNKNOW; ResetStates(); @@ -51,6 +52,7 @@ GSRendererOGL::GSRendererOGL() UserHacks_merge_sprite = false; UserHacks_unscale_pt_ln = false; UserHacks_HPO = 0; + UserHacks_tri_filter = TriFiltering::None; } } @@ -744,7 +746,7 @@ void GSRendererOGL::RealignTargetTextureCoordinate(const GSTextureCache::Source* GSVertex* v = &m_vertex.buff[0]; const GSVector2& scale = tex->m_texture->GetScale(); - bool linear = m_vt.IsLinear(); + bool linear = m_vt.IsRealLinear(); int t_position = v[0].U; GSVector4 half_offset(0.0f); @@ -814,50 +816,28 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) 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; + bool bilinear = m_vt.IsLinear(); int trilinear = 0; bool trilinear_auto = false; - switch (m_filter) + switch (UserHacks_tri_filter) { - case Filtering::Nearest: - bilinear = false; - break; - - case Filtering::Bilinear_Forced: - bilinear = true; - break; - - case Filtering::Bilinear_PS2: - bilinear = m_vt.IsLinear(); - break; - - case Filtering::Trilinear_Always: - bilinear = true; + case TriFiltering::Forced: trilinear = static_cast(GS_MIN_FILTER::Linear_Mipmap_Linear); trilinear_auto = m_mipmap != 2; break; - case Filtering::Trilinear: - bilinear = m_vt.IsLinear(); + case TriFiltering::PS2: if (need_mipmap && m_mipmap != 2) { trilinear = m_context->TEX1.MMIN; trilinear_auto = true; } break; - case Filtering::Trilinear_Bilinear_Forced: - bilinear = true; - if (need_mipmap && m_mipmap != 2) { - trilinear = (m_context->TEX1.MMIN | 4) & 0x5; - trilinear_auto = true; - } + case TriFiltering::None: 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()); - // 1 and 0 are equivalent m_ps_sel.wms = (wms & 2) ? wms : 0; m_ps_sel.wmt = (wmt & 2) ? wmt : 0; diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index 8b8663a81bf9d..d92749ba0804a 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -55,6 +55,7 @@ class GSRendererOGL final : public GSRendererHW bool UserHacks_merge_sprite; bool UserHacks_unscale_pt_ln; int UserHacks_HPO; + TriFiltering UserHacks_tri_filter; GSDeviceOGL::VSConstantBuffer vs_cb; GSDeviceOGL::PSConstantBuffer ps_cb; diff --git a/plugins/GSdx/GSSetting.cpp b/plugins/GSdx/GSSetting.cpp index 83c79ee22cb18..0a43926867254 100644 --- a/plugins/GSdx/GSSetting.cpp +++ b/plugins/GSdx/GSSetting.cpp @@ -33,11 +33,17 @@ const char* dialog_message(int ID, bool* updateText) { case IDC_FILTER: return "Control the texture filtering of the emulation.\n\n" "Nearest:\nAlways disable interpolation, rendering will be blocky.\n\n" + "Bilinear Forced (excluding sprite):\nAlways enable interpolation except for sprites (FMV/Text/2D elements)." + " Rendering is smoother but it could generate a few glitches. If upscaling is enabled, this setting is recommended over 'Bilinear Forced'\n\n" "Bilinear Forced:\nAlways enable interpolation. Rendering is smoother but it could generate some glitches.\n\n" - "Bilinear PS2:\nUse same mode as the PS2. It is the more accurate option.\n\n" + "Bilinear PS2:\nUse same mode as the PS2. It is the more accurate option.\n\n"; +#ifdef __unix__ + case IDC_TRI_FILTER: + return "Control the texture tri-filtering of the emulation.\n\n" + "None:\nNo extra trilinear filtering.\n\n" "Trilinear:\nUse OpenGL trilinear interpolation when PS2 uses mipmaps.\n\n" - "Trilinear Forced Bilinear:\nSame as above but always enable bilinear interpolation.\n\n" - "Trilinear Ultra:\nAlways enable full trilinear interpolation. Warning Slow!\n\n"; + "Trilinear Forced:\nAlways enable full trilinear interpolation. Warning Slow!\n\n"; +#endif case IDC_CRC_LEVEL: return "Control the number of Auto-CRC hacks applied to games.\n\n" "None:\nRemove nearly all CRC hacks (debug only).\n\n" diff --git a/plugins/GSdx/GSSetting.h b/plugins/GSdx/GSSetting.h index 83ffedc60f5c9..e8061d3c95e4c 100644 --- a/plugins/GSdx/GSSetting.h +++ b/plugins/GSdx/GSSetting.h @@ -43,6 +43,7 @@ const char* dialog_message(int ID, bool* updateText = NULL); #ifndef _WIN32 enum { IDC_FILTER, + IDC_TRI_FILTER, IDC_SKIPDRAWHACK, IDC_SKIPDRAWHACKEDIT, IDC_ALPHAHACK, diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 79623e7a293dd..7a767fc5b54e3 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -151,7 +151,7 @@ void GSSettingsDlg::OnInit() ComboBoxInit(IDC_INTERLACE, theApp.m_gs_interlace, theApp.GetConfigI("interlace")); ComboBoxInit(IDC_UPSCALE_MULTIPLIER, theApp.m_gs_upscale_multiplier, theApp.GetConfigI("upscale_multiplier")); ComboBoxInit(IDC_AFCOMBO, theApp.m_gs_max_anisotropy, theApp.GetConfigI("MaxAnisotropy")); - ComboBoxInit(IDC_FILTER, theApp.m_gs_filter, theApp.GetConfigI("filter")); + ComboBoxInit(IDC_FILTER, theApp.m_gs_bifilter, theApp.GetConfigI("filter")); ComboBoxInit(IDC_ACCURATE_BLEND_UNIT, theApp.m_gs_acc_blend_level, theApp.GetConfigI("accurate_blending_unit")); ComboBoxInit(IDC_CRC_LEVEL, theApp.m_gs_crc_level, theApp.GetConfigI("crc_hack_level")); @@ -190,33 +190,9 @@ void GSSettingsDlg::OnInit() AddTooltip(IDC_LOGZ); AddTooltip(IDC_LARGE_FB); - UpdateFilteringCombobox(); UpdateControls(); } -void GSSettingsDlg::UpdateFilteringCombobox() -{ - INT_PTR i; - ComboBoxGetSelData(IDC_RENDERER, i); - bool opengl = static_cast(i) == GSRendererType::OGL_HW; - bool hw_mode = opengl || static_cast(i) == GSRendererType::DX1011_HW || static_cast(i) == GSRendererType::DX9_HW; - if (!hw_mode) - return; - - uint8 filter = (ComboBoxGetSelData(IDC_FILTER, i)) ? static_cast(i) : static_cast(theApp.GetConfigI("filter")); - if (!opengl) //Currently Trilinear is only exclusive to OpenGL, remove those combobox items when any other renderer is used - { - auto head = theApp.m_gs_filter.begin(); - auto tail = head + static_cast(Filtering::Trilinear); - vector list(head, tail); - ComboBoxInit(IDC_FILTER, list, std::max(uint8(Filtering::Nearest), std::min(filter, uint8(Filtering::Bilinear_PS2)))); - } - else - { - ComboBoxInit(IDC_FILTER, theApp.m_gs_filter, filter); - } -} - bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) { switch (id) @@ -231,7 +207,6 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code) case IDC_RENDERER: if (code == CBN_SELCHANGE) { - UpdateFilteringCombobox(); UpdateControls(); } break; diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index 8b74911beb231..d98da22e8590b 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -88,7 +88,7 @@ class GSSettingsDlg : public GSDialog D3D_FEATURE_LEVEL level; Adapter(const std::string &n, const std::string &i, const D3D_FEATURE_LEVEL &l) : name(n), id(i), level(l) {} }; - + std::vector adapters; vector m_ocl_devs; @@ -96,7 +96,6 @@ class GSSettingsDlg : public GSDialog void UpdateRenderers(); void UpdateControls(); - void UpdateFilteringCombobox(); protected: void OnInit(); diff --git a/plugins/GSdx/GSVertexTrace.cpp b/plugins/GSdx/GSVertexTrace.cpp index 49845b89c5fc8..bb8957948e9ae 100644 --- a/plugins/GSdx/GSVertexTrace.cpp +++ b/plugins/GSdx/GSVertexTrace.cpp @@ -32,9 +32,9 @@ void GSVertexTrace::InitVectors() } GSVertexTrace::GSVertexTrace(const GSState* state) - : m_state(state) + : m_state(state), m_primclass(GS_INVALID_CLASS) { - m_primclass = GS_INVALID_CLASS; + m_force_filter = static_cast(theApp.GetConfigI("filter")); memset(&m_alpha, 0, sizeof(m_alpha)); #define InitUpdate3(P, IIP, TME, FST, COLOR) \ @@ -88,37 +88,58 @@ void GSVertexTrace::Update(const void* vertex, const uint32* index, int v_count, if(TEX1.MXL == 0) // MXL == 0 => MMIN ignored, tested it on ps2 { m_filter.linear = m_filter.mmag; - - return; } + else + { + float K = (float)TEX1.K / 16; - float K = (float)TEX1.K / 16; + if(TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated + { + // LOD = log2(1/|Q|) * (1 << L) + K - if(TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated - { - // LOD = log2(1/|Q|) * (1 << L) + K + GSVector4::storel(&m_lod, m_max.t.uph(m_min.t).log2(3).neg() * (float)(1 << TEX1.L) + K); - GSVector4::storel(&m_lod, m_max.t.uph(m_min.t).log2(3).neg() * (float)(1 << TEX1.L) + K); + if(m_lod.x > m_lod.y) {float tmp = m_lod.x; m_lod.x = m_lod.y; m_lod.y = tmp;} + } + else + { + m_lod.x = K; + m_lod.y = K; + } - if(m_lod.x > m_lod.y) {float tmp = m_lod.x; m_lod.x = m_lod.y; m_lod.y = tmp;} - } - else - { - m_lod.x = K; - m_lod.y = K; + if(m_lod.y <= 0) + { + m_filter.linear = m_filter.mmag; + } + else if(m_lod.x > 0) + { + m_filter.linear = m_filter.mmin; + } + else + { + m_filter.linear = m_filter.mmag | m_filter.mmin; + } } - if(m_lod.y <= 0) - { - m_filter.linear = m_filter.mmag; - } - else if(m_lod.x > 0) - { - m_filter.linear = m_filter.mmin; - } - else + switch (m_force_filter) { - m_filter.linear = m_filter.mmag | m_filter.mmin; + case BiFiltering::Nearest: + m_filter.opt_linear = 0; + break; + + case BiFiltering::Forced_But_Sprite: + // Special case to reduce the number of glitch when upscaling is enabled + m_filter.opt_linear = (m_primclass == GS_SPRITE_CLASS) ? m_filter.linear : 1; + break; + + case BiFiltering::Forced: + m_filter.opt_linear = 1; + break; + + case BiFiltering::PS2: + default: + m_filter.opt_linear = m_filter.linear; + break; } } } diff --git a/plugins/GSdx/GSVertexTrace.h b/plugins/GSdx/GSVertexTrace.h index 09b3909296f3b..4c8854101bfdc 100644 --- a/plugins/GSdx/GSVertexTrace.h +++ b/plugins/GSdx/GSVertexTrace.h @@ -31,6 +31,8 @@ class GSState; class alignas(32) GSVertexTrace : public GSAlignedClass<32> { + BiFiltering m_force_filter; + public: struct Vertex {GSVector4i c; GSVector4 p, t;}; struct VertexAlpha {int min, max; bool valid;}; @@ -61,9 +63,9 @@ class alignas(32) GSVertexTrace : public GSAlignedClass<32> struct {uint32 rgba:16, xyzf:4, stq:4;}; } m_eq; - union + union { - struct {uint32 mmag:1, mmin:1, linear:1;}; + struct {uint32 mmag:1, mmin:1, linear:1, opt_linear:1;}; } m_filter; GSVector2 m_lod; // x = min, y = max @@ -76,7 +78,8 @@ class alignas(32) GSVertexTrace : public GSAlignedClass<32> void Update(const void* vertex, const uint32* index, int v_count, int i_count, GS_PRIM_CLASS primclass); - bool IsLinear() const {return m_filter.linear;} + bool IsLinear() const {return m_filter.opt_linear;} + bool IsRealLinear() const {return m_filter.linear;} void CorrectDepthTrace(const void* vertex, int count); }; diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index e9cf893e1eac9..57dcd5dd7d148 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -201,12 +201,14 @@ void GSdxApp::Init() m_gs_max_anisotropy.push_back(GSSetting(8, "8x", "")); m_gs_max_anisotropy.push_back(GSSetting(16, "16x", "")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Nearest), "Nearest", "")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Bilinear_Forced), "Bilinear", "Forced")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Bilinear_PS2), "Bilinear", "PS2")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Trilinear), "Trilinear", "")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Trilinear_Bilinear_Forced), "Trilinear", "Forced Bilinear")); - m_gs_filter.push_back(GSSetting(static_cast(Filtering::Trilinear_Always), "Trilinear", "Ultra/Slow")); + m_gs_bifilter.push_back(GSSetting(static_cast(BiFiltering::Nearest), "Nearest", "")); + m_gs_bifilter.push_back(GSSetting(static_cast(BiFiltering::Forced_But_Sprite), "Bilinear", "Forced excluding sprite")); + m_gs_bifilter.push_back(GSSetting(static_cast(BiFiltering::Forced), "Bilinear", "Forced")); + m_gs_bifilter.push_back(GSSetting(static_cast(BiFiltering::PS2), "Bilinear", "PS2")); + + m_gs_trifilter.push_back(GSSetting(static_cast(TriFiltering::None), "None", "")); + m_gs_trifilter.push_back(GSSetting(static_cast(TriFiltering::PS2), "Trilinear", "")); + m_gs_trifilter.push_back(GSSetting(static_cast(TriFiltering::Forced), "Trilinear", "Ultra/Slow")); m_gs_gl_ext.push_back(GSSetting(-1, "Auto", "")); m_gs_gl_ext.push_back(GSSetting(0, "Force-Disabled", "")); @@ -307,7 +309,7 @@ void GSdxApp::Init() m_default_configuration["dump"] = "0"; m_default_configuration["extrathreads"] = "2"; m_default_configuration["extrathreads_height"] = "4"; - m_default_configuration["filter"] = "2"; + m_default_configuration["filter"] = to_string(static_cast(BiFiltering::PS2)); m_default_configuration["force_texture_clear"] = "0"; m_default_configuration["fxaa"] = "0"; m_default_configuration["interlace"] = "7"; @@ -380,6 +382,7 @@ void GSdxApp::Init() m_default_configuration["UserHacks_SpriteHack"] = "0"; m_default_configuration["UserHacks_TCOffset"] = "0"; m_default_configuration["UserHacks_TextureInsideRt"] = "0"; + m_default_configuration["UserHacks_TriFilter"] = to_string(static_cast(TriFiltering::None)); m_default_configuration["UserHacks_WildHack"] = "0"; m_default_configuration["wrap_gs_mem"] = "0"; m_default_configuration["vsync"] = "0"; diff --git a/plugins/GSdx/GSdx.h b/plugins/GSdx/GSdx.h index c3623e3246397..9c80630a2ca1b 100644 --- a/plugins/GSdx/GSdx.h +++ b/plugins/GSdx/GSdx.h @@ -68,7 +68,8 @@ class GSdxApp vector m_gs_aspectratio; vector m_gs_upscale_multiplier; vector m_gs_max_anisotropy; - vector m_gs_filter; + vector m_gs_bifilter; + vector m_gs_trifilter; vector m_gs_gl_ext; vector m_gs_hack; vector m_gs_offset_hack;