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 .
*
* 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 , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
* http : //www.gnu.org/copyleft/gpl.html
*
*/
# pragma once
# include "GSRendererHW.h"
template < class Vertex >
class GSRendererDX : public GSRendererHW < Vertex >
{
2009-07-12 13:46:05 +00:00
GSVector2 m_pixelcenter ;
2009-06-27 03:32:33 +00:00
bool m_logz ;
bool m_fba ;
2009-08-19 01:08:40 +00:00
int m_pixoff_x ;
int m_pixoff_y ;
2009-06-27 03:32:33 +00:00
protected :
int m_topology ;
virtual void UpdateFBA ( GSTexture * rt ) { }
public :
2009-09-18 19:54:56 +00:00
GSRendererDX ( GSTextureCache * tc , const GSVector2 & pixelcenter = GSVector2 ( 0 , 0 ) )
: GSRendererHW < Vertex > ( tc )
2009-07-12 13:46:05 +00:00
, m_pixelcenter ( pixelcenter )
2009-06-27 03:32:33 +00:00
, m_topology ( - 1 )
{
m_logz = ! ! theApp . GetConfig ( " logz " , 0 ) ;
m_fba = ! ! theApp . GetConfig ( " fba " , 1 ) ;
2009-08-19 01:08:40 +00:00
m_pixoff_x = theApp . GetConfig ( " pixoff_x " , 0 ) ;
m_pixoff_y = theApp . GetConfig ( " pixoff_y " , 0 ) ;
2009-06-27 03:32:33 +00:00
}
virtual ~ GSRendererDX ( )
{
}
2009-09-17 07:40:38 +00:00
bool 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 ;
return true ;
}
2009-09-18 00:16:52 +00:00
__forceinline void Draw ( GSTexture * rt , GSTexture * ds , GSTextureCache : : Source * tex )
2009-06-27 03:32:33 +00:00
{
GSDrawingEnvironment & env = m_env ;
GSDrawingContext * context = m_context ;
2009-11-07 17:50:48 +00:00
assert ( m_dev ! = NULL ) ;
2009-09-18 00:16:52 +00:00
GSDeviceDX & dev = ( GSDeviceDX & ) * m_dev ;
2009-06-27 03:32:33 +00:00
//
2009-11-07 17:50:48 +00:00
if ( m_context - > TEST . DATE )
{
const GSVector2i & size = rt - > GetSize ( ) ;
GSVector4 s = GSVector4 ( rt - > GetScale ( ) . x / size . x , rt - > GetScale ( ) . y / size . y ) ;
GSVector4 o = GSVector4 ( - 1.0f , 1.0f ) ;
GSVector4 src = ( ( m_vt . m_min . p . xyxy ( m_vt . m_max . p ) + o . xxyy ( ) ) * s . xyxy ( ) ) . sat ( o . zzyy ( ) ) ;
GSVector4 dst = src * 2.0f + o . xxxx ( ) ;
2009-06-27 03:32:33 +00:00
2009-11-07 17:50:48 +00:00
GSVertexPT1 vertices [ ] =
{
{ GSVector4 ( dst . x , - dst . y , 0.5f , 1.0f ) , GSVector2 ( src . x , src . y ) } ,
{ GSVector4 ( dst . z , - dst . y , 0.5f , 1.0f ) , GSVector2 ( src . z , src . y ) } ,
{ GSVector4 ( dst . x , - dst . w , 0.5f , 1.0f ) , GSVector2 ( src . x , src . w ) } ,
{ GSVector4 ( dst . z , - dst . w , 0.5f , 1.0f ) , GSVector2 ( src . z , src . w ) } ,
} ;
dev . SetupDATE ( rt , ds , vertices , m_context - > TEST . DATM ) ;
}
2009-06-27 03:32:33 +00:00
//
2009-09-18 00:16:52 +00:00
dev . BeginScene ( ) ;
2009-06-27 03:32:33 +00:00
// om
2009-09-18 00:16:52 +00:00
GSDeviceDX : : OMDepthStencilSelector om_dssel ;
2009-06-27 03:32:33 +00:00
2009-07-16 21:36:07 +00:00
if ( context - > TEST . ZTE )
{
om_dssel . ztst = context - > TEST . ZTST ;
om_dssel . zwe = ! context - > ZBUF . ZMSK ;
}
else
{
om_dssel . ztst = ZTST_ALWAYS ;
}
2009-06-27 03:32:33 +00:00
2009-08-07 21:11:27 +00:00
if ( context - > FRAME . PSM ! = PSM_PSMCT24 )
{
om_dssel . date = context - > TEST . DATE ;
}
if ( m_fba )
{
om_dssel . fba = context - > FBA . FBA ;
}
2009-06-27 03:32:33 +00:00
2009-09-18 00:16:52 +00:00
GSDeviceDX : : OMBlendSelector om_bsel ;
2009-07-05 12:58:59 +00:00
2009-08-07 21:11:27 +00:00
if ( ! IsOpaque ( ) )
2009-07-05 12:58:59 +00:00
{
2009-08-07 21:11:27 +00:00
om_bsel . abe = PRIM - > ABE | | PRIM - > AA1 & & m_vt . m_primclass = = GS_LINE_CLASS ;
2009-07-05 12:58:59 +00:00
om_bsel . a = context - > ALPHA . A ;
om_bsel . b = context - > ALPHA . B ;
om_bsel . c = context - > ALPHA . C ;
om_bsel . d = context - > ALPHA . D ;
if ( env . PABE . PABE )
{
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 ;
}
else
{
2009-10-24 18:39:36 +00:00
//Breath of Fire Dragon Quarter triggers this in battles. Graphics are fine though.
2009-07-05 12:58:59 +00:00
ASSERT ( 0 ) ;
}
}
}
2009-07-16 21:36:07 +00:00
om_bsel . wrgba = ~ GSVector4i : : load ( ( int ) context - > FRAME . FBMSK ) . eq8 ( GSVector4i : : xffffffff ( ) ) . mask ( ) ;
2009-06-27 03:32:33 +00:00
// vs
2009-09-18 00:16:52 +00:00
GSDeviceDX : : VSSelector vs_sel ;
2009-06-27 03:32:33 +00:00
vs_sel . tme = PRIM - > TME ;
vs_sel . fst = PRIM - > FST ;
vs_sel . logz = m_logz ? 1 : 0 ;
2009-07-16 21:36:07 +00:00
if ( om_dssel . ztst > = ZTST_ALWAYS & & om_dssel . zwe )
2009-06-27 03:32:33 +00:00
{
if ( context - > ZBUF . PSM = = PSM_PSMZ24 )
{
if ( m_vt . m_max . p . z > 0xffffff )
{
2009-10-24 18:39:36 +00:00
//ASSERT(m_vt.m_min.p.z > 0xffffff);
// Fixme :Following conditional fixes some dialog frame in Wild Arms 3, but may not be what was intended.
if ( m_vt . m_min . p . z > 0xffffff )
{
vs_sel . bppz = 1 ;
om_dssel . ztst = ZTST_ALWAYS ;
}
//else printf ("GSdx: Z issue, please report\n");
2009-06-27 03:32:33 +00:00
}
}
else if ( context - > ZBUF . PSM = = PSM_PSMZ16 | | context - > ZBUF . PSM = = PSM_PSMZ16S )
{
if ( m_vt . m_max . p . z > 0xffff )
{
2009-10-24 18:39:36 +00:00
//ASSERT(m_vt.m_min.p.z > 0xffff); // sfex capcom logo
// Fixme : Same as above, I guess.
if ( m_vt . m_min . p . z > 0xffff )
{
vs_sel . bppz = 2 ;
om_dssel . ztst = ZTST_ALWAYS ;
}
//else printf ("GSdx: Z issue, please report\n");
2009-06-27 03:32:33 +00:00
}
}
}
2009-09-18 00:16:52 +00:00
GSDeviceDX : : VSConstantBuffer vs_cb ;
2009-06-27 03:32:33 +00:00
2009-08-02 23:07:30 +00:00
float sx = 2.0f * rt - > GetScale ( ) . x / ( rt - > GetWidth ( ) < < 4 ) ;
float sy = 2.0f * rt - > GetScale ( ) . y / ( rt - > GetHeight ( ) < < 4 ) ;
2009-08-19 01:08:40 +00:00
float ox = ( float ) ( int ) context - > XYOFFSET . OFX + m_pixoff_x ;
float oy = ( float ) ( int ) context - > XYOFFSET . OFY + m_pixoff_y ;
2009-08-02 23:07:30 +00:00
float ox2 = 2.0f * m_pixelcenter . x / rt - > GetWidth ( ) ;
float oy2 = 2.0f * m_pixelcenter . y / rt - > GetHeight ( ) ;
2009-11-01 11:42:12 +00:00
float adjust_offset = 0.0f ;
float adjust_size = 0.0f ;
2009-06-27 03:32:33 +00:00
// gs
2009-09-18 00:16:52 +00:00
GSDeviceDX : : GSSelector gs_sel ;
2009-06-27 03:32:33 +00:00
gs_sel . iip = PRIM - > IIP ;
2009-07-22 03:55:28 +00:00
gs_sel . prim = m_vt . m_primclass ;
2009-06-27 03:32:33 +00:00
// ps
2009-09-18 00:16:52 +00:00
GSDeviceDX : : PSSelector ps_sel ;
GSDeviceDX : : PSSamplerSelector ps_ssel ;
GSDeviceDX : : PSConstantBuffer ps_cb ;
2009-06-27 03:32:33 +00:00
2009-07-12 13:46:05 +00:00
ps_sel . clr1 = om_bsel . IsCLR1 ( ) ;
2009-06-27 03:32:33 +00:00
ps_sel . fba = context - > FBA . FBA ;
ps_sel . aout = context - > FRAME . PSM = = PSM_PSMCT16 | | context - > FRAME . PSM = = PSM_PSMCT16S | | ( context - > FRAME . FBMSK & 0xff000000 ) = = 0x7f000000 ? 1 : 0 ;
2009-07-12 13:46:05 +00:00
if ( PRIM - > FGE )
2009-07-05 12:58:59 +00:00
{
2009-07-12 13:46:05 +00:00
ps_sel . fog = 1 ;
ps_cb . FogColor_AREF = GSVector4 ( env . FOGCOL . u32 [ 0 ] ) / 255 ;
2009-07-05 12:58:59 +00:00
}
2009-06-27 03:32:33 +00:00
2009-07-12 13:46:05 +00:00
if ( context - > TEST . ATE )
2009-06-27 03:32:33 +00:00
{
2009-07-12 13:46:05 +00:00
ps_sel . atst = context - > TEST . ATST ;
2009-07-05 12:58:59 +00:00
switch ( ps_sel . atst )
{
case ATST_LESS :
ps_cb . FogColor_AREF . a = ( float ) ( ( int ) context - > TEST . AREF - 1 ) ;
break ;
case ATST_GREATER :
ps_cb . FogColor_AREF . a = ( float ) ( ( int ) context - > TEST . AREF + 1 ) ;
break ;
default :
ps_cb . FogColor_AREF . a = ( float ) ( int ) context - > TEST . AREF ;
break ;
}
2009-06-27 03:32:33 +00:00
}
2009-07-26 15:30:25 +00:00
else
{
ps_sel . atst = ATST_ALWAYS ;
}
2009-06-27 03:32:33 +00:00
if ( tex )
{
2009-07-12 13:46:05 +00:00
ps_sel . wms = context - > CLAMP . WMS ;
ps_sel . wmt = context - > CLAMP . WMT ;
2009-07-06 16:35:06 +00:00
ps_sel . fmt = tex - > m_fmt ;
2009-07-12 13:46:05 +00:00
ps_sel . aem = env . TEXA . AEM ;
ps_sel . tfx = context - > TEX0 . TFX ;
ps_sel . tcc = context - > TEX0 . TCC ;
ps_sel . ltf = m_filter = = 2 ? IsLinear ( ) : m_filter ;
2009-07-01 21:14:12 +00:00
ps_sel . rt = tex - > m_target ;
2009-06-27 03:32:33 +00:00
2009-08-02 23:07:30 +00:00
int w = tex - > m_texture - > GetWidth ( ) ;
int h = tex - > m_texture - > GetHeight ( ) ;
2009-06-27 03:32:33 +00:00
2009-07-12 13:46:05 +00:00
int tw = ( int ) ( 1 < < context - > TEX0 . TW ) ;
int th = ( int ) ( 1 < < context - > TEX0 . TH ) ;
2009-07-16 21:36:07 +00:00
GSVector4 WH ( tw , th , w , h ) ;
2009-11-01 11:42:12 +00:00
//if (w > 0 && w < 129) { adjust_size = 0.0001f; adjust_offset = -0.000000f; } //0.07f for ar tonelico but max 0.007f for shadow hearts)
//else if (w > 128 && w < 257) { adjust_size = 0.0010f; adjust_offset = -0.000000f; } //0.007f; WA games want stuffx at 0.52
//else if (w > 256 && w < 513) { adjust_size = 0.4000f; adjust_offset = -0.000000f; } //offset -0.0005f;
//else if (w > 512 && w < 1025){ adjust_size = 0.4000f; adjust_offset = -0.000000f; } //TotA battle blur wants -0.000015f, but that's too much for WA games.
//adjust_offset = -0.001f; } //0.07f for ar tonelico but max 0.007f for shadow hearts)
//adjust_offset = 0.0002f; } //0.007f;
//adjust_offset = -0.0005f; } //offset -0.0005f;
//adjust_offset = -0.000006f; } //TotA battle blur wants -0.000015f, but that's too much for WA games.
2009-07-12 13:46:05 +00:00
2009-07-16 21:36:07 +00:00
if ( PRIM - > FST )
2009-06-27 03:32:33 +00:00
{
2009-11-01 11:42:12 +00:00
vs_cb . TextureScale = GSVector4 ( ( 1.0f / 16 ) ) / ( WH . xyxy ( ) + adjust_size ) ;
2009-06-27 03:32:33 +00:00
2009-07-16 21:36:07 +00:00
ps_sel . fst = 1 ;
2009-06-27 03:32:33 +00:00
}
2009-07-16 21:36:07 +00:00
ps_cb . WH = WH ;
ps_cb . HalfTexel = GSVector4 ( - 0.5f , 0.5f ) . xxyy ( ) / WH . zwzw ( ) ;
ps_cb . MskFix = GSVector4i ( context - > CLAMP . MINU , context - > CLAMP . MINV , context - > CLAMP . MAXU , context - > CLAMP . MAXV ) ;
GSVector4 clamp ( ps_cb . MskFix ) ;
GSVector4 ta ( env . TEXA & GSVector4i : : x000000ff ( ) ) ;
ps_cb . MinMax = clamp / WH . xyxy ( ) ;
ps_cb . MinF_TA = ( clamp + 0.5f ) . xyxy ( ta ) / WH . xyxy ( GSVector4 ( 255 , 255 ) ) ;
ps_ssel . tau = ( context - > CLAMP . WMS + 3 ) > > 1 ;
ps_ssel . tav = ( context - > CLAMP . WMT + 3 ) > > 1 ;
ps_ssel . ltf = ps_sel . ltf ;
2009-06-27 03:32:33 +00:00
}
else
{
ps_sel . tfx = 4 ;
}
2009-11-01 11:42:12 +00:00
vs_cb . VertexScale = GSVector4 ( sx , - sy , 1.0f / UINT_MAX , 0.0f ) ;
vs_cb . VertexOffset = GSVector4 ( ox * sx + ox2 + 1 + adjust_offset , - ( oy * sy + oy2 + 1 + adjust_offset ) , 0.0f , - 1.0f ) ;
2009-06-27 03:32:33 +00:00
// rs
2009-08-02 23:07:30 +00:00
GSVector4i scissor = GSVector4i ( GSVector4 ( rt - > GetScale ( ) ) . xyxy ( ) * context - > scissor . in ) . rintersect ( GSVector4i ( rt - > GetSize ( ) ) . zwxy ( ) ) ;
2009-06-27 03:32:33 +00:00
2009-09-18 00:16:52 +00:00
dev . OMSetRenderTargets ( rt , ds , & scissor ) ;
dev . PSSetShaderResources ( tex ? tex - > m_texture : NULL , tex ? tex - > m_palette : NULL ) ;
2009-06-27 03:32:33 +00:00
uint8 afix = context - > ALPHA . FIX ;
2009-09-18 00:16:52 +00:00
dev . SetupOM ( om_dssel , om_bsel , afix ) ;
dev . SetupIA ( m_vertices , m_count , m_topology ) ;
dev . SetupVS ( vs_sel , & vs_cb ) ;
dev . SetupGS ( gs_sel ) ;
dev . SetupPS ( ps_sel , & ps_cb , ps_ssel ) ;
2009-06-27 03:32:33 +00:00
// draw
if ( context - > TEST . DoFirstPass ( ) )
{
2009-09-18 00:16:52 +00:00
dev . DrawPrimitive ( ) ;
2009-06-27 03:32:33 +00:00
}
if ( context - > TEST . DoSecondPass ( ) )
{
ASSERT ( ! env . PABE . PABE ) ;
static const uint32 iatst [ ] = { 1 , 0 , 5 , 6 , 7 , 2 , 3 , 4 } ;
ps_sel . atst = iatst [ ps_sel . atst ] ;
2009-07-01 22:29:24 +00:00
switch ( ps_sel . atst )
{
case ATST_LESS :
ps_cb . FogColor_AREF . a = ( float ) ( ( int ) context - > TEST . AREF - 1 ) ;
break ;
case ATST_GREATER :
ps_cb . FogColor_AREF . a = ( float ) ( ( int ) context - > TEST . AREF + 1 ) ;
break ;
default :
ps_cb . FogColor_AREF . a = ( float ) ( int ) context - > TEST . AREF ;
break ;
}
2009-09-18 00:16:52 +00:00
dev . SetupPS ( ps_sel , & ps_cb , ps_ssel ) ;
2009-06-27 03:32:33 +00:00
bool z = om_dssel . zwe ;
bool r = om_bsel . wr ;
bool g = om_bsel . wg ;
bool b = om_bsel . wb ;
bool a = om_bsel . wa ;
switch ( context - > TEST . AFAIL )
{
case 0 : z = r = g = b = a = false ; break ; // none
case 1 : z = false ; break ; // rgba
case 2 : r = g = b = a = false ; break ; // z
case 3 : z = a = false ; break ; // rgb
default : __assume ( 0 ) ;
}
if ( z | | r | | g | | b | | a )
{
om_dssel . zwe = z ;
om_bsel . wr = r ;
om_bsel . wg = g ;
om_bsel . wb = b ;
om_bsel . wa = a ;
2009-09-18 00:16:52 +00:00
dev . SetupOM ( om_dssel , om_bsel , afix ) ;
2009-06-27 03:32:33 +00:00
2009-09-18 00:16:52 +00:00
dev . DrawPrimitive ( ) ;
2009-06-27 03:32:33 +00:00
}
}
2009-09-18 00:16:52 +00:00
dev . EndScene ( ) ;
2009-06-27 03:32:33 +00:00
if ( om_dssel . fba ) UpdateFBA ( rt ) ;
}
} ;