diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 86902de7c3..d5dd22967e 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -353,7 +353,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd) ASSERT(sizeof(PSSamplerSelector) == 4); ASSERT(sizeof(OMDepthStencilSelector) == 4); ASSERT(sizeof(OMColorMaskSelector) == 4); - ASSERT(sizeof(OMBlendSelector) == 4); return true; } @@ -663,6 +662,7 @@ GLuint GSDeviceOGL::CompilePS(PSSelector sel) + format("#define PS_WRITE_RG %d\n", sel.write_rg) + format("#define PS_FBMASK %d\n", sel.fbmask) + format("#define PS_HDR %d\n", sel.hdr) + + format("#define PS_PABE %d\n", sel.pabe); ; return m_shader->Compile("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, tfx_fs_all_glsl, macro); diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index a86e2a22aa..5edab6f4e1 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -285,6 +285,7 @@ class GSDeviceOGL : public GSDevice uint32 blend_c:2; uint32 blend_d:2; uint32 clr1:1; // useful? + uint32 pabe:1; uint32 hdr:1; uint32 colclip:1; @@ -292,7 +293,7 @@ class GSDeviceOGL : public GSDevice uint32 tcoffsethack:1; //uint32 point_sampler:1; Not tested, so keep the bit for blend - uint32 _free2:20; + uint32 _free2:19; }; uint64 key; @@ -378,42 +379,6 @@ class GSDeviceOGL : public GSDevice OMColorMaskSelector(uint32 c) { wrgba = c; } }; - struct OMBlendSelector - { - union - { - struct - { - uint32 abe:1; - uint32 a:2; - uint32 b:2; - uint32 c:2; - uint32 d:2; - - uint32 _free:23; - }; - - struct - { - uint32 _abe:1; - uint32 abcd:8; - - uint32 _free2:23; - }; - - uint32 key; - }; - - operator uint32() {return key;} - - OMBlendSelector() : key(0) {} - - bool IsCLR1() const - { - return (key & 0x19f) == 0x93; // abe == 1 && a == 1 && b == 2 && d == 1 - } - }; - struct D3D9Blend {int bogus, op, src, dst;}; static const D3D9Blend m_blendMapD3D9[3*3*3*3 + 1]; static const int m_NO_BLEND; diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 18b5567ac5..0bd8abedb7 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -303,91 +303,74 @@ bool GSRendererOGL::EmulateTextureShuffleAndFbmask(GSDeviceOGL::PSSelector& ps_s bool GSRendererOGL::EmulateBlending(GSDeviceOGL::PSSelector& ps_sel, bool DATE_GL42) { + GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; const GIFRegALPHA& ALPHA = m_context->ALPHA; bool require_barrier = false; - GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; + bool sw_blending = false; float afix = (float)m_context->ALPHA.FIX / 0x80; - GSDeviceOGL::OMBlendSelector om_bsel; - om_bsel.abe = PRIM->ABE || PRIM->AA1 && m_vt.m_primclass == GS_LINE_CLASS; - - om_bsel.a = ALPHA.A; - om_bsel.b = ALPHA.B; - om_bsel.c = ALPHA.C; - om_bsel.d = ALPHA.D; + // No blending so early exit + if (!(PRIM->ABE || PRIM->AA1 && m_vt.m_primclass == GS_LINE_CLASS)) { +#ifdef ENABLE_OGL_DEBUG + if (m_env.PABE.PABE) { + GL_INS("!!! ENV PABE without ABE !!!"); + } +#endif + dev->OMSetBlendState(); + return false; + } if (m_env.PABE.PABE) { GL_INS("!!! ENV PABE not supported !!!"); - // FIXME it could be supported with SW blending! - if (om_bsel.a == 0 && om_bsel.b == 1 && om_bsel.c == 0 && om_bsel.d == 1) - { - // this works because with PABE alpha blending is on when alpha >= 0x80, but since the pixel shader - // cannot output anything over 0x80 (== 1.0) blending with 0x80 or turning it off gives the same result - om_bsel.abe = 0; + if (m_sw_blending >= ACC_BLEND_CCLIP_DALPHA) { + ps_sel.pabe = 1; + require_barrier |= (ALPHA.C == 1); + sw_blending = true; } - else - { - //Breath of Fire Dragon Quarter triggers this in battles. Graphics are fine though. - //ASSERT(0); - } - } - - // No blending so early exit - if (!om_bsel.abe) { - dev->OMSetBlendState(); - return require_barrier; + //Breath of Fire Dragon Quarter triggers this in battles. Graphics are fine though. + //ASSERT(0); } // Compute the blending equation to detect special case - int blend_sel = ((om_bsel.a * 3 + om_bsel.b) * 3 + om_bsel.c) * 3 + om_bsel.d; - int blend_flag = GSDeviceOGL::m_blendMapD3D9[blend_sel].bogus; + int blend_index = ((ALPHA.A * 3 + ALPHA.B) * 3 + ALPHA.C) * 3 + ALPHA.D; + int blend_flag = GSDeviceOGL::m_blendMapD3D9[blend_index].bogus; + // SW Blend is (nearly) free. Let's use it. - bool free_blend = (blend_flag & BLEND_NO_BAR) || (m_prim_overlap == PRIM_OVERLAP_NO); - // We really need SW blending for this one, barely used - bool impossible_blend = (blend_flag & BLEND_A_MAX); + bool impossible_or_free_blend = (blend_flag & (BLEND_NO_BAR|BLEND_A_MAX|BLEND_ACCU)) + || (m_prim_overlap == PRIM_OVERLAP_NO); + // Do the multiplication in shader for blending accumulation: Cs*As + Cd or Cs*Af + Cd bool accumulation_blend = (blend_flag & BLEND_ACCU); - bool sw_blending_base = m_sw_blending && (free_blend || impossible_blend); + // Warning no break on purpose + switch (m_sw_blending) { + case ACC_BLEND_ULTRA: sw_blending |= true; + case ACC_BLEND_FULL: sw_blending |= !( (ALPHA.A == ALPHA.B) || (ALPHA.C == 2 && ALPHA.FIX <= 128u) ); + case ACC_BLEND_CCLIP_DALPHA: sw_blending |= (ALPHA.C == 1) || (m_env.COLCLAMP.CLAMP == 0); + case ACC_BLEND_SPRITE: sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS; + case ACC_BLEND_FREE: sw_blending |= ps_sel.fbmask || impossible_or_free_blend; + default: sw_blending |= accumulation_blend; + } + // SW Blending + // GL42 interact very badly with sw blending. GL42 uses the primitiveID to find the primitive + // that write the bad alpha value. Sw blending will force the draw to run primitive by primitive + // (therefore primitiveID will be constant to 1) + sw_blending &= !DATE_GL42; // Color clip if (m_env.COLCLAMP.CLAMP == 0) { if (accumulation_blend) { ps_sel.hdr = 1; GL_INS("COLCLIP Fast HDR mode ENABLED"); - } else if (m_sw_blending >= ACC_BLEND_CCLIP_DALPHA || sw_blending_base) { + } else if (sw_blending) { ps_sel.colclip = 1; - sw_blending_base = true; GL_INS("COLCLIP SW ENABLED (blending is %d/%d/%d/%d)", ALPHA.A, ALPHA.B, ALPHA.C, ALPHA.D); } else { GL_INS("Sorry colclip isn't supported"); } } - // Note: Option is duplicated, one impact the blend unit / the other the shader. - sw_blending_base |= accumulation_blend; - - // Warning no break on purpose - bool sw_blending_adv = false; - switch (m_sw_blending) { - case ACC_BLEND_ULTRA: sw_blending_adv |= true; - case ACC_BLEND_FULL: sw_blending_adv |= !( (ALPHA.A == ALPHA.B) || (ALPHA.C == 2 && afix <= 1.002f) ); - case ACC_BLEND_CCLIP_DALPHA: sw_blending_adv |= (ALPHA.C == 1); - case ACC_BLEND_SPRITE: sw_blending_adv |= m_vt.m_primclass == GS_SPRITE_CLASS; - default: break; - } - - bool sw_blending = sw_blending_base // Free case or Impossible blend - || sw_blending_adv // complex blending case (for special effect) - || ps_sel.fbmask; // accurate fbmask - - - // SW Blending - // GL42 interact very badly with sw blending. GL42 uses the primitiveID to find the primitive - // that write the bad alpha value. Sw blending will force the draw to run primitive by primitive - // (therefore primitiveID will be constant to 1) - sw_blending &= !DATE_GL42; // Seriously don't expect me to support this kind of crazyness. // No mix of COLCLIP + accumulation_blend + DATE GL42 // Neither fbmask and GL42 @@ -397,18 +380,17 @@ bool GSRendererOGL::EmulateBlending(GSDeviceOGL::PSSelector& ps_sel, bool DATE_G // For stat to optimize accurate option #if 0 GL_INS("BLEND_INFO: %d/%d/%d/%d. Clamp:%d. Prim:%d number %d (sw %d)", - om_bsel.a, om_bsel.b, om_bsel.c, om_bsel.d, m_env.COLCLAMP.CLAMP, m_vt.m_primclass, m_vertex.next, sw_blending); + ALPHA.A, ALPHA.B, ALPHA.C, ALPHA.D, m_env.COLCLAMP.CLAMP, m_vt.m_primclass, m_vertex.next, sw_blending); #endif if (sw_blending) { - ps_sel.blend_a = om_bsel.a; - ps_sel.blend_b = om_bsel.b; - ps_sel.blend_c = om_bsel.c; - ps_sel.blend_d = om_bsel.d; + ps_sel.blend_a = ALPHA.A; + ps_sel.blend_b = ALPHA.B; + ps_sel.blend_c = ALPHA.C; + ps_sel.blend_d = ALPHA.D; if (accumulation_blend) { // Keep HW blending to do the addition - dev->OMSetBlendState(blend_sel); - om_bsel.abe = 1; + dev->OMSetBlendState(blend_index); // Remove the addition from the SW blending ps_sel.blend_d = 2; } else { @@ -424,13 +406,13 @@ bool GSRendererOGL::EmulateBlending(GSDeviceOGL::PSSelector& ps_sel, bool DATE_G // No need to flush for every primitive require_barrier |= !(blend_flag & BLEND_NO_BAR) && !accumulation_blend; } else { - ps_sel.clr1 = om_bsel.IsCLR1(); + ps_sel.clr1 = (blend_flag & BLEND_C_CLR); if (ps_sel.dfmt == 1 && ALPHA.C == 1) { // 24 bits doesn't have an alpha channel so use 1.0f fix factor as equivalent - int hacked_blend_sel = blend_sel + 3; // +3 <=> +1 on C - dev->OMSetBlendState(hacked_blend_sel, 1.0f, true); + int hacked_blend_index = blend_index + 3; // +3 <=> +1 on C + dev->OMSetBlendState(hacked_blend_index, 1.0f, true); } else { - dev->OMSetBlendState(blend_sel, afix, (ALPHA.C == 2)); + dev->OMSetBlendState(blend_index, afix, (ALPHA.C == 2)); } }