Home | History | Annotate | Download | only in nine
      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