1 /* 2 * Copyright 2015 Axel Davy <axel.davy (at) ens.fr> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 23 #ifndef _NINE_LIMITS_H_ 24 #define _NINE_LIMITS_H_ 25 26 #include "assert.h" 27 #include "d3d9types.h" 28 29 // state can be any value 30 #define NINE_STATE_NO_LIMIT 0 31 // value is clamped if below min or max 32 #define NINE_STATE_CLAMP 1 33 // boolean: 0 -> false; any other value -> true 34 #define NINE_STATE_BOOL 2 35 // a mask is applied on the value 36 #define NINE_STATE_MASK 3 37 // if outside a range, state value is changed to a default value 38 #define NINE_STATE_RANGE_DEF_VAL 4 39 40 struct nine_state_behaviour { 41 unsigned state_value_behaviour; 42 union { 43 struct { 44 unsigned min; 45 unsigned max; 46 } clamp; 47 unsigned mask; 48 struct { 49 unsigned min; 50 unsigned max; 51 unsigned default_val; 52 } range_def_val; 53 } u; 54 }; 55 56 #define __NO_LIMIT_RS(o) \ 57 [D3DRS_##o] = {NINE_STATE_NO_LIMIT} 58 59 #define __CLAMP_RS(o, m, M) \ 60 [D3DRS_##o] = {NINE_STATE_CLAMP, {.clamp = {m, M}}} 61 62 #define __BOOLEAN_RS(o) \ 63 [D3DRS_##o] = {NINE_STATE_BOOL} 64 65 #define __MASK_RS(o, m) \ 66 [D3DRS_##o] = {NINE_STATE_MASK, {.mask = m}} 67 68 #define __RANGE_DEF_VAL_RS(o, m, M, d) \ 69 [D3DRS_##o] = {NINE_STATE_RANGE_DEF_VAL, {.range_def_val = {m, M, d}}} 70 71 #define __TO_DETERMINE_RS(o, m, M) \ 72 [D3DRS_##o] = {NINE_STATE_NO_LIMIT} 73 74 static const struct nine_state_behaviour 75 render_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { 76 __TO_DETERMINE_RS(ZENABLE, 0, 3), 77 __TO_DETERMINE_RS(FILLMODE, 1, 3), 78 __CLAMP_RS(SHADEMODE, 1, 3), 79 __BOOLEAN_RS(ZWRITEENABLE), 80 __BOOLEAN_RS(ALPHATESTENABLE), 81 __BOOLEAN_RS(LASTPIXEL), 82 __RANGE_DEF_VAL_RS(SRCBLEND, 1, 17, D3DBLEND_ZERO), 83 __RANGE_DEF_VAL_RS(DESTBLEND, 1, 17, D3DBLEND_ZERO), 84 __CLAMP_RS(CULLMODE, 1, 3), 85 __CLAMP_RS(ZFUNC, 1, 8), 86 __MASK_RS(ALPHAREF, 0x000000FF), 87 __CLAMP_RS(ALPHAFUNC, 1, 8), 88 __BOOLEAN_RS(DITHERENABLE), 89 __BOOLEAN_RS(ALPHABLENDENABLE), 90 __BOOLEAN_RS(FOGENABLE), 91 __BOOLEAN_RS(SPECULARENABLE), 92 __NO_LIMIT_RS(FOGCOLOR), 93 __MASK_RS(FOGTABLEMODE, 0x00000007), 94 __NO_LIMIT_RS(FOGSTART), /* a bit more complex than that, lets ignore */ 95 __NO_LIMIT_RS(FOGEND), 96 __NO_LIMIT_RS(FOGDENSITY), /* actually should be between 0.0 and 1.0 */ 97 __BOOLEAN_RS(RANGEFOGENABLE), 98 __BOOLEAN_RS(STENCILENABLE), 99 __CLAMP_RS(STENCILFAIL, 1, 8), 100 __CLAMP_RS(STENCILZFAIL, 1, 8), 101 __CLAMP_RS(STENCILPASS, 1, 8), 102 __CLAMP_RS(STENCILFUNC, 1, 8), 103 __NO_LIMIT_RS(STENCILREF), 104 __NO_LIMIT_RS(STENCILMASK), 105 __NO_LIMIT_RS(STENCILWRITEMASK), 106 __NO_LIMIT_RS(TEXTUREFACTOR), 107 __TO_DETERMINE_RS(WRAP0, 0, 15), 108 __TO_DETERMINE_RS(WRAP1, 0, 15), 109 __TO_DETERMINE_RS(WRAP2, 0, 15), 110 __TO_DETERMINE_RS(WRAP3, 0, 15), 111 __TO_DETERMINE_RS(WRAP4, 0, 15), 112 __TO_DETERMINE_RS(WRAP5, 0, 15), 113 __TO_DETERMINE_RS(WRAP6, 0, 15), 114 __TO_DETERMINE_RS(WRAP7, 0, 15), 115 __BOOLEAN_RS(CLIPPING), 116 __BOOLEAN_RS(LIGHTING), 117 __NO_LIMIT_RS(AMBIENT), 118 __MASK_RS(FOGVERTEXMODE, 0x00000007), 119 __BOOLEAN_RS(COLORVERTEX), 120 __BOOLEAN_RS(LOCALVIEWER), 121 __BOOLEAN_RS(NORMALIZENORMALS), 122 __TO_DETERMINE_RS(DIFFUSEMATERIALSOURCE, 0, 2), 123 __TO_DETERMINE_RS(SPECULARMATERIALSOURCE, 0, 2), 124 __TO_DETERMINE_RS(AMBIENTMATERIALSOURCE, 0, 2), 125 __TO_DETERMINE_RS(EMISSIVEMATERIALSOURCE, 0, 2), 126 __TO_DETERMINE_RS(VERTEXBLEND, 0, 256), /* values between 4 and 254 -both included- are forbidden too */ 127 __NO_LIMIT_RS(CLIPPLANEENABLE), /* expected check seems complex */ 128 __TO_DETERMINE_RS(POINTSIZE, 0, 0xFFFFFFFF), 129 __TO_DETERMINE_RS(POINTSIZE_MIN, 0, 0x7FFFFFFF), /* float >= 0.0 */ 130 __BOOLEAN_RS(POINTSPRITEENABLE), 131 __BOOLEAN_RS(POINTSCALEENABLE), 132 __TO_DETERMINE_RS(POINTSCALE_A, 0, 0x7FFFFFFF), /* float >= 0.0 */ 133 __TO_DETERMINE_RS(POINTSCALE_B, 0, 0x7FFFFFFF), /* float >= 0.0 */ 134 __TO_DETERMINE_RS(POINTSCALE_C, 0, 0x7FFFFFFF), /* float >= 0.0 */ 135 __BOOLEAN_RS(MULTISAMPLEANTIALIAS), 136 __NO_LIMIT_RS(MULTISAMPLEMASK), 137 __TO_DETERMINE_RS(PATCHEDGESTYLE, 0, 1), 138 __TO_DETERMINE_RS(DEBUGMONITORTOKEN, 0, 1), 139 __TO_DETERMINE_RS(POINTSIZE_MAX, 0, 0x7FFFFFFF), /* check more complex than that */ 140 __BOOLEAN_RS(INDEXEDVERTEXBLENDENABLE), 141 __TO_DETERMINE_RS(COLORWRITEENABLE, 0, 15), 142 __NO_LIMIT_RS(TWEENFACTOR), 143 __CLAMP_RS(BLENDOP, 1, 5), 144 __TO_DETERMINE_RS(POSITIONDEGREE, 1, 5), /* can actually be only 1 or 5 */ 145 __TO_DETERMINE_RS(NORMALDEGREE, 1, 2), 146 __BOOLEAN_RS(SCISSORTESTENABLE), 147 __NO_LIMIT_RS(SLOPESCALEDEPTHBIAS), 148 __BOOLEAN_RS(ANTIALIASEDLINEENABLE), 149 __NO_LIMIT_RS(MINTESSELLATIONLEVEL), 150 __NO_LIMIT_RS(MAXTESSELLATIONLEVEL), 151 __NO_LIMIT_RS(ADAPTIVETESS_X), 152 __NO_LIMIT_RS(ADAPTIVETESS_Y), 153 __NO_LIMIT_RS(ADAPTIVETESS_Z), 154 __NO_LIMIT_RS(ADAPTIVETESS_W), 155 __BOOLEAN_RS(ENABLEADAPTIVETESSELLATION), 156 __BOOLEAN_RS(TWOSIDEDSTENCILMODE), 157 __CLAMP_RS(CCW_STENCILFAIL, 1, 8), 158 __CLAMP_RS(CCW_STENCILZFAIL, 1, 8), 159 __CLAMP_RS(CCW_STENCILPASS, 1, 8), 160 __CLAMP_RS(CCW_STENCILFUNC, 1, 8), 161 __TO_DETERMINE_RS(COLORWRITEENABLE1, 0, 15), 162 __TO_DETERMINE_RS(COLORWRITEENABLE2, 0, 15), 163 __TO_DETERMINE_RS(COLORWRITEENABLE3, 0, 15), 164 __NO_LIMIT_RS(BLENDFACTOR), 165 __BOOLEAN_RS(SRGBWRITEENABLE), 166 __NO_LIMIT_RS(DEPTHBIAS), 167 __TO_DETERMINE_RS(WRAP8, 0, 15), 168 __TO_DETERMINE_RS(WRAP9, 0, 15), 169 __TO_DETERMINE_RS(WRAP10, 0, 15), 170 __TO_DETERMINE_RS(WRAP11, 0, 15), 171 __TO_DETERMINE_RS(WRAP12, 0, 15), 172 __TO_DETERMINE_RS(WRAP13, 0, 15), 173 __TO_DETERMINE_RS(WRAP14, 0, 15), 174 __TO_DETERMINE_RS(WRAP15, 0, 15), 175 __BOOLEAN_RS(SEPARATEALPHABLENDENABLE), 176 __RANGE_DEF_VAL_RS(SRCBLENDALPHA, 1, 17, D3DBLEND_ZERO), 177 __RANGE_DEF_VAL_RS(DESTBLENDALPHA, 1, 17, D3DBLEND_ZERO), 178 __CLAMP_RS(BLENDOPALPHA, 1, 5) 179 }; 180 181 static DWORD inline 182 nine_fix_render_state_value(D3DRENDERSTATETYPE State, 183 DWORD Value) 184 { 185 struct nine_state_behaviour behaviour = render_state_limits_table[State]; 186 187 switch (behaviour.state_value_behaviour) { 188 case NINE_STATE_NO_LIMIT: 189 break; 190 case NINE_STATE_CLAMP: 191 if (Value < behaviour.u.clamp.min) 192 Value = behaviour.u.clamp.min; 193 else if (Value > behaviour.u.clamp.max) 194 Value = behaviour.u.clamp.max; 195 break; 196 case NINE_STATE_BOOL: 197 Value = Value ? 1 : 0; 198 break; 199 case NINE_STATE_MASK: 200 Value = Value & behaviour.u.mask; 201 break; 202 case NINE_STATE_RANGE_DEF_VAL: 203 if (Value < behaviour.u.range_def_val.min || Value > behaviour.u.range_def_val.max) 204 Value = behaviour.u.range_def_val.default_val; 205 break; 206 } 207 208 return Value; 209 } 210 211 struct nine_limits 212 { 213 unsigned min; 214 unsigned max; 215 }; 216 217 #define __VALUE_SAMP(o, m, M) \ 218 [D3DSAMP_##o] = {m, M} 219 220 static const struct nine_limits 221 sampler_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { 222 __VALUE_SAMP(ADDRESSU, 1, 5), 223 __VALUE_SAMP(ADDRESSV, 1, 5), 224 __VALUE_SAMP(ADDRESSW, 1, 5), 225 __VALUE_SAMP(BORDERCOLOR, 0, 0xFFFFFFFF), 226 __VALUE_SAMP(MAGFILTER, 0, 8), /* 4-5 should be forbidden */ 227 __VALUE_SAMP(MINFILTER, 0, 8), /* same */ 228 __VALUE_SAMP(MIPFILTER, 0, 8), /* same */ 229 __VALUE_SAMP(MIPMAPLODBIAS, 0, 0xFFFFFFFF), 230 __VALUE_SAMP(MAXMIPLEVEL, 0, 0xFFFFFFFF), 231 __VALUE_SAMP(MAXANISOTROPY, 1, 0xFFFFFFFF), /* Max value should be pCaps->MaxAnisotropy */ 232 __VALUE_SAMP(SRGBTEXTURE, 0, 1), 233 __VALUE_SAMP(ELEMENTINDEX, 0, 0xFFFFFFFF), 234 __VALUE_SAMP(DMAPOFFSET, 0, 0xFFFFFFFF) 235 }; 236 237 static BOOL inline 238 nine_check_sampler_state_value(D3DSAMPLERSTATETYPE State, 239 DWORD Value) 240 { 241 struct nine_limits limit; 242 243 limit = sampler_state_limits_table[State]; 244 return (limit.min <= Value && Value <= limit.max); 245 } 246 247 #endif /* _NINE_HELPERS_H_ */ 248