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/Common/GPU/D3D9/D3D9StateCache.h
Views: 1401
1
#pragma once
2
3
#include <cstring>
4
#include <wrl/client.h>
5
6
#include "Common/GPU/D3D9/D3D9ShaderCompiler.h"
7
8
// TODO: Get rid of these somehow.
9
extern Microsoft::WRL::ComPtr<IDirect3DDevice9> pD3Ddevice9;
10
extern Microsoft::WRL::ComPtr<IDirect3DDevice9Ex> pD3DdeviceEx9;
11
12
class DirectXState {
13
private:
14
template<D3DRENDERSTATETYPE cap, bool init>
15
class BoolState {
16
bool _value;
17
public:
18
BoolState() : _value(init) {
19
DirectXState::state_count++;
20
}
21
22
inline void set(bool value) {
23
if (_value != value) {
24
_value = value;
25
restore();
26
}
27
}
28
void force(bool value) {
29
bool old = _value;
30
set(value);
31
_value = old;
32
}
33
inline void enable() {
34
set(true);
35
}
36
inline void disable() {
37
set(false);
38
}
39
operator bool() const {
40
return isset();
41
}
42
inline bool isset() {
43
return _value;
44
}
45
void restore() {
46
pD3Ddevice9->SetRenderState(cap, _value);
47
}
48
};
49
50
template<D3DRENDERSTATETYPE state1, DWORD p1def>
51
class DxState1 {
52
D3DRENDERSTATETYPE _state1;
53
DWORD p1;
54
public:
55
DxState1() : _state1(state1), p1(p1def) {
56
DirectXState::state_count++;
57
}
58
59
inline void set(DWORD newp1) {
60
if (p1 != newp1) {
61
p1 = newp1;
62
restore();
63
}
64
}
65
void force(DWORD newp1) {
66
DWORD old = p1;
67
set(newp1);
68
p1 = old;
69
}
70
void restore() {
71
pD3Ddevice9->SetRenderState(_state1, p1);
72
}
73
};
74
75
template<D3DSAMPLERSTATETYPE state1, DWORD p1def>
76
class DxSampler0State1 {
77
D3DSAMPLERSTATETYPE _state1;
78
DWORD p1;
79
public:
80
DxSampler0State1() : _state1(state1), p1(p1def) {
81
DirectXState::state_count++;
82
}
83
84
inline void set(DWORD newp1) {
85
if (p1 != newp1) {
86
p1 = newp1;
87
restore();
88
}
89
}
90
void force(DWORD newp1) {
91
DWORD old = p1;
92
set(newp1);
93
p1 = old;
94
}
95
void restore() {
96
pD3Ddevice9->SetSamplerState(0, _state1, p1);
97
}
98
};
99
100
// Can't have FLOAT template parameters...
101
template<D3DSAMPLERSTATETYPE state1, DWORD p1def>
102
class DxSampler0State1Float {
103
D3DSAMPLERSTATETYPE _state1;
104
union {
105
FLOAT p1;
106
DWORD p1d;
107
};
108
public:
109
DxSampler0State1Float() : _state1(state1), p1d(p1def) {
110
DirectXState::state_count++;
111
}
112
113
inline void set(FLOAT newp1) {
114
if (p1 != newp1) {
115
p1 = newp1;
116
restore();
117
}
118
}
119
void force(FLOAT newp1) {
120
FLOAT old = p1;
121
set(newp1);
122
p1 = old;
123
}
124
void restore() {
125
pD3Ddevice9->SetSamplerState(0, _state1, p1d);
126
}
127
};
128
129
template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def>
130
class DxState2 {
131
D3DRENDERSTATETYPE _state1;
132
D3DRENDERSTATETYPE _state2;
133
DWORD p1;
134
DWORD p2;
135
public:
136
DxState2() : _state1(state1),_state2(state2), p1(p1def), p2(p2def) {
137
DirectXState::state_count++;
138
}
139
140
inline void set(DWORD newp1, DWORD newp2) {
141
if (p1 != newp1) {
142
p1 = newp1;
143
pD3Ddevice9->SetRenderState(_state1, p1);
144
}
145
if (p2 != newp2) {
146
p2 = newp2;
147
pD3Ddevice9->SetRenderState(_state2, p2);
148
}
149
}
150
void force(DWORD newp1, DWORD newp2) {
151
DWORD old1 = p1;
152
DWORD old2 = p2;
153
set(newp1, newp2);
154
p1 = old1;
155
p2 = old2;
156
}
157
void restore() {
158
pD3Ddevice9->SetRenderState(_state1, p1);
159
pD3Ddevice9->SetRenderState(_state2, p2);
160
}
161
};
162
163
template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def, D3DRENDERSTATETYPE state3, DWORD p3def>
164
class DxState3 {
165
D3DRENDERSTATETYPE _state1;
166
D3DRENDERSTATETYPE _state2;
167
D3DRENDERSTATETYPE _state3;
168
DWORD p1;
169
DWORD p2;
170
DWORD p3;
171
public:
172
DxState3() : _state1(state1),_state2(state2), _state3(state3),
173
p1(p1def), p2(p2def), p3(p3def) {
174
}
175
176
inline void set(DWORD newp1, DWORD newp2, DWORD newp3) {
177
if (p1 != newp1) {
178
p1 = newp1;
179
pD3Ddevice9->SetRenderState(_state1, p1);
180
}
181
if (p2 != newp2) {
182
p2 = newp2;
183
pD3Ddevice9->SetRenderState(_state2, p2);
184
}
185
if (p3 != newp3) {
186
p3 = newp3;
187
pD3Ddevice9->SetRenderState(_state3, p3);
188
}
189
}
190
void force(DWORD newp1, DWORD newp2, DWORD newp3) {
191
DWORD old1 = p1;
192
DWORD old2 = p2;
193
DWORD old3 = p3;
194
set(newp1, newp2, newp3);
195
p1 = old1;
196
p2 = old2;
197
p3 = old3;
198
}
199
void restore() {
200
pD3Ddevice9->SetRenderState(_state1, p1);
201
pD3Ddevice9->SetRenderState(_state2, p2);
202
pD3Ddevice9->SetRenderState(_state3, p3);
203
}
204
};
205
206
template<D3DRENDERSTATETYPE state1, DWORD p1def, D3DRENDERSTATETYPE state2, DWORD p2def, D3DRENDERSTATETYPE state3, DWORD p3def, D3DRENDERSTATETYPE state4, DWORD p4def>
207
class DxState4 {
208
D3DRENDERSTATETYPE _state1;
209
D3DRENDERSTATETYPE _state2;
210
D3DRENDERSTATETYPE _state3;
211
D3DRENDERSTATETYPE _state4;
212
DWORD p1;
213
DWORD p2;
214
DWORD p3;
215
DWORD p4;
216
public:
217
DxState4() : _state1(state1), _state2(state2), _state3(state3), _state4(state4),
218
p1(p1def), p2(p2def), p3(p3def), p4(p4def) {
219
}
220
221
inline void set(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) {
222
if (p1 != newp1) {
223
p1 = newp1;
224
pD3Ddevice9->SetRenderState(_state1, p1);
225
}
226
if (p2 != newp2) {
227
p2 = newp2;
228
pD3Ddevice9->SetRenderState(_state2, p2);
229
}
230
if (p3 != newp3) {
231
p3 = newp3;
232
pD3Ddevice9->SetRenderState(_state3, p3);
233
}
234
if (p4 != newp4) {
235
p4 = newp4;
236
pD3Ddevice9->SetRenderState(_state4, p4);
237
}
238
}
239
void force(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) {
240
DWORD old1 = p1;
241
DWORD old2 = p2;
242
DWORD old3 = p3;
243
DWORD old4 = p4;
244
set(newp1, newp2, newp3, newp4);
245
p1 = old1;
246
p2 = old2;
247
p3 = old3;
248
p4 = old4;
249
}
250
void restore() {
251
pD3Ddevice9->SetRenderState(_state1, p1);
252
pD3Ddevice9->SetRenderState(_state2, p2);
253
pD3Ddevice9->SetRenderState(_state3, p3);
254
pD3Ddevice9->SetRenderState(_state4, p4);
255
}
256
};
257
258
259
class SavedBlendFactor {
260
DWORD c;
261
public:
262
SavedBlendFactor() {
263
c = 0xFFFFFFFF;
264
DirectXState::state_count++;
265
}
266
inline void set(const float v[4]) {
267
DWORD newc = D3DCOLOR_COLORVALUE(v[0], v[1], v[2], v[3]);
268
if (c != newc) {
269
c = newc;
270
restore();
271
}
272
}
273
void setDWORD(DWORD newc) {
274
newc = ((newc >> 8) & 0xff) | (newc & 0xff00ff00) | ((newc << 16) & 0xff0000); // ARGB -> ABGR fix
275
if (c != newc) {
276
c = newc;
277
restore();
278
}
279
}
280
void force(const float v[4]) {
281
DWORD old = c;
282
set(v);
283
c = old;
284
}
285
inline void restore() {
286
pD3Ddevice9->SetRenderState(D3DRS_BLENDFACTOR, c);
287
}
288
};
289
290
class StateVp {
291
D3DVIEWPORT9 viewport;
292
public:
293
StateVp() {
294
memset(&viewport, 0, sizeof(viewport));
295
// It's an error if w/h is zero, so let's start with something that can work.
296
viewport.Width = 1;
297
viewport.Height = 1;
298
}
299
inline void set(int x, int y, int w, int h, float n = 0.f, float f = 1.f) {
300
D3DVIEWPORT9 newviewport;
301
newviewport.X = x;
302
newviewport.Y = y;
303
newviewport.Width = w;
304
newviewport.Height = h;
305
newviewport.MinZ = n;
306
newviewport.MaxZ = f;
307
if (memcmp(&viewport, &newviewport, sizeof(viewport)) != 0) {
308
viewport = newviewport;
309
restore();
310
}
311
}
312
313
void force(int x, int y, int w, int h, float n = 0.f, float f = 1.f) {
314
D3DVIEWPORT9 old = viewport;
315
set(x, y, w, h, n, f);
316
viewport = old;
317
}
318
319
inline void restore() {
320
pD3Ddevice9->SetViewport(&viewport);
321
}
322
};
323
324
class StateScissor {
325
RECT rect;
326
public:
327
inline void set(int x1, int y1, int x2, int y2) {
328
RECT newrect = {x1, y1, x2, y2};
329
if (memcmp(&rect, &newrect, sizeof(rect))) {
330
rect = newrect;
331
restore();
332
}
333
}
334
335
void force(int x1, int y1, int x2, int y2) {
336
RECT old = rect;
337
set(x1, y1, x2, y2);
338
rect = old;
339
}
340
341
inline void restore() {
342
pD3Ddevice9->SetScissorRect(&rect);
343
}
344
};
345
346
bool initialized;
347
348
public:
349
static int state_count;
350
DirectXState() : initialized(false) {}
351
void Initialize();
352
void Restore();
353
354
// When adding a state here, don't forget to add it to DirectxState::Restore() too
355
BoolState<D3DRS_ALPHABLENDENABLE, false> blend;
356
BoolState<D3DRS_SEPARATEALPHABLENDENABLE, false> blendSeparate;
357
DxState4<D3DRS_SRCBLEND, D3DBLEND_SRCALPHA, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO> blendFunc;
358
DxState2<D3DRS_BLENDOP, D3DBLENDOP_ADD, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD> blendEquation;
359
SavedBlendFactor blendColor;
360
361
BoolState<D3DRS_SCISSORTESTENABLE, false> scissorTest;
362
363
DxState1<D3DRS_CULLMODE, D3DCULL_NONE> cullMode;
364
DxState1<D3DRS_SHADEMODE, D3DSHADE_GOURAUD> shadeMode;
365
DxState1<D3DRS_CLIPPLANEENABLE, 0> clipPlaneEnable;
366
367
BoolState<D3DRS_ZENABLE, false> depthTest;
368
369
DxState1<D3DRS_ALPHAFUNC, D3DCMP_ALWAYS> alphaTestFunc;
370
DxState1<D3DRS_ALPHAREF, 0> alphaTestRef;
371
BoolState<D3DRS_ALPHATESTENABLE, false> alphaTest;
372
373
DxState1<D3DRS_ZFUNC, D3DCMP_LESSEQUAL> depthFunc;
374
DxState1<D3DRS_ZWRITEENABLE, TRUE> depthWrite;
375
376
DxState1<D3DRS_COLORWRITEENABLE, 0xF> colorMask;
377
378
StateVp viewport;
379
StateScissor scissorRect;
380
381
BoolState<D3DRS_STENCILENABLE, false> stencilTest;
382
383
DxState3<D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP> stencilOp;
384
DxState1<D3DRS_STENCILFUNC, D3DCMP_ALWAYS> stencilFunc;
385
DxState1<D3DRS_STENCILREF, 0> stencilRef;
386
DxState1<D3DRS_STENCILWRITEMASK, 0xFFFFFFFF> stencilWriteMask;
387
DxState1<D3DRS_STENCILMASK, 0xFFFFFFFF> stencilCompareMask;
388
389
DxSampler0State1<D3DSAMP_MINFILTER, D3DTEXF_POINT> texMinFilter;
390
DxSampler0State1<D3DSAMP_MAGFILTER, D3DTEXF_POINT> texMagFilter;
391
DxSampler0State1<D3DSAMP_MIPFILTER, D3DTEXF_NONE> texMipFilter;
392
DxSampler0State1Float<D3DSAMP_MIPMAPLODBIAS, 0> texMipLodBias;
393
DxSampler0State1<D3DSAMP_MAXMIPLEVEL, 0> texMaxMipLevel;
394
DxSampler0State1<D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP> texAddressU;
395
DxSampler0State1<D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP> texAddressV;
396
DxSampler0State1<D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP> texAddressW;
397
};
398
399
#undef STATE1
400
#undef STATE2
401
402
extern DirectXState dxstate;
403
404