mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-10 23:02:59 +02:00
Ports the "Unscale Point and Line" hack to the Direct3D11 Hardware renderer. And enables the "Unscale Point and Line" hack for Custom Resolutions with Direct3D11 and OpenGL.
227 lines
4.8 KiB
C++
227 lines
4.8 KiB
C++
/*
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "GSRendererDX9.h"
|
|
#include "GSCrc.h"
|
|
#include "resource.h"
|
|
|
|
GSRendererDX9::GSRendererDX9()
|
|
: GSRendererDX(new GSTextureCache9(this))
|
|
{
|
|
}
|
|
|
|
bool GSRendererDX9::CreateDevice(GSDevice* dev)
|
|
{
|
|
if(!__super::CreateDevice(dev))
|
|
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;
|
|
}
|
|
|
|
void GSRendererDX9::SetupIA(const float& sx, const float& sy)
|
|
{
|
|
D3DPRIMITIVETYPE topology;
|
|
|
|
switch(m_vt.m_primclass)
|
|
{
|
|
case GS_POINT_CLASS:
|
|
|
|
topology = D3DPT_POINTLIST;
|
|
|
|
break;
|
|
|
|
case GS_LINE_CLASS:
|
|
|
|
topology = D3DPT_LINELIST;
|
|
|
|
if(PRIM->IIP == 0)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case GS_TRIANGLE_CLASS:
|
|
|
|
topology = D3DPT_TRIANGLELIST;
|
|
|
|
if(PRIM->IIP == 0)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case GS_SPRITE_CLASS:
|
|
|
|
topology = D3DPT_TRIANGLELIST;
|
|
|
|
// each sprite converted to quad needs twice the space
|
|
|
|
Lines2Sprites();
|
|
|
|
break;
|
|
|
|
default:
|
|
__assume(0);
|
|
}
|
|
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
(*dev)->SetRenderState(D3DRS_SHADEMODE, PRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT); // TODO
|
|
|
|
void* ptr = NULL;
|
|
|
|
if(dev->IAMapVertexBuffer(&ptr, sizeof(GSVertexHW9), m_vertex.next))
|
|
{
|
|
GSVertex* RESTRICT s = (GSVertex*)m_vertex.buff;
|
|
GSVertexHW9* RESTRICT d = (GSVertexHW9*)ptr;
|
|
|
|
for(uint32 i = 0; i < m_vertex.next; i++, s++, d++)
|
|
{
|
|
GSVector4 p = GSVector4(GSVector4i::load(s->XYZ.u32[0]).upl16());
|
|
|
|
if(PRIM->TME && !PRIM->FST)
|
|
{
|
|
p = p.xyxy(GSVector4((float)s->XYZ.Z, s->RGBAQ.Q));
|
|
}
|
|
else
|
|
{
|
|
p = p.xyxy(GSVector4::load((float)s->XYZ.Z));
|
|
}
|
|
|
|
GSVector4 t = GSVector4::zero();
|
|
|
|
if(PRIM->TME)
|
|
{
|
|
if(PRIM->FST)
|
|
{
|
|
if(UserHacks_WildHack && !isPackedUV_HackFlag)
|
|
{
|
|
t = GSVector4(GSVector4i::load(s->UV & 0x3FEF3FEF).upl16());
|
|
//printf("GSDX: %08X | D3D9(%d) %s\n", s->UV & 0x3FEF3FEF, m_vertex.next, i == 0 ? "*" : "");
|
|
}
|
|
else
|
|
{
|
|
t = GSVector4(GSVector4i::load(s->UV).upl16());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t = GSVector4::loadl(&s->ST);
|
|
}
|
|
}
|
|
|
|
t = t.xyxy(GSVector4::cast(GSVector4i(s->RGBAQ.u32[0], s->FOG)));
|
|
|
|
d->p = p;
|
|
d->t = t;
|
|
}
|
|
|
|
dev->IAUnmapVertexBuffer();
|
|
}
|
|
|
|
dev->IASetIndexBuffer(m_index.buff, m_index.tail);
|
|
|
|
dev->IASetPrimitiveTopology(topology);
|
|
}
|
|
|
|
void GSRendererDX9::UpdateFBA(GSTexture* rt)
|
|
{
|
|
if (!rt)
|
|
return;
|
|
|
|
GSDevice9* dev = (GSDevice9*)m_dev;
|
|
|
|
dev->BeginScene();
|
|
|
|
// om
|
|
|
|
dev->OMSetDepthStencilState(&m_fba.dss);
|
|
dev->OMSetBlendState(&m_fba.bs, 0);
|
|
|
|
// ia
|
|
|
|
GSVector4 s = GSVector4(rt->GetScale().x / rt->GetWidth(), rt->GetScale().y / rt->GetHeight());
|
|
GSVector4 off = GSVector4(-1.0f, 1.0f);
|
|
|
|
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + off.xxyy()) * s.xyxy()).sat(off.zzyy());
|
|
GSVector4 dst = src * 2.0f + off.xxxx();
|
|
|
|
GSVertexPT1 vertices[] =
|
|
{
|
|
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(0)},
|
|
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(0)},
|
|
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(0)},
|
|
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(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();
|
|
}
|