/[pcsx2_0.9.7]/trunk/plugins/GSdx/GSDevice9.cpp
ViewVC logotype

Contents of /trunk/plugins/GSdx/GSDevice9.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File size: 27502 byte(s)
re-commit (had local access denied errors when committing)
1 /*
2 * Copyright (C) 2007-2009 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
22 #include "stdafx.h"
23 #include "GSdx.h"
24 #include "GSDevice9.h"
25 #include "resource.h"
26
27 GSDevice9::GSDevice9()
28 : m_lost(false)
29 {
30 m_rbswapped = true;
31
32 memset(&m_pp, 0, sizeof(m_pp));
33 //memset(&m_ddcaps, 0, sizeof(m_ddcaps)); // Unreferenced
34 memset(&m_d3dcaps, 0, sizeof(m_d3dcaps));
35
36 memset(&m_state, 0, sizeof(m_state));
37
38 m_state.bf = 0xffffffff;
39 }
40
41 GSDevice9::~GSDevice9()
42 {
43 for_each(m_mskfix.begin(), m_mskfix.end(), delete_second());
44
45 for_each(m_om_bs.begin(), m_om_bs.end(), delete_second());
46 for_each(m_om_dss.begin(), m_om_dss.end(), delete_second());
47 for_each(m_ps_ss.begin(), m_ps_ss.end(), delete_second());
48
49 if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
50 if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
51 }
52
53 static bool TestDepthFormat(CComPtr<IDirect3D9> &d3d, D3DFORMAT format)
54 {
55 if (FAILED(d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format)))
56 return false;
57 if (FAILED(d3d->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, format)))
58 return false;
59 return true;
60 }
61
62 bool GSDevice9::Create(GSWnd* wnd)
63 {
64 if(!__super::Create(wnd))
65 {
66 return false;
67 }
68
69 // dd
70
71 // Unreferenced
72 /*CComPtr<IDirectDraw7> dd;
73
74 hr = DirectDrawCreateEx(0, (void**)&dd, IID_IDirectDraw7, 0);
75
76 if(FAILED(hr)) return false;
77
78 memset(&m_ddcaps, 0, sizeof(m_ddcaps));
79
80 m_ddcaps.dwSize = sizeof(DDCAPS);
81
82 hr = dd->GetCaps(&m_ddcaps, NULL);
83
84 if(FAILED(hr)) return false;
85
86 dd = NULL;*/
87
88 // d3d
89
90 m_d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION));
91
92 if(!m_d3d) return false;
93
94 if (TestDepthFormat(m_d3d, D3DFMT_D32))
95 m_depth_format = D3DFMT_D32;
96 else if (TestDepthFormat(m_d3d, D3DFMT_D32F_LOCKABLE))
97 m_depth_format = D3DFMT_D32F_LOCKABLE;
98 else if (TestDepthFormat(m_d3d, D3DFMT_D24S8))
99 m_depth_format = D3DFMT_D24S8;
100 else
101 return false;
102
103 memset(&m_d3dcaps, 0, sizeof(m_d3dcaps));
104
105 m_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_d3dcaps);
106
107 //
108
109 if(m_d3dcaps.VertexShaderVersion < (m_d3dcaps.PixelShaderVersion & ~0x10000))
110 {
111 if(m_d3dcaps.VertexShaderVersion > D3DVS_VERSION(0, 0))
112 {
113 ASSERT(0);
114
115 return false;
116 }
117
118 // else vertex shader should be emulated in software (gma950)
119 }
120
121 m_d3dcaps.VertexShaderVersion = m_d3dcaps.PixelShaderVersion & ~0x10000;
122
123 if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
124 {
125 SetFeatureLevel(D3D_FEATURE_LEVEL_9_3, false);
126 }
127 else if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(2, 0))
128 {
129 SetFeatureLevel(D3D_FEATURE_LEVEL_9_2, false);
130 }
131 else
132 {
133 string s = format(
134 "Supported pixel shader version is too low!\n\nSupported: %d.%d\nNeeded: 2.0 or higher",
135 D3DSHADER_VERSION_MAJOR(m_d3dcaps.PixelShaderVersion), D3DSHADER_VERSION_MINOR(m_d3dcaps.PixelShaderVersion));
136
137 MessageBox(NULL, s.c_str(), "GSdx", MB_OK);
138
139 return false;
140 }
141
142 // msaa
143
144 for(uint32 i = 2; i <= 16; i++)
145 {
146 DWORD quality[2] = {0, 0};
147
148 if(SUCCEEDED(m_d3d->CheckDeviceMultiSampleType(m_d3dcaps.AdapterOrdinal, m_d3dcaps.DeviceType, D3DFMT_A8R8G8B8, TRUE, (D3DMULTISAMPLE_TYPE)i, &quality[0])) && quality[0] > 0
149 && SUCCEEDED(m_d3d->CheckDeviceMultiSampleType(m_d3dcaps.AdapterOrdinal, m_d3dcaps.DeviceType, m_depth_format, TRUE, (D3DMULTISAMPLE_TYPE)i, &quality[1])) && quality[1] > 0)
150 {
151 m_msaa_desc.Count = i;
152 m_msaa_desc.Quality = std::min<DWORD>(quality[0] - 1, quality[1] - 1);
153
154 if(i >= m_msaa) break;
155 }
156 }
157
158 if (m_msaa_desc.Count == 1)
159 m_msaa = 0;
160
161 //
162
163 if(!Reset(1, 1))
164 {
165 return false;
166 }
167
168 m_dev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
169
170 // convert
171
172 static const D3DVERTEXELEMENT9 il_convert[] =
173 {
174 {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
175 {0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
176 D3DDECL_END()
177 };
178
179 CompileShader(IDR_CONVERT_FX, "vs_main", NULL, &m_convert.vs, il_convert, countof(il_convert), &m_convert.il);
180
181 for(int i = 0; i < countof(m_convert.ps); i++)
182 {
183 CompileShader(IDR_CONVERT_FX, format("ps_main%d", i), NULL, &m_convert.ps[i]);
184 }
185
186 m_convert.dss.DepthEnable = false;
187 m_convert.dss.StencilEnable = false;
188
189 m_convert.bs.BlendEnable = false;
190 m_convert.bs.RenderTargetWriteMask = D3DCOLORWRITEENABLE_RGBA;
191
192 m_convert.ln.FilterMin[0] = D3DTEXF_LINEAR;
193 m_convert.ln.FilterMag[0] = D3DTEXF_LINEAR;
194 m_convert.ln.FilterMin[1] = D3DTEXF_LINEAR;
195 m_convert.ln.FilterMag[1] = D3DTEXF_LINEAR;
196 m_convert.ln.AddressU = D3DTADDRESS_CLAMP;
197 m_convert.ln.AddressV = D3DTADDRESS_CLAMP;
198
199 m_convert.pt.FilterMin[0] = D3DTEXF_POINT;
200 m_convert.pt.FilterMag[0] = D3DTEXF_POINT;
201 m_convert.pt.FilterMin[1] = D3DTEXF_POINT;
202 m_convert.pt.FilterMag[1] = D3DTEXF_POINT;
203 m_convert.pt.AddressU = D3DTADDRESS_CLAMP;
204 m_convert.pt.AddressV = D3DTADDRESS_CLAMP;
205
206 // merge
207
208 for(int i = 0; i < countof(m_merge.ps); i++)
209 {
210 CompileShader(IDR_MERGE_FX, format("ps_main%d", i), NULL, &m_merge.ps[i]);
211 }
212
213 m_merge.bs.BlendEnable = true;
214 m_merge.bs.BlendOp = D3DBLENDOP_ADD;
215 m_merge.bs.SrcBlend = D3DBLEND_SRCALPHA;
216 m_merge.bs.DestBlend = D3DBLEND_INVSRCALPHA;
217 m_merge.bs.BlendOpAlpha = D3DBLENDOP_ADD;
218 m_merge.bs.SrcBlendAlpha = D3DBLEND_ONE;
219 m_merge.bs.DestBlendAlpha = D3DBLEND_ZERO;
220 m_merge.bs.RenderTargetWriteMask = D3DCOLORWRITEENABLE_RGBA;
221
222 // interlace
223
224 for(int i = 0; i < countof(m_interlace.ps); i++)
225 {
226 CompileShader(IDR_INTERLACE_FX, format("ps_main%d", i), NULL, &m_interlace.ps[i]);
227 }
228
229 // create shader layout
230
231 VSSelector sel;
232 VSConstantBuffer cb;
233
234 SetupVS(sel, &cb);
235
236 //
237
238 memset(&m_date.dss, 0, sizeof(m_date.dss));
239
240 m_date.dss.StencilEnable = true;
241 m_date.dss.StencilReadMask = 1;
242 m_date.dss.StencilWriteMask = 1;
243 m_date.dss.StencilFunc = D3DCMP_ALWAYS;
244 m_date.dss.StencilPassOp = D3DSTENCILOP_REPLACE;
245 m_date.dss.StencilRef = 1;
246
247 memset(&m_date.bs, 0, sizeof(m_date.bs));
248
249 //
250
251 return true;
252 }
253
254 void GSDevice9::SetVsync(bool enable)
255 {
256 if( m_vsync == enable ) return;
257 __super::SetVsync(enable);
258
259 // Clever trick: Delete the backbuffer, so that the next Present will fail and
260 // cause a DXDevice9::Reset call, which re-creates the backbuffer with current
261 // vsync settings. :)
262
263 delete m_backbuffer;
264 m_backbuffer = NULL;
265 }
266
267 bool GSDevice9::Reset(int w, int h)
268 {
269 if(!__super::Reset(w, h))
270 return false;
271
272 HRESULT hr;
273
274 int mode = (!m_wnd->IsManaged() || theApp.GetConfig("windowed", 1)) ? Windowed : Fullscreen;
275 if(mode == DontCare)
276 {
277 mode = m_pp.Windowed ? Windowed : Fullscreen;
278 }
279
280 if(!m_lost)
281 {
282 if(m_swapchain && mode != Fullscreen && m_pp.Windowed)
283 {
284 m_swapchain = NULL;
285
286 m_pp.BackBufferWidth = w;
287 m_pp.BackBufferHeight = h;
288 m_pp.PresentationInterval = m_vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
289
290 hr = m_dev->CreateAdditionalSwapChain(&m_pp, &m_swapchain);
291
292 if(FAILED(hr)) return false;
293
294 CComPtr<IDirect3DSurface9> backbuffer;
295 hr = m_swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
296 m_backbuffer = new GSTexture9(backbuffer);
297
298 return true;
299 }
300 }
301
302 m_swapchain = NULL;
303
304 m_vb = NULL;
305 m_vb_old = NULL;
306
307 m_vertices.start = 0;
308 m_vertices.count = 0;
309
310 if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
311 if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
312
313 memset(&m_state, 0, sizeof(m_state));
314
315 m_state.bf = 0xffffffff;
316
317 memset(&m_pp, 0, sizeof(m_pp));
318
319 m_pp.Windowed = TRUE;
320 m_pp.hDeviceWindow = (HWND)m_wnd->GetHandle();
321 m_pp.SwapEffect = D3DSWAPEFFECT_FLIP;
322 m_pp.BackBufferFormat = D3DFMT_X8R8G8B8;
323 m_pp.BackBufferWidth = 1;
324 m_pp.BackBufferHeight = 1;
325 m_pp.PresentationInterval = m_vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
326
327 // m_pp.Flags |= D3DPRESENTFLAG_VIDEO; // enables tv-out (but I don't think anyone would still use a regular tv...)
328
329 int mw = theApp.GetConfig("ModeWidth", 0);
330 int mh = theApp.GetConfig("ModeHeight", 0);
331 int mrr = theApp.GetConfig("ModeRefreshRate", 0);
332
333 if(m_wnd->IsManaged() && mode == Fullscreen && mw > 0 && mh > 0 && mrr >= 0)
334 {
335 m_pp.Windowed = FALSE;
336 m_pp.BackBufferWidth = mw;
337 m_pp.BackBufferHeight = mh;
338 // m_pp.FullScreen_RefreshRateInHz = mrr;
339
340 m_wnd->HideFrame();
341 }
342
343 if(!m_dev)
344 {
345 uint32 flags = m_d3dcaps.VertexProcessingCaps ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
346
347 if(flags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
348 {
349 flags |= D3DCREATE_PUREDEVICE;
350 }
351
352 hr = m_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)m_wnd->GetHandle(), flags, &m_pp, &m_dev);
353
354 if(FAILED(hr)) return false;
355 }
356 else
357 {
358 hr = m_dev->Reset(&m_pp);
359
360 if(FAILED(hr))
361 {
362 if(D3DERR_DEVICELOST == hr)
363 {
364 Sleep(1000);
365
366 hr = m_dev->Reset(&m_pp);
367 }
368
369 if(FAILED(hr)) return false;
370 }
371 }
372
373 if(m_pp.Windowed)
374 {
375 m_pp.BackBufferWidth = 1;
376 m_pp.BackBufferHeight = 1;
377
378 hr = m_dev->CreateAdditionalSwapChain(&m_pp, &m_swapchain);
379
380 if(FAILED(hr)) return false;
381 }
382
383 CComPtr<IDirect3DSurface9> backbuffer;
384
385 if(m_swapchain)
386 {
387 hr = m_swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
388 }
389 else
390 {
391 hr = m_dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
392 }
393
394 m_backbuffer = new GSTexture9(backbuffer);
395
396 m_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
397 m_dev->SetRenderState(D3DRS_LIGHTING, FALSE);
398 m_dev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
399 m_dev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
400
401 return true;
402 }
403
404 bool GSDevice9::IsLost(bool update)
405 {
406 if(!m_lost || update)
407 {
408 HRESULT hr = m_dev->TestCooperativeLevel();
409
410 m_lost = hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET;
411 }
412
413 return m_lost;
414 }
415
416 void GSDevice9::Flip()
417 {
418 m_dev->EndScene();
419
420 HRESULT hr;
421
422 if(m_swapchain)
423 {
424 hr = m_swapchain->Present(NULL, NULL, NULL, NULL, 0);
425 }
426 else
427 {
428 hr = m_dev->Present(NULL, NULL, NULL, NULL);
429 }
430
431 m_dev->BeginScene();
432
433 if(FAILED(hr))
434 {
435 m_lost = true;
436 }
437 }
438
439 void GSDevice9::BeginScene()
440 {
441 // m_dev->BeginScene();
442 }
443
444 void GSDevice9::DrawPrimitive()
445 {
446 int prims = 0;
447
448 switch(m_state.topology)
449 {
450 case D3DPT_TRIANGLELIST:
451 prims = m_vertices.count / 3;
452 break;
453 case D3DPT_LINELIST:
454 prims = m_vertices.count / 2;
455 break;
456 case D3DPT_POINTLIST:
457 prims = m_vertices.count;
458 break;
459 case D3DPT_TRIANGLESTRIP:
460 case D3DPT_TRIANGLEFAN:
461 prims = m_vertices.count - 2;
462 break;
463 case D3DPT_LINESTRIP:
464 prims = m_vertices.count - 1;
465 break;
466 }
467
468 m_dev->DrawPrimitive(m_state.topology, m_vertices.start, prims);
469 }
470
471 void GSDevice9::EndScene()
472 {
473 // m_dev->EndScene();
474
475 __super::EndScene();
476 }
477
478 void GSDevice9::ClearRenderTarget(GSTexture* t, const GSVector4& c)
479 {
480 ClearRenderTarget(t, (c * 255 + 0.5f).zyxw().rgba32());
481 }
482
483 void GSDevice9::ClearRenderTarget(GSTexture* rt, uint32 c)
484 {
485 CComPtr<IDirect3DSurface9> surface;
486 m_dev->GetRenderTarget(0, &surface);
487 m_dev->SetRenderTarget(0, *(GSTexture9*)rt);
488 m_dev->Clear(0, NULL, D3DCLEAR_TARGET, c, 0, 0);
489 m_dev->SetRenderTarget(0, surface);
490 }
491
492 void GSDevice9::ClearDepth(GSTexture* t, float c)
493 {
494 CComPtr<IDirect3DSurface9> dssurface;
495 m_dev->GetDepthStencilSurface(&dssurface);
496 m_dev->SetDepthStencilSurface(*(GSTexture9*)t);
497 m_dev->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, c, 0);
498 m_dev->SetDepthStencilSurface(dssurface);
499 }
500
501 void GSDevice9::ClearStencil(GSTexture* t, uint8 c)
502 {
503 CComPtr<IDirect3DSurface9> dssurface;
504 m_dev->GetDepthStencilSurface(&dssurface);
505 m_dev->SetDepthStencilSurface(*(GSTexture9*)t);
506 m_dev->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 0, c);
507 m_dev->SetDepthStencilSurface(dssurface);
508 }
509
510 GSTexture* GSDevice9::Create(int type, int w, int h, bool msaa, int format)
511 {
512 HRESULT hr;
513
514 CComPtr<IDirect3DTexture9> texture;
515 CComPtr<IDirect3DSurface9> surface;
516
517 switch(type)
518 {
519 case GSTexture::RenderTarget:
520 if(msaa) hr = m_dev->CreateRenderTarget(w, h, (D3DFORMAT)format, (D3DMULTISAMPLE_TYPE)m_msaa_desc.Count, m_msaa_desc.Quality, FALSE, &surface, NULL);
521 else hr = m_dev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)format, D3DPOOL_DEFAULT, &texture, NULL);
522 break;
523 case GSTexture::DepthStencil:
524 if(msaa) hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, (D3DMULTISAMPLE_TYPE)m_msaa_desc.Count, m_msaa_desc.Quality, FALSE, &surface, NULL);
525 else hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
526 break;
527 case GSTexture::Texture:
528 hr = m_dev->CreateTexture(w, h, 1, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &texture, NULL);
529 break;
530 case GSTexture::Offscreen:
531 hr = m_dev->CreateOffscreenPlainSurface(w, h, (D3DFORMAT)format, D3DPOOL_SYSTEMMEM, &surface, NULL);
532 break;
533 }
534
535 GSTexture9* t = NULL;
536
537 if(surface)
538 {
539 t = new GSTexture9(surface);
540 }
541
542 if(texture)
543 {
544 t = new GSTexture9(texture);
545 }
546
547 if(t)
548 {
549 switch(type)
550 {
551 case GSTexture::RenderTarget:
552 ClearRenderTarget(t, 0);
553 break;
554 case GSTexture::DepthStencil:
555 ClearDepth(t, 0);
556 break;
557 }
558 }
559
560 return t;
561 }
562
563 GSTexture* GSDevice9::CreateRenderTarget(int w, int h, bool msaa, int format)
564 {
565 return __super::CreateRenderTarget(w, h, msaa, format ? format : D3DFMT_A8R8G8B8);
566 }
567
568 GSTexture* GSDevice9::CreateDepthStencil(int w, int h, bool msaa, int format)
569 {
570 return __super::CreateDepthStencil(w, h, msaa, format ? format : m_depth_format);
571 }
572
573 GSTexture* GSDevice9::CreateTexture(int w, int h, int format)
574 {
575 return __super::CreateTexture(w, h, format ? format : D3DFMT_A8R8G8B8);
576 }
577
578 GSTexture* GSDevice9::CreateOffscreen(int w, int h, int format)
579 {
580 return __super::CreateOffscreen(w, h, format ? format : D3DFMT_A8R8G8B8);
581 }
582
583 GSTexture* GSDevice9::Resolve(GSTexture* t)
584 {
585 ASSERT(t != NULL && t->IsMSAA());
586
587 if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
588 {
589 dst->SetScale(t->GetScale());
590
591 m_dev->StretchRect(*(GSTexture9*)t, NULL, *(GSTexture9*)dst, NULL, D3DTEXF_POINT);
592
593 return dst;
594 }
595
596 return NULL;
597 }
598
599 GSTexture* GSDevice9::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
600 {
601 GSTexture* dst = NULL;
602
603 if(format == 0)
604 {
605 format = D3DFMT_A8R8G8B8;
606 }
607
608 if(format != D3DFMT_A8R8G8B8)
609 {
610 ASSERT(0);
611
612 return false;
613 }
614
615 if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
616 {
617 GSVector4 dr(0, 0, w, h);
618
619 if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
620 {
621 StretchRect(src2, sr, rt, dr, m_convert.ps[1], NULL, 0);
622
623 if(src2 != src) Recycle(src2);
624 }
625
626 dst = CreateOffscreen(w, h, format);
627
628 if(dst)
629 {
630 m_dev->GetRenderTargetData(*(GSTexture9*)rt, *(GSTexture9*)dst);
631 }
632
633 Recycle(rt);
634 }
635
636 return dst;
637 }
638
639 void GSDevice9::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
640 {
641 m_dev->StretchRect(*(GSTexture9*)st, r, *(GSTexture9*)dt, r, D3DTEXF_NONE);
642 }
643
644 void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
645 {
646 StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, 0, linear);
647 }
648
649 void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len, bool linear)
650 {
651 StretchRect(st, sr, dt, dr, ps, ps_cb, ps_cb_len, &m_convert.bs, linear);
652 }
653
654 void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len, Direct3DBlendState9* bs, bool linear)
655 {
656 BeginScene();
657
658 GSVector2i ds = dt->GetSize();
659
660 // om
661
662 OMSetDepthStencilState(&m_convert.dss);
663 OMSetBlendState(bs, 0);
664 OMSetRenderTargets(dt, NULL);
665
666 // ia
667
668 float left = dr.x * 2 / ds.x - 1.0f;
669 float top = 1.0f - dr.y * 2 / ds.y;
670 float right = dr.z * 2 / ds.x - 1.0f;
671 float bottom = 1.0f - dr.w * 2 / ds.y;
672
673 GSVertexPT1 vertices[] =
674 {
675 {GSVector4(left, top, 0.5f, 1.0f), GSVector2(sr.x, sr.y)},
676 {GSVector4(right, top, 0.5f, 1.0f), GSVector2(sr.z, sr.y)},
677 {GSVector4(left, bottom, 0.5f, 1.0f), GSVector2(sr.x, sr.w)},
678 {GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sr.z, sr.w)},
679 };
680
681 for(int i = 0; i < countof(vertices); i++)
682 {
683 vertices[i].p.x -= 1.0f / ds.x;
684 vertices[i].p.y += 1.0f / ds.y;
685 }
686
687 IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
688 IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
689
690 // vs
691
692 VSSetShader(m_convert.vs, NULL, 0);
693 IASetInputLayout(m_convert.il);
694
695 // ps
696
697 PSSetSamplerState(linear ? &m_convert.ln : &m_convert.pt);
698 PSSetShaderResources(st, NULL);
699 PSSetShader(ps, ps_cb, ps_cb_len);
700
701 //
702
703 DrawPrimitive();
704
705 //
706
707 EndScene();
708 }
709
710 void GSDevice9::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
711 {
712 ClearRenderTarget(dt, c);
713
714 if(st[1] && !slbg)
715 {
716 StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0], NULL, true);
717 }
718
719 if(st[0])
720 {
721 MergeConstantBuffer cb;
722
723 cb.BGColor = c;
724
725 StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], (const float*)&cb, 1, &m_merge.bs, true);
726 }
727 }
728
729 void GSDevice9::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset)
730 {
731 GSVector4 s = GSVector4(dt->GetSize());
732
733 GSVector4 sr(0, 0, 1, 1);
734 GSVector4 dr(0.0f, yoffset, s.x, s.y + yoffset);
735
736 InterlaceConstantBuffer cb;
737
738 cb.ZrH = GSVector2(0, 1.0f / s.y);
739 cb.hH = (float)s.y / 2;
740
741 StretchRect(st, sr, dt, dr, m_interlace.ps[shader], (const float*)&cb, 1, linear);
742 }
743
744 void GSDevice9::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1 (&iaVertices)[4], bool datm)
745 {
746 const GSVector2i& size = rt->GetSize();
747
748 if(GSTexture* t = CreateRenderTarget(size.x, size.y, rt->IsMSAA()))
749 {
750 // sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
751
752 BeginScene();
753
754 ClearStencil(ds, 0);
755
756 // om
757
758 OMSetDepthStencilState(&m_date.dss);
759 OMSetBlendState(&m_date.bs, 0);
760 OMSetRenderTargets(t, ds);
761
762 // ia
763
764 IASetVertexBuffer(iaVertices, sizeof(iaVertices[0]), countof(iaVertices));
765 IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
766
767 // vs
768
769 VSSetShader(m_convert.vs, NULL, 0);
770 IASetInputLayout(m_convert.il);
771
772 // ps
773
774 GSTexture* rt2 = rt->IsMSAA() ? Resolve(rt) : rt;
775
776 PSSetShaderResources(rt2, NULL);
777 PSSetShader(m_convert.ps[datm ? 2 : 3], NULL, 0);
778 PSSetSamplerState(&m_convert.pt);
779
780 //
781
782 DrawPrimitive();
783
784 //
785
786 EndScene();
787
788 Recycle(t);
789
790 if(rt2 != rt) Recycle(rt2);
791 }
792 }
793
794 void GSDevice9::IASetVertexBuffer(const void* vertices, size_t stride, size_t count)
795 {
796 ASSERT(m_vertices.count == 0);
797
798 if(count * stride > m_vertices.limit * m_vertices.stride)
799 {
800 m_vb_old = m_vb;
801 m_vb = NULL;
802
803 m_vertices.start = 0;
804 m_vertices.count = 0;
805 m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
806 }
807
808 if(m_vb == NULL)
809 {
810 HRESULT hr;
811
812 hr = m_dev->CreateVertexBuffer(m_vertices.limit * stride, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vb, NULL);
813
814 if(FAILED(hr)) return;
815 }
816
817 uint32 flags = D3DLOCK_NOOVERWRITE;
818
819 if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride)
820 {
821 m_vertices.start = 0;
822
823 flags = D3DLOCK_DISCARD;
824 }
825
826 void* v = NULL;
827
828 if(SUCCEEDED(m_vb->Lock(m_vertices.start * stride, count * stride, &v, flags)))
829 {
830 GSVector4i::storent(v, vertices, count * stride);
831
832 m_vb->Unlock();
833 }
834
835 m_vertices.count = count;
836 m_vertices.stride = stride;
837
838 IASetVertexBuffer(m_vb, stride);
839 }
840
841 void GSDevice9::IASetVertexBuffer(IDirect3DVertexBuffer9* vb, size_t stride)
842 {
843 if(m_state.vb != vb || m_state.vb_stride != stride)
844 {
845 m_state.vb = vb;
846 m_state.vb_stride = stride;
847
848 m_dev->SetStreamSource(0, vb, 0, stride);
849 }
850 }
851
852 void GSDevice9::IASetInputLayout(IDirect3DVertexDeclaration9* layout)
853 {
854 if(m_state.layout != layout)
855 {
856 m_state.layout = layout;
857
858 m_dev->SetVertexDeclaration(layout);
859 }
860 }
861
862 void GSDevice9::IASetPrimitiveTopology(D3DPRIMITIVETYPE topology)
863 {
864 m_state.topology = topology;
865 }
866
867 void GSDevice9::VSSetShader(IDirect3DVertexShader9* vs, const float* vs_cb, int vs_cb_len)
868 {
869 if(m_state.vs != vs)
870 {
871 m_state.vs = vs;
872
873 m_dev->SetVertexShader(vs);
874 }
875
876 if(vs_cb && vs_cb_len > 0)
877 {
878 int size = vs_cb_len * sizeof(float) * 4;
879
880 if(m_state.vs_cb_len != vs_cb_len || m_state.vs_cb == NULL || memcmp(m_state.vs_cb, vs_cb, size))
881 {
882 if(m_state.vs_cb == NULL || m_state.vs_cb_len < vs_cb_len)
883 {
884 if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
885
886 m_state.vs_cb = (float*)_aligned_malloc(size, 16);
887 }
888
889 m_state.vs_cb_len = vs_cb_len;
890
891 memcpy(m_state.vs_cb, vs_cb, size);
892
893 m_dev->SetVertexShaderConstantF(0, vs_cb, vs_cb_len);
894 }
895 }
896 }
897
898 void GSDevice9::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
899 {
900 PSSetShaderResource(0, sr0);
901 PSSetShaderResource(1, sr1);
902 PSSetShaderResource(2, NULL);
903 }
904
905 void GSDevice9::PSSetShaderResource(int i, GSTexture* sr)
906 {
907 IDirect3DTexture9* srv = NULL;
908 if (sr) srv = *(GSTexture9*)sr;
909
910 if (m_state.ps_srvs[i] != srv) {
911 m_state.ps_srvs[i] = srv;
912 m_dev->SetTexture(i, srv);
913 }
914 }
915
916 void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len)
917 {
918 if(m_state.ps != ps)
919 {
920 m_state.ps = ps;
921
922 m_dev->SetPixelShader(ps);
923 }
924
925 if(ps_cb && ps_cb_len > 0)
926 {
927 int size = ps_cb_len * sizeof(float) * 4;
928
929 if(m_state.ps_cb_len != ps_cb_len || m_state.ps_cb == NULL || memcmp(m_state.ps_cb, ps_cb, size))
930 {
931 if(m_state.ps_cb == NULL || m_state.ps_cb_len < ps_cb_len)
932 {
933 if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
934
935 m_state.ps_cb = (float*)_aligned_malloc(size, 16);
936 }
937
938 m_state.ps_cb_len = ps_cb_len;
939
940 memcpy(m_state.ps_cb, ps_cb, size);
941
942 m_dev->SetPixelShaderConstantF(0, ps_cb, ps_cb_len);
943 }
944 }
945 }
946
947 void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
948 {
949 if(ss && m_state.ps_ss != ss)
950 {
951 m_state.ps_ss = ss;
952
953 m_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, ss->AddressU);
954 m_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, ss->AddressV);
955 m_dev->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
956 m_dev->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
957 m_dev->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
958 m_dev->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
959 m_dev->SetSamplerState(3, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
960 m_dev->SetSamplerState(3, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
961 m_dev->SetSamplerState(4, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
962 m_dev->SetSamplerState(4, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
963 m_dev->SetSamplerState(0, D3DSAMP_MINFILTER, ss->FilterMin[0]);
964 m_dev->SetSamplerState(0, D3DSAMP_MAGFILTER, ss->FilterMag[0]);
965 m_dev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_POINT);
966 m_dev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
967 m_dev->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_POINT);
968 m_dev->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
969 m_dev->SetSamplerState(3, D3DSAMP_MINFILTER, D3DTEXF_POINT);
970 m_dev->SetSamplerState(3, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
971 m_dev->SetSamplerState(4, D3DSAMP_MINFILTER, D3DTEXF_POINT);
972 m_dev->SetSamplerState(4, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
973 }
974 }
975
976 void GSDevice9::OMSetDepthStencilState(Direct3DDepthStencilState9* dss)
977 {
978 if(m_state.dss != dss)
979 {
980 m_state.dss = dss;
981
982 m_dev->SetRenderState(D3DRS_ZENABLE, dss->DepthEnable);
983 m_dev->SetRenderState(D3DRS_ZWRITEENABLE, dss->DepthWriteMask);
984
985 if(dss->DepthEnable)
986 {
987 m_dev->SetRenderState(D3DRS_ZFUNC, dss->DepthFunc);
988 }
989
990 m_dev->SetRenderState(D3DRS_STENCILENABLE, dss->StencilEnable);
991
992 if(dss->StencilEnable)
993 {
994 m_dev->SetRenderState(D3DRS_STENCILMASK, dss->StencilReadMask);
995 m_dev->SetRenderState(D3DRS_STENCILWRITEMASK, dss->StencilWriteMask);
996 m_dev->SetRenderState(D3DRS_STENCILFUNC, dss->StencilFunc);
997 m_dev->SetRenderState(D3DRS_STENCILPASS, dss->StencilPassOp);
998 m_dev->SetRenderState(D3DRS_STENCILFAIL, dss->StencilFailOp);
999 m_dev->SetRenderState(D3DRS_STENCILZFAIL, dss->StencilDepthFailOp);
1000 m_dev->SetRenderState(D3DRS_STENCILREF, dss->StencilRef);
1001 }
1002 }
1003 }
1004
1005 void GSDevice9::OMSetBlendState(Direct3DBlendState9* bs, uint32 bf)
1006 {
1007 if(m_state.bs != bs || m_state.bf != bf)
1008 {
1009 m_state.bs = bs;
1010 m_state.bf = bf;
1011
1012 m_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, bs->BlendEnable);
1013
1014 if(bs->BlendEnable)
1015 {
1016 m_dev->SetRenderState(D3DRS_BLENDOP, bs->BlendOp);
1017 m_dev->SetRenderState(D3DRS_SRCBLEND, bs->SrcBlend);
1018 m_dev->SetRenderState(D3DRS_DESTBLEND, bs->DestBlend);
1019 m_dev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1020 m_dev->SetRenderState(D3DRS_BLENDOPALPHA, bs->BlendOpAlpha);
1021 m_dev->SetRenderState(D3DRS_SRCBLENDALPHA, bs->SrcBlendAlpha);
1022 m_dev->SetRenderState(D3DRS_DESTBLENDALPHA, bs->DestBlendAlpha);
1023 m_dev->SetRenderState(D3DRS_BLENDFACTOR, bf);
1024 }
1025
1026 m_dev->SetRenderState(D3DRS_COLORWRITEENABLE, bs->RenderTargetWriteMask);
1027 }
1028 }
1029
1030 void GSDevice9::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
1031 {
1032 IDirect3DSurface9* rtv = NULL;
1033 IDirect3DSurface9* dsv = NULL;
1034
1035 if(rt) rtv = *(GSTexture9*)rt;
1036 if(ds) dsv = *(GSTexture9*)ds;
1037
1038 if(m_state.rtv != rtv)
1039 {
1040 m_state.rtv = rtv;
1041
1042 m_dev->SetRenderTarget(0, rtv);
1043 }
1044
1045 if(m_state.dsv != dsv)
1046 {
1047 m_state.dsv = dsv;
1048
1049 m_dev->SetDepthStencilSurface(dsv);
1050 }
1051
1052 GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
1053
1054 if(!m_state.scissor.eq(r))
1055 {
1056 m_state.scissor = r;
1057
1058 m_dev->SetScissorRect(r);
1059 }
1060 }
1061
1062 HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO* macro, IDirect3DVertexShader9** vs, const D3DVERTEXELEMENT9* layout, int count, IDirect3DVertexDeclaration9** il)
1063 {
1064 vector<D3DXMACRO> m;
1065
1066 PrepareShaderMacro(m, macro);
1067
1068 HRESULT hr;
1069
1070 CComPtr<ID3DXBuffer> shader, error;
1071
1072 hr = D3DXCompileShaderFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), &m[0], NULL, entry.c_str(), m_shader.vs.c_str(), 0, &shader, &error, NULL);
1073
1074 if(SUCCEEDED(hr))
1075 {
1076 hr = m_dev->CreateVertexShader((DWORD*)shader->GetBufferPointer(), vs);
1077 }
1078 else if(error)
1079 {
1080 printf("%s\n", (const char*)error->GetBufferPointer());
1081 }
1082
1083 ASSERT(SUCCEEDED(hr));
1084
1085 if(FAILED(hr))
1086 {
1087 return hr;
1088 }
1089
1090 hr = m_dev->CreateVertexDeclaration(layout, il);
1091
1092 if(FAILED(hr))
1093 {
1094 return hr;
1095 }
1096
1097 return S_OK;
1098 }
1099
1100 HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO* macro, IDirect3DPixelShader9** ps)
1101 {
1102 uint32 flags = 0;
1103
1104 if(m_shader.level >= D3D_FEATURE_LEVEL_9_3)
1105 {
1106 flags |= D3DXSHADER_AVOID_FLOW_CONTROL;
1107 }
1108 else
1109 {
1110 flags |= D3DXSHADER_SKIPVALIDATION;
1111 }
1112
1113 vector<D3DXMACRO> m;
1114
1115 PrepareShaderMacro(m, macro);
1116
1117 HRESULT hr;
1118
1119 CComPtr<ID3DXBuffer> shader, error;
1120
1121 hr = D3DXCompileShaderFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), &m[0], NULL, entry.c_str(), m_shader.ps.c_str(), flags, &shader, &error, NULL);
1122
1123 if(SUCCEEDED(hr))
1124 {
1125 hr = m_dev->CreatePixelShader((DWORD*)shader->GetBufferPointer(), ps);
1126 }
1127 else if(error)
1128 {
1129 printf("%s\n", (const char*)error->GetBufferPointer());
1130 }
1131
1132 ASSERT(SUCCEEDED(hr));
1133
1134 if(FAILED(hr))
1135 {
1136 return hr;
1137 }
1138
1139 return S_OK;
1140 }

  ViewVC Help
Powered by ViewVC 1.1.22