mirror of https://github.com/PCSX2/pcsx2.git
GSdx: The revision makes every super robot taisen game look perfect! Just joking :P But I tested OG and Alpha 3, and didn't notice anything terribly bad till the beginning of the first battle stage.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4335 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
feda59bf99
commit
9b658615f5
|
@ -218,7 +218,7 @@ void GSDevice::Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVec
|
|||
}
|
||||
}
|
||||
|
||||
DoMerge(tex, sr, dr, m_merge, slbg, mmod, c);
|
||||
DoMerge(tex, sr, m_merge, dr, slbg, mmod, c);
|
||||
|
||||
for(int i = 0; i < countof(tex); i++)
|
||||
{
|
||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
|||
virtual GSTexture* Create(int type, int w, int h, bool msaa, int format) = 0;
|
||||
virtual GSTexture* Fetch(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
virtual void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c) = 0;
|
||||
virtual void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c) = 0;
|
||||
virtual void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset) = 0;
|
||||
|
||||
public:
|
||||
|
|
|
@ -577,7 +577,7 @@ void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
PSSetShaderResources(NULL, NULL);
|
||||
}
|
||||
|
||||
void GSDevice11::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
|
||||
void GSDevice11::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
|
||||
{
|
||||
ClearRenderTarget(dt, c);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class GSDevice11 : public GSDeviceDX
|
|||
{
|
||||
GSTexture* Create(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
|
||||
|
||||
//
|
||||
|
|
|
@ -766,7 +766,7 @@ void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, c
|
|||
EndScene();
|
||||
}
|
||||
|
||||
void GSDevice9::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
|
||||
void GSDevice9::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
|
||||
{
|
||||
ClearRenderTarget(dt, c);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class GSDevice9 : public GSDeviceDX
|
|||
{
|
||||
GSTexture* Create(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
|
||||
|
||||
//
|
||||
|
|
|
@ -29,7 +29,7 @@ class GSDeviceNull : public GSDevice
|
|||
private:
|
||||
GSTexture* Create(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c) {}
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c) {}
|
||||
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0) {}
|
||||
|
||||
public:
|
||||
|
|
|
@ -41,6 +41,8 @@ bool GSDeviceSW::Reset(int w, int h)
|
|||
if(!GSDevice::Reset(w, h))
|
||||
return false;
|
||||
|
||||
// TODO: m_backbuffer should be a window wrapper, or some native bitmap, software-only StretchRect to a full screen window may be too slow
|
||||
|
||||
m_backbuffer = new GSTextureSW(GSTexture::RenderTarget, w, h);
|
||||
|
||||
return true;
|
||||
|
@ -117,9 +119,222 @@ void GSDeviceSW::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
|
|||
}
|
||||
}
|
||||
|
||||
class ShaderBase
|
||||
{
|
||||
protected:
|
||||
GSVector4i Sample(const GSVector4i& c, const GSVector4i& uf, const GSVector4i& vf)
|
||||
{
|
||||
GSVector4i c0 = c.upl8();
|
||||
GSVector4i c1 = c.uph8();
|
||||
|
||||
c0 = c0.lerp16<0>(c1, vf);
|
||||
c0 = c0.lerp16<0>(c0.srl<8>(), uf);
|
||||
|
||||
return c0;
|
||||
}
|
||||
|
||||
GSVector4i Blend(const GSVector4i& c0, const GSVector4i& c1)
|
||||
{
|
||||
return c0.lerp16<0>(c1, c1.wwwwl().sll16(7));
|
||||
}
|
||||
|
||||
GSVector4i Blend2x(const GSVector4i& c0, const GSVector4i& c1)
|
||||
{
|
||||
return c0.lerp16<0>(c1, c1.wwwwl().sll16(1).pu16().uph8().sll16(7)); // .sll16(1).pu16() => 2x, then clamp (...)
|
||||
}
|
||||
|
||||
GSVector4i Blend(const GSVector4i& c0, const GSVector4i& c1, const GSVector4i& f)
|
||||
{
|
||||
return c0.lerp16<0>(c1, f);
|
||||
}
|
||||
};
|
||||
|
||||
class ShaderCopy : public ShaderBase
|
||||
{
|
||||
public:
|
||||
void operator() (uint32* RESTRICT dst, const GSVector4i& c, const GSVector4i& uf, const GSVector4i& vf)
|
||||
{
|
||||
*dst = Sample(c, uf, vf).pu16().extract32<0>();
|
||||
}
|
||||
|
||||
void operator() (uint32* RESTRICT dst, uint32 c)
|
||||
{
|
||||
*dst = c;
|
||||
}
|
||||
};
|
||||
|
||||
class ShaderAlphaBlend : public ShaderBase
|
||||
{
|
||||
public:
|
||||
void operator() (uint32* RESTRICT dst, const GSVector4i& c, const GSVector4i& uf, const GSVector4i& vf)
|
||||
{
|
||||
*dst = Blend(Sample(c, uf, vf), GSVector4i(*dst).uph8()).pu16().extract32<0>();
|
||||
}
|
||||
|
||||
void operator() (uint32* RESTRICT dst, uint32 c)
|
||||
{
|
||||
*dst = Blend(GSVector4i(c), GSVector4i(*dst).uph8()).pu16().extract32<0>();
|
||||
}
|
||||
};
|
||||
|
||||
class ShaderAlpha2xBlend : public ShaderBase
|
||||
{
|
||||
public:
|
||||
void operator() (uint32* RESTRICT dst, const GSVector4i& c, const GSVector4i& uf, const GSVector4i& vf)
|
||||
{
|
||||
*dst = Blend2x(Sample(c, uf, vf), GSVector4i(*dst).uph8()).pu16().extract32<0>();
|
||||
}
|
||||
|
||||
void operator() (uint32* RESTRICT dst, uint32 c)
|
||||
{
|
||||
*dst = Blend2x(GSVector4i(c), GSVector4i(*dst).uph8()).pu16().extract32<0>();
|
||||
}
|
||||
};
|
||||
|
||||
__aligned(class, 16) ShaderFactorBlend : public ShaderBase
|
||||
{
|
||||
GSVector4i m_f;
|
||||
|
||||
public:
|
||||
ShaderFactorBlend(uint32 f)
|
||||
{
|
||||
m_f = GSVector4i((f << 16) | f).xxxx().srl16(1);
|
||||
}
|
||||
|
||||
void operator() (uint32* RESTRICT dst, const GSVector4i& c, const GSVector4i& uf, const GSVector4i& vf)
|
||||
{
|
||||
*dst = Blend(Sample(c, uf, vf), GSVector4i(*dst).uph8(), m_f).pu16().extract32<0>();
|
||||
}
|
||||
|
||||
void operator() (uint32* RESTRICT dst, uint32 c)
|
||||
{
|
||||
*dst = Blend(GSVector4i(c), GSVector4i(*dst).uph8(), m_f).pu16().extract32<0>();
|
||||
}
|
||||
};
|
||||
|
||||
template<class SHADER> static void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, SHADER shader, bool linear)
|
||||
{
|
||||
GSVector4i r(dr.ceil());
|
||||
|
||||
r = r.rintersect(GSVector4i(dt->GetSize()).zwxy());
|
||||
|
||||
if(r.rempty()) return;
|
||||
|
||||
GSTexture::GSMap dm;
|
||||
|
||||
if(!dt->Map(dm, &r)) return;
|
||||
|
||||
GSTexture::GSMap sm;
|
||||
|
||||
if(!st->Map(sm, NULL)) {dt->Unmap(); return;}
|
||||
|
||||
GSVector2i ssize = st->GetSize();
|
||||
|
||||
GSVector4 p = dr;
|
||||
GSVector4 t = sr * GSVector4(ssize).xyxy() * GSVector4((float)0x10000);
|
||||
|
||||
GSVector4 tl = p.xyxy(t);
|
||||
GSVector4 br = p.zwzw(t);
|
||||
GSVector4 tlbr = br - tl;
|
||||
|
||||
tlbr /= tlbr.xyxy();
|
||||
|
||||
if(tl.x < (float)r.left) tl.z += tlbr.z * ((float)r.left - tl.x);
|
||||
if(tl.y < (float)r.top) tl.w += tlbr.w * ((float)r.top - tl.y);
|
||||
|
||||
GSVector4i uvdudv(tl.zwzw(tlbr));
|
||||
|
||||
GSVector4i uv = uvdudv.xxyy() + GSVector4i(0, 0x10000).xyxy();
|
||||
GSVector4i du = uvdudv.zzzz().srl<8>();
|
||||
GSVector4i dv = uvdudv.wwww().sll<8>();
|
||||
|
||||
// TODO: clipping may not be that necessary knowing we don't address outside (except the linear filter +1 pixel)
|
||||
|
||||
GSVector4i uvmax = GSVector4i((ssize.x - 1) << 16, (ssize.y - 1) << 16).xxyy();
|
||||
|
||||
GSVector4i v = uv;
|
||||
|
||||
if(linear)
|
||||
{
|
||||
for(int j = r.height(); j > 0; j--, v += dv, dm.bits += dm.pitch)
|
||||
{
|
||||
GSVector4i vf = v.zzwwh().zzww().srl16(1);
|
||||
GSVector4i vi = v.max_i16(GSVector4i::zero()).min_i16(uvmax);
|
||||
|
||||
int v0 = vi.extract16<5>();
|
||||
int v1 = vi.extract16<7>();
|
||||
|
||||
uint32* RESTRICT src0 = (uint32*)&sm.bits[v0 * sm.pitch];
|
||||
uint32* RESTRICT src1 = (uint32*)&sm.bits[v1 * sm.pitch];
|
||||
uint32* RESTRICT dst = (uint32*)dm.bits;
|
||||
|
||||
GSVector4i u = v;
|
||||
|
||||
for(int i = r.width(); i > 0; i--, dst++, u += du)
|
||||
{
|
||||
GSVector4i uf = u.xxyyh().xxyy().srl16(1);
|
||||
GSVector4i ui = u.max_i16(GSVector4i::zero()).min_i16(uvmax);
|
||||
|
||||
int u0 = ui.extract16<1>();
|
||||
int u1 = ui.extract16<3>();
|
||||
|
||||
shader(dst, GSVector4i(src0[u0], src0[u1], src1[u0], src1[u1]), uf, vf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = r.height(); j > 0; j--, v += dv, dm.bits += dm.pitch)
|
||||
{
|
||||
GSVector4i vi = v.max_i16(GSVector4i::zero()).min_i16(uvmax);
|
||||
|
||||
uint32* RESTRICT src = (uint32*)&sm.bits[vi.extract16<5>() * sm.pitch];
|
||||
uint32* RESTRICT dst = (uint32*)dm.bits;
|
||||
|
||||
GSVector4i u = v;
|
||||
|
||||
for(int i = r.width(); i > 0; i--, dst++, u += du)
|
||||
{
|
||||
GSVector4i ui = u.max_i16(GSVector4i::zero()).min_i16(uvmax);
|
||||
|
||||
shader(dst, src[ui.extract16<1>()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
st->Unmap();
|
||||
dt->Unmap();
|
||||
}
|
||||
|
||||
void GSDeviceSW::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
|
||||
{
|
||||
// TODO: only used to stretch m_current to m_backbuffer, no blending needed (yet)
|
||||
// TODO: if dt == m_backbuffer && m_backbuffer is special
|
||||
|
||||
if(shader == 0)
|
||||
{
|
||||
if((sr == GSVector4(0, 0, 1, 1) & dr == GSVector4(dt->GetSize()).zwxy()).alltrue() && st->GetSize() == dt->GetSize())
|
||||
{
|
||||
// shortcut
|
||||
|
||||
CopyRect(st, dt, GSVector4i(dt->GetSize()).zwxy());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderCopy s;
|
||||
|
||||
::StretchRect(st, sr, dt, dr, s, linear);
|
||||
}
|
||||
else if(shader == 1)
|
||||
{
|
||||
ShaderAlphaBlend s;
|
||||
|
||||
::StretchRect(st, sr, dt, dr, s, linear);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceSW::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
||||
|
@ -139,22 +354,36 @@ void GSDeviceSW::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
|
|||
|
||||
//
|
||||
|
||||
void GSDeviceSW::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
|
||||
void GSDeviceSW::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
|
||||
{
|
||||
ClearRenderTarget(dt, c);
|
||||
|
||||
if(st[1] && !slbg)
|
||||
{
|
||||
// TODO: copy (StretchRect)
|
||||
StretchRect(st[1], *sr, dt, *dr);
|
||||
}
|
||||
|
||||
if(st[0])
|
||||
{
|
||||
// TODO: blend
|
||||
//
|
||||
// mmod 0 => alpha = min(st[0].a * 2, 1)
|
||||
// mmod 1 => alpha = c.a
|
||||
if(mmod == 0)
|
||||
{
|
||||
// alpha = min(st[0].a * 2, 1)
|
||||
|
||||
ShaderAlpha2xBlend s;
|
||||
|
||||
::StretchRect(st[0], sr[0], dt, *dr, s, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alpha = c.a
|
||||
|
||||
ShaderFactorBlend s((uint32)(int)(c.a * 255));
|
||||
|
||||
::StretchRect(st[0], sr[0], dt, *dr, s, true);
|
||||
}
|
||||
}
|
||||
|
||||
// dt->Save("c:\\1.bmp");
|
||||
}
|
||||
|
||||
void GSDeviceSW::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset)
|
||||
|
@ -164,11 +393,22 @@ void GSDeviceSW::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool line
|
|||
GSVector4 sr(0, 0, 1, 1);
|
||||
GSVector4 dr(0.0f, yoffset, s.x, s.y + yoffset);
|
||||
|
||||
// TODO
|
||||
//
|
||||
// shader 0/1 => copy even/odd lines
|
||||
// shader 2 => blend lines (1:2:1 filter)
|
||||
// shader 3 => copy all lines (StretchRect)
|
||||
if(shader == 0 || shader == 1)
|
||||
{
|
||||
// TODO: 0/1 => update even/odd lines of dt
|
||||
}
|
||||
else if(shader == 2)
|
||||
{
|
||||
// TODO: blend lines (1:2:1 filter)
|
||||
}
|
||||
else if(shader == 3)
|
||||
{
|
||||
StretchRect(st, sr, dt, dr, 0, linear);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceSW::Clear(GSTexture* t, uint32 c)
|
||||
|
|
|
@ -28,7 +28,7 @@ class GSDeviceSW : public GSDevice
|
|||
{
|
||||
GSTexture* Create(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c);
|
||||
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
|
||||
|
||||
void Clear(GSTexture* t, uint32 c);
|
||||
|
|
|
@ -140,7 +140,7 @@ bool GSTextureSW::Save(const string& fn, bool dds)
|
|||
|
||||
memset(&bfh, 0, sizeof(bfh));
|
||||
|
||||
uint8* bfType = (uint8*)bfh.bfType;
|
||||
uint8* bfType = (uint8*)&bfh.bfType;
|
||||
|
||||
// bfh.bfType = 'MB';
|
||||
bfType[0] = 0x42;
|
||||
|
|
|
@ -903,6 +903,11 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
GSVector4i madd(const GSVector4i& v) const
|
||||
{
|
||||
return GSVector4i(_mm_madd_epi16(m, v.m));
|
||||
}
|
||||
|
||||
template<int shift> __forceinline GSVector4i lerp16(const GSVector4i& a, const GSVector4i& f) const
|
||||
{
|
||||
// (a - this) * f << shift + this
|
||||
|
|
|
@ -42,12 +42,12 @@ string format(const char* fmt, ...)
|
|||
|
||||
void* vmalloc(size_t size, bool code)
|
||||
{
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, code ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, code ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void vmfree(void* ptr, size_t size)
|
||||
{
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -56,27 +56,27 @@ void vmfree(void* ptr, size_t size)
|
|||
|
||||
void* vmalloc(size_t size, bool code)
|
||||
{
|
||||
size_t mask = getpagesize() - 1;
|
||||
size_t mask = getpagesize() - 1;
|
||||
|
||||
size = (size + mask) & ~mask;
|
||||
size = (size + mask) & ~mask;
|
||||
|
||||
int flags = PROT_READ | PROT_WRITE;
|
||||
int flags = PROT_READ | PROT_WRITE;
|
||||
|
||||
if(code)
|
||||
{
|
||||
flags |= PROT_EXEC;
|
||||
}
|
||||
if(code)
|
||||
{
|
||||
flags |= PROT_EXEC;
|
||||
}
|
||||
|
||||
return mmap(NULL, size, flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
return mmap(NULL, size, flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
}
|
||||
|
||||
void vmfree(void* ptr, size_t size)
|
||||
{
|
||||
size_t mask = getpagesize() - 1;
|
||||
size_t mask = getpagesize() - 1;
|
||||
|
||||
size = (size + mask) & ~mask;
|
||||
size = (size + mask) & ~mask;
|
||||
|
||||
munmap(ptr, size);
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue