2010-04-25 00:31:27 +00:00
|
|
|
/*
|
2009-06-27 03:32:33 +00:00
|
|
|
* Copyright (C) 2007-2009 Gabest
|
|
|
|
* http://www.gabest.org
|
|
|
|
*
|
|
|
|
* This Program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-06-27 03:32:33 +00:00
|
|
|
* This Program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-06-27 03:32:33 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
2010-04-25 00:31:27 +00:00
|
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
2009-06-27 03:32:33 +00:00
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "GSRendererDX9.h"
|
|
|
|
#include "GSCrc.h"
|
|
|
|
#include "resource.h"
|
|
|
|
|
2009-09-18 19:54:56 +00:00
|
|
|
GSRendererDX9::GSRendererDX9()
|
2012-01-05 02:40:24 +00:00
|
|
|
: GSRendererDX(new GSVertexTraceDX9(this), sizeof(GSVertexHW9), new GSTextureCache9(this))
|
2009-06-27 03:32:33 +00:00
|
|
|
{
|
2012-01-05 02:40:24 +00:00
|
|
|
InitConvertVertex(GSRendererDX9);
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 07:40:38 +00:00
|
|
|
bool GSRendererDX9::CreateDevice(GSDevice* dev)
|
2009-06-27 03:32:33 +00:00
|
|
|
{
|
2009-09-17 07:40:38 +00:00
|
|
|
if(!__super::CreateDevice(dev))
|
2009-06-27 03:32:33 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
memset(&m_fba.dss, 0, sizeof(m_fba.dss));
|
|
|
|
|
|
|
|
m_fba.dss.StencilEnable = true;
|
|
|
|
m_fba.dss.StencilReadMask = 2;
|
|
|
|
m_fba.dss.StencilWriteMask = 2;
|
|
|
|
m_fba.dss.StencilFunc = D3DCMP_EQUAL;
|
|
|
|
m_fba.dss.StencilPassOp = D3DSTENCILOP_ZERO;
|
|
|
|
m_fba.dss.StencilFailOp = D3DSTENCILOP_ZERO;
|
|
|
|
m_fba.dss.StencilDepthFailOp = D3DSTENCILOP_ZERO;
|
|
|
|
m_fba.dss.StencilRef = 2;
|
|
|
|
|
|
|
|
memset(&m_fba.bs, 0, sizeof(m_fba.bs));
|
|
|
|
|
|
|
|
m_fba.bs.RenderTargetWriteMask = D3DCOLORWRITEENABLE_ALPHA;
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
template<uint32 prim, uint32 tme, uint32 fst>
|
2012-01-06 00:17:52 +00:00
|
|
|
void GSRendererDX9::ConvertVertex(size_t dst_index, size_t src_index)
|
2009-06-27 03:32:33 +00:00
|
|
|
{
|
2012-01-06 00:17:52 +00:00
|
|
|
GSVertex* s = (GSVertex*)((GSVertexHW9*)m_vertex.buff + src_index);
|
|
|
|
GSVertexHW9* d = (GSVertexHW9*)m_vertex.buff + dst_index;
|
|
|
|
|
|
|
|
GSVector4 p = GSVector4(GSVector4i::load(s->XYZ.u32[0]).upl16());
|
2009-06-27 03:32:33 +00:00
|
|
|
|
|
|
|
if(tme && !fst)
|
|
|
|
{
|
2012-01-06 00:17:52 +00:00
|
|
|
p = p.xyxy(GSVector4((float)s->XYZ.Z, s->RGBAQ.Q));
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-06 00:17:52 +00:00
|
|
|
p = p.xyxy(GSVector4::load((float)s->XYZ.Z));
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
GSVector4 t = GSVector4::zero();
|
2009-06-27 03:32:33 +00:00
|
|
|
|
|
|
|
if(tme)
|
|
|
|
{
|
|
|
|
if(fst)
|
|
|
|
{
|
2012-01-08 17:10:00 +00:00
|
|
|
t = GSVector4(GSVector4i::load(s->UV).upl16());
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-06 00:17:52 +00:00
|
|
|
t = GSVector4::loadl(&s->ST);
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 17:10:00 +00:00
|
|
|
t = t.xyxy(GSVector4::cast(GSVector4i(s->RGBAQ.u32[0], s->FOG)));
|
2012-01-05 02:40:24 +00:00
|
|
|
|
2012-01-06 00:17:52 +00:00
|
|
|
d->p = p;
|
|
|
|
d->t = t;
|
2012-01-05 02:40:24 +00:00
|
|
|
}
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
void GSRendererDX9::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
|
|
|
{
|
|
|
|
switch(m_vt->m_primclass)
|
2011-02-07 01:59:05 +00:00
|
|
|
{
|
2012-01-05 02:40:24 +00:00
|
|
|
case GS_POINT_CLASS:
|
|
|
|
|
|
|
|
m_topology = D3DPT_POINTLIST;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_LINE_CLASS:
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
m_topology = D3DPT_LINELIST;
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
if(PRIM->IIP == 0)
|
2011-02-07 01:59:05 +00:00
|
|
|
{
|
2012-01-05 02:40:24 +00:00
|
|
|
for(size_t i = 0, j = m_index.tail; i < j; i += 2)
|
|
|
|
{
|
|
|
|
uint32 tmp = m_index.buff[i + 0];
|
|
|
|
m_index.buff[i + 0] = m_index.buff[i + 1];
|
|
|
|
m_index.buff[i + 1] = tmp;
|
|
|
|
}
|
2011-02-07 01:59:05 +00:00
|
|
|
}
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_TRIANGLE_CLASS:
|
|
|
|
|
|
|
|
m_topology = D3DPT_TRIANGLELIST;
|
2009-07-16 21:36:07 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
if(PRIM->IIP == 0)
|
2011-02-07 01:59:05 +00:00
|
|
|
{
|
2012-01-05 02:40:24 +00:00
|
|
|
for(size_t i = 0, j = m_index.tail; i < j; i += 3)
|
|
|
|
{
|
|
|
|
uint32 tmp = m_index.buff[i + 0];
|
|
|
|
m_index.buff[i + 0] = m_index.buff[i + 2];
|
|
|
|
m_index.buff[i + 2] = tmp;
|
|
|
|
}
|
2011-02-07 01:59:05 +00:00
|
|
|
}
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GS_SPRITE_CLASS:
|
|
|
|
|
|
|
|
m_topology = D3DPT_TRIANGLELIST;
|
|
|
|
|
|
|
|
// each sprite converted to quad needs twice the space
|
|
|
|
|
|
|
|
while(m_vertex.tail * 2 > m_vertex.maxcount)
|
2011-02-07 01:59:05 +00:00
|
|
|
{
|
2012-01-05 02:40:24 +00:00
|
|
|
GrowVertexBuffer();
|
2011-02-07 01:59:05 +00:00
|
|
|
}
|
2009-06-27 03:32:33 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
// assume vertices are tightly packed and sequentially indexed (it should be the case)
|
|
|
|
|
2012-01-06 00:17:52 +00:00
|
|
|
if(m_vertex.next >= 2)
|
2011-02-07 01:59:05 +00:00
|
|
|
{
|
2012-01-06 00:17:52 +00:00
|
|
|
size_t count = m_vertex.next;
|
2012-01-05 02:40:24 +00:00
|
|
|
|
|
|
|
int i = (int)count * 2 - 4;
|
|
|
|
GSVertexHW9* s = (GSVertexHW9*)&m_vertex.buff[sizeof(GSVertexHW9) * count] - 2;
|
|
|
|
GSVertexHW9* q = (GSVertexHW9*)&m_vertex.buff[sizeof(GSVertexHW9) * (count * 2)] - 4;
|
|
|
|
uint32* RESTRICT index = &m_index.buff[count * 3] - 6;
|
|
|
|
|
|
|
|
for(; i >= 0; i -= 4, s -= 2, q -= 4, index -= 6)
|
|
|
|
{
|
|
|
|
GSVertexHW9 v0 = s[0];
|
|
|
|
GSVertexHW9 v1 = s[1];
|
2010-08-17 04:38:49 +00:00
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
v0.p = v0.p.xyzw(v1.p); // z, q
|
|
|
|
v0.t = v0.t.xyzw(v1.t); // c, f
|
|
|
|
|
|
|
|
q[0] = v0;
|
|
|
|
q[3] = v1;
|
|
|
|
|
|
|
|
// swap x, s
|
|
|
|
|
|
|
|
GSVector4 p = v0.p.insert<0, 0>(v1.p);
|
|
|
|
GSVector4 t = v0.t.insert<0, 0>(v1.t);
|
|
|
|
v1.p = v1.p.insert<0, 0>(v0.p);
|
|
|
|
v1.t = v1.t.insert<0, 0>(v0.t);
|
|
|
|
v0.p = p;
|
|
|
|
v0.t = t;
|
|
|
|
|
|
|
|
q[1] = v0;
|
|
|
|
q[2] = v1;
|
|
|
|
|
|
|
|
index[0] = i + 0;
|
|
|
|
index[1] = i + 1;
|
|
|
|
index[2] = i + 2;
|
|
|
|
index[3] = i + 1;
|
|
|
|
index[4] = i + 2;
|
|
|
|
index[5] = i + 3;
|
|
|
|
}
|
|
|
|
|
2012-01-06 00:17:52 +00:00
|
|
|
m_vertex.head = m_vertex.tail = m_vertex.next = count * 2;
|
2012-01-05 02:40:24 +00:00
|
|
|
m_index.tail = count * 3;
|
|
|
|
}
|
2009-06-27 03:32:33 +00:00
|
|
|
|
|
|
|
break;
|
2012-01-05 02:40:24 +00:00
|
|
|
|
2009-06-27 03:32:33 +00:00
|
|
|
default:
|
|
|
|
__assume(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
(*(GSDevice9*)m_dev)->SetRenderState(D3DRS_SHADEMODE, PRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT); // TODO
|
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
__super::DrawPrims(rt, ds, tex);
|
2009-06-27 03:32:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GSRendererDX9::UpdateFBA(GSTexture* rt)
|
|
|
|
{
|
|
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
|
|
|
|
dev->BeginScene();
|
|
|
|
|
|
|
|
// om
|
|
|
|
|
|
|
|
dev->OMSetDepthStencilState(&m_fba.dss);
|
|
|
|
dev->OMSetBlendState(&m_fba.bs, 0);
|
|
|
|
|
|
|
|
// ia
|
|
|
|
|
2009-08-02 23:07:30 +00:00
|
|
|
GSVector4 s = GSVector4(rt->GetScale().x / rt->GetWidth(), rt->GetScale().y / rt->GetHeight());
|
2009-06-27 03:32:33 +00:00
|
|
|
GSVector4 o = GSVector4(-1.0f, 1.0f);
|
|
|
|
|
2012-01-05 02:40:24 +00:00
|
|
|
GSVector4 src = ((m_vt->m_min.p.xyxy(m_vt->m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
|
2009-06-27 03:32:33 +00:00
|
|
|
GSVector4 dst = src * 2.0f + o.xxxx();
|
|
|
|
|
|
|
|
GSVertexPT1 vertices[] =
|
|
|
|
{
|
|
|
|
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
|
|
|
|
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
|
|
|
|
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
|
|
|
|
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
|
|
|
|
};
|
|
|
|
|
|
|
|
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
|
|
|
|
dev->IASetInputLayout(dev->m_convert.il);
|
|
|
|
dev->IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
|
|
|
|
|
|
|
|
// vs
|
|
|
|
|
|
|
|
dev->VSSetShader(dev->m_convert.vs, NULL, 0);
|
|
|
|
|
|
|
|
// ps
|
|
|
|
|
|
|
|
dev->PSSetShader(dev->m_convert.ps[4], NULL, 0);
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
dev->DrawPrimitive();
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
dev->EndScene();
|
|
|
|
}
|