1 /*
2 * Copyright 2015 Axel Davy <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef _NINE_LIMITS_H_
7 #define _NINE_LIMITS_H_
8
9 #include "assert.h"
10 #include "d3d9types.h"
11
12 // state can be any value
13 #define NINE_STATE_NO_LIMIT 0
14 // value is clamped if below min or max
15 #define NINE_STATE_CLAMP 1
16 // boolean: 0 -> false; any other value -> true
17 #define NINE_STATE_BOOL 2
18 // a mask is applied on the value
19 #define NINE_STATE_MASK 3
20 // if outside a range, state value is changed to a default value
21 #define NINE_STATE_RANGE_DEF_VAL 4
22
23 struct nine_state_behaviour {
24 unsigned state_value_behaviour;
25 union {
26 struct {
27 unsigned min;
28 unsigned max;
29 } clamp;
30 unsigned mask;
31 struct {
32 unsigned min;
33 unsigned max;
34 unsigned default_val;
35 } range_def_val;
36 } u;
37 };
38
39 #define __NO_LIMIT_RS(o) \
40 [D3DRS_##o] = {NINE_STATE_NO_LIMIT}
41
42 #define __CLAMP_RS(o, m, M) \
43 [D3DRS_##o] = {NINE_STATE_CLAMP, {.clamp = {m, M}}}
44
45 #define __BOOLEAN_RS(o) \
46 [D3DRS_##o] = {NINE_STATE_BOOL}
47
48 #define __MASK_RS(o, m) \
49 [D3DRS_##o] = {NINE_STATE_MASK, {.mask = m}}
50
51 #define __RANGE_DEF_VAL_RS(o, m, M, d) \
52 [D3DRS_##o] = {NINE_STATE_RANGE_DEF_VAL, {.range_def_val = {m, M, d}}}
53
54 #define __TO_DETERMINE_RS(o, m, M) \
55 [D3DRS_##o] = {NINE_STATE_NO_LIMIT}
56
57 static const struct nine_state_behaviour
58 render_state_limits_table[D3DRS_BLENDOPALPHA + 1] = {
59 __TO_DETERMINE_RS(ZENABLE, 0, 3),
60 __TO_DETERMINE_RS(FILLMODE, 1, 3),
61 __CLAMP_RS(SHADEMODE, 1, 3),
62 __BOOLEAN_RS(ZWRITEENABLE),
63 __BOOLEAN_RS(ALPHATESTENABLE),
64 __BOOLEAN_RS(LASTPIXEL),
65 __RANGE_DEF_VAL_RS(SRCBLEND, 1, 17, D3DBLEND_ZERO),
66 __RANGE_DEF_VAL_RS(DESTBLEND, 1, 17, D3DBLEND_ZERO),
67 __CLAMP_RS(CULLMODE, 1, 3),
68 __CLAMP_RS(ZFUNC, 1, 8),
69 __MASK_RS(ALPHAREF, 0x000000FF),
70 __CLAMP_RS(ALPHAFUNC, 1, 8),
71 __BOOLEAN_RS(DITHERENABLE),
72 __BOOLEAN_RS(ALPHABLENDENABLE),
73 __BOOLEAN_RS(FOGENABLE),
74 __BOOLEAN_RS(SPECULARENABLE),
75 __NO_LIMIT_RS(FOGCOLOR),
76 __MASK_RS(FOGTABLEMODE, 0x00000003),
77 __NO_LIMIT_RS(FOGSTART), /* a bit more complex than that, lets ignore */
78 __NO_LIMIT_RS(FOGEND),
79 __NO_LIMIT_RS(FOGDENSITY), /* actually should be between 0.0 and 1.0 */
80 __BOOLEAN_RS(RANGEFOGENABLE),
81 __BOOLEAN_RS(STENCILENABLE),
82 __CLAMP_RS(STENCILFAIL, 1, 8),
83 __CLAMP_RS(STENCILZFAIL, 1, 8),
84 __CLAMP_RS(STENCILPASS, 1, 8),
85 __CLAMP_RS(STENCILFUNC, 1, 8),
86 __NO_LIMIT_RS(STENCILREF),
87 __NO_LIMIT_RS(STENCILMASK),
88 __NO_LIMIT_RS(STENCILWRITEMASK),
89 __NO_LIMIT_RS(TEXTUREFACTOR),
90 __TO_DETERMINE_RS(WRAP0, 0, 15),
91 __TO_DETERMINE_RS(WRAP1, 0, 15),
92 __TO_DETERMINE_RS(WRAP2, 0, 15),
93 __TO_DETERMINE_RS(WRAP3, 0, 15),
94 __TO_DETERMINE_RS(WRAP4, 0, 15),
95 __TO_DETERMINE_RS(WRAP5, 0, 15),
96 __TO_DETERMINE_RS(WRAP6, 0, 15),
97 __TO_DETERMINE_RS(WRAP7, 0, 15),
98 __BOOLEAN_RS(CLIPPING),
99 __BOOLEAN_RS(LIGHTING),
100 __NO_LIMIT_RS(AMBIENT),
101 __MASK_RS(FOGVERTEXMODE, 0x00000003),
102 __BOOLEAN_RS(COLORVERTEX),
103 __BOOLEAN_RS(LOCALVIEWER),
104 __BOOLEAN_RS(NORMALIZENORMALS),
105 __TO_DETERMINE_RS(DIFFUSEMATERIALSOURCE, 0, 2),
106 __TO_DETERMINE_RS(SPECULARMATERIALSOURCE, 0, 2),
107 __TO_DETERMINE_RS(AMBIENTMATERIALSOURCE, 0, 2),
108 __TO_DETERMINE_RS(EMISSIVEMATERIALSOURCE, 0, 2),
109 __TO_DETERMINE_RS(VERTEXBLEND, 0, 256), /* values between 4 and 254 -both included- are forbidden too */
110 __NO_LIMIT_RS(CLIPPLANEENABLE), /* expected check seems complex */
111 __TO_DETERMINE_RS(POINTSIZE, 0, 0xFFFFFFFF),
112 __TO_DETERMINE_RS(POINTSIZE_MIN, 0, 0x7FFFFFFF), /* float >= 0.0 */
113 __BOOLEAN_RS(POINTSPRITEENABLE),
114 __BOOLEAN_RS(POINTSCALEENABLE),
115 __TO_DETERMINE_RS(POINTSCALE_A, 0, 0x7FFFFFFF), /* float >= 0.0 */
116 __TO_DETERMINE_RS(POINTSCALE_B, 0, 0x7FFFFFFF), /* float >= 0.0 */
117 __TO_DETERMINE_RS(POINTSCALE_C, 0, 0x7FFFFFFF), /* float >= 0.0 */
118 __BOOLEAN_RS(MULTISAMPLEANTIALIAS),
119 __NO_LIMIT_RS(MULTISAMPLEMASK),
120 __TO_DETERMINE_RS(PATCHEDGESTYLE, 0, 1),
121 __TO_DETERMINE_RS(DEBUGMONITORTOKEN, 0, 1),
122 __TO_DETERMINE_RS(POINTSIZE_MAX, 0, 0x7FFFFFFF), /* check more complex than that */
123 __BOOLEAN_RS(INDEXEDVERTEXBLENDENABLE),
124 __TO_DETERMINE_RS(COLORWRITEENABLE, 0, 15),
125 __NO_LIMIT_RS(TWEENFACTOR),
126 __CLAMP_RS(BLENDOP, 1, 5),
127 __TO_DETERMINE_RS(POSITIONDEGREE, 1, 5), /* can actually be only 1 or 5 */
128 __TO_DETERMINE_RS(NORMALDEGREE, 1, 2),
129 __BOOLEAN_RS(SCISSORTESTENABLE),
130 __NO_LIMIT_RS(SLOPESCALEDEPTHBIAS),
131 __BOOLEAN_RS(ANTIALIASEDLINEENABLE),
132 __NO_LIMIT_RS(MINTESSELLATIONLEVEL),
133 __NO_LIMIT_RS(MAXTESSELLATIONLEVEL),
134 __NO_LIMIT_RS(ADAPTIVETESS_X),
135 __NO_LIMIT_RS(ADAPTIVETESS_Y),
136 __NO_LIMIT_RS(ADAPTIVETESS_Z),
137 __NO_LIMIT_RS(ADAPTIVETESS_W),
138 __BOOLEAN_RS(ENABLEADAPTIVETESSELLATION),
139 __BOOLEAN_RS(TWOSIDEDSTENCILMODE),
140 __CLAMP_RS(CCW_STENCILFAIL, 1, 8),
141 __CLAMP_RS(CCW_STENCILZFAIL, 1, 8),
142 __CLAMP_RS(CCW_STENCILPASS, 1, 8),
143 __CLAMP_RS(CCW_STENCILFUNC, 1, 8),
144 __TO_DETERMINE_RS(COLORWRITEENABLE1, 0, 15),
145 __TO_DETERMINE_RS(COLORWRITEENABLE2, 0, 15),
146 __TO_DETERMINE_RS(COLORWRITEENABLE3, 0, 15),
147 __NO_LIMIT_RS(BLENDFACTOR),
148 __BOOLEAN_RS(SRGBWRITEENABLE),
149 __NO_LIMIT_RS(DEPTHBIAS),
150 __TO_DETERMINE_RS(WRAP8, 0, 15),
151 __TO_DETERMINE_RS(WRAP9, 0, 15),
152 __TO_DETERMINE_RS(WRAP10, 0, 15),
153 __TO_DETERMINE_RS(WRAP11, 0, 15),
154 __TO_DETERMINE_RS(WRAP12, 0, 15),
155 __TO_DETERMINE_RS(WRAP13, 0, 15),
156 __TO_DETERMINE_RS(WRAP14, 0, 15),
157 __TO_DETERMINE_RS(WRAP15, 0, 15),
158 __BOOLEAN_RS(SEPARATEALPHABLENDENABLE),
159 __RANGE_DEF_VAL_RS(SRCBLENDALPHA, 1, 17, D3DBLEND_ZERO),
160 __RANGE_DEF_VAL_RS(DESTBLENDALPHA, 1, 17, D3DBLEND_ZERO),
161 __CLAMP_RS(BLENDOPALPHA, 1, 5)
162 };
163
164 static DWORD inline
nine_fix_render_state_value(D3DRENDERSTATETYPE State,DWORD Value)165 nine_fix_render_state_value(D3DRENDERSTATETYPE State,
166 DWORD Value)
167 {
168 struct nine_state_behaviour behaviour = render_state_limits_table[State];
169
170 switch (behaviour.state_value_behaviour) {
171 case NINE_STATE_NO_LIMIT:
172 break;
173 case NINE_STATE_CLAMP:
174 if (Value < behaviour.u.clamp.min)
175 Value = behaviour.u.clamp.min;
176 else if (Value > behaviour.u.clamp.max)
177 Value = behaviour.u.clamp.max;
178 break;
179 case NINE_STATE_BOOL:
180 Value = Value ? 1 : 0;
181 break;
182 case NINE_STATE_MASK:
183 Value = Value & behaviour.u.mask;
184 break;
185 case NINE_STATE_RANGE_DEF_VAL:
186 if (Value < behaviour.u.range_def_val.min || Value > behaviour.u.range_def_val.max)
187 Value = behaviour.u.range_def_val.default_val;
188 break;
189 }
190
191 return Value;
192 }
193
194 struct nine_limits
195 {
196 unsigned min;
197 unsigned max;
198 };
199
200 #define __VALUE_SAMP(o, m, M) \
201 [D3DSAMP_##o] = {m, M}
202
203 static const struct nine_limits
204 sampler_state_limits_table[D3DRS_BLENDOPALPHA + 1] = {
205 __VALUE_SAMP(ADDRESSU, 1, 5),
206 __VALUE_SAMP(ADDRESSV, 1, 5),
207 __VALUE_SAMP(ADDRESSW, 1, 5),
208 __VALUE_SAMP(BORDERCOLOR, 0, 0xFFFFFFFF),
209 __VALUE_SAMP(MAGFILTER, 0, 8), /* 4-5 should be forbidden */
210 __VALUE_SAMP(MINFILTER, 0, 8), /* same */
211 __VALUE_SAMP(MIPFILTER, 0, 8), /* same */
212 __VALUE_SAMP(MIPMAPLODBIAS, 0, 0xFFFFFFFF),
213 __VALUE_SAMP(MAXMIPLEVEL, 0, 0xFFFFFFFF),
214 __VALUE_SAMP(MAXANISOTROPY, 1, 0xFFFFFFFF), /* Max value should be pCaps->MaxAnisotropy */
215 __VALUE_SAMP(SRGBTEXTURE, 0, 1),
216 __VALUE_SAMP(ELEMENTINDEX, 0, 0xFFFFFFFF),
217 __VALUE_SAMP(DMAPOFFSET, 0, 0xFFFFFFFF)
218 };
219
220 static BOOL inline
nine_check_sampler_state_value(D3DSAMPLERSTATETYPE State,DWORD Value)221 nine_check_sampler_state_value(D3DSAMPLERSTATETYPE State,
222 DWORD Value)
223 {
224 struct nine_limits limit;
225
226 limit = sampler_state_limits_table[State];
227 return (limit.min <= Value && Value <= limit.max);
228 }
229
230 #endif /* _NINE_HELPERS_H_ */
231