diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 54265309af..ce85ece8b3 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -39,6 +39,7 @@ GSRendererOGL::GSRendererOGL() UserHacks_TCO_y = ((UserHacks_TCOffset >> 16) & 0xFFFF) / -1000.0f; 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_New"); m_prim_overlap = PRIM_OVERLAP_UNKNOW; ResetStates(); @@ -49,6 +50,7 @@ GSRendererOGL::GSRendererOGL() UserHacks_TCO_y = 0; UserHacks_merge_sprite = false; UserHacks_unscale_pt_ln = false; + UserHacks_HPO = 0; } } @@ -736,6 +738,59 @@ void GSRendererOGL::EmulateBlending(bool DATE_GL42) } } +void GSRendererOGL::RealignTargetTextureCoordinate(const GSTextureCache::Source* tex) +{ + if (!UserHacks_HPO || GetUpscaleMultiplier() == 1) return; + + GSVertex* v = &m_vertex.buff[0]; + const GSVector2& scale = tex->m_texture->GetScale(); + bool linear = m_vt.IsLinear(); + int t_position = v[0].U; + GSVector4 half_offset(0.0f); + + // FIXME Let's start with something wrong same mess on X and Y + // FIXME Maybe it will be enough to check linear + + if (PRIM->FST) { + + if (UserHacks_HPO > 1) { + if (!linear && t_position == 8) { + half_offset.x = 8; + half_offset.y = 8; + } else if (linear && t_position == 16) { + half_offset.x = 16; + half_offset.y = 16; + } + } else { + if (!linear && t_position == 8) { + half_offset.x = 8 - 8 / scale.x; + half_offset.y = 8 - 8 / scale.y; + } else if (linear && t_position == 16) { + half_offset.x = 16 - 16 / scale.x; + half_offset.y = 16 - 16 / scale.y; + } + } + + GL_INS("offset detected %f,%f t_pos %d (linear %d, scale %f)", + half_offset.x, half_offset.y, t_position, linear, scale.x); + + } else if (m_vt.m_eq.q) { + float tw = (float)(1 << m_context->TEX0.TW); + float th = (float)(1 << m_context->TEX0.TH); + float q = v[0].RGBAQ.Q; + + // Tales of Abyss + half_offset.x = 0.5f * q / tw; + half_offset.y = 0.5f * q / th; + + GL_INS("ST offset detected %f,%f (linear %d, scale %f)", + half_offset.x, half_offset.y, linear, scale.x); + + } + + vs_cb.TextureOffset = GSVector4(half_offset); +} + void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) { GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; @@ -829,6 +884,8 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) // The purpose of texture shuffle is to move color channel. Extra interpolation is likely a bad idea. bilinear &= m_vt.IsLinear(); + RealignTargetTextureCoordinate(tex); + } else if (tex->m_target) { // Use an old target. AEM and index aren't resolved it must be done // on the GPU @@ -877,6 +934,8 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex) bilinear &= m_vt.IsLinear(); } + RealignTargetTextureCoordinate(tex); + } else if (tex->m_palette) { // Use a standard 8 bits texture. AEM is already done on the CLUT // Therefore you only need to set the index @@ -1158,6 +1217,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour bool ate_second_pass = m_context->TEST.DoSecondPass(); ResetStates(); + vs_cb.TextureOffset = GSVector4(0.0f); ASSERT(m_dev != NULL); GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; @@ -1354,7 +1414,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour //The resulting shifted output aligns better with common blending / corona / blurring effects, //but introduces a few bad pixels on the edges. - if (rt && rt->LikelyOffset) + if (rt && rt->LikelyOffset && !UserHacks_HPO) { ox2 *= rt->OffsetHack_modx; oy2 *= rt->OffsetHack_mody; diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index a633d203e5..8b8663a81b 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -54,6 +54,7 @@ class GSRendererOGL final : public GSRendererHW float UserHacks_TCO_x, UserHacks_TCO_y; bool UserHacks_merge_sprite; bool UserHacks_unscale_pt_ln; + int UserHacks_HPO; GSDeviceOGL::VSConstantBuffer vs_cb; GSDeviceOGL::PSConstantBuffer ps_cb; @@ -75,6 +76,7 @@ class GSRendererOGL final : public GSRendererHW inline void ResetStates(); inline void Lines2Sprites(); inline void SetupIA(const float& sx, const float& sy); + inline void RealignTargetTextureCoordinate(const GSTextureCache::Source* tex); inline void EmulateTextureShuffleAndFbmask(); inline void EmulateChannelShuffle(GSTexture** rt, const GSTextureCache::Source* tex); inline void EmulateBlending(bool DATE_GL42); diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index 4d89ac9625..dd2ce6df0f 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -351,6 +351,7 @@ void GSdxApp::Init() m_default_configuration["UserHacks_DisableGsMemClear"] = "0"; m_default_configuration["UserHacks_DisablePartialInvalidation"] = "0"; m_default_configuration["UserHacks_HalfPixelOffset"] = "0"; + m_default_configuration["UserHacks_HalfPixelOffset_New"] = "0"; m_default_configuration["UserHacks_merge_pp_sprite"] = "0"; m_default_configuration["UserHacks_MSAA"] = "0"; m_default_configuration["UserHacks_unscale_point_line"] = "0"; diff --git a/plugins/GSdx/res/glsl/tfx_vgs.glsl b/plugins/GSdx/res/glsl/tfx_vgs.glsl index 229ea8815f..eb405e8ef2 100644 --- a/plugins/GSdx/res/glsl/tfx_vgs.glsl +++ b/plugins/GSdx/res/glsl/tfx_vgs.glsl @@ -27,7 +27,7 @@ void texture_coord() vec2 uv = vec2(i_uv) - TextureOffset.xy; // Float coordinate - VSout.t_float.xy = i_st - TextureOffset.zw; // FIXME or .xy check final code + VSout.t_float.xy = i_st - TextureOffset.xy; VSout.t_float.w = i_q; // Integer coordinate => normalized diff --git a/plugins/GSdx/res/glsl_source.h b/plugins/GSdx/res/glsl_source.h index de4a99a7f0..39a403b580 100644 --- a/plugins/GSdx/res/glsl_source.h +++ b/plugins/GSdx/res/glsl_source.h @@ -770,7 +770,7 @@ static const char* const tfx_vgs_glsl = " vec2 uv = vec2(i_uv) - TextureOffset.xy;\n" "\n" " // Float coordinate\n" - " VSout.t_float.xy = i_st - TextureOffset.zw; // FIXME or .xy check final code\n" + " VSout.t_float.xy = i_st - TextureOffset.xy;\n" " VSout.t_float.w = i_q;\n" "\n" " // Integer coordinate => normalized\n"