GSRendererHW.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:46k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include "GSRendererHW.h"
  23. #define INTERNALRESX 1024
  24. #define INTERNALRESY 1024
  25. inline BYTE SCALE_ALPHA(BYTE a) 
  26. {
  27. return (((a)&0x80)?0xff:((a)<<1));
  28. }
  29. static const float one_over_log_2pow32 = 1.0f / (log(2.0f)*32);
  30. //
  31. GSRendererHW::GSRendererHW(HWND hWnd, HRESULT& hr)
  32. : GSRenderer<GSVertexHW>(INTERNALRESX, INTERNALRESY, hWnd, hr)
  33. {
  34. Reset();
  35. }
  36. GSRendererHW::~GSRendererHW()
  37. {
  38. }
  39. HRESULT GSRendererHW::ResetDevice(bool fForceWindowed)
  40. {
  41. m_pRTs.RemoveAll();
  42. m_pDSs.RemoveAll();
  43. m_tc.RemoveAll();
  44. return __super::ResetDevice(fForceWindowed);
  45. }
  46. void GSRendererHW::Reset()
  47. {
  48. m_primtype = D3DPT_FORCE_DWORD;
  49. m_tc.RemoveAll();
  50. m_pRTs.RemoveAll();
  51. m_pDSs.RemoveAll();
  52. POSITION pos = m_pRenderWnds.GetStartPosition();
  53. while(pos)
  54. {
  55. DWORD FBP;
  56. CGSWnd* pWnd = NULL;
  57. m_pRenderWnds.GetNextAssoc(pos, FBP, pWnd);
  58. pWnd->DestroyWindow();
  59. delete pWnd;
  60. }
  61. m_pRenderWnds.RemoveAll();
  62. __super::Reset();
  63. }
  64. void GSRendererHW::VertexKick(bool fSkip)
  65. {
  66. GSVertexHW& v = m_vl.AddTail();
  67. v.x = (float)((int)m_v.XYZ.X - (int)m_ctxt->XYOFFSET.OFX) * (1.0f/16);
  68. v.y = (float)((int)m_v.XYZ.Y - (int)m_ctxt->XYOFFSET.OFY) * (1.0f/16);
  69. //if(m_v.XYZ.Z && m_v.XYZ.Z < 0x100) m_v.XYZ.Z = 0x100;
  70. //v.z = 1.0f * (m_v.XYZ.Z>>8)/(UINT_MAX>>8);
  71. v.z = log(1.0f + m_v.XYZ.Z) * one_over_log_2pow32;
  72. //v.z = (float)m_v.XYZ.Z / UINT_MAX;
  73. //v.rhw = v.z ? 1.0f/v.z : 1.0f;
  74. v.rhw = m_v.RGBAQ.Q > 0 ? m_v.RGBAQ.Q : 1.0f; // TODO
  75. //v.rhw = m_v.RGBAQ.Q;
  76. v.color = m_v.RGBAQ.ai32[0];
  77. if(m_pPRIM->TME)
  78. {
  79. if(m_pPRIM->FST)
  80. {
  81. v.tu = (float)(int)m_v.UV.U / (16 << m_ctxt->TEX0.TW);
  82. v.tv = (float)(int)m_v.UV.V / (16 << m_ctxt->TEX0.TH);
  83. v.rhw = 1.0f;
  84. }
  85. else
  86. {
  87. float w = m_v.RGBAQ.Q ? 1.0f / m_v.RGBAQ.Q : 1.0f;
  88. v.tu = m_v.ST.S * w;
  89. v.tv = m_v.ST.T * w;
  90. }
  91. }
  92. else
  93. {
  94. v.a = SCALE_ALPHA(v.a);
  95. }
  96. v.fog = (m_pPRIM->FGE ? m_v.FOG.F : 0xff) << 24;
  97. __super::VertexKick(fSkip);
  98. }
  99. int GSRendererHW::DrawingKick(bool fSkip)
  100. {
  101. GSVertexHW* pVertices = &m_pVertices[m_nVertices];
  102. int nVertices = 0;
  103. CRect sc(m_ctxt->SCISSOR.SCAX0, m_ctxt->SCISSOR.SCAY0, m_ctxt->SCISSOR.SCAX1+1, m_ctxt->SCISSOR.SCAY1+1);
  104. switch(m_PRIM)
  105. {
  106. case 3: // triangle list
  107. m_primtype = D3DPT_TRIANGLELIST;
  108. m_vl.RemoveAt(0, pVertices[nVertices++]);
  109. m_vl.RemoveAt(0, pVertices[nVertices++]);
  110. m_vl.RemoveAt(0, pVertices[nVertices++]);
  111. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left && pVertices[nVertices-3].x < sc.left
  112. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top && pVertices[nVertices-3].y < sc.top
  113. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right && pVertices[nVertices-3].x >= sc.right
  114. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom && pVertices[nVertices-3].y >= sc.bottom)
  115. return 0;
  116. LOGV((pVertices[0], _T("TriList")));
  117. LOGV((pVertices[1], _T("TriList")));
  118. LOGV((pVertices[2], _T("TriList")));
  119. break;
  120. case 4: // triangle strip
  121. m_primtype = D3DPT_TRIANGLELIST;
  122. m_vl.RemoveAt(0, pVertices[nVertices++]);
  123. m_vl.GetAt(0, pVertices[nVertices++]);
  124. m_vl.GetAt(1, pVertices[nVertices++]);
  125. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left && pVertices[nVertices-3].x < sc.left
  126. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top && pVertices[nVertices-3].y < sc.top
  127. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right && pVertices[nVertices-3].x >= sc.right
  128. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom && pVertices[nVertices-3].y >= sc.bottom)
  129. return 0;
  130. LOGV((pVertices[0], _T("TriStrip")));
  131. LOGV((pVertices[1], _T("TriStrip")));
  132. LOGV((pVertices[2], _T("TriStrip")));
  133. break;
  134. case 5: // triangle fan
  135. m_primtype = D3DPT_TRIANGLELIST;
  136. m_vl.GetAt(0, pVertices[nVertices++]);
  137. m_vl.RemoveAt(1, pVertices[nVertices++]);
  138. m_vl.GetAt(1, pVertices[nVertices++]);
  139. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left && pVertices[nVertices-3].x < sc.left
  140. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top && pVertices[nVertices-3].y < sc.top
  141. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right && pVertices[nVertices-3].x >= sc.right
  142. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom && pVertices[nVertices-3].y >= sc.bottom)
  143. return 0;
  144. LOGV((pVertices[0], _T("TriFan")));
  145. LOGV((pVertices[1], _T("TriFan")));
  146. LOGV((pVertices[2], _T("TriFan")));
  147. break;
  148. case 6: // sprite
  149. m_primtype = D3DPT_TRIANGLELIST;
  150. m_vl.RemoveAt(0, pVertices[nVertices++]);
  151. m_vl.RemoveAt(0, pVertices[nVertices++]);
  152. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left
  153. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top
  154. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right
  155. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom)
  156. return 0;
  157. nVertices += 2;
  158. /*
  159. float lod;
  160. if(m_ctxt->TEX1.LCM) lod = -log(pVertices[nVertices-1].rhw)/log(2.0f) * (1 << m_ctxt->TEX1.L) + m_ctxt->TEX1.K;
  161. else lod = m_ctxt->TEX1.K;
  162. int filter;
  163. if(lod < 0) filter = m_ctxt->TEX1.MMAG&1;
  164. else filter = m_ctxt->TEX1.MMIN&1;
  165. // if(!filter)
  166. {
  167. pVertices[nVertices-2].x -= 0.5f;
  168. pVertices[nVertices-2].y -= 0.5f;
  169. pVertices[nVertices-1].x -= 0.5f;
  170. pVertices[nVertices-1].y -= 0.5f;
  171. }
  172. */
  173. // ASSERT(pVertices[0].z == pVertices[1].z);
  174. pVertices[0].z = pVertices[1].z;
  175. pVertices[2] = pVertices[1];
  176. pVertices[3] = pVertices[1];
  177. pVertices[1].y = pVertices[0].y;
  178. pVertices[1].tv = pVertices[0].tv;
  179. pVertices[2].x = pVertices[0].x;
  180. pVertices[2].tu = pVertices[0].tu;
  181. LOGV((pVertices[0], _T("Sprite")));
  182. LOGV((pVertices[1], _T("Sprite")));
  183. LOGV((pVertices[2], _T("Sprite")));
  184. LOGV((pVertices[3], _T("Sprite")));
  185. nVertices += 2;
  186. pVertices[5] = pVertices[3];
  187. pVertices[3] = pVertices[1];
  188. pVertices[4] = pVertices[2];
  189. break;
  190. case 1: // line
  191. m_primtype = D3DPT_LINELIST;
  192. m_vl.RemoveAt(0, pVertices[nVertices++]);
  193. m_vl.RemoveAt(0, pVertices[nVertices++]);
  194. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left
  195. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top
  196. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right
  197. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom)
  198. return 0;
  199. LOGV((pVertices[0], _T("LineList")));
  200. LOGV((pVertices[1], _T("LineList")));
  201. break;
  202. case 2: // line strip
  203. m_primtype = D3DPT_LINELIST;
  204. m_vl.RemoveAt(0, pVertices[nVertices++]);
  205. m_vl.GetAt(0, pVertices[nVertices++]);
  206. if(pVertices[nVertices-1].x < sc.left && pVertices[nVertices-2].x < sc.left
  207. || pVertices[nVertices-1].y < sc.top && pVertices[nVertices-2].y < sc.top
  208. || pVertices[nVertices-1].x >= sc.right && pVertices[nVertices-2].x >= sc.right
  209. || pVertices[nVertices-1].y >= sc.bottom && pVertices[nVertices-2].y >= sc.bottom)
  210. return 0;
  211. LOGV((pVertices[0], _T("LineStrip")));
  212. LOGV((pVertices[1], _T("LineStrip")));
  213. break;
  214. case 0: // point
  215. m_primtype = D3DPT_POINTLIST;
  216. m_vl.RemoveAt(0, pVertices[nVertices++]);
  217. if(pVertices[nVertices-1].x < sc.left
  218. || pVertices[nVertices-1].y < sc.top
  219. || pVertices[nVertices-1].x >= sc.right
  220. || pVertices[nVertices-1].y >= sc.bottom)
  221. return 0;
  222. LOGV((pVertices[0], _T("PointList")));
  223. break;
  224. default:
  225. //ASSERT(0);
  226. m_vl.RemoveAll();
  227. return 0;
  228. }
  229. /*
  230. int gt = 0;
  231. for(int i = 0; i < nVertices; i++)
  232. if(pVertices[i].rhw > 0) gt++;
  233. if(gt != nVertices) 
  234. return 0;
  235. */
  236. if(fSkip || !m_rs.IsEnabled(0) && !m_rs.IsEnabled(1))
  237. return 0;
  238. if(!m_pPRIM->IIP)
  239. {
  240. pVertices[0].color = pVertices[nVertices-1].color;
  241. if(m_PRIM == 6) pVertices[3].color = pVertices[5].color;
  242. /*for(int i = nVertices-1; i > 0; i--)
  243. pVertices[i-1].color = pVertices[i].color;*/
  244. }
  245. return nVertices;
  246. }
  247. void GSRendererHW::FlushPrim()
  248. {
  249. if(m_nVertices > 0 && !(m_pPRIM->TME && HasSharedBits(m_ctxt->TEX0.TBP0, m_ctxt->TEX0.PSM, m_ctxt->FRAME.Block(), m_ctxt->FRAME.PSM)))
  250. do
  251. {
  252. int nPrims = 0;
  253. switch(m_primtype)
  254. {
  255. case D3DPT_TRIANGLELIST: ASSERT(!(m_nVertices%3)); nPrims = m_nVertices/3; break;
  256. case D3DPT_TRIANGLESTRIP: ASSERT(m_nVertices > 2); nPrims = m_nVertices-2; break;
  257. case D3DPT_TRIANGLEFAN: ASSERT(m_nVertices > 2); nPrims = m_nVertices-2; break;
  258. case D3DPT_LINELIST: ASSERT(!(m_nVertices&1)); nPrims = m_nVertices/2; break;
  259. case D3DPT_LINESTRIP: ASSERT(m_nVertices > 1); nPrims = m_nVertices-1; break;
  260. case D3DPT_POINTLIST: nPrims = m_nVertices; break;
  261. default: ASSERT(0); return;
  262. }
  263. LOG(_T("FlushPrim(pt=%d, nVertices=%d, nPrims=%d)n"), m_primtype, m_nVertices, nPrims);
  264. m_perfmon.IncCounter(GSPerfMon::c_prim, nPrims);
  265. //////////////////////
  266. HRESULT hr;
  267. scale_t scale(
  268. (float)m_bd.Width / (m_ctxt->FRAME.FBW*64), 
  269. // (float)m_bd.Width / m_rs.GetDispRect(m_rs.IsEnabled(1)?1:0).right, 
  270. (float)m_bd.Height / m_rs.GetDispRect(m_rs.IsEnabled(1)?1:0).bottom);
  271. //////////////////////
  272. CComPtr<IDirect3DTexture9> pRT;
  273. CComPtr<IDirect3DSurface9> pDS;
  274. bool fClearRT = false;
  275. bool fClearDS = false;
  276. if(!m_pRTs.Lookup(m_ctxt->FRAME.Block(), pRT))
  277. {
  278. hr = m_pD3DDev->CreateTexture(m_bd.Width, m_bd.Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRT, NULL);
  279. if(S_OK != hr) {ASSERT(0); return;}
  280. m_pRTs[m_ctxt->FRAME.Block()] = pRT;
  281. #ifdef DEBUG_RENDERTARGETS
  282. CGSWnd* pWnd = NULL;
  283. if(!m_pRenderWnds.Lookup(m_ctxt->FRAME.Block(), pWnd))
  284. {
  285. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  286. pWnd = new CGSWnd();
  287. CString str; str.Format(_T("%05x"), m_ctxt->FRAME.Block());
  288. pWnd->Create(str);
  289. m_pRenderWnds[m_ctxt->FRAME.Block()] = pWnd;
  290. pWnd->Show();
  291. }
  292. #endif
  293. fClearRT = true;
  294. }
  295. if(!m_pDSs.Lookup(m_ctxt->ZBUF.ZBP, pDS))
  296. {
  297. hr = m_pD3DDev->CreateDepthStencilSurface(m_bd.Width, m_bd.Height, m_fmtDepthStencil, D3DMULTISAMPLE_NONE, 0, FALSE, &pDS, NULL);
  298. if(S_OK != hr) {ASSERT(0); return;}
  299. m_pDSs[m_ctxt->ZBUF.ZBP] = pDS;
  300. fClearDS = true;
  301. }
  302. if(!pRT || !pDS) {ASSERT(0); return;}
  303. //////////////////////
  304. GSTextureBase t;
  305. if(m_pPRIM->TME)
  306. {
  307. if(m_ctxt->TEX0.TBP0 == 0x800)
  308. {
  309. int i = 0;
  310. }
  311. bool fFetched = 
  312. m_fEnablePalettizedTextures && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 0) ? m_tc.FetchP(this, t) : 
  313. m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 0) ? m_tc.FetchNP(this, t) :
  314. m_tc.Fetch(this, t);
  315. if(!fFetched) break;
  316. if(nPrims > 100 && t.m_pPalette) // TODO: find the optimal value for nPrims > ?
  317. {
  318. CComPtr<IDirect3DTexture9> pRT;
  319. hr = m_pD3DDev->CreateTexture(t.m_desc.Width, t.m_desc.Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRT, NULL);
  320. CComPtr<IDirect3DSurface9> pRTSurf;
  321. hr = pRT->GetSurfaceLevel(0, &pRTSurf);
  322. hr = m_pD3DDev->SetRenderTarget(0, pRTSurf);
  323. hr = m_pD3DDev->SetDepthStencilSurface(NULL);
  324. hr = m_pD3DDev->SetTexture(0, t.m_pTexture);
  325. hr = m_pD3DDev->SetTexture(1, t.m_pPalette);
  326. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
  327. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
  328. hr = m_pD3DDev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
  329. hr = m_pD3DDev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_POINT);
  330. hr = m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
  331. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  332. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  333. hr = m_pD3DDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
  334. hr = m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  335. hr = m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  336. hr = m_pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
  337. hr = m_pD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RGBA);
  338. hr = m_pD3DDev->SetPixelShader(m_pHLSLTFX[37]);
  339. struct
  340. {
  341. float x, y, z, rhw;
  342. float tu, tv;
  343. }
  344. pVertices[] =
  345. {
  346. {0, 0, 0.5f, 2.0f, 0, 0},
  347. {(float)t.m_desc.Width, 0, 0.5f, 2.0f, 1, 0},
  348. {0, (float)t.m_desc.Height, 0.5f, 2.0f, 0, 1},
  349. {(float)t.m_desc.Width, (float)t.m_desc.Height, 0.5f, 2.0f, 1, 1},
  350. };
  351. hr = m_pD3DDev->BeginScene();
  352. hr = m_pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  353. hr = m_pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
  354. hr = m_pD3DDev->EndScene();
  355. t.m_pTexture = pRT;
  356. t.m_pPalette = NULL;
  357. t.m_pTexture->GetLevelDesc(0, &t.m_desc);
  358. }
  359. }
  360. //////////////////////
  361. hr = m_pD3DDev->BeginScene();
  362. //////////////////////
  363. CComPtr<IDirect3DSurface9> pSurf;
  364. hr = pRT->GetSurfaceLevel(0, &pSurf);
  365. hr = m_pD3DDev->SetRenderTarget(0, pSurf);
  366. hr = m_pD3DDev->SetDepthStencilSurface(pDS);
  367. if(fClearRT) hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
  368. if(fClearDS) hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
  369. D3DSURFACE_DESC rd;
  370. ZeroMemory(&rd, sizeof(rd));
  371. pRT->GetLevelDesc(0, &rd);
  372. //////////////////////
  373. hr = m_pD3DDev->SetRenderState(D3DRS_SHADEMODE, m_pPRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT);
  374. //////////////////////
  375. float tsx = 1.0f, tsy = 1.0f;
  376. if(m_pPRIM->TME)
  377. {
  378. tsx = 1.0f * (1 << m_ctxt->TEX0.TW) / t.m_desc.Width * t.m_scale.x;
  379. tsy = 1.0f * (1 << m_ctxt->TEX0.TH) / t.m_desc.Height * t.m_scale.y;
  380. }
  381. ASSERT(abs(tsx - 1.0f) < 0.001 && abs(tsy - 1.0f) < 0.001);
  382. SetupTexture(t, tsx, tsy);
  383. //////////////////////
  384. SetupAlphaBlend();
  385. //////////////////////
  386. SetupColorMask();
  387. //////////////////////
  388. SetupZBuffer();
  389. //////////////////////
  390. SetupAlphaTest();
  391. //////////////////////
  392. SetupScissor(scale);
  393. scale.Set(pRT);
  394. //////////////////////
  395. // ASSERT(!m_de.PABE.PABE); // bios
  396. // ASSERT(!m_ctxt->FBA.FBA); // bios
  397. // ASSERT(!m_ctxt->TEST.DATE); // sfex3 (after the capcom logo), vf4 (first menu fading in)
  398. //////////////////////
  399. {
  400. // hr = m_pD3DDev->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
  401. // hr = m_pD3DDev->SetTexture(1, pRT);
  402. GSVertexHW* pVertices = m_pVertices;
  403. for(int i = m_nVertices; i-- > 0; pVertices++)
  404. {
  405. pVertices->x *= scale.x;
  406. pVertices->y *= scale.y;
  407. // pVertices->tu2 = pVertices->x / rd.Width;
  408. // pVertices->tv2 = pVertices->y / rd.Height;
  409. if(m_pPRIM->TME)
  410. {
  411. // FIXME
  412. float base, fract;
  413. fract = modf(pVertices->tu, &base);
  414. fract *= tsx;
  415. //ASSERT(-1 <= fract && fract <= 1.01);
  416. pVertices->tu = base + fract;
  417. fract = modf(pVertices->tv, &base);
  418. fract *= tsy;
  419. //ASSERT(-1 <= fract && fract <= 1.01);
  420. pVertices->tv = base + fract;
  421. }
  422. /*
  423. if(m_pPRIM->TME)
  424. {
  425. pVertices->tu *= tsx;
  426. pVertices->tv *= tsy;
  427. }
  428. */
  429. if(m_pPRIM->FGE)
  430. {
  431. pVertices->fog = (pVertices->fog & 0xff000000) | (m_de.FOGCOL.ai32[0] & 0x00ffffff);
  432. // D3DCOLOR_ARGB(pVertices->fog >> 24, m_de.FOGCOL.FCB, m_de.FOGCOL.FCG, m_de.FOGCOL.FCR)
  433. }
  434. }
  435. }
  436. hr = m_pD3DDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX1);
  437. if(1)//!m_de.PABE.PABE)
  438. {
  439. hr = m_pD3DDev->DrawPrimitiveUP(m_primtype, nPrims, m_pVertices, sizeof(GSVertexHW));
  440. }
  441. /* else
  442. {
  443. ASSERT(!m_ctxt->TEST.ATE); // TODO
  444. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); 
  445. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAREF, 0xfe);
  446. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
  447. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  448. hr = m_pD3DDev->DrawPrimitive(m_primtype, 0, nPrims);
  449. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
  450. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  451. hr = m_pD3DDev->DrawPrimitive(m_primtype, 0, nPrims);
  452. }
  453. */
  454. if(m_ctxt->TEST.ATE && m_ctxt->TEST.AFAIL && m_ctxt->TEST.ATST != 1)
  455. {
  456. ASSERT(!m_de.PABE.PABE);
  457. static const DWORD iafunc[] = {D3DCMP_ALWAYS, D3DCMP_NEVER, D3DCMP_GREATEREQUAL, D3DCMP_GREATER, D3DCMP_NOTEQUAL, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_EQUAL};
  458. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, iafunc[m_ctxt->TEST.ATST]);
  459. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAREF, (DWORD)SCALE_ALPHA(m_ctxt->TEST.AREF));
  460. int mask = 0;
  461. bool zwrite = false;
  462. switch(m_ctxt->TEST.AFAIL)
  463. {
  464. case 0: break; // keep
  465. case 1: mask = D3DCOLORWRITEENABLE_RGBA; break; // fbuf
  466. case 2: zwrite = true; break; // zbuf
  467. case 3: mask = D3DCOLORWRITEENABLE_RGB; break; // fbuf w/o alpha
  468. default: __assume(0);
  469. }
  470. hr = m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, zwrite);
  471. hr = m_pD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, mask);
  472. if(mask || zwrite)
  473. hr = m_pD3DDev->DrawPrimitiveUP(m_primtype, nPrims, m_pVertices, sizeof(GSVertexHW));
  474. }
  475. hr = m_pD3DDev->EndScene();
  476. //////////////////////
  477. GIFRegTEX0 TEX0;
  478. TEX0.TBP0 = m_ctxt->FRAME.Block();
  479. TEX0.TBW = m_ctxt->FRAME.FBW;
  480. TEX0.PSM = m_ctxt->FRAME.PSM;
  481. m_tc.AddRT(TEX0, pRT, scale); 
  482. }
  483. while(0);
  484. m_primtype = D3DPT_FORCE_DWORD;
  485. __super::FlushPrim();
  486. }
  487. void GSRendererHW::Flip()
  488. {
  489. HRESULT hr;
  490. FlipInfo rt[2];
  491. for(int i = 0; i < countof(rt); i++)
  492. {
  493. if(!m_rs.IsEnabled(i)) continue;
  494. DWORD FBP = m_rs.DISPFB[i].FBP<<5;
  495. #ifdef DEBUG_RENDERTARGETS
  496. if(::GetAsyncKeyState(VK_SPACE)&0x80000000) FBP = m_ctxt->FRAME.Block();
  497. #endif
  498. CSurfMap<IDirect3DTexture9>::CPair* pPair = m_pRTs.PLookup(FBP);
  499. if(!pPair)
  500. {
  501. for(CSurfMap<IDirect3DTexture9>::CPair* pPair2 = m_pRTs.PGetFirstAssoc(); 
  502. pPair2; 
  503. pPair2 = m_pRTs.PGetNextAssoc(pPair2))
  504. {
  505. if(pPair2->key <= FBP && (!pPair || pPair2->key >= pPair->key))
  506. {
  507. pPair = pPair2;
  508. }
  509. }
  510. }
  511. if(!pPair)
  512. {
  513. CComPtr<IDirect3DTexture9> pRT;
  514. if(S_OK == m_pD3DDev->CreateTexture(m_bd.Width, m_bd.Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRT, NULL))
  515. {
  516. m_pRTs[FBP] = pRT;
  517. EXECUTE_ASSERT(pPair = m_pRTs.PLookup(FBP));
  518. #ifdef DEBUG_RENDERTARGETS
  519. CGSWnd* pWnd = NULL;
  520. if(!m_pRenderWnds.Lookup(m_ctxt->FRAME.Block(), pWnd))
  521. {
  522. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  523. pWnd = new CGSWnd();
  524. CString str; str.Format(_T("%05x"), FBP);
  525. pWnd->Create(str);
  526. m_pRenderWnds[FBP] = pWnd;
  527. pWnd->Show();
  528. }
  529. #endif
  530. CRect r = m_rs.GetDispRect(m_rs.IsEnabled(1)?1:0);
  531. scale_t scale(
  532. (float)m_bd.Width / (m_rs.DISPFB[i].FBW*64), 
  533. // (float)m_bd.Width / m_rs.GetDispRect(m_rs.IsEnabled(1)?1:0).right, 
  534. (float)m_bd.Height / r.bottom);
  535. scale.Set(pRT);
  536. GIFRegTEX0 TEX0;
  537. TEX0.TBP0 = m_rs.DISPFB[i].FBP;
  538. TEX0.TBW = m_rs.DISPFB[i].FBW;
  539. TEX0.PSM = m_rs.DISPFB[i].PSM;
  540. m_tc.AddRT(TEX0, pRT, scale);
  541. GIFRegBITBLTBUF BITBLTBUF;
  542. BITBLTBUF.DBP = TEX0.TBP0;
  543. BITBLTBUF.DBW = TEX0.TBW;
  544. BITBLTBUF.DPSM = TEX0.PSM;
  545. m_tc.InvalidateTexture(this, BITBLTBUF, r);
  546. }
  547. }
  548. if(pPair)
  549. {
  550. m_tc.ResetAge(pPair->key);
  551. rt[i].pRT = pPair->value;
  552. ZeroMemory(&rt[i].rd, sizeof(rt[i].rd));
  553. hr = rt[i].pRT->GetLevelDesc(0, &rt[i].rd);
  554. rt[i].scale.Get(rt[i].pRT);
  555. }
  556. }
  557. FinishFlip(rt);
  558. #ifdef DEBUG_RENDERTARGETS
  559. CRect dst(0, 0, m_bd.Width, m_bd.Height);
  560. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  561. if(!m_pRenderWnds.IsEmpty())
  562. {
  563. POSITION pos = m_pRenderWnds.GetStartPosition();
  564. while(pos)
  565. {
  566. DWORD fbp;
  567. CGSWnd* pWnd = NULL;
  568. m_pRenderWnds.GetNextAssoc(pos, fbp, pWnd);
  569. CComPtr<IDirect3DTexture9> pRT;
  570. if(m_pRTs.Lookup(fbp, pRT))
  571. {
  572. D3DSURFACE_DESC rd;
  573. ZeroMemory(&rd, sizeof(rd));
  574. hr = pRT->GetLevelDesc(0, &rd);
  575. hr = m_pD3DDev->SetTexture(0, pRT);
  576. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
  577. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  578. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  579. scale_t scale(pRT);
  580. CRect rect = m_rs.GetDispRect(m_rs.IsEnabled(1)?1:0);
  581. //CSize size = m_rs.GetSize(m_rs.IsEnabled(1)?1:0);
  582. CRect src = CRect(0, 0, scale.x*rect.right, scale.y*rect.bottom);
  583. struct
  584. {
  585. float x, y, z, rhw;
  586. float tu, tv;
  587. }
  588. pVertices[] =
  589. {
  590. {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / rd.Width, (float)src.top / rd.Height},
  591. {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / rd.Width, (float)src.top / rd.Height},
  592. {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / rd.Width, (float)src.bottom / rd.Height},
  593. {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / rd.Width, (float)src.bottom / rd.Height},
  594. };
  595. for(int i = 0; i < countof(pVertices); i++)
  596. {
  597. pVertices[i].x -= 0.5;
  598. pVertices[i].y -= 0.5;
  599. }
  600. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  601. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  602. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  603. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  604. hr = m_pD3DDev->SetPixelShader(NULL);
  605. hr = m_pD3DDev->BeginScene();
  606. hr = m_pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  607. hr = m_pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
  608. hr = m_pD3DDev->EndScene();
  609. hr = m_pD3DDev->Present(NULL, NULL, pWnd->m_hWnd, NULL);
  610. hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
  611. CString str;
  612. str.Format(_T("PCSX2 - %05x - %05x"), fbp, m_ctxt->TEX0.TBP0);
  613. if(fbp == (m_ctxt->FRAME.Block()))
  614. {
  615. // pWnd->SetFocus();
  616. str += _T(" - Drawing");
  617. }
  618. pWnd->SetWindowText(str);
  619. MSG msg;
  620. ZeroMemory(&msg, sizeof(msg));
  621. while(msg.message != WM_QUIT)
  622. {
  623. if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
  624. {
  625. TranslateMessage(&msg);
  626. DispatchMessage(&msg);
  627. }
  628. #ifdef DEBUG_RENDERTARGETS
  629. else if(!(::GetAsyncKeyState(VK_RCONTROL)&0x80000000))
  630. {
  631. break;
  632. }
  633. #endif
  634. }
  635. #ifdef DEBUG_RENDERTARGETS
  636. if(::GetAsyncKeyState(VK_LCONTROL)&0x80000000)
  637. Sleep(500);
  638. #endif
  639. }
  640. else
  641. {
  642. if(IsWindow(pWnd->m_hWnd)) pWnd->DestroyWindow();
  643. m_pRenderWnds.RemoveKey(fbp);
  644. }
  645. CString str;
  646. str.Format(_T("PCSX2 - %05x - %05x"), m_ctxt->FRAME.Block(), m_ctxt->TEX0.TBP0);
  647. SetWindowText(m_hWnd, str);
  648. }
  649. }
  650. else
  651. {
  652. SetWindowText(m_hWnd, _T("PCSX2"));
  653. }
  654. #endif
  655. }
  656. void GSRendererHW::EndFrame()
  657. {
  658. m_tc.IncAge(m_pRTs);
  659. }
  660. void GSRendererHW::InvalidateTexture(const GIFRegBITBLTBUF& BITBLTBUF, CRect r)
  661. {
  662. m_tc.InvalidateTexture(this, BITBLTBUF, &r);
  663. }
  664. void GSRendererHW::InvalidateLocalMem(DWORD TBP0, DWORD BW, DWORD PSM, CRect r)
  665. {
  666. m_tc.InvalidateLocalMem(this, TBP0, BW, PSM, &r);
  667. }
  668. void GSRendererHW::MinMaxUV(int w, int h, CRect& r)
  669. {
  670. r.SetRect(0, 0, w, h);
  671. uvmm_t uv;
  672. CSize bsm;
  673. if(m_ctxt->CLAMP.WMS < 3 || m_ctxt->CLAMP.WMT < 3)
  674. {
  675. UVMinMax(m_nVertices, (vertex_t*)m_pVertices, &uv);
  676. CSize bs = GSLocalMemory::m_psmtbl[m_ctxt->TEX0.PSM].bs;
  677. bsm.SetSize(bs.cx-1, bs.cy-1);
  678. }
  679. // FIXME: region clamp returns the right rect but we should still update the whole texture later in TC...
  680. if(m_ctxt->CLAMP.WMS < 3)
  681. {
  682. if(m_ctxt->CLAMP.WMS == 0)
  683. {
  684. float fmin = floor(uv.umin);
  685. float fmax = floor(uv.umax);
  686. if(fmin != fmax) {uv.umin = 0; uv.umax = 1.0f;}
  687. else {uv.umin -= fmin; uv.umax -= fmax;}
  688. // FIXME
  689. if(uv.umin == 0 && uv.umax != 1.0f) uv.umax = 1.0f;
  690. }
  691. else if(m_ctxt->CLAMP.WMS == 1)
  692. {
  693. if(uv.umin < 0) uv.umin = 0;
  694. if(uv.umax > 1.0f) uv.umax = 1.0f;
  695. }
  696. else if(m_ctxt->CLAMP.WMS == 2)
  697. {
  698. float minu = 1.0f * m_ctxt->CLAMP.MINU / w;
  699. float maxu = 1.0f * m_ctxt->CLAMP.MAXU / w;
  700. if(uv.umin < minu) uv.umin = minu;
  701. if(uv.umax > maxu) uv.umax = maxu;
  702. }
  703. r.left = max((int)(uv.umin * w) & ~bsm.cx, 0);
  704. r.right = min(((int)(uv.umax * w) + bsm.cx + 1) & ~bsm.cx, w);
  705. }
  706. if(m_ctxt->CLAMP.WMT < 3)
  707. {
  708. if(m_ctxt->CLAMP.WMT == 0)
  709. {
  710. float fmin = floor(uv.vmin);
  711. float fmax = floor(uv.vmax);
  712. if(fmin != fmax) {uv.vmin = 0; uv.vmax = 1.0f;}
  713. else {uv.vmin -= fmin; uv.vmax -= fmax;}
  714. // FIXME
  715. if(uv.vmin == 0 && uv.vmax != 1.0f) uv.vmax = 1.0f;
  716. }
  717. else if(m_ctxt->CLAMP.WMT == 1)
  718. {
  719. if(uv.vmin < 0) uv.vmin = 0;
  720. if(uv.vmax > 1.0f) uv.vmax = 1.0f;
  721. }
  722. else if(m_ctxt->CLAMP.WMT == 2)
  723. {
  724. float minv = 1.0f * m_ctxt->CLAMP.MINV / h;
  725. float maxv = 1.0f * m_ctxt->CLAMP.MAXV / h;
  726. if(uv.vmin < minv) uv.vmin = minv;
  727. if(uv.vmax > maxv) uv.vmax = maxv;
  728. }
  729. r.top = max((int)(uv.vmin * h) & ~bsm.cy, 0);
  730. r.bottom = min(((int)(uv.vmax * h) + bsm.cy + 1) & ~bsm.cy, h);
  731. }
  732. ASSERT(r.left <= r.right);
  733. ASSERT(r.top <= r.bottom);
  734. }
  735. void GSRendererHW::SetupTexture(const GSTextureBase& t, float tsx, float tsy)
  736. {
  737. HRESULT hr;
  738. int tw = 0, th = 0;
  739. float rw = 0, rh = 0;
  740. IDirect3DPixelShader9* pPixelShader = NULL;
  741. if(m_pPRIM->TME && t.m_pTexture)
  742. {
  743. tw = t.m_desc.Width;
  744. th = t.m_desc.Height;
  745. rw = 1.0f / tw;
  746. rh = 1.0f / th;
  747. hr = m_pD3DDev->SetTexture(0, t.m_pTexture);
  748. hr = m_pD3DDev->SetTexture(1, t.m_pPalette);
  749. D3DTEXTUREADDRESS u, v;
  750. switch(m_ctxt->CLAMP.WMS)
  751. {
  752. case 0: case 3: u = D3DTADDRESS_WRAP; break; // repeat
  753. case 1: case 2: u = D3DTADDRESS_CLAMP; break; // clamp
  754. default: __assume(0);
  755. }
  756. switch(m_ctxt->CLAMP.WMT)
  757. {
  758. case 0: case 3: v = D3DTADDRESS_WRAP; break; // repeat
  759. case 1: case 2: v = D3DTADDRESS_CLAMP; break; // clamp
  760. default: __assume(0);
  761. }
  762. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, u);
  763. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, v);
  764. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, t.m_pPalette ? D3DTEXF_POINT : m_texfilter);
  765. hr = m_pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, t.m_pPalette ? D3DTEXF_POINT : m_texfilter);
  766. hr = m_pD3DDev->SetSamplerState(1, D3DSAMP_MAGFILTER, t.m_pPalette ? D3DTEXF_POINT : m_texfilter);
  767. hr = m_pD3DDev->SetSamplerState(1, D3DSAMP_MINFILTER, t.m_pPalette ? D3DTEXF_POINT : m_texfilter);
  768. if(!pPixelShader && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 0) && m_pHLSLTFX[m_ctxt->TEX0.TFX])
  769. {
  770. int i = m_ctxt->TEX0.TFX;
  771. switch(t.m_desc.Format)
  772. {
  773. default: 
  774. ASSERT(0);
  775. break;
  776. case D3DFMT_A8R8G8B8:
  777. //ASSERT(m_ctxt->TEX0.PSM != PSM_PSMCT24); // format must be D3DFMT_X8R8G8B8 for PSM_PSMCT24
  778. //if(m_ctxt->TEX0.PSM == PSM_PSMCT24) {i += 4; if(m_de.TEXA.AEM) i += 4;}
  779. if(m_ctxt->TEX0.PSM == PSM_PSMT8H) i += 32;
  780. break;
  781. case D3DFMT_X8R8G8B8:
  782. i += 4; if(m_de.TEXA.AEM) i += 4;
  783. break;
  784. case D3DFMT_A1R5G5B5:
  785. i += 12; if(m_de.TEXA.AEM) i += 4; 
  786. break;
  787. case D3DFMT_L8:
  788. i += 24;
  789. ASSERT(t.m_pPalette);
  790. break;
  791. }
  792. pPixelShader = m_pHLSLTFX[i];
  793. }
  794. if(!pPixelShader && m_caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
  795. {
  796. switch(m_ctxt->TEX0.TFX)
  797. {
  798. case 0:
  799. if(!m_ctxt->TEX0.TCC) pPixelShader = m_pPixelShaders[0];
  800. else if(!t.m_fRT) pPixelShader = m_pPixelShaders[1];
  801. else pPixelShader = m_pPixelShaders[2];
  802. break;
  803. case 1:
  804. if(!t.m_fRT) pPixelShader = m_pPixelShaders[3];
  805. else pPixelShader = m_pPixelShaders[4];
  806. break;
  807. case 2:
  808. if(!m_ctxt->TEX0.TCC) pPixelShader = m_pPixelShaders[5];
  809. else if(!t.m_fRT) pPixelShader = m_pPixelShaders[6];
  810. else pPixelShader = m_pPixelShaders[7];
  811. break;
  812. case 3:
  813. if(!m_ctxt->TEX0.TCC) pPixelShader = m_pPixelShaders[8];
  814. else if(!t.m_fRT) pPixelShader = m_pPixelShaders[9];
  815. else pPixelShader = m_pPixelShaders[10];
  816. break;
  817. default: 
  818. __assume(0);
  819. }
  820. }
  821. if(!pPixelShader)
  822. {
  823. int stage = 0;
  824. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
  825. hr = m_pD3DDev->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
  826. switch(m_ctxt->TEX0.TFX)
  827. {
  828. case 0:
  829. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
  830. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  831. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  832. if(m_ctxt->TEX0.TCC)
  833. {
  834. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, t.m_fRT ? D3DTOP_MODULATE2X : D3DTOP_MODULATE4X);
  835. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  836. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  837. }
  838. else
  839. {
  840. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADD);
  841. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  842. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  843. }
  844. stage++;
  845. break;
  846. case 1:
  847. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  848. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  849. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, t.m_fRT ? D3DTOP_SELECTARG1 : D3DTOP_ADD);
  850. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  851. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
  852. stage++;
  853. break;
  854. case 2:
  855. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
  856. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  857. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  858. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  859. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  860. if(m_ctxt->TEX0.TCC)
  861. {
  862. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADD);
  863. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
  864. ASSERT(!t.m_fRT); // FIXME
  865. }
  866. stage++;
  867. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_ADD);
  868. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_CURRENT);
  869. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG2, D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE);
  870. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADD);
  871. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
  872. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  873. stage++;
  874. break;
  875. case 3:
  876. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
  877. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  878. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  879. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  880. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  881. if(m_ctxt->TEX0.TCC)
  882. {
  883. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  884. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  885. ASSERT(!t.m_fRT); // FIXME
  886. }
  887. stage++;
  888. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_ADD);
  889. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG1, D3DTA_CURRENT);
  890. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLORARG2, D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE);
  891. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_ADD);
  892. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
  893. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  894. stage++;
  895. break;
  896. default: 
  897. __assume(0);
  898. }
  899. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE);
  900. hr = m_pD3DDev->SetTextureStageState(stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  901. }
  902. }
  903. else
  904. {
  905. hr = m_pD3DDev->SetTexture(0, NULL);
  906. hr = m_pD3DDev->SetTexture(1, NULL);
  907. if(!pPixelShader && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 0) && m_pHLSLTFX[36])
  908. {
  909. pPixelShader = m_pHLSLTFX[36];
  910. }
  911. if(!pPixelShader && m_caps.PixelShaderVersion >= D3DPS_VERSION(1, 1) && m_pPixelShaders[11])
  912. {
  913. pPixelShader = m_pPixelShaders[11];
  914. }
  915. if(!pPixelShader)
  916. {
  917. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
  918. hr = m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  919. }
  920. }
  921. float fConstData[][4] = 
  922. {
  923. {(float)m_ctxt->TEX0.TCC - 0.5f, t.m_fRT ? 1.0f : 2.0f, min(2.0f * m_de.TEXA.TA0 / 255, 1), min(2.0f * m_de.TEXA.TA1 / 255, 1)},
  924. {(float)tw, (float)th, 0, 0},
  925. {rw, rh, 0, 0},
  926. {rw, 0, 0, 0},
  927. {0, rh, 0, 0},
  928. };
  929. hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
  930. hr = m_pD3DDev->SetPixelShader(pPixelShader);
  931. }
  932. void GSRendererHW::SetupAlphaBlend()
  933. {
  934. HRESULT hr;
  935. DWORD ABE = FALSE;
  936. hr = m_pD3DDev->GetRenderState(D3DRS_ALPHABLENDENABLE, &ABE);
  937. bool fABE = m_pPRIM->ABE || (m_primtype == D3DPT_LINELIST || m_primtype == D3DPT_LINESTRIP) && m_pPRIM->AA1; // FIXME
  938. if(fABE != !!ABE)
  939. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, fABE);
  940. if(fABE)
  941. {
  942. // (A:Cs/Cd/0 - B:Cs/Cd/0) * C:As/Ad/FIX + D:Cs/Cd/0
  943. BYTE FIX = SCALE_ALPHA(m_ctxt->ALPHA.FIX);
  944. hr = m_pD3DDev->SetRenderState(D3DRS_BLENDFACTOR, (0x010101*FIX)|(FIX<<24));
  945. D3DBLENDOP op = D3DBLENDOP_ADD;
  946. D3DBLEND src = D3DBLEND_SRCALPHA, dst = D3DBLEND_INVSRCALPHA;
  947. static const struct {bool bogus; D3DBLENDOP op; D3DBLEND src, dst;} blendmap[3*3*3*3] =
  948. {
  949. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0000: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  950. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0001: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  951. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0002: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  952. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0010: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  953. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0011: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  954. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0012: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  955. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0020: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  956. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0021: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  957. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0022: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  958. {1, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // * 0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
  959. {0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA}, // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
  960. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
  961. {1, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // * 0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
  962. {0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA}, // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
  963. {0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
  964. {1, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, // * 0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
  965. {0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_INVBLENDFACTOR}, // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
  966. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
  967. {1, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // * 0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
  968. {0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ONE}, // 0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
  969. {0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // 0202: (Cs - 0)*As + 0 ==> Cs*As
  970. {1, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // * 0210: (Cs - 0)*Ad + Cs ==> Cs*(As + 1)
  971. {0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ONE}, // 0211: (Cs - 0)*Ad + Cd ==> Cs*Ad + Cd
  972. {0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, // 0212: (Cs - 0)*Ad + 0 ==> Cs*Ad
  973. {1, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // * 0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
  974. {0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ONE}, // 0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
  975. {0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // 0222: (Cs - 0)*F + 0 ==> Cs*F
  976. {0, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCALPHA}, // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
  977. {1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // * 1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
  978. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
  979. {0, D3DBLENDOP_ADD, D3DBLEND_INVDESTALPHA, D3DBLEND_DESTALPHA}, // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
  980. {1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // * 1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
  981. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
  982. {0, D3DBLENDOP_ADD, D3DBLEND_INVBLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
  983. {1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},// * 1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
  984. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},// 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
  985. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1100: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  986. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1101: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  987. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1102: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  988. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1110: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  989. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1111: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  990. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1112: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  991. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1120: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  992. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1121: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  993. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 1122: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  994. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_SRCALPHA}, // 1200: (Cd - 0)*As + Cs ==> Cs + Cd*As
  995. {1, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_SRCALPHA}, // * 1201: (Cd - 0)*As + Cd ==> Cd*(1 + As)
  996. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_SRCALPHA}, // 1202: (Cd - 0)*As + 0 ==> Cd*As
  997. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 1210: (Cd - 0)*Ad + Cs ==> Cs + Cd*Ad
  998. {1, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_DESTALPHA}, // * 1211: (Cd - 0)*Ad + Cd ==> Cd*(1 + Ad)
  999. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_DESTALPHA}, // 1212: (Cd - 0)*Ad + 0 ==> Cd*Ad
  1000. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 1220: (Cd - 0)*F + Cs ==> Cs + Cd*F
  1001. {1, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_BLENDFACTOR}, // * 1221: (Cd - 0)*F + Cd ==> Cd*(1 + F)
  1002. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_BLENDFACTOR}, // 1222: (Cd - 0)*F + 0 ==> Cd*F
  1003. {0, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_ZERO}, // 2000: (0 - Cs)*As + Cs ==> Cs*(1 - As)
  1004. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_ONE}, // 2001: (0 - Cs)*As + Cd ==> Cd - Cs*As
  1005. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // 2002: (0 - Cs)*As + 0 ==> 0 - Cs*As
  1006. {0, D3DBLENDOP_ADD, D3DBLEND_INVDESTALPHA, D3DBLEND_ZERO}, // 2010: (0 - Cs)*Ad + Cs ==> Cs*(1 - Ad)
  1007. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_ONE}, // 2011: (0 - Cs)*Ad + Cd ==> Cd - Cs*Ad
  1008. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, // 2012: (0 - Cs)*Ad + 0 ==> 0 - Cs*Ad
  1009. {0, D3DBLENDOP_ADD, D3DBLEND_INVBLENDFACTOR, D3DBLEND_ZERO}, // 2020: (0 - Cs)*F + Cs ==> Cs*(1 - F)
  1010. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_ONE}, // 2021: (0 - Cs)*F + Cd ==> Cd - Cs*F
  1011. {0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // 2022: (0 - Cs)*F + 0 ==> 0 - Cs*F
  1012. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_SRCALPHA}, // 2100: (0 - Cd)*As + Cs ==> Cs - Cd*As
  1013. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVSRCALPHA}, // 2101: (0 - Cd)*As + Cd ==> Cd*(1 - As)
  1014. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ZERO, D3DBLEND_SRCALPHA}, // 2102: (0 - Cd)*As + 0 ==> 0 - Cd*As
  1015. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 2110: (0 - Cd)*Ad + Cs ==> Cs - Cd*Ad
  1016. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVDESTALPHA}, // 2111: (0 - Cd)*Ad + Cd ==> Cd*(1 - Ad)
  1017. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_DESTALPHA}, // 2112: (0 - Cd)*Ad + 0 ==> 0 - Cd*Ad
  1018. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 2120: (0 - Cd)*F + Cs ==> Cs - Cd*F
  1019. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_INVBLENDFACTOR}, // 2121: (0 - Cd)*F + Cd ==> Cd*(1 - F)
  1020. {0, D3DBLENDOP_SUBTRACT, D3DBLEND_ONE, D3DBLEND_BLENDFACTOR}, // 2122: (0 - Cd)*F + 0 ==> 0 - Cd*F
  1021. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2200: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  1022. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2201: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  1023. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2202: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  1024. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2210: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  1025. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2211: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  1026. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2212: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  1027. {0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 2220: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cs ==> Cs
  1028. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 2221: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + Cd ==> Cd
  1029. {0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 2222: (Cs/Cd/0 - Cs/Cd/0)*As/Ad/F + 0 ==> 0
  1030. };
  1031. // bogus: 0100, 0110, 0120, 0200, 0210, 0220, 1001, 1011, 1021, 1201, 1211, 1221
  1032. int i = (((m_ctxt->ALPHA.A&3)*3+(m_ctxt->ALPHA.B&3))*3+(m_ctxt->ALPHA.C&3))*3+(m_ctxt->ALPHA.D&3);
  1033. ASSERT(m_ctxt->ALPHA.A != 3);
  1034. ASSERT(m_ctxt->ALPHA.B != 3);
  1035. ASSERT(m_ctxt->ALPHA.C != 3);
  1036. ASSERT(m_ctxt->ALPHA.D != 3);
  1037. ASSERT(!blendmap[i].bogus);
  1038. hr = m_pD3DDev->SetRenderState(D3DRS_BLENDOP, blendmap[i].op);
  1039. hr = m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, blendmap[i].src);
  1040. hr = m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, blendmap[i].dst);
  1041. }
  1042. }
  1043. void GSRendererHW::SetupColorMask()
  1044. {
  1045. HRESULT hr;
  1046. // close approx., to be tested...
  1047. int mask = D3DCOLORWRITEENABLE_RGBA;
  1048. if((m_ctxt->FRAME.FBMSK&0xff000000) == 0xff000000) mask &= ~D3DCOLORWRITEENABLE_ALPHA;
  1049. if((m_ctxt->FRAME.FBMSK&0x00ff0000) == 0x00ff0000) mask &= ~D3DCOLORWRITEENABLE_BLUE;
  1050. if((m_ctxt->FRAME.FBMSK&0x0000ff00) == 0x0000ff00) mask &= ~D3DCOLORWRITEENABLE_GREEN;
  1051. if((m_ctxt->FRAME.FBMSK&0x000000ff) == 0x000000ff) mask &= ~D3DCOLORWRITEENABLE_RED;
  1052. //if(m_ctxt->FRAME.PSM == PSM_PSMCT24) mask &= ~D3DCOLORWRITEENABLE_ALPHA;
  1053. hr = m_pD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, mask);
  1054. // ASSERT(m_ctxt->FRAME.FBMSK == 0); // wild arms (also 8H+pal on RT...)
  1055. }
  1056. void GSRendererHW::SetupZBuffer()
  1057. {
  1058. HRESULT hr;
  1059. hr = m_pD3DDev->SetRenderState(D3DRS_ZENABLE, m_ctxt->TEST.ZTE);
  1060. hr = m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, !m_ctxt->ZBUF.ZMSK);
  1061. if(m_ctxt->TEST.ZTE)
  1062. {
  1063. static const DWORD zfunc[] = {D3DCMP_NEVER, D3DCMP_ALWAYS, D3DCMP_GREATEREQUAL, D3DCMP_GREATER};
  1064. hr = m_pD3DDev->SetRenderState(D3DRS_ZFUNC, zfunc[m_ctxt->TEST.ZTST]);
  1065. // hr = m_pD3DDev->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
  1066. // FIXME
  1067. if(m_ctxt->ZBUF.ZMSK && m_ctxt->TEST.ZTST == 1)
  1068. {
  1069. for(int i = 0; i < m_nVertices; i++)
  1070. m_pVertices[i].z = 0;
  1071. }
  1072. }
  1073. }
  1074. void GSRendererHW::SetupAlphaTest()
  1075. {
  1076. HRESULT hr = m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, m_ctxt->TEST.ATE);
  1077. if(m_ctxt->TEST.ATE)
  1078. {
  1079. static const DWORD afunc[] = {D3DCMP_NEVER, D3DCMP_ALWAYS, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_EQUAL, D3DCMP_GREATEREQUAL, D3DCMP_GREATER, D3DCMP_NOTEQUAL};
  1080. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAFUNC, afunc[m_ctxt->TEST.ATST]);
  1081. hr = m_pD3DDev->SetRenderState(D3DRS_ALPHAREF, (DWORD)SCALE_ALPHA(m_ctxt->TEST.AREF));
  1082. }
  1083. }
  1084. void GSRendererHW::SetupScissor(scale_t& s)
  1085. {
  1086. HRESULT hr = m_pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
  1087. CRect r(
  1088. (int)(s.x * m_ctxt->SCISSOR.SCAX0),
  1089. (int)(s.y * m_ctxt->SCISSOR.SCAY0), 
  1090. (int)(s.x * (m_ctxt->SCISSOR.SCAX1+1)),
  1091. (int)(s.y * (m_ctxt->SCISSOR.SCAY1+1)));
  1092. if(/*r.Width() == m_bd.Width &&*/ r.bottom > m_bd.Height && r.bottom <= m_bd.Height*2
  1093. /*r.bottom == m_bd.Height*2*/
  1094. )
  1095. {
  1096. // TODO: isn't there a better way? what about s.x?
  1097. // s.y = s.y * m_bd.Height / r.bottom;
  1098. }
  1099. r &= CRect(0, 0, m_bd.Width, m_bd.Height);
  1100. hr = m_pD3DDev->SetScissorRect(r);
  1101. }