1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef _NINE_PIXELSHADER9_H_
24bf215546Sopenharmony_ci#define _NINE_PIXELSHADER9_H_
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "iunknown.h"
27bf215546Sopenharmony_ci#include "nine_shader.h"
28bf215546Sopenharmony_ci#include "nine_state.h"
29bf215546Sopenharmony_ci#include "basetexture9.h"
30bf215546Sopenharmony_ci#include "nine_ff.h"
31bf215546Sopenharmony_ci#include "surface9.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_cistruct nine_lconstf;
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistruct NinePixelShader9
36bf215546Sopenharmony_ci{
37bf215546Sopenharmony_ci    struct NineUnknown base;
38bf215546Sopenharmony_ci    struct nine_shader_variant variant;
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci    struct {
41bf215546Sopenharmony_ci        const DWORD *tokens;
42bf215546Sopenharmony_ci        DWORD size;
43bf215546Sopenharmony_ci        uint8_t version; /* (major << 4) | minor */
44bf215546Sopenharmony_ci    } byte_code;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci    uint8_t bumpenvmat_needed;
47bf215546Sopenharmony_ci    uint16_t sampler_mask;
48bf215546Sopenharmony_ci    uint8_t rt_mask;
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci    boolean int_slots_used[NINE_MAX_CONST_I];
51bf215546Sopenharmony_ci    boolean bool_slots_used[NINE_MAX_CONST_B];
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci    unsigned const_int_slots;
54bf215546Sopenharmony_ci    unsigned const_bool_slots;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci    struct nine_shader_constant_combination *c_combinations;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci    uint64_t ff_key[6];
59bf215546Sopenharmony_ci    void *ff_cso;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci    uint64_t last_key;
62bf215546Sopenharmony_ci    void *last_cso;
63bf215546Sopenharmony_ci    unsigned *last_const_ranges;
64bf215546Sopenharmony_ci    unsigned last_const_used_size; /* in bytes */
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci    uint64_t next_key;
67bf215546Sopenharmony_ci};
68bf215546Sopenharmony_cistatic inline struct NinePixelShader9 *
69bf215546Sopenharmony_ciNinePixelShader9( void *data )
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci    return (struct NinePixelShader9 *)data;
72bf215546Sopenharmony_ci}
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_cistatic inline BOOL
75bf215546Sopenharmony_ciNinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
76bf215546Sopenharmony_ci                            struct nine_context *context )
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci    uint16_t samplers_shadow;
79bf215546Sopenharmony_ci    uint16_t samplers_fetch4;
80bf215546Sopenharmony_ci    uint16_t samplers_ps1_types;
81bf215546Sopenharmony_ci    uint8_t projected;
82bf215546Sopenharmony_ci    uint64_t key;
83bf215546Sopenharmony_ci    BOOL res;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci    samplers_shadow = (uint16_t)((context->samplers_shadow & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0));
86bf215546Sopenharmony_ci    samplers_fetch4 = (uint16_t)((context->samplers_fetch4 & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0));
87bf215546Sopenharmony_ci    key = samplers_shadow & ps->sampler_mask;
88bf215546Sopenharmony_ci    samplers_fetch4 &= ps->sampler_mask;
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci    if (unlikely(ps->byte_code.version < 0x20)) {
91bf215546Sopenharmony_ci        /* variable targets */
92bf215546Sopenharmony_ci        uint32_t m = ps->sampler_mask;
93bf215546Sopenharmony_ci        samplers_ps1_types = 0;
94bf215546Sopenharmony_ci        while (m) {
95bf215546Sopenharmony_ci            int s = ffs(m) - 1;
96bf215546Sopenharmony_ci            m &= ~(1 << s);
97bf215546Sopenharmony_ci            samplers_ps1_types |= (context->texture[s].enabled ? context->texture[s].pstype : 1) << (s * 2);
98bf215546Sopenharmony_ci        }
99bf215546Sopenharmony_ci        /* Note: For ps 1.X, only samplers 0 1 2 and 3 are available (except 1.4 where 4 and 5 are available).
100bf215546Sopenharmony_ci         * ps < 1.4: samplers_shadow 4b, samplers_ps1_types 8b, projected 8b
101bf215546Sopenharmony_ci         * ps 1.4: samplers_shadow 6b, samplers_ps1_types 12b
102bf215546Sopenharmony_ci         * Tot ps X.X samplers_shadow + extra: 20b */
103bf215546Sopenharmony_ci        assert((ps->byte_code.version < 0x14 && !(ps->sampler_mask & 0xFFF0)) || !(ps->sampler_mask & 0xFFC0));
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci        if (unlikely(ps->byte_code.version < 0x14)) {
106bf215546Sopenharmony_ci            key |= samplers_ps1_types << 4;
107bf215546Sopenharmony_ci            projected = nine_ff_get_projected_key_programmable(context);
108bf215546Sopenharmony_ci            key |= ((uint64_t) projected) << 12;
109bf215546Sopenharmony_ci        } else {
110bf215546Sopenharmony_ci            key |= samplers_ps1_types << 6;
111bf215546Sopenharmony_ci        }
112bf215546Sopenharmony_ci    }
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci    if (ps->byte_code.version < 0x30) {
115bf215546Sopenharmony_ci        key |= ((uint64_t)context->rs[D3DRS_FOGENABLE]) << 20;
116bf215546Sopenharmony_ci        key |= ((uint64_t)context->rs[D3DRS_FOGTABLEMODE]) << 21;
117bf215546Sopenharmony_ci    }
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci    /* centroid interpolation automatically used for color ps inputs */
120bf215546Sopenharmony_ci    if (context->rt[0]->base.info.nr_samples)
121bf215546Sopenharmony_ci        key |= ((uint64_t)1) << 22;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci    if ((ps->const_int_slots > 0 || ps->const_bool_slots > 0) && context->inline_constants)
124bf215546Sopenharmony_ci        key |= ((uint64_t)nine_shader_constant_combination_key(&ps->c_combinations,
125bf215546Sopenharmony_ci                                                               ps->int_slots_used,
126bf215546Sopenharmony_ci                                                               ps->bool_slots_used,
127bf215546Sopenharmony_ci                                                               (void *)context->ps_const_i,
128bf215546Sopenharmony_ci                                                               context->ps_const_b)) << 24;
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci    key |= ((uint64_t)(context->rs[NINED3DRS_FETCH4] & samplers_fetch4)) << 32;
131bf215546Sopenharmony_ci    res = ps->last_key != key;
132bf215546Sopenharmony_ci    if (res)
133bf215546Sopenharmony_ci        ps->next_key = key;
134bf215546Sopenharmony_ci    return res;
135bf215546Sopenharmony_ci}
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_civoid *
138bf215546Sopenharmony_ciNinePixelShader9_GetVariant( struct NinePixelShader9 *ps,
139bf215546Sopenharmony_ci                             unsigned **const_ranges,
140bf215546Sopenharmony_ci                             unsigned *const_used_size );
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci/*** public ***/
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ciHRESULT
145bf215546Sopenharmony_ciNinePixelShader9_new( struct NineDevice9 *pDevice,
146bf215546Sopenharmony_ci                      struct NinePixelShader9 **ppOut,
147bf215546Sopenharmony_ci                      const DWORD *pFunction, void *cso );
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ciHRESULT
150bf215546Sopenharmony_ciNinePixelShader9_ctor( struct NinePixelShader9 *,
151bf215546Sopenharmony_ci                       struct NineUnknownParams *pParams,
152bf215546Sopenharmony_ci                       const DWORD *pFunction, void *cso );
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_civoid
155bf215546Sopenharmony_ciNinePixelShader9_dtor( struct NinePixelShader9 * );
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ciHRESULT NINE_WINAPI
158bf215546Sopenharmony_ciNinePixelShader9_GetFunction( struct NinePixelShader9 *This,
159bf215546Sopenharmony_ci                              void *pData,
160bf215546Sopenharmony_ci                              UINT *pSizeOfData );
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci#endif /* _NINE_PIXELSHADER9_H_ */
163