CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/GPU/D3D9Context.cpp
Views: 1401
1
#include "ppsspp_config.h"
2
3
#include "Common/CommonWindows.h"
4
#include <d3d9.h>
5
6
#include "Common/GPU/D3D9/D3D9StateCache.h"
7
8
#include "Common/System/Display.h"
9
#include "Common/Data/Encoding/Utf8.h"
10
#include "Common/Data/Text/I18n.h"
11
#include "Common/Log.h"
12
#include "Common/OSVersion.h"
13
14
#include "Core/Config.h"
15
#include "Core/ConfigValues.h"
16
#include "Core/System.h"
17
#include "Common/OSVersion.h"
18
#include "Windows/GPU/D3D9Context.h"
19
#include "Windows/W32Util/Misc.h"
20
#include "Common/GPU/thin3d.h"
21
#include "Common/GPU/thin3d_create.h"
22
#include "Common/GPU/D3D9/D3DCompilerLoader.h"
23
24
typedef HRESULT (__stdcall *DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
25
26
bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
27
bool windowed = true;
28
hWnd_ = wnd;
29
30
// D3D9 has no need for display rotation.
31
g_display.rotation = DisplayRotation::ROTATE_0;
32
g_display.rot_matrix.setIdentity();
33
34
DIRECT3DCREATE9EX g_pfnCreate9ex;
35
36
hD3D9_ = LoadLibrary(TEXT("d3d9.dll"));
37
if (!hD3D9_) {
38
ERROR_LOG(Log::G3D, "Missing d3d9.dll");
39
*error_message = "D3D9.dll missing - try reinstalling DirectX.";
40
return false;
41
}
42
43
bool result = LoadD3DCompilerDynamic();
44
if (!result) {
45
*error_message = "D3DCompiler not found! Try reinstalling DirectX.";
46
return false;
47
}
48
49
g_pfnCreate9ex = (DIRECT3DCREATE9EX)GetProcAddress(hD3D9_, "Direct3DCreate9Ex");
50
has9Ex_ = (g_pfnCreate9ex != NULL) && IsVistaOrHigher();
51
52
if (has9Ex_) {
53
HRESULT result = g_pfnCreate9ex(D3D_SDK_VERSION, &d3dEx_);
54
d3d_ = d3dEx_;
55
if (FAILED(result)) {
56
FreeLibrary(hD3D9_);
57
*error_message = "D3D9Ex available but context creation failed. Try reinstalling DirectX.";
58
return false;
59
}
60
} else {
61
d3d_ = Direct3DCreate9(D3D_SDK_VERSION);
62
if (!d3d_) {
63
FreeLibrary(hD3D9_);
64
*error_message = "Failed to create D3D9 context. Try reinstalling DirectX.";
65
return false;
66
}
67
}
68
adapterId_ = D3DADAPTER_DEFAULT;
69
70
D3DCAPS9 d3dCaps;
71
72
D3DDISPLAYMODE d3ddm;
73
if (FAILED(d3d_->GetAdapterDisplayMode(adapterId_, &d3ddm))) {
74
*error_message = "GetAdapterDisplayMode failed";
75
d3d_ = nullptr;
76
return false;
77
}
78
79
if (FAILED(d3d_->GetDeviceCaps(adapterId_, D3DDEVTYPE_HAL, &d3dCaps))) {
80
*error_message = "GetDeviceCaps failed (?)";
81
d3d_ = nullptr;
82
return false;
83
}
84
85
HRESULT hr;
86
if (FAILED(hr = d3d_->CheckDeviceFormat(adapterId_,
87
D3DDEVTYPE_HAL,
88
d3ddm.Format,
89
D3DUSAGE_DEPTHSTENCIL,
90
D3DRTYPE_SURFACE,
91
D3DFMT_D24S8))) {
92
if (hr == D3DERR_NOTAVAILABLE) {
93
*error_message = "D24S8 depth/stencil not available";
94
d3d_ = nullptr;
95
return false;
96
}
97
}
98
99
DWORD dwBehaviorFlags = D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
100
if (d3dCaps.VertexProcessingCaps != 0)
101
dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
102
else
103
dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
104
105
int xres, yres;
106
W32Util::GetWindowRes(hWnd_, &xres, &yres);
107
108
presentParams_ = {};
109
presentParams_.BackBufferWidth = xres;
110
presentParams_.BackBufferHeight = yres;
111
presentParams_.BackBufferFormat = d3ddm.Format;
112
presentParams_.MultiSampleType = D3DMULTISAMPLE_NONE;
113
presentParams_.SwapEffect = D3DSWAPEFFECT_DISCARD;
114
presentParams_.Windowed = windowed;
115
presentParams_.hDeviceWindow = wnd;
116
presentParams_.EnableAutoDepthStencil = true;
117
presentParams_.AutoDepthStencilFormat = D3DFMT_D24S8;
118
presentParams_.PresentationInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
119
120
if (has9Ex_) {
121
if (windowed && IsWin7OrHigher()) {
122
// This "new" flip mode should give higher performance but doesn't.
123
//pp.BackBufferCount = 2;
124
//pp.SwapEffect = D3DSWAPEFFECT_FLIPEX;
125
}
126
hr = d3dEx_->CreateDeviceEx(adapterId_, D3DDEVTYPE_HAL, wnd, dwBehaviorFlags, &presentParams_, NULL, &deviceEx_);
127
device_ = deviceEx_;
128
} else {
129
hr = d3d_->CreateDevice(adapterId_, D3DDEVTYPE_HAL, wnd, dwBehaviorFlags, &presentParams_, &device_);
130
}
131
132
if (FAILED(hr)) {
133
*error_message = "Failed to create D3D device";
134
d3d_ = nullptr;
135
return false;
136
}
137
138
device_->BeginScene();
139
pD3Ddevice9 = device_;
140
pD3DdeviceEx9 = deviceEx_;
141
142
if (deviceEx_ && IsWin7OrHigher()) {
143
// TODO: This makes it slower?
144
//deviceEx->SetMaximumFrameLatency(1);
145
}
146
draw_ = Draw::T3DCreateDX9Context(d3d_.Get(), d3dEx_.Get(), adapterId_, device_.Get(), deviceEx_.Get());
147
SetGPUBackend(GPUBackend::DIRECT3D9);
148
if (!draw_->CreatePresets()) {
149
// Shader compiler not installed? Return an error so we can fall back to GL.
150
device_ = nullptr;
151
d3d_ = nullptr;
152
*error_message = "DirectX9 runtime not correctly installed. Please install.";
153
return false;
154
}
155
if (draw_)
156
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr);
157
return true;
158
}
159
160
void D3D9Context::Resize() {
161
// This should only be called from the emu thread.
162
int xres, yres;
163
W32Util::GetWindowRes(hWnd_, &xres, &yres);
164
uint32_t newInterval = swapInterval_ == 1 ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
165
bool w_changed = presentParams_.BackBufferWidth != xres;
166
bool h_changed = presentParams_.BackBufferHeight != yres;
167
bool i_changed = presentParams_.PresentationInterval != newInterval;
168
169
if (device_ && (w_changed || h_changed || i_changed)) {
170
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr);
171
presentParams_.BackBufferWidth = xres;
172
presentParams_.BackBufferHeight = yres;
173
presentParams_.PresentationInterval = newInterval;
174
HRESULT hr = device_->Reset(&presentParams_);
175
if (FAILED(hr)) {
176
// Had to remove DXGetErrorStringA calls here because dxerr.lib is deprecated and will not link with VS 2015.
177
_assert_msg_(false, "Unable to reset D3D9 device");
178
}
179
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr);
180
}
181
}
182
183
void D3D9Context::Shutdown() {
184
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr);
185
delete draw_;
186
draw_ = nullptr;
187
device_->EndScene();
188
device_ = nullptr;
189
d3d_ = nullptr;
190
UnloadD3DCompiler();
191
pD3Ddevice9 = nullptr;
192
pD3DdeviceEx9 = nullptr;
193
device_ = nullptr;
194
hWnd_ = nullptr;
195
FreeLibrary(hD3D9_);
196
hD3D9_ = nullptr;
197
}
198
199