17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2015 Axel Davy <axel.davy@ens.fr>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
227ec681f3Smrg
237ec681f3Smrg#ifndef _NINE_LIMITS_H_
247ec681f3Smrg#define _NINE_LIMITS_H_
257ec681f3Smrg
267ec681f3Smrg#include "assert.h"
277ec681f3Smrg#include "d3d9types.h"
287ec681f3Smrg
297ec681f3Smrg// state can be any value
307ec681f3Smrg#define NINE_STATE_NO_LIMIT 0
317ec681f3Smrg// value is clamped if below min or max
327ec681f3Smrg#define NINE_STATE_CLAMP 1
337ec681f3Smrg// boolean: 0 -> false; any other value -> true
347ec681f3Smrg#define NINE_STATE_BOOL 2
357ec681f3Smrg// a mask is applied on the value
367ec681f3Smrg#define NINE_STATE_MASK 3
377ec681f3Smrg// if outside a range, state value is changed to a default value
387ec681f3Smrg#define NINE_STATE_RANGE_DEF_VAL 4
397ec681f3Smrg
407ec681f3Smrgstruct nine_state_behaviour {
417ec681f3Smrg  unsigned state_value_behaviour;
427ec681f3Smrg  union {
437ec681f3Smrg    struct {
447ec681f3Smrg      unsigned min;
457ec681f3Smrg      unsigned max;
467ec681f3Smrg    } clamp;
477ec681f3Smrg    unsigned mask;
487ec681f3Smrg    struct {
497ec681f3Smrg      unsigned min;
507ec681f3Smrg      unsigned max;
517ec681f3Smrg      unsigned default_val;
527ec681f3Smrg    } range_def_val;
537ec681f3Smrg  } u;
547ec681f3Smrg};
557ec681f3Smrg
567ec681f3Smrg#define __NO_LIMIT_RS(o) \
577ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_NO_LIMIT}
587ec681f3Smrg
597ec681f3Smrg#define __CLAMP_RS(o, m, M) \
607ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_CLAMP, {.clamp = {m, M}}}
617ec681f3Smrg
627ec681f3Smrg#define __BOOLEAN_RS(o) \
637ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_BOOL}
647ec681f3Smrg
657ec681f3Smrg#define __MASK_RS(o, m) \
667ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_MASK, {.mask = m}}
677ec681f3Smrg
687ec681f3Smrg#define __RANGE_DEF_VAL_RS(o, m, M, d) \
697ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_RANGE_DEF_VAL, {.range_def_val = {m, M, d}}}
707ec681f3Smrg
717ec681f3Smrg#define __TO_DETERMINE_RS(o, m, M) \
727ec681f3Smrg    [D3DRS_##o] = {NINE_STATE_NO_LIMIT}
737ec681f3Smrg
747ec681f3Smrgstatic const struct nine_state_behaviour
757ec681f3Smrgrender_state_limits_table[D3DRS_BLENDOPALPHA + 1] = {
767ec681f3Smrg    __TO_DETERMINE_RS(ZENABLE, 0, 3),
777ec681f3Smrg    __TO_DETERMINE_RS(FILLMODE, 1, 3),
787ec681f3Smrg    __CLAMP_RS(SHADEMODE, 1, 3),
797ec681f3Smrg    __BOOLEAN_RS(ZWRITEENABLE),
807ec681f3Smrg    __BOOLEAN_RS(ALPHATESTENABLE),
817ec681f3Smrg    __BOOLEAN_RS(LASTPIXEL),
827ec681f3Smrg    __RANGE_DEF_VAL_RS(SRCBLEND, 1, 17, D3DBLEND_ZERO),
837ec681f3Smrg    __RANGE_DEF_VAL_RS(DESTBLEND, 1, 17, D3DBLEND_ZERO),
847ec681f3Smrg    __CLAMP_RS(CULLMODE, 1, 3),
857ec681f3Smrg    __CLAMP_RS(ZFUNC, 1, 8),
867ec681f3Smrg    __MASK_RS(ALPHAREF, 0x000000FF),
877ec681f3Smrg    __CLAMP_RS(ALPHAFUNC, 1, 8),
887ec681f3Smrg    __BOOLEAN_RS(DITHERENABLE),
897ec681f3Smrg    __BOOLEAN_RS(ALPHABLENDENABLE),
907ec681f3Smrg    __BOOLEAN_RS(FOGENABLE),
917ec681f3Smrg    __BOOLEAN_RS(SPECULARENABLE),
927ec681f3Smrg    __NO_LIMIT_RS(FOGCOLOR),
937ec681f3Smrg    __MASK_RS(FOGTABLEMODE, 0x00000007),
947ec681f3Smrg    __NO_LIMIT_RS(FOGSTART), /* a bit more complex than that, lets ignore */
957ec681f3Smrg    __NO_LIMIT_RS(FOGEND),
967ec681f3Smrg    __NO_LIMIT_RS(FOGDENSITY), /* actually should be between 0.0 and 1.0 */
977ec681f3Smrg    __BOOLEAN_RS(RANGEFOGENABLE),
987ec681f3Smrg    __BOOLEAN_RS(STENCILENABLE),
997ec681f3Smrg    __CLAMP_RS(STENCILFAIL, 1, 8),
1007ec681f3Smrg    __CLAMP_RS(STENCILZFAIL, 1, 8),
1017ec681f3Smrg    __CLAMP_RS(STENCILPASS, 1, 8),
1027ec681f3Smrg    __CLAMP_RS(STENCILFUNC, 1, 8),
1037ec681f3Smrg    __NO_LIMIT_RS(STENCILREF),
1047ec681f3Smrg    __NO_LIMIT_RS(STENCILMASK),
1057ec681f3Smrg    __NO_LIMIT_RS(STENCILWRITEMASK),
1067ec681f3Smrg    __NO_LIMIT_RS(TEXTUREFACTOR),
1077ec681f3Smrg    __TO_DETERMINE_RS(WRAP0, 0, 15),
1087ec681f3Smrg    __TO_DETERMINE_RS(WRAP1, 0, 15),
1097ec681f3Smrg    __TO_DETERMINE_RS(WRAP2, 0, 15),
1107ec681f3Smrg    __TO_DETERMINE_RS(WRAP3, 0, 15),
1117ec681f3Smrg    __TO_DETERMINE_RS(WRAP4, 0, 15),
1127ec681f3Smrg    __TO_DETERMINE_RS(WRAP5, 0, 15),
1137ec681f3Smrg    __TO_DETERMINE_RS(WRAP6, 0, 15),
1147ec681f3Smrg    __TO_DETERMINE_RS(WRAP7, 0, 15),
1157ec681f3Smrg    __BOOLEAN_RS(CLIPPING),
1167ec681f3Smrg    __BOOLEAN_RS(LIGHTING),
1177ec681f3Smrg    __NO_LIMIT_RS(AMBIENT),
1187ec681f3Smrg    __MASK_RS(FOGVERTEXMODE, 0x00000007),
1197ec681f3Smrg    __BOOLEAN_RS(COLORVERTEX),
1207ec681f3Smrg    __BOOLEAN_RS(LOCALVIEWER),
1217ec681f3Smrg    __BOOLEAN_RS(NORMALIZENORMALS),
1227ec681f3Smrg    __TO_DETERMINE_RS(DIFFUSEMATERIALSOURCE, 0, 2),
1237ec681f3Smrg    __TO_DETERMINE_RS(SPECULARMATERIALSOURCE, 0, 2),
1247ec681f3Smrg    __TO_DETERMINE_RS(AMBIENTMATERIALSOURCE, 0, 2),
1257ec681f3Smrg    __TO_DETERMINE_RS(EMISSIVEMATERIALSOURCE, 0, 2),
1267ec681f3Smrg    __TO_DETERMINE_RS(VERTEXBLEND, 0, 256), /* values between 4 and 254 -both included- are forbidden too */
1277ec681f3Smrg    __NO_LIMIT_RS(CLIPPLANEENABLE), /* expected check seems complex */
1287ec681f3Smrg    __TO_DETERMINE_RS(POINTSIZE, 0, 0xFFFFFFFF),
1297ec681f3Smrg    __TO_DETERMINE_RS(POINTSIZE_MIN, 0, 0x7FFFFFFF), /* float >= 0.0 */
1307ec681f3Smrg    __BOOLEAN_RS(POINTSPRITEENABLE),
1317ec681f3Smrg    __BOOLEAN_RS(POINTSCALEENABLE),
1327ec681f3Smrg    __TO_DETERMINE_RS(POINTSCALE_A, 0, 0x7FFFFFFF), /* float >= 0.0 */
1337ec681f3Smrg    __TO_DETERMINE_RS(POINTSCALE_B, 0, 0x7FFFFFFF), /* float >= 0.0 */
1347ec681f3Smrg    __TO_DETERMINE_RS(POINTSCALE_C, 0, 0x7FFFFFFF), /* float >= 0.0 */
1357ec681f3Smrg    __BOOLEAN_RS(MULTISAMPLEANTIALIAS),
1367ec681f3Smrg    __NO_LIMIT_RS(MULTISAMPLEMASK),
1377ec681f3Smrg    __TO_DETERMINE_RS(PATCHEDGESTYLE, 0, 1),
1387ec681f3Smrg    __TO_DETERMINE_RS(DEBUGMONITORTOKEN, 0, 1),
1397ec681f3Smrg    __TO_DETERMINE_RS(POINTSIZE_MAX, 0, 0x7FFFFFFF), /* check more complex than that */
1407ec681f3Smrg    __BOOLEAN_RS(INDEXEDVERTEXBLENDENABLE),
1417ec681f3Smrg    __TO_DETERMINE_RS(COLORWRITEENABLE, 0, 15),
1427ec681f3Smrg    __NO_LIMIT_RS(TWEENFACTOR),
1437ec681f3Smrg    __CLAMP_RS(BLENDOP, 1, 5),
1447ec681f3Smrg    __TO_DETERMINE_RS(POSITIONDEGREE, 1, 5), /* can actually be only 1 or 5 */
1457ec681f3Smrg    __TO_DETERMINE_RS(NORMALDEGREE, 1, 2),
1467ec681f3Smrg    __BOOLEAN_RS(SCISSORTESTENABLE),
1477ec681f3Smrg    __NO_LIMIT_RS(SLOPESCALEDEPTHBIAS),
1487ec681f3Smrg    __BOOLEAN_RS(ANTIALIASEDLINEENABLE),
1497ec681f3Smrg    __NO_LIMIT_RS(MINTESSELLATIONLEVEL),
1507ec681f3Smrg    __NO_LIMIT_RS(MAXTESSELLATIONLEVEL),
1517ec681f3Smrg    __NO_LIMIT_RS(ADAPTIVETESS_X),
1527ec681f3Smrg    __NO_LIMIT_RS(ADAPTIVETESS_Y),
1537ec681f3Smrg    __NO_LIMIT_RS(ADAPTIVETESS_Z),
1547ec681f3Smrg    __NO_LIMIT_RS(ADAPTIVETESS_W),
1557ec681f3Smrg    __BOOLEAN_RS(ENABLEADAPTIVETESSELLATION),
1567ec681f3Smrg    __BOOLEAN_RS(TWOSIDEDSTENCILMODE),
1577ec681f3Smrg    __CLAMP_RS(CCW_STENCILFAIL, 1, 8),
1587ec681f3Smrg    __CLAMP_RS(CCW_STENCILZFAIL, 1, 8),
1597ec681f3Smrg    __CLAMP_RS(CCW_STENCILPASS, 1, 8),
1607ec681f3Smrg    __CLAMP_RS(CCW_STENCILFUNC, 1, 8),
1617ec681f3Smrg    __TO_DETERMINE_RS(COLORWRITEENABLE1, 0, 15),
1627ec681f3Smrg    __TO_DETERMINE_RS(COLORWRITEENABLE2, 0, 15),
1637ec681f3Smrg    __TO_DETERMINE_RS(COLORWRITEENABLE3, 0, 15),
1647ec681f3Smrg    __NO_LIMIT_RS(BLENDFACTOR),
1657ec681f3Smrg    __BOOLEAN_RS(SRGBWRITEENABLE),
1667ec681f3Smrg    __NO_LIMIT_RS(DEPTHBIAS),
1677ec681f3Smrg    __TO_DETERMINE_RS(WRAP8, 0, 15),
1687ec681f3Smrg    __TO_DETERMINE_RS(WRAP9, 0, 15),
1697ec681f3Smrg    __TO_DETERMINE_RS(WRAP10, 0, 15),
1707ec681f3Smrg    __TO_DETERMINE_RS(WRAP11, 0, 15),
1717ec681f3Smrg    __TO_DETERMINE_RS(WRAP12, 0, 15),
1727ec681f3Smrg    __TO_DETERMINE_RS(WRAP13, 0, 15),
1737ec681f3Smrg    __TO_DETERMINE_RS(WRAP14, 0, 15),
1747ec681f3Smrg    __TO_DETERMINE_RS(WRAP15, 0, 15),
1757ec681f3Smrg    __BOOLEAN_RS(SEPARATEALPHABLENDENABLE),
1767ec681f3Smrg    __RANGE_DEF_VAL_RS(SRCBLENDALPHA, 1, 17, D3DBLEND_ZERO),
1777ec681f3Smrg    __RANGE_DEF_VAL_RS(DESTBLENDALPHA, 1, 17, D3DBLEND_ZERO),
1787ec681f3Smrg    __CLAMP_RS(BLENDOPALPHA, 1, 5)
1797ec681f3Smrg};
1807ec681f3Smrg
1817ec681f3Smrgstatic DWORD inline
1827ec681f3Smrgnine_fix_render_state_value(D3DRENDERSTATETYPE State,
1837ec681f3Smrg                            DWORD Value)
1847ec681f3Smrg{
1857ec681f3Smrg    struct nine_state_behaviour behaviour = render_state_limits_table[State];
1867ec681f3Smrg
1877ec681f3Smrg    switch (behaviour.state_value_behaviour) {
1887ec681f3Smrg    case NINE_STATE_NO_LIMIT:
1897ec681f3Smrg        break;
1907ec681f3Smrg    case NINE_STATE_CLAMP:
1917ec681f3Smrg        if (Value < behaviour.u.clamp.min)
1927ec681f3Smrg            Value = behaviour.u.clamp.min;
1937ec681f3Smrg        else if (Value > behaviour.u.clamp.max)
1947ec681f3Smrg            Value = behaviour.u.clamp.max;
1957ec681f3Smrg        break;
1967ec681f3Smrg    case NINE_STATE_BOOL:
1977ec681f3Smrg        Value = Value ? 1 : 0;
1987ec681f3Smrg        break;
1997ec681f3Smrg    case NINE_STATE_MASK:
2007ec681f3Smrg        Value = Value & behaviour.u.mask;
2017ec681f3Smrg        break;
2027ec681f3Smrg    case NINE_STATE_RANGE_DEF_VAL:
2037ec681f3Smrg        if (Value < behaviour.u.range_def_val.min || Value > behaviour.u.range_def_val.max)
2047ec681f3Smrg            Value = behaviour.u.range_def_val.default_val;
2057ec681f3Smrg        break;
2067ec681f3Smrg    }
2077ec681f3Smrg
2087ec681f3Smrg    return Value;
2097ec681f3Smrg}
2107ec681f3Smrg
2117ec681f3Smrgstruct nine_limits
2127ec681f3Smrg{
2137ec681f3Smrg    unsigned min;
2147ec681f3Smrg    unsigned max;
2157ec681f3Smrg};
2167ec681f3Smrg
2177ec681f3Smrg#define __VALUE_SAMP(o, m, M) \
2187ec681f3Smrg    [D3DSAMP_##o] = {m, M}
2197ec681f3Smrg
2207ec681f3Smrgstatic const struct nine_limits
2217ec681f3Smrgsampler_state_limits_table[D3DRS_BLENDOPALPHA + 1] = {
2227ec681f3Smrg    __VALUE_SAMP(ADDRESSU, 1, 5),
2237ec681f3Smrg    __VALUE_SAMP(ADDRESSV, 1, 5),
2247ec681f3Smrg    __VALUE_SAMP(ADDRESSW, 1, 5),
2257ec681f3Smrg    __VALUE_SAMP(BORDERCOLOR, 0, 0xFFFFFFFF),
2267ec681f3Smrg    __VALUE_SAMP(MAGFILTER, 0, 8), /* 4-5 should be forbidden */
2277ec681f3Smrg    __VALUE_SAMP(MINFILTER, 0, 8), /* same */
2287ec681f3Smrg    __VALUE_SAMP(MIPFILTER, 0, 8), /* same */
2297ec681f3Smrg    __VALUE_SAMP(MIPMAPLODBIAS, 0, 0xFFFFFFFF),
2307ec681f3Smrg    __VALUE_SAMP(MAXMIPLEVEL, 0, 0xFFFFFFFF),
2317ec681f3Smrg    __VALUE_SAMP(MAXANISOTROPY, 1, 0xFFFFFFFF), /* Max value should be pCaps->MaxAnisotropy */
2327ec681f3Smrg    __VALUE_SAMP(SRGBTEXTURE, 0, 1),
2337ec681f3Smrg    __VALUE_SAMP(ELEMENTINDEX, 0, 0xFFFFFFFF),
2347ec681f3Smrg    __VALUE_SAMP(DMAPOFFSET, 0, 0xFFFFFFFF)
2357ec681f3Smrg};
2367ec681f3Smrg
2377ec681f3Smrgstatic BOOL inline
2387ec681f3Smrgnine_check_sampler_state_value(D3DSAMPLERSTATETYPE State,
2397ec681f3Smrg                               DWORD Value)
2407ec681f3Smrg{
2417ec681f3Smrg    struct nine_limits limit;
2427ec681f3Smrg
2437ec681f3Smrg    limit = sampler_state_limits_table[State];
2447ec681f3Smrg    return (limit.min <= Value && Value <= limit.max);
2457ec681f3Smrg}
2467ec681f3Smrg
2477ec681f3Smrg#endif /* _NINE_HELPERS_H_ */
248