diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 600d2a590c..e1a129bd5f 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -751,39 +751,52 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour #endif } - // Post-processing hack + // Upscaling hack to avoid various line/grid issues if (UserHacks_merge_sprite && tex && tex->m_target && (m_vt.m_primclass == GS_SPRITE_CLASS)) { if (PRIM->FST && GSLocalMemory::m_psm[tex->m_TEX0.PSM].fmt < 2 && ((m_vt.m_eq.value & 0xCFFFF) == 0xCFFFF)) { -#ifdef ENABLE_OGL_DEBUG - const GSVector4 delta_p = m_vt.m_max.p - m_vt.m_min.p; - const GSVector4 delta_t = m_vt.m_max.t - m_vt.m_min.t; - GL_INS("PP SAMPLER: Dp %f %f Dt %f %f", delta_p.x, delta_p.y, delta_t.x, delta_t.y); + + // Ideally the hack ought to be enabled in a true paving mode only. I don't know how to do it accurately + // neither in a fast way. So instead let's just take the hypothesis that all sprites must have the same + // size. + // Tested on Tekken 5. + GSVertex* v = &m_vertex.buff[0]; + bool is_paving = true; + // SSE optimization: shuffle m[1] to have (4*32 bits) X, Y, U, V + int first_dpX = v[1].XYZ.X - v[0].XYZ.X; + int first_dpU = v[1].U - v[0].U; + for (int i = 0; i < m_vertex.next; i += 2) { + int dpX = v[i+1].XYZ.X - v[i].XYZ.X; + int dpU = v[i+1].U - v[i].U; + if (dpX != first_dpX || dpU != first_dpU) { + is_paving = false; + break; + } + } + +#if 0 + GSVector4 delta_p = m_vt.m_max.p - m_vt.m_min.p; + GSVector4 delta_t = m_vt.m_max.t - m_vt.m_min.t; + bool is_blit = PrimitiveOverlap() == PRIM_OVERLAP_NO; + GL_INS("PP SAMPLER: Dp %f %f Dt %f %f. Is blit %d, is paving %d, count %d", delta_p.x, delta_p.y, delta_t.x, delta_t.y, is_blit, is_paving, m_vertex.tail); #endif - //fprintf(stderr, "SAMPLER: Dp %f %f Dt %f %f\n", delta_p.x, delta_p.y, delta_t.x, delta_t.y); - GSVertex* s = &m_vertex.buff[0]; - //fprintf(stderr, "Before %d %d => %d %d \n", s[0].XYZ.X, s[0].XYZ.Y, s[1].XYZ.Y, s[1].XYZ.Y); - //fprintf(stderr, "SAMPLER: p %f %f OFFSET %d\n", m_vt.m_min.p.x, m_vt.m_max.p.x, m_context->XYOFFSET.OFX); + if (is_paving) { + // Replace all sprite with a single fullscreen sprite. + GSVertex* s = &m_vertex.buff[0]; - s[0].XYZ.X = (16.0f * m_vt.m_min.p.x) + m_context->XYOFFSET.OFX; - s[1].XYZ.X = (16.0f * m_vt.m_max.p.x) + m_context->XYOFFSET.OFX; - s[0].XYZ.Y = (16.0f * m_vt.m_min.p.y) + m_context->XYOFFSET.OFY; - s[1].XYZ.Y = (16.0f * m_vt.m_max.p.y) + m_context->XYOFFSET.OFY; + s[0].XYZ.X = (16.0f * m_vt.m_min.p.x) + m_context->XYOFFSET.OFX; + s[1].XYZ.X = (16.0f * m_vt.m_max.p.x) + m_context->XYOFFSET.OFX; + s[0].XYZ.Y = (16.0f * m_vt.m_min.p.y) + m_context->XYOFFSET.OFY; + s[1].XYZ.Y = (16.0f * m_vt.m_max.p.y) + m_context->XYOFFSET.OFY; - //fprintf(stderr, "After %d %d => %d %d \n", s[0].XYZ.X, s[0].XYZ.Y, s[1].XYZ.Y, s[1].XYZ.Y); + s[0].U = 16.0f * m_vt.m_min.t.x; + s[0].V = 16.0f * m_vt.m_min.t.y; + s[1].U = 16.0f * m_vt.m_max.t.x; + s[1].V = 16.0f * m_vt.m_max.t.y; - //fprintf(stderr, "Before %d %d => %d %d \n", s[0].U, s[0].V, s[1].U, s[1].V); - - s[0].U = 16.0f * m_vt.m_min.t.x; - s[0].V = 16.0f * m_vt.m_min.t.y; - s[1].U = 16.0f * m_vt.m_max.t.x; - s[1].V = 16.0f * m_vt.m_max.t.y; - - //fprintf(stderr, "After %d %d => %d %d \n", s[0].U, s[0].V, s[1].U, s[1].V); - - m_vertex.head = m_vertex.tail = m_vertex.next = 2; - m_index.tail = 2; - //exit(0); + m_vertex.head = m_vertex.tail = m_vertex.next = 2; + m_index.tail = 2; + } } }