• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* FF is big and ugly so feel free to write lines as long as you like.
3  * Aieeeeeeeee !
4  *
5  * Let me make that clearer:
6  * Aieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ! !! !!!
7  */
8 
9 #include "device9.h"
10 #include "basetexture9.h"
11 #include "vertexdeclaration9.h"
12 #include "vertexshader9.h"
13 #include "pixelshader9.h"
14 #include "nine_ff.h"
15 #include "nine_defines.h"
16 #include "nine_helpers.h"
17 #include "nine_pipe.h"
18 #include "nine_dump.h"
19 
20 #include "pipe/p_context.h"
21 #include "tgsi/tgsi_ureg.h"
22 #include "tgsi/tgsi_dump.h"
23 #include "util/u_box.h"
24 #include "util/u_hash_table.h"
25 #include "util/u_upload_mgr.h"
26 
27 #define DBG_CHANNEL DBG_FF
28 
29 #define NINE_FF_NUM_VS_CONST 196
30 #define NINE_FF_NUM_PS_CONST 24
31 
32 struct fvec4
33 {
34     float x, y, z, w;
35 };
36 
37 struct nine_ff_vs_key
38 {
39     union {
40         struct {
41             uint32_t position_t : 1;
42             uint32_t lighting   : 1;
43             uint32_t darkness   : 1; /* lighting enabled but no active lights */
44             uint32_t localviewer : 1;
45             uint32_t vertexpointsize : 1;
46             uint32_t pointscale : 1;
47             uint32_t vertexblend : 3;
48             uint32_t vertexblend_indexed : 1;
49             uint32_t vertextween : 1;
50             uint32_t mtl_diffuse : 2; /* 0 = material, 1 = color1, 2 = color2 */
51             uint32_t mtl_ambient : 2;
52             uint32_t mtl_specular : 2;
53             uint32_t mtl_emissive : 2;
54             uint32_t fog_mode : 2;
55             uint32_t fog_range : 1;
56             uint32_t color0in_one : 1;
57             uint32_t color1in_zero : 1;
58             uint32_t has_normal : 1;
59             uint32_t fog : 1;
60             uint32_t normalizenormals : 1;
61             uint32_t ucp : 1;
62             uint32_t pad1 : 4;
63             uint32_t tc_dim_input: 16; /* 8 * 2 bits */
64             uint32_t pad2 : 16;
65             uint32_t tc_dim_output: 24; /* 8 * 3 bits */
66             uint32_t pad3 : 8;
67             uint32_t tc_gen : 24; /* 8 * 3 bits */
68             uint32_t pad4 : 8;
69             uint32_t tc_idx : 24;
70             uint32_t pad5 : 8;
71             uint32_t passthrough;
72         };
73         uint64_t value64[3]; /* don't forget to resize VertexShader9.ff_key */
74         uint32_t value32[6];
75     };
76 };
77 
78 /* Texture stage state:
79  *
80  * COLOROP       D3DTOP 5 bit
81  * ALPHAOP       D3DTOP 5 bit
82  * COLORARG0     D3DTA  3 bit
83  * COLORARG1     D3DTA  3 bit
84  * COLORARG2     D3DTA  3 bit
85  * ALPHAARG0     D3DTA  3 bit
86  * ALPHAARG1     D3DTA  3 bit
87  * ALPHAARG2     D3DTA  3 bit
88  * RESULTARG     D3DTA  1 bit (CURRENT:0 or TEMP:1)
89  * TEXCOORDINDEX 0 - 7  3 bit
90  * ===========================
91  *                     32 bit per stage
92  */
93 struct nine_ff_ps_key
94 {
95     union {
96         struct {
97             struct {
98                 uint32_t colorop   : 5;
99                 uint32_t alphaop   : 5;
100                 uint32_t colorarg0 : 3;
101                 uint32_t colorarg1 : 3;
102                 uint32_t colorarg2 : 3;
103                 uint32_t alphaarg0 : 3;
104                 uint32_t alphaarg1 : 3;
105                 uint32_t alphaarg2 : 3;
106                 uint32_t resultarg : 1; /* CURRENT:0 or TEMP:1 */
107                 uint32_t textarget : 2; /* 1D/2D/3D/CUBE */
108                 uint32_t pad       : 1;
109                 /* that's 32 bit exactly */
110             } ts[8];
111             uint32_t projected : 16;
112             uint32_t fog : 1; /* for vFog coming from VS */
113             uint32_t fog_mode : 2;
114             uint32_t fog_source : 1; /* 0: Z, 1: W */
115             uint32_t specular : 1;
116             uint32_t pad1 : 11; /* 9 32-bit words with this */
117             uint8_t colorarg_b4[3];
118             uint8_t colorarg_b5[3];
119             uint8_t alphaarg_b4[3]; /* 11 32-bit words plus a byte */
120             uint8_t pad2[3];
121         };
122         uint64_t value64[6]; /* don't forget to resize PixelShader9.ff_key */
123         uint32_t value32[12];
124     };
125 };
126 
nine_ff_vs_key_hash(const void * key)127 static uint32_t nine_ff_vs_key_hash(const void *key)
128 {
129     const struct nine_ff_vs_key *vs = key;
130     unsigned i;
131     uint32_t hash = vs->value32[0];
132     for (i = 1; i < ARRAY_SIZE(vs->value32); ++i)
133         hash ^= vs->value32[i];
134     return hash;
135 }
nine_ff_vs_key_comp(const void * key1,const void * key2)136 static bool nine_ff_vs_key_comp(const void *key1, const void *key2)
137 {
138     struct nine_ff_vs_key *a = (struct nine_ff_vs_key *)key1;
139     struct nine_ff_vs_key *b = (struct nine_ff_vs_key *)key2;
140 
141     return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0;
142 }
nine_ff_ps_key_hash(const void * key)143 static uint32_t nine_ff_ps_key_hash(const void *key)
144 {
145     const struct nine_ff_ps_key *ps = key;
146     unsigned i;
147     uint32_t hash = ps->value32[0];
148     for (i = 1; i < ARRAY_SIZE(ps->value32); ++i)
149         hash ^= ps->value32[i];
150     return hash;
151 }
nine_ff_ps_key_comp(const void * key1,const void * key2)152 static bool nine_ff_ps_key_comp(const void *key1, const void *key2)
153 {
154     struct nine_ff_ps_key *a = (struct nine_ff_ps_key *)key1;
155     struct nine_ff_ps_key *b = (struct nine_ff_ps_key *)key2;
156 
157     return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0;
158 }
nine_ff_fvf_key_hash(const void * key)159 static uint32_t nine_ff_fvf_key_hash(const void *key)
160 {
161     return *(DWORD *)key;
162 }
nine_ff_fvf_key_comp(const void * key1,const void * key2)163 static bool nine_ff_fvf_key_comp(const void *key1, const void *key2)
164 {
165     return *(DWORD *)key1 == *(DWORD *)key2;
166 }
167 
168 static void nine_ff_prune_vs(struct NineDevice9 *);
169 static void nine_ff_prune_ps(struct NineDevice9 *);
170 
nine_ureg_tgsi_dump(struct ureg_program * ureg,boolean override)171 static void nine_ureg_tgsi_dump(struct ureg_program *ureg, boolean override)
172 {
173     if (debug_get_bool_option("NINE_FF_DUMP", FALSE) || override) {
174         const struct tgsi_token *toks = ureg_get_tokens(ureg, NULL);
175         tgsi_dump(toks, 0);
176         ureg_free_tokens(toks);
177     }
178 }
179 
180 #define _X(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_X)
181 #define _Y(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Y)
182 #define _Z(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Z)
183 #define _W(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_W)
184 
185 #define _XXXX(r) ureg_scalar(r, TGSI_SWIZZLE_X)
186 #define _YYYY(r) ureg_scalar(r, TGSI_SWIZZLE_Y)
187 #define _ZZZZ(r) ureg_scalar(r, TGSI_SWIZZLE_Z)
188 #define _WWWW(r) ureg_scalar(r, TGSI_SWIZZLE_W)
189 
190 #define _XYZW(r) (r)
191 
192 /* AL should contain base address of lights table. */
193 #define LIGHT_CONST(i)                                                \
194     ureg_src_indirect(ureg_DECL_constant(ureg, i), _X(AL))
195 
196 #define MATERIAL_CONST(i) \
197     ureg_DECL_constant(ureg, 19 + (i))
198 
199 #define _CONST(n) ureg_DECL_constant(ureg, n)
200 
201 /* VS FF constants layout:
202  *
203  * CONST[ 0.. 3] D3DTS_WORLD * D3DTS_VIEW * D3DTS_PROJECTION
204  * CONST[ 4.. 7] D3DTS_WORLD * D3DTS_VIEW
205  * CONST[ 8..11] D3DTS_PROJECTION
206  * CONST[12..15] D3DTS_VIEW^(-1)
207  * CONST[16..18] Normal matrix
208  *
209  * CONST[19].xyz  MATERIAL.Emissive + Material.Ambient * RS.Ambient
210  * CONST[20]      MATERIAL.Diffuse
211  * CONST[21]      MATERIAL.Ambient
212  * CONST[22]      MATERIAL.Specular
213  * CONST[23].x___ MATERIAL.Power
214  * CONST[24]      MATERIAL.Emissive
215  * CONST[25]      RS.Ambient
216  *
217  * CONST[26].x___ RS.PointSizeMin
218  * CONST[26]._y__ RS.PointSizeMax
219  * CONST[26].__z_ RS.PointSize
220  * CONST[26].___w RS.PointScaleA
221  * CONST[27].x___ RS.PointScaleB
222  * CONST[27]._y__ RS.PointScaleC
223  *
224  * CONST[28].x___ RS.FogEnd
225  * CONST[28]._y__ 1.0f / (RS.FogEnd - RS.FogStart)
226  * CONST[28].__z_ RS.FogDensity
227 
228  * CONST[30].x___ TWEENFACTOR
229  *
230  * CONST[32].x___ LIGHT[0].Type
231  * CONST[32]._yzw LIGHT[0].Attenuation0,1,2
232  * CONST[33]      LIGHT[0].Diffuse
233  * CONST[34]      LIGHT[0].Specular
234  * CONST[35]      LIGHT[0].Ambient
235  * CONST[36].xyz_ LIGHT[0].Position
236  * CONST[36].___w LIGHT[0].Range
237  * CONST[37].xyz_ LIGHT[0].Direction
238  * CONST[37].___w LIGHT[0].Falloff
239  * CONST[38].x___ cos(LIGHT[0].Theta / 2)
240  * CONST[38]._y__ cos(LIGHT[0].Phi / 2)
241  * CONST[38].__z_ 1.0f / (cos(LIGHT[0].Theta / 2) - cos(Light[0].Phi / 2))
242  * CONST[39].xyz_ LIGHT[0].HalfVector (for directional lights)
243  * CONST[39].___w 1 if this is the last active light, 0 if not
244  * CONST[40]      LIGHT[1]
245  * CONST[48]      LIGHT[2]
246  * CONST[56]      LIGHT[3]
247  * CONST[64]      LIGHT[4]
248  * CONST[72]      LIGHT[5]
249  * CONST[80]      LIGHT[6]
250  * CONST[88]      LIGHT[7]
251  * NOTE: no lighting code is generated if there are no active lights
252  *
253  * CONST[100].x___ Viewport 2/width
254  * CONST[100]._y__ Viewport 2/height
255  * CONST[100].__z_ Viewport 1/(zmax - zmin)
256  * CONST[100].___w Viewport width
257  * CONST[101].x___ Viewport x0
258  * CONST[101]._y__ Viewport y0
259  * CONST[101].__z_ Viewport z0
260  *
261  * CONST[128..131] D3DTS_TEXTURE0
262  * CONST[132..135] D3DTS_TEXTURE1
263  * CONST[136..139] D3DTS_TEXTURE2
264  * CONST[140..143] D3DTS_TEXTURE3
265  * CONST[144..147] D3DTS_TEXTURE4
266  * CONST[148..151] D3DTS_TEXTURE5
267  * CONST[152..155] D3DTS_TEXTURE6
268  * CONST[156..159] D3DTS_TEXTURE7
269  *
270  * CONST[160] D3DTS_WORLDMATRIX[0] * D3DTS_VIEW
271  * CONST[164] D3DTS_WORLDMATRIX[1] * D3DTS_VIEW
272  * ...
273  * CONST[192] D3DTS_WORLDMATRIX[8] * D3DTS_VIEW
274  */
275 struct vs_build_ctx
276 {
277     struct ureg_program *ureg;
278     const struct nine_ff_vs_key *key;
279 
280     uint16_t input[PIPE_MAX_ATTRIBS];
281     unsigned num_inputs;
282 
283     struct ureg_src aVtx;
284     struct ureg_src aNrm;
285     struct ureg_src aCol[2];
286     struct ureg_src aTex[8];
287     struct ureg_src aPsz;
288     struct ureg_src aInd;
289     struct ureg_src aWgt;
290 
291     struct ureg_src aVtx1; /* tweening */
292     struct ureg_src aNrm1;
293 
294     struct ureg_src mtlA;
295     struct ureg_src mtlD;
296     struct ureg_src mtlS;
297     struct ureg_src mtlE;
298 };
299 
300 static inline unsigned
get_texcoord_sn(struct pipe_screen * screen)301 get_texcoord_sn(struct pipe_screen *screen)
302 {
303     if (screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD))
304         return TGSI_SEMANTIC_TEXCOORD;
305     return TGSI_SEMANTIC_GENERIC;
306 }
307 
308 static inline struct ureg_src
build_vs_add_input(struct vs_build_ctx * vs,uint16_t ndecl)309 build_vs_add_input(struct vs_build_ctx *vs, uint16_t ndecl)
310 {
311     const unsigned i = vs->num_inputs++;
312     assert(i < PIPE_MAX_ATTRIBS);
313     vs->input[i] = ndecl;
314     return ureg_DECL_vs_input(vs->ureg, i);
315 }
316 
317 /* NOTE: dst may alias src */
318 static inline void
ureg_normalize3(struct ureg_program * ureg,struct ureg_dst dst,struct ureg_src src)319 ureg_normalize3(struct ureg_program *ureg,
320                 struct ureg_dst dst, struct ureg_src src)
321 {
322     struct ureg_dst tmp = ureg_DECL_temporary(ureg);
323     struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
324 
325     ureg_DP3(ureg, tmp_x, src, src);
326     ureg_RSQ(ureg, tmp_x, _X(tmp));
327     ureg_MUL(ureg, dst, src, _X(tmp));
328     ureg_release_temporary(ureg, tmp);
329 }
330 
331 static void *
nine_ff_build_vs(struct NineDevice9 * device,struct vs_build_ctx * vs)332 nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
333 {
334     const struct nine_ff_vs_key *key = vs->key;
335     struct ureg_program *ureg = ureg_create(PIPE_SHADER_VERTEX);
336     struct ureg_dst oPos, oCol[2], oPsz, oFog;
337     struct ureg_dst AR;
338     unsigned i, c;
339     unsigned label[32], l = 0;
340     boolean need_aNrm = key->lighting || key->passthrough & (1 << NINE_DECLUSAGE_NORMAL);
341     boolean has_aNrm;
342     boolean need_aVtx = key->lighting || key->fog_mode || key->pointscale || key->ucp;
343     const unsigned texcoord_sn = get_texcoord_sn(device->screen);
344 
345     vs->ureg = ureg;
346 
347     /* Check which inputs we should transform. */
348     for (i = 0; i < 8 * 3; i += 3) {
349         switch ((key->tc_gen >> i) & 0x7) {
350         case NINED3DTSS_TCI_CAMERASPACENORMAL:
351             need_aNrm = TRUE;
352             break;
353         case NINED3DTSS_TCI_CAMERASPACEPOSITION:
354             need_aVtx = TRUE;
355             break;
356         case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
357             need_aVtx = need_aNrm = TRUE;
358             break;
359         case NINED3DTSS_TCI_SPHEREMAP:
360             need_aVtx = need_aNrm = TRUE;
361             break;
362         default:
363             break;
364         }
365     }
366 
367     has_aNrm = need_aNrm && key->has_normal;
368 
369     /* Declare and record used inputs (needed for linkage with vertex format):
370      * (texture coordinates handled later)
371      */
372     vs->aVtx = build_vs_add_input(vs,
373         key->position_t ? NINE_DECLUSAGE_POSITIONT : NINE_DECLUSAGE_POSITION);
374 
375     vs->aNrm = ureg_imm1f(ureg, 0.0f);
376     if (has_aNrm)
377         vs->aNrm = build_vs_add_input(vs, NINE_DECLUSAGE_NORMAL);
378 
379     vs->aCol[0] = ureg_imm1f(ureg, 1.0f);
380     vs->aCol[1] = ureg_imm1f(ureg, 0.0f);
381 
382     if (key->lighting || key->darkness) {
383         const unsigned mask = key->mtl_diffuse | key->mtl_specular |
384                               key->mtl_ambient | key->mtl_emissive;
385         if ((mask & 0x1) && !key->color0in_one)
386             vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0));
387         if ((mask & 0x2) && !key->color1in_zero)
388             vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1));
389 
390         vs->mtlD = MATERIAL_CONST(1);
391         vs->mtlA = MATERIAL_CONST(2);
392         vs->mtlS = MATERIAL_CONST(3);
393         vs->mtlE = MATERIAL_CONST(5);
394         if (key->mtl_diffuse  == 1) vs->mtlD = vs->aCol[0]; else
395         if (key->mtl_diffuse  == 2) vs->mtlD = vs->aCol[1];
396         if (key->mtl_ambient  == 1) vs->mtlA = vs->aCol[0]; else
397         if (key->mtl_ambient  == 2) vs->mtlA = vs->aCol[1];
398         if (key->mtl_specular == 1) vs->mtlS = vs->aCol[0]; else
399         if (key->mtl_specular == 2) vs->mtlS = vs->aCol[1];
400         if (key->mtl_emissive == 1) vs->mtlE = vs->aCol[0]; else
401         if (key->mtl_emissive == 2) vs->mtlE = vs->aCol[1];
402     } else {
403         if (!key->color0in_one) vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0));
404         if (!key->color1in_zero) vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1));
405     }
406 
407     if (key->vertexpointsize)
408         vs->aPsz = build_vs_add_input(vs, NINE_DECLUSAGE_PSIZE);
409 
410     if (key->vertexblend_indexed || key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES))
411         vs->aInd = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDINDICES);
412     if (key->vertexblend || key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT))
413         vs->aWgt = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDWEIGHT);
414     if (key->vertextween) {
415         vs->aVtx1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(POSITION,1));
416         vs->aNrm1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(NORMAL,1));
417     }
418 
419     /* Declare outputs:
420      */
421     oPos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); /* HPOS */
422     oCol[0] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0));
423     oCol[1] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1));
424     if (key->fog || key->passthrough & (1 << NINE_DECLUSAGE_FOG)) {
425         oFog = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 16);
426         oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X);
427     }
428 
429     if (key->vertexpointsize || key->pointscale) {
430         oPsz = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_PSIZE, 0,
431                                        TGSI_WRITEMASK_X, 0, 1);
432         oPsz = ureg_writemask(oPsz, TGSI_WRITEMASK_X);
433     }
434 
435     if (key->lighting || key->vertexblend)
436         AR = ureg_DECL_address(ureg);
437 
438     /* === Vertex transformation / vertex blending:
439      */
440 
441     if (key->position_t) {
442         if (device->driver_caps.window_space_position_support) {
443             ureg_MOV(ureg, oPos, vs->aVtx);
444         } else {
445             struct ureg_dst tmp = ureg_DECL_temporary(ureg);
446             /* vs->aVtx contains the coordinates buffer wise.
447             * later in the pipeline, clipping, viewport and division
448             * by w (rhw = 1/w) are going to be applied, so do the reverse
449             * of these transformations (except clipping) to have the good
450             * position at the end.*/
451             ureg_MOV(ureg, tmp, vs->aVtx);
452             /* X from [X_min, X_min + width] to [-1, 1], same for Y. Z to [0, 1] */
453             ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), ureg_negate(_CONST(101)));
454             ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _CONST(100));
455             ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, -1.0f));
456             /* Y needs to be reversed */
457             ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_negate(ureg_src(tmp)));
458             /* Replace w by 1 if it equals to 0 */
459             ureg_CMP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_negate(ureg_abs(ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_W))),
460                      ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_W), ureg_imm1f(ureg, 1.0f));
461             /* inverse rhw */
462             ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), _W(tmp));
463             /* multiply X, Y, Z by w */
464             ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _W(tmp));
465             ureg_MOV(ureg, oPos, ureg_src(tmp));
466             ureg_release_temporary(ureg, tmp);
467         }
468     } else if (key->vertexblend) {
469         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
470         struct ureg_dst tmp2 = ureg_DECL_temporary(ureg);
471         struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg);
472         struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg);
473         struct ureg_dst sum_blendweights = ureg_DECL_temporary(ureg);
474         struct ureg_src cWM[4];
475 
476         for (i = 160; i <= 195; ++i)
477             ureg_DECL_constant(ureg, i);
478 
479         /* translate world matrix index to constant file index */
480         if (key->vertexblend_indexed) {
481             ureg_MAD(ureg, tmp, vs->aInd, ureg_imm1f(ureg, 4.0f), ureg_imm1f(ureg, 160.0f));
482             ureg_ARL(ureg, AR, ureg_src(tmp));
483         }
484 
485         ureg_MOV(ureg, aVtx_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f));
486         ureg_MOV(ureg, aNrm_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f));
487         ureg_MOV(ureg, sum_blendweights, ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f));
488 
489         for (i = 0; i < key->vertexblend; ++i) {
490             for (c = 0; c < 4; ++c) {
491                 cWM[c] = ureg_src_dimension(ureg_src_register(TGSI_FILE_CONSTANT, (160 + i * 4) * !key->vertexblend_indexed + c), 0);
492                 if (key->vertexblend_indexed)
493                     cWM[c] = ureg_src_indirect(cWM[c], ureg_scalar(ureg_src(AR), i));
494             }
495 
496             /* multiply by WORLD(index) */
497             ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), cWM[0]);
498             ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), cWM[1], ureg_src(tmp));
499             ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), cWM[2], ureg_src(tmp));
500             ureg_MAD(ureg, tmp, _WWWW(vs->aVtx), cWM[3], ureg_src(tmp));
501 
502             if (has_aNrm) {
503                 /* Note: the spec says the transpose of the inverse of the
504                  * WorldView matrices should be used, but all tests show
505                  * otherwise.
506                  * Only case unknown: D3DVBF_0WEIGHTS */
507                 ureg_MUL(ureg, tmp2, _XXXX(vs->aNrm), cWM[0]);
508                 ureg_MAD(ureg, tmp2, _YYYY(vs->aNrm), cWM[1], ureg_src(tmp2));
509                 ureg_MAD(ureg, tmp2, _ZZZZ(vs->aNrm), cWM[2], ureg_src(tmp2));
510             }
511 
512             if (i < (key->vertexblend - 1)) {
513                 /* accumulate weighted position value */
514                 ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(vs->aWgt, i), ureg_src(aVtx_dst));
515                 if (has_aNrm)
516                     ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(vs->aWgt, i), ureg_src(aNrm_dst));
517                 /* subtract weighted position value for last value */
518                 ureg_ADD(ureg, sum_blendweights, ureg_src(sum_blendweights), ureg_negate(ureg_scalar(vs->aWgt, i)));
519             }
520         }
521 
522         /* the last weighted position is always 1 - sum_of_previous_weights */
523         ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aVtx_dst));
524         if (has_aNrm)
525             ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aNrm_dst));
526 
527         /* multiply by VIEW_PROJ */
528         ureg_MUL(ureg, tmp, _X(aVtx_dst), _CONST(8));
529         ureg_MAD(ureg, tmp, _Y(aVtx_dst), _CONST(9),  ureg_src(tmp));
530         ureg_MAD(ureg, tmp, _Z(aVtx_dst), _CONST(10), ureg_src(tmp));
531         ureg_MAD(ureg, oPos, _W(aVtx_dst), _CONST(11), ureg_src(tmp));
532 
533         if (need_aVtx)
534             vs->aVtx = ureg_src(aVtx_dst);
535 
536         ureg_release_temporary(ureg, tmp);
537         ureg_release_temporary(ureg, tmp2);
538         ureg_release_temporary(ureg, sum_blendweights);
539         if (!need_aVtx)
540             ureg_release_temporary(ureg, aVtx_dst);
541 
542         if (has_aNrm) {
543             if (key->normalizenormals)
544                ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst));
545             vs->aNrm = ureg_src(aNrm_dst);
546         } else
547             ureg_release_temporary(ureg, aNrm_dst);
548     } else {
549         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
550 
551         if (key->vertextween) {
552             struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg);
553             ureg_LRP(ureg, aVtx_dst, _XXXX(_CONST(30)), vs->aVtx1, vs->aVtx);
554             vs->aVtx = ureg_src(aVtx_dst);
555             if (has_aNrm) {
556                 struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg);
557                 ureg_LRP(ureg, aNrm_dst, _XXXX(_CONST(30)), vs->aNrm1, vs->aNrm);
558                 vs->aNrm = ureg_src(aNrm_dst);
559             }
560         }
561 
562         /* position = vertex * WORLD_VIEW_PROJ */
563         ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(0));
564         ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(1), ureg_src(tmp));
565         ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(2), ureg_src(tmp));
566         ureg_MAD(ureg, oPos, _WWWW(vs->aVtx), _CONST(3), ureg_src(tmp));
567         ureg_release_temporary(ureg, tmp);
568 
569         if (need_aVtx) {
570             struct ureg_dst aVtx_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
571             ureg_MUL(ureg, aVtx_dst, _XXXX(vs->aVtx), _CONST(4));
572             ureg_MAD(ureg, aVtx_dst, _YYYY(vs->aVtx), _CONST(5), ureg_src(aVtx_dst));
573             ureg_MAD(ureg, aVtx_dst, _ZZZZ(vs->aVtx), _CONST(6), ureg_src(aVtx_dst));
574             ureg_MAD(ureg, aVtx_dst, _WWWW(vs->aVtx), _CONST(7), ureg_src(aVtx_dst));
575             vs->aVtx = ureg_src(aVtx_dst);
576         }
577         if (has_aNrm) {
578             struct ureg_dst aNrm_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
579             ureg_MUL(ureg, aNrm_dst, _XXXX(vs->aNrm), _CONST(16));
580             ureg_MAD(ureg, aNrm_dst, _YYYY(vs->aNrm), _CONST(17), ureg_src(aNrm_dst));
581             ureg_MAD(ureg, aNrm_dst, _ZZZZ(vs->aNrm), _CONST(18), ureg_src(aNrm_dst));
582             if (key->normalizenormals)
583                ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst));
584             vs->aNrm = ureg_src(aNrm_dst);
585         }
586     }
587 
588     /* === Process point size:
589      */
590     if (key->vertexpointsize || key->pointscale) {
591         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
592         struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
593         struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
594         struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z);
595         if (key->vertexpointsize) {
596             struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
597             ureg_MAX(ureg, tmp_z, _XXXX(vs->aPsz), _XXXX(cPsz1));
598             ureg_MIN(ureg, tmp_z, _Z(tmp), _YYYY(cPsz1));
599         } else {
600             struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
601             ureg_MOV(ureg, tmp_z, _ZZZZ(cPsz1));
602         }
603 
604         if (key->pointscale) {
605             struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
606             struct ureg_src cPsz2 = ureg_DECL_constant(ureg, 27);
607 
608             ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx);
609             ureg_RSQ(ureg, tmp_y, _X(tmp));
610             ureg_MUL(ureg, tmp_y, _Y(tmp), _X(tmp));
611             ureg_CMP(ureg, tmp_y, ureg_negate(_Y(tmp)), _Y(tmp), ureg_imm1f(ureg, 0.0f));
612             ureg_MAD(ureg, tmp_x, _Y(tmp), _YYYY(cPsz2), _XXXX(cPsz2));
613             ureg_MAD(ureg, tmp_x, _Y(tmp), _X(tmp), _WWWW(cPsz1));
614             ureg_RSQ(ureg, tmp_x, _X(tmp));
615             ureg_MUL(ureg, tmp_x, _X(tmp), _Z(tmp));
616             ureg_MUL(ureg, tmp_x, _X(tmp), _WWWW(_CONST(100)));
617             ureg_MAX(ureg, tmp_x, _X(tmp), _XXXX(cPsz1));
618             ureg_MIN(ureg, tmp_z, _X(tmp), _YYYY(cPsz1));
619         }
620 
621         ureg_MOV(ureg, oPsz, _Z(tmp));
622         ureg_release_temporary(ureg, tmp);
623     }
624 
625     for (i = 0; i < 8; ++i) {
626         struct ureg_dst tmp, tmp_x, tmp2;
627         struct ureg_dst oTex, input_coord, transformed, t, aVtx_normed;
628         unsigned c, writemask;
629         const unsigned tci = (key->tc_gen >> (i * 3)) & 0x7;
630         const unsigned idx = (key->tc_idx >> (i * 3)) & 0x7;
631         unsigned dim_input = 1 + ((key->tc_dim_input >> (i * 2)) & 0x3);
632         const unsigned dim_output = (key->tc_dim_output >> (i * 3)) & 0x7;
633 
634         /* No texture output of index s */
635         if (tci == NINED3DTSS_TCI_DISABLE)
636             continue;
637         oTex = ureg_DECL_output(ureg, texcoord_sn, i);
638         tmp = ureg_DECL_temporary(ureg);
639         tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
640         input_coord = ureg_DECL_temporary(ureg);
641         transformed = ureg_DECL_temporary(ureg);
642 
643         /* Get the coordinate */
644         switch (tci) {
645         case NINED3DTSS_TCI_PASSTHRU:
646             /* NINED3DTSS_TCI_PASSTHRU => Use texcoord coming from index idx *
647              * Else the idx is used only to determine wrapping mode. */
648             vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_i(TEXCOORD,idx));
649             ureg_MOV(ureg, input_coord, vs->aTex[idx]);
650             break;
651         case NINED3DTSS_TCI_CAMERASPACENORMAL:
652             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aNrm);
653             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
654             dim_input = 4;
655             break;
656         case NINED3DTSS_TCI_CAMERASPACEPOSITION:
657             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aVtx);
658             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
659             dim_input = 4;
660             break;
661         case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
662             tmp.WriteMask = TGSI_WRITEMASK_XYZ;
663             aVtx_normed = ureg_DECL_temporary(ureg);
664             ureg_normalize3(ureg, aVtx_normed, vs->aVtx);
665             ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm);
666             ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp));
667             ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp));
668             ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp)));
669             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
670             ureg_release_temporary(ureg, aVtx_normed);
671             dim_input = 4;
672             tmp.WriteMask = TGSI_WRITEMASK_XYZW;
673             break;
674         case NINED3DTSS_TCI_SPHEREMAP:
675             /* Implement the formula of GL_SPHERE_MAP */
676             tmp.WriteMask = TGSI_WRITEMASK_XYZ;
677             aVtx_normed = ureg_DECL_temporary(ureg);
678             tmp2 = ureg_DECL_temporary(ureg);
679             ureg_normalize3(ureg, aVtx_normed, vs->aVtx);
680             ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm);
681             ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp));
682             ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp));
683             ureg_ADD(ureg, tmp, ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp)));
684             /* now tmp = normed(Vtx) - 2 dot3(normed(Vtx), Nrm) Nrm */
685             ureg_MOV(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_XYZ), ureg_src(tmp));
686             ureg_MUL(ureg, tmp2, ureg_src(tmp2), ureg_src(tmp2));
687             ureg_DP3(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_src(tmp2));
688             ureg_RSQ(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2));
689             ureg_MUL(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_imm1f(ureg, 0.5f));
690             /* tmp2 = 0.5 / sqrt(tmp.x^2 + tmp.y^2 + (tmp.z+1)^2)
691              * TODO: z coordinates are a bit different gl vs d3d, should the formula be adapted ? */
692             ureg_MUL(ureg, tmp, ureg_src(tmp), _X(tmp2));
693             ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, 0.5f));
694             ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_ZW), ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f));
695             ureg_release_temporary(ureg, aVtx_normed);
696             ureg_release_temporary(ureg, tmp2);
697             dim_input = 4;
698             tmp.WriteMask = TGSI_WRITEMASK_XYZW;
699             break;
700         default:
701             assert(0);
702             break;
703         }
704 
705         /* Apply the transformation */
706         /* dim_output == 0 => do not transform the components.
707          * XYZRHW also disables transformation */
708         if (!dim_output || key->position_t) {
709             ureg_release_temporary(ureg, transformed);
710             transformed = input_coord;
711             writemask = TGSI_WRITEMASK_XYZW;
712         } else {
713             for (c = 0; c < dim_output; c++) {
714                 t = ureg_writemask(transformed, 1 << c);
715                 switch (dim_input) {
716                 /* dim_input = 1 2 3: -> we add trailing 1 to input*/
717                 case 1: ureg_MAD(ureg, t, _X(input_coord), _XXXX(_CONST(128 + i * 4 + c)), _YYYY(_CONST(128 + i * 4 + c)));
718                         break;
719                 case 2: ureg_DP2(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c));
720                         ureg_ADD(ureg, t, ureg_src(transformed), _ZZZZ(_CONST(128 + i * 4 + c)));
721                         break;
722                 case 3: ureg_DP3(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c));
723                         ureg_ADD(ureg, t, ureg_src(transformed), _WWWW(_CONST(128 + i * 4 + c)));
724                         break;
725                 case 4: ureg_DP4(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); break;
726                 default:
727                     assert(0);
728                 }
729             }
730             writemask = (1 << dim_output) - 1;
731             ureg_release_temporary(ureg, input_coord);
732         }
733 
734         ureg_MOV(ureg, ureg_writemask(oTex, writemask), ureg_src(transformed));
735         ureg_release_temporary(ureg, transformed);
736         ureg_release_temporary(ureg, tmp);
737     }
738 
739     /* === Lighting:
740      *
741      * DIRECTIONAL:  Light at infinite distance, parallel rays, no attenuation.
742      * POINT: Finite distance to scene, divergent rays, isotropic, attenuation.
743      * SPOT: Finite distance, divergent rays, angular dependence, attenuation.
744      *
745      * vec3 normal = normalize(in.Normal * NormalMatrix);
746      * vec3 hitDir = light.direction;
747      * float atten = 1.0;
748      *
749      * if (light.type != DIRECTIONAL)
750      * {
751      *     vec3 hitVec = light.position - eyeVertex;
752      *     float d = length(hitVec);
753      *     hitDir = hitVec / d;
754      *     atten = 1 / ((light.atten2 * d + light.atten1) * d + light.atten0);
755      * }
756      *
757      * if (light.type == SPOTLIGHT)
758      * {
759      *     float rho = dp3(-hitVec, light.direction);
760      *     if (rho < cos(light.phi / 2))
761      *         atten = 0;
762      *     if (rho < cos(light.theta / 2))
763      *         atten *= pow(some_func(rho), light.falloff);
764      * }
765      *
766      * float nDotHit = dp3_sat(normal, hitVec);
767      * float powFact = 0.0;
768      *
769      * if (nDotHit > 0.0)
770      * {
771      *     vec3 midVec = normalize(hitDir + eye);
772      *     float nDotMid = dp3_sat(normal, midVec);
773      *     pFact = pow(nDotMid, material.power);
774      * }
775      *
776      * ambient += light.ambient * atten;
777      * diffuse += light.diffuse * atten * nDotHit;
778      * specular += light.specular * atten * powFact;
779      */
780     if (key->lighting) {
781         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
782         struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
783         struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
784         struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z);
785         struct ureg_dst rAtt = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W);
786         struct ureg_dst rHit = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
787         struct ureg_dst rMid = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
788 
789         struct ureg_dst rCtr = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W);
790 
791         struct ureg_dst AL = ureg_writemask(AR, TGSI_WRITEMASK_X);
792 
793         /* Light.*.Alpha is not used. */
794         struct ureg_dst rD = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
795         struct ureg_dst rA = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ);
796         struct ureg_dst rS = ureg_DECL_temporary(ureg);
797 
798         struct ureg_src mtlP = _XXXX(MATERIAL_CONST(4));
799 
800         struct ureg_src cLKind = _XXXX(LIGHT_CONST(0));
801         struct ureg_src cLAtt0 = _YYYY(LIGHT_CONST(0));
802         struct ureg_src cLAtt1 = _ZZZZ(LIGHT_CONST(0));
803         struct ureg_src cLAtt2 = _WWWW(LIGHT_CONST(0));
804         struct ureg_src cLColD = _XYZW(LIGHT_CONST(1));
805         struct ureg_src cLColS = _XYZW(LIGHT_CONST(2));
806         struct ureg_src cLColA = _XYZW(LIGHT_CONST(3));
807         struct ureg_src cLPos  = _XYZW(LIGHT_CONST(4));
808         struct ureg_src cLRng  = _WWWW(LIGHT_CONST(4));
809         struct ureg_src cLDir  = _XYZW(LIGHT_CONST(5));
810         struct ureg_src cLFOff = _WWWW(LIGHT_CONST(5));
811         struct ureg_src cLTht  = _XXXX(LIGHT_CONST(6));
812         struct ureg_src cLPhi  = _YYYY(LIGHT_CONST(6));
813         struct ureg_src cLSDiv = _ZZZZ(LIGHT_CONST(6));
814         struct ureg_src cLLast = _WWWW(LIGHT_CONST(7));
815 
816         const unsigned loop_label = l++;
817 
818         /* Declare all light constants to allow indirect adressing */
819         for (i = 32; i < 96; i++)
820             ureg_DECL_constant(ureg, i);
821 
822         ureg_MOV(ureg, rCtr, ureg_imm1f(ureg, 32.0f)); /* &lightconst(0) */
823         ureg_MOV(ureg, rD, ureg_imm1f(ureg, 0.0f));
824         ureg_MOV(ureg, rA, ureg_imm1f(ureg, 0.0f));
825         ureg_MOV(ureg, rS, ureg_imm1f(ureg, 0.0f));
826 
827         /* loop management */
828         ureg_BGNLOOP(ureg, &label[loop_label]);
829         ureg_ARL(ureg, AL, _W(rCtr));
830 
831         /* if (not DIRECTIONAL light): */
832         ureg_SNE(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_DIRECTIONAL));
833         ureg_MOV(ureg, rHit, ureg_negate(cLDir));
834         ureg_MOV(ureg, rAtt, ureg_imm1f(ureg, 1.0f));
835         ureg_IF(ureg, _X(tmp), &label[l++]);
836         {
837             /* hitDir = light.position - eyeVtx
838              * d = length(hitDir)
839              */
840             ureg_ADD(ureg, rHit, cLPos, ureg_negate(vs->aVtx));
841             ureg_DP3(ureg, tmp_x, ureg_src(rHit), ureg_src(rHit));
842             ureg_RSQ(ureg, tmp_y, _X(tmp));
843             ureg_MUL(ureg, tmp_x, _X(tmp), _Y(tmp)); /* length */
844 
845             /* att = 1.0 / (light.att0 + (light.att1 + light.att2 * d) * d) */
846             ureg_MAD(ureg, rAtt, _X(tmp), cLAtt2, cLAtt1);
847             ureg_MAD(ureg, rAtt, _X(tmp), _W(rAtt), cLAtt0);
848             ureg_RCP(ureg, rAtt, _W(rAtt));
849             /* cut-off if distance exceeds Light.Range */
850             ureg_SLT(ureg, tmp_x, _X(tmp), cLRng);
851             ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp));
852         }
853         ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
854         ureg_ENDIF(ureg);
855 
856         /* normalize hitDir */
857         ureg_normalize3(ureg, rHit, ureg_src(rHit));
858 
859         /* if (SPOT light) */
860         ureg_SEQ(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_SPOT));
861         ureg_IF(ureg, _X(tmp), &label[l++]);
862         {
863             /* rho = dp3(-hitDir, light.spotDir)
864              *
865              * if (rho  > light.ctht2) NOTE: 0 <= phi <= pi, 0 <= theta <= phi
866              *     spotAtt = 1
867              * else
868              * if (rho <= light.cphi2)
869              *     spotAtt = 0
870              * else
871              *     spotAtt = (rho - light.cphi2) / (light.ctht2 - light.cphi2) ^ light.falloff
872              */
873             ureg_DP3(ureg, tmp_y, ureg_negate(ureg_src(rHit)), cLDir); /* rho */
874             ureg_ADD(ureg, tmp_x, _Y(tmp), ureg_negate(cLPhi));
875             ureg_MUL(ureg, tmp_x, _X(tmp), cLSDiv);
876             ureg_POW(ureg, tmp_x, _X(tmp), cLFOff); /* spotAtten */
877             ureg_SGE(ureg, tmp_z, _Y(tmp), cLTht); /* if inside theta && phi */
878             ureg_SGE(ureg, tmp_y, _Y(tmp), cLPhi); /* if inside phi */
879             ureg_MAD(ureg, ureg_saturate(tmp_x), _X(tmp), _Y(tmp), _Z(tmp));
880             ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp));
881         }
882         ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
883         ureg_ENDIF(ureg);
884 
885         /* directional factors, let's not use LIT because of clarity */
886 
887         if (has_aNrm) {
888             if (key->localviewer) {
889                 ureg_normalize3(ureg, rMid, vs->aVtx);
890                 ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_negate(ureg_src(rMid)));
891             } else {
892                 ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_imm3f(ureg, 0.0f, 0.0f, -1.0f));
893             }
894             ureg_normalize3(ureg, rMid, ureg_src(rMid));
895             ureg_DP3(ureg, ureg_saturate(tmp_x), vs->aNrm, ureg_src(rHit));
896             ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid));
897             ureg_MUL(ureg, tmp_z, _X(tmp), _Y(tmp));
898             /* Tests show that specular is computed only if (dp3(normal,hitDir) > 0).
899              * For front facing, it is more restrictive than test (dp3(normal,mid) > 0).
900              * No tests were made for backfacing, so add the two conditions */
901             ureg_IF(ureg, _Z(tmp), &label[l++]);
902             {
903                 ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid));
904                 ureg_POW(ureg, tmp_y, _Y(tmp), mtlP);
905                 ureg_MUL(ureg, tmp_y, _W(rAtt), _Y(tmp)); /* power factor * att */
906                 ureg_MAD(ureg, rS, cLColS, _Y(tmp), ureg_src(rS)); /* accumulate specular */
907             }
908             ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
909             ureg_ENDIF(ureg);
910 
911             ureg_MUL(ureg, tmp_x, _W(rAtt), _X(tmp)); /* dp3(normal,hitDir) * att */
912             ureg_MAD(ureg, rD, cLColD, _X(tmp), ureg_src(rD)); /* accumulate diffuse */
913         }
914 
915         ureg_MAD(ureg, rA, cLColA, _W(rAtt), ureg_src(rA)); /* accumulate ambient */
916 
917         /* break if this was the last light */
918         ureg_IF(ureg, cLLast, &label[l++]);
919         ureg_BRK(ureg);
920         ureg_ENDIF(ureg);
921         ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg));
922 
923         ureg_ADD(ureg, rCtr, _W(rCtr), ureg_imm1f(ureg, 8.0f));
924         ureg_fixup_label(ureg, label[loop_label], ureg_get_instruction_number(ureg));
925         ureg_ENDLOOP(ureg, &label[loop_label]);
926 
927         /* Apply to material:
928          *
929          * oCol[0] = (material.emissive + material.ambient * rs.ambient) +
930          *           material.ambient * ambient +
931          *           material.diffuse * diffuse +
932          * oCol[1] = material.specular * specular;
933          */
934         if (key->mtl_emissive == 0 && key->mtl_ambient == 0)
935             ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), vs->mtlA, _CONST(19));
936         else {
937             ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), _CONST(25));
938             ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), vs->mtlA, ureg_src(tmp), vs->mtlE);
939         }
940 
941         ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), ureg_src(rD), vs->mtlD, ureg_src(tmp));
942         ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD);
943         ureg_MUL(ureg, oCol[1], ureg_src(rS), vs->mtlS);
944         ureg_release_temporary(ureg, rAtt);
945         ureg_release_temporary(ureg, rHit);
946         ureg_release_temporary(ureg, rMid);
947         ureg_release_temporary(ureg, rCtr);
948         ureg_release_temporary(ureg, rD);
949         ureg_release_temporary(ureg, rA);
950         ureg_release_temporary(ureg, rS);
951         ureg_release_temporary(ureg, rAtt);
952         ureg_release_temporary(ureg, tmp);
953     } else
954     /* COLOR */
955     if (key->darkness) {
956         if (key->mtl_emissive == 0 && key->mtl_ambient == 0)
957             ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), _CONST(19));
958         else
959             ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE);
960         ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD);
961         ureg_MOV(ureg, oCol[1], ureg_imm1f(ureg, 0.0f));
962     } else {
963         ureg_MOV(ureg, oCol[0], vs->aCol[0]);
964         ureg_MOV(ureg, oCol[1], vs->aCol[1]);
965     }
966 
967     /* === Process fog.
968      *
969      * exp(x) = ex2(log2(e) * x)
970      */
971     if (key->fog_mode) {
972         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
973         struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
974         struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z);
975         if (key->fog_range) {
976             ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx);
977             ureg_RSQ(ureg, tmp_z, _X(tmp));
978             ureg_MUL(ureg, tmp_z, _Z(tmp), _X(tmp));
979         } else {
980             ureg_MOV(ureg, tmp_z, ureg_abs(_ZZZZ(vs->aVtx)));
981         }
982 
983         if (key->fog_mode == D3DFOG_EXP) {
984             ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28)));
985             ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f));
986             ureg_EX2(ureg, tmp_x, _X(tmp));
987         } else
988         if (key->fog_mode == D3DFOG_EXP2) {
989             ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28)));
990             ureg_MUL(ureg, tmp_x, _X(tmp), _X(tmp));
991             ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f));
992             ureg_EX2(ureg, tmp_x, _X(tmp));
993         } else
994         if (key->fog_mode == D3DFOG_LINEAR) {
995             ureg_ADD(ureg, tmp_x, _XXXX(_CONST(28)), ureg_negate(_Z(tmp)));
996             ureg_MUL(ureg, ureg_saturate(tmp_x), _X(tmp), _YYYY(_CONST(28)));
997         }
998         ureg_MOV(ureg, oFog, _X(tmp));
999         ureg_release_temporary(ureg, tmp);
1000     } else if (key->fog && !(key->passthrough & (1 << NINE_DECLUSAGE_FOG))) {
1001         ureg_MOV(ureg, oFog, ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W));
1002     }
1003 
1004     if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) {
1005         struct ureg_src input;
1006         struct ureg_dst output;
1007         input = vs->aWgt;
1008         output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 19);
1009         ureg_MOV(ureg, output, input);
1010     }
1011     if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) {
1012         struct ureg_src input;
1013         struct ureg_dst output;
1014         input = vs->aInd;
1015         output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 20);
1016         ureg_MOV(ureg, output, input);
1017     }
1018     if (key->passthrough & (1 << NINE_DECLUSAGE_NORMAL)) {
1019         struct ureg_src input;
1020         struct ureg_dst output;
1021         input = vs->aNrm;
1022         output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 21);
1023         ureg_MOV(ureg, output, input);
1024     }
1025     if (key->passthrough & (1 << NINE_DECLUSAGE_TANGENT)) {
1026         struct ureg_src input;
1027         struct ureg_dst output;
1028         input = build_vs_add_input(vs, NINE_DECLUSAGE_TANGENT);
1029         output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 22);
1030         ureg_MOV(ureg, output, input);
1031     }
1032     if (key->passthrough & (1 << NINE_DECLUSAGE_BINORMAL)) {
1033         struct ureg_src input;
1034         struct ureg_dst output;
1035         input = build_vs_add_input(vs, NINE_DECLUSAGE_BINORMAL);
1036         output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 23);
1037         ureg_MOV(ureg, output, input);
1038     }
1039     if (key->passthrough & (1 << NINE_DECLUSAGE_FOG)) {
1040         struct ureg_src input;
1041         struct ureg_dst output;
1042         input = build_vs_add_input(vs, NINE_DECLUSAGE_FOG);
1043         input = ureg_scalar(input, TGSI_SWIZZLE_X);
1044         output = oFog;
1045         ureg_MOV(ureg, output, input);
1046     }
1047     if (key->passthrough & (1 << NINE_DECLUSAGE_DEPTH)) {
1048         (void) 0; /* TODO: replace z of position output ? */
1049     }
1050 
1051     /* ucp for ff applies on world coordinates.
1052      * aVtx is in worldview coordinates. */
1053     if (key->ucp) {
1054         struct ureg_dst clipVect = ureg_DECL_output(ureg, TGSI_SEMANTIC_CLIPVERTEX, 0);
1055         struct ureg_dst tmp = ureg_DECL_temporary(ureg);
1056         ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(12));
1057         ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(13),  ureg_src(tmp));
1058         ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(14), ureg_src(tmp));
1059         ureg_ADD(ureg, clipVect, _CONST(15), ureg_src(tmp));
1060         ureg_release_temporary(ureg, tmp);
1061     }
1062 
1063     if (key->position_t && device->driver_caps.window_space_position_support)
1064         ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
1065 
1066     ureg_END(ureg);
1067     nine_ureg_tgsi_dump(ureg, FALSE);
1068     return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL);
1069 }
1070 
1071 /* PS FF constants layout:
1072  *
1073  * CONST[ 0.. 7]      stage[i].D3DTSS_CONSTANT
1074  * CONST[ 8..15].x___ stage[i].D3DTSS_BUMPENVMAT00
1075  * CONST[ 8..15]._y__ stage[i].D3DTSS_BUMPENVMAT01
1076  * CONST[ 8..15].__z_ stage[i].D3DTSS_BUMPENVMAT10
1077  * CONST[ 8..15].___w stage[i].D3DTSS_BUMPENVMAT11
1078  * CONST[16..19].x_z_ stage[i].D3DTSS_BUMPENVLSCALE
1079  * CONST[17..19]._y_w stage[i].D3DTSS_BUMPENVLOFFSET
1080  *
1081  * CONST[20] D3DRS_TEXTUREFACTOR
1082  * CONST[21] D3DRS_FOGCOLOR
1083  * CONST[22].x___ RS.FogEnd
1084  * CONST[22]._y__ 1.0f / (RS.FogEnd - RS.FogStart)
1085  * CONST[22].__z_ RS.FogDensity
1086  */
1087 struct ps_build_ctx
1088 {
1089     struct ureg_program *ureg;
1090 
1091     struct ureg_src vC[2]; /* DIFFUSE, SPECULAR */
1092     struct ureg_src vT[8]; /* TEXCOORD[i] */
1093     struct ureg_dst rCur; /* D3DTA_CURRENT */
1094     struct ureg_dst rMod;
1095     struct ureg_src rCurSrc;
1096     struct ureg_dst rTmp; /* D3DTA_TEMP */
1097     struct ureg_src rTmpSrc;
1098     struct ureg_dst rTex;
1099     struct ureg_src rTexSrc;
1100     struct ureg_src cBEM[8];
1101     struct ureg_src s[8];
1102 
1103     struct {
1104         unsigned index;
1105         unsigned index_pre_mod;
1106     } stage;
1107 };
1108 
1109 static struct ureg_src
ps_get_ts_arg(struct ps_build_ctx * ps,unsigned ta)1110 ps_get_ts_arg(struct ps_build_ctx *ps, unsigned ta)
1111 {
1112     struct ureg_src reg;
1113 
1114     switch (ta & D3DTA_SELECTMASK) {
1115     case D3DTA_CONSTANT:
1116         reg = ureg_DECL_constant(ps->ureg, ps->stage.index);
1117         break;
1118     case D3DTA_CURRENT:
1119         reg = (ps->stage.index == ps->stage.index_pre_mod) ? ureg_src(ps->rMod) : ps->rCurSrc;
1120         break;
1121     case D3DTA_DIFFUSE:
1122         reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR);
1123         break;
1124     case D3DTA_SPECULAR:
1125         reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR);
1126         break;
1127     case D3DTA_TEMP:
1128         reg = ps->rTmpSrc;
1129         break;
1130     case D3DTA_TEXTURE:
1131         reg = ps->rTexSrc;
1132         break;
1133     case D3DTA_TFACTOR:
1134         reg = ureg_DECL_constant(ps->ureg, 20);
1135         break;
1136     default:
1137         assert(0);
1138         reg = ureg_src_undef();
1139         break;
1140     }
1141     if (ta & D3DTA_COMPLEMENT) {
1142         struct ureg_dst dst = ureg_DECL_temporary(ps->ureg);
1143         ureg_ADD(ps->ureg, dst, ureg_imm1f(ps->ureg, 1.0f), ureg_negate(reg));
1144         reg = ureg_src(dst);
1145     }
1146     if (ta & D3DTA_ALPHAREPLICATE)
1147         reg = _WWWW(reg);
1148     return reg;
1149 }
1150 
1151 static struct ureg_dst
ps_get_ts_dst(struct ps_build_ctx * ps,unsigned ta)1152 ps_get_ts_dst(struct ps_build_ctx *ps, unsigned ta)
1153 {
1154     assert(!(ta & (D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE)));
1155 
1156     switch (ta & D3DTA_SELECTMASK) {
1157     case D3DTA_CURRENT:
1158         return ps->rCur;
1159     case D3DTA_TEMP:
1160         return ps->rTmp;
1161     default:
1162         assert(0);
1163         return ureg_dst_undef();
1164     }
1165 }
1166 
ps_d3dtop_args_mask(D3DTEXTUREOP top)1167 static uint8_t ps_d3dtop_args_mask(D3DTEXTUREOP top)
1168 {
1169     switch (top) {
1170     case D3DTOP_DISABLE:
1171         return 0x0;
1172     case D3DTOP_SELECTARG1:
1173     case D3DTOP_PREMODULATE:
1174         return 0x2;
1175     case D3DTOP_SELECTARG2:
1176         return 0x4;
1177     case D3DTOP_MULTIPLYADD:
1178     case D3DTOP_LERP:
1179         return 0x7;
1180     default:
1181         return 0x6;
1182     }
1183 }
1184 
1185 static inline boolean
is_MOV_no_op(struct ureg_dst dst,struct ureg_src src)1186 is_MOV_no_op(struct ureg_dst dst, struct ureg_src src)
1187 {
1188     return !dst.WriteMask ||
1189         (dst.File == src.File &&
1190          dst.Index == src.Index &&
1191          !dst.Indirect &&
1192          !dst.Saturate &&
1193          !src.Indirect &&
1194          !src.Negate &&
1195          !src.Absolute &&
1196          (!(dst.WriteMask & TGSI_WRITEMASK_X) || (src.SwizzleX == TGSI_SWIZZLE_X)) &&
1197          (!(dst.WriteMask & TGSI_WRITEMASK_Y) || (src.SwizzleY == TGSI_SWIZZLE_Y)) &&
1198          (!(dst.WriteMask & TGSI_WRITEMASK_Z) || (src.SwizzleZ == TGSI_SWIZZLE_Z)) &&
1199          (!(dst.WriteMask & TGSI_WRITEMASK_W) || (src.SwizzleW == TGSI_SWIZZLE_W)));
1200 
1201 }
1202 
1203 static void
ps_do_ts_op(struct ps_build_ctx * ps,unsigned top,struct ureg_dst dst,struct ureg_src * arg)1204 ps_do_ts_op(struct ps_build_ctx *ps, unsigned top, struct ureg_dst dst, struct ureg_src *arg)
1205 {
1206     struct ureg_program *ureg = ps->ureg;
1207     struct ureg_dst tmp = ureg_DECL_temporary(ureg);
1208     struct ureg_dst tmp2 = ureg_DECL_temporary(ureg);
1209     struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
1210 
1211     tmp.WriteMask = dst.WriteMask;
1212 
1213     if (top != D3DTOP_SELECTARG1 && top != D3DTOP_SELECTARG2 &&
1214         top != D3DTOP_MODULATE && top != D3DTOP_PREMODULATE &&
1215         top != D3DTOP_BLENDDIFFUSEALPHA && top != D3DTOP_BLENDTEXTUREALPHA &&
1216         top != D3DTOP_BLENDFACTORALPHA && top != D3DTOP_BLENDCURRENTALPHA &&
1217         top != D3DTOP_BUMPENVMAP && top != D3DTOP_BUMPENVMAPLUMINANCE &&
1218         top != D3DTOP_LERP)
1219         dst = ureg_saturate(dst);
1220 
1221     switch (top) {
1222     case D3DTOP_SELECTARG1:
1223         if (!is_MOV_no_op(dst, arg[1]))
1224             ureg_MOV(ureg, dst, arg[1]);
1225         break;
1226     case D3DTOP_SELECTARG2:
1227         if (!is_MOV_no_op(dst, arg[2]))
1228             ureg_MOV(ureg, dst, arg[2]);
1229         break;
1230     case D3DTOP_MODULATE:
1231         ureg_MUL(ureg, dst, arg[1], arg[2]);
1232         break;
1233     case D3DTOP_MODULATE2X:
1234         ureg_MUL(ureg, tmp, arg[1], arg[2]);
1235         ureg_ADD(ureg, dst, ureg_src(tmp), ureg_src(tmp));
1236         break;
1237     case D3DTOP_MODULATE4X:
1238         ureg_MUL(ureg, tmp, arg[1], arg[2]);
1239         ureg_MUL(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 4.0f));
1240         break;
1241     case D3DTOP_ADD:
1242         ureg_ADD(ureg, dst, arg[1], arg[2]);
1243         break;
1244     case D3DTOP_ADDSIGNED:
1245         ureg_ADD(ureg, tmp, arg[1], arg[2]);
1246         ureg_ADD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, -0.5f));
1247         break;
1248     case D3DTOP_ADDSIGNED2X:
1249         ureg_ADD(ureg, tmp, arg[1], arg[2]);
1250         ureg_MAD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f));
1251         break;
1252     case D3DTOP_SUBTRACT:
1253         ureg_ADD(ureg, dst, arg[1], ureg_negate(arg[2]));
1254         break;
1255     case D3DTOP_ADDSMOOTH:
1256         ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1]));
1257         ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], arg[1]);
1258         break;
1259     case D3DTOP_BLENDDIFFUSEALPHA:
1260         ureg_LRP(ureg, dst, _WWWW(ps->vC[0]), arg[1], arg[2]);
1261         break;
1262     case D3DTOP_BLENDTEXTUREALPHA:
1263         /* XXX: alpha taken from previous stage, texture or result ? */
1264         ureg_LRP(ureg, dst, _W(ps->rTex), arg[1], arg[2]);
1265         break;
1266     case D3DTOP_BLENDFACTORALPHA:
1267         ureg_LRP(ureg, dst, _WWWW(_CONST(20)), arg[1], arg[2]);
1268         break;
1269     case D3DTOP_BLENDTEXTUREALPHAPM:
1270         ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_W(ps->rTex)));
1271         ureg_MAD(ureg, dst, arg[2], _X(tmp), arg[1]);
1272         break;
1273     case D3DTOP_BLENDCURRENTALPHA:
1274         ureg_LRP(ureg, dst, _WWWW(ps->rCurSrc), arg[1], arg[2]);
1275         break;
1276     case D3DTOP_PREMODULATE:
1277         ureg_MOV(ureg, dst, arg[1]);
1278         ps->stage.index_pre_mod = ps->stage.index + 1;
1279         break;
1280     case D3DTOP_MODULATEALPHA_ADDCOLOR:
1281         ureg_MAD(ureg, dst, _WWWW(arg[1]), arg[2], arg[1]);
1282         break;
1283     case D3DTOP_MODULATECOLOR_ADDALPHA:
1284         ureg_MAD(ureg, dst, arg[1], arg[2], _WWWW(arg[1]));
1285         break;
1286     case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
1287         ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_WWWW(arg[1])));
1288         ureg_MAD(ureg, dst, _X(tmp), arg[2], arg[1]);
1289         break;
1290     case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
1291         ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1]));
1292         ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], _WWWW(arg[1]));
1293         break;
1294     case D3DTOP_BUMPENVMAP:
1295         break;
1296     case D3DTOP_BUMPENVMAPLUMINANCE:
1297         break;
1298     case D3DTOP_DOTPRODUCT3:
1299         ureg_ADD(ureg, tmp, arg[1], ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5));
1300         ureg_ADD(ureg, tmp2, arg[2] , ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5));
1301         ureg_DP3(ureg, tmp, ureg_src(tmp), ureg_src(tmp2));
1302         ureg_MUL(ureg, ureg_saturate(dst), ureg_src(tmp), ureg_imm4f(ureg,4.0,4.0,4.0,4.0));
1303         break;
1304     case D3DTOP_MULTIPLYADD:
1305         ureg_MAD(ureg, dst, arg[1], arg[2], arg[0]);
1306         break;
1307     case D3DTOP_LERP:
1308         ureg_LRP(ureg, dst, arg[0], arg[1], arg[2]);
1309         break;
1310     case D3DTOP_DISABLE:
1311         /* no-op ? */
1312         break;
1313     default:
1314         assert(!"invalid D3DTOP");
1315         break;
1316     }
1317     ureg_release_temporary(ureg, tmp);
1318     ureg_release_temporary(ureg, tmp2);
1319 }
1320 
1321 static void *
nine_ff_build_ps(struct NineDevice9 * device,struct nine_ff_ps_key * key)1322 nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key)
1323 {
1324     struct ps_build_ctx ps;
1325     struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT);
1326     struct ureg_dst oCol;
1327     unsigned s;
1328     const unsigned texcoord_sn = get_texcoord_sn(device->screen);
1329 
1330     memset(&ps, 0, sizeof(ps));
1331     ps.ureg = ureg;
1332     ps.stage.index_pre_mod = -1;
1333 
1334     ps.vC[0] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR);
1335 
1336     ps.rCur = ureg_DECL_temporary(ureg);
1337     ps.rTmp = ureg_DECL_temporary(ureg);
1338     ps.rTex = ureg_DECL_temporary(ureg);
1339     ps.rCurSrc = ureg_src(ps.rCur);
1340     ps.rTmpSrc = ureg_src(ps.rTmp);
1341     ps.rTexSrc = ureg_src(ps.rTex);
1342 
1343     /* Initial values */
1344     ureg_MOV(ureg, ps.rCur, ps.vC[0]);
1345     ureg_MOV(ureg, ps.rTmp, ureg_imm1f(ureg, 0.0f));
1346     ureg_MOV(ureg, ps.rTex, ureg_imm1f(ureg, 0.0f));
1347 
1348     for (s = 0; s < 8; ++s) {
1349         ps.s[s] = ureg_src_undef();
1350 
1351         if (key->ts[s].colorop != D3DTOP_DISABLE) {
1352             if (key->ts[s].colorarg0 == D3DTA_SPECULAR ||
1353                 key->ts[s].colorarg1 == D3DTA_SPECULAR ||
1354                 key->ts[s].colorarg2 == D3DTA_SPECULAR)
1355                 ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR);
1356 
1357             if (key->ts[s].colorarg0 == D3DTA_TEXTURE ||
1358                 key->ts[s].colorarg1 == D3DTA_TEXTURE ||
1359                 key->ts[s].colorarg2 == D3DTA_TEXTURE ||
1360                 key->ts[s].colorop == D3DTOP_BLENDTEXTUREALPHA ||
1361                 key->ts[s].colorop == D3DTOP_BLENDTEXTUREALPHAPM) {
1362                 ps.s[s] = ureg_DECL_sampler(ureg, s);
1363                 ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
1364             }
1365             if (s && (key->ts[s - 1].colorop == D3DTOP_PREMODULATE ||
1366                       key->ts[s - 1].alphaop == D3DTOP_PREMODULATE))
1367                 ps.s[s] = ureg_DECL_sampler(ureg, s);
1368         }
1369 
1370         if (key->ts[s].alphaop != D3DTOP_DISABLE) {
1371             if (key->ts[s].alphaarg0 == D3DTA_SPECULAR ||
1372                 key->ts[s].alphaarg1 == D3DTA_SPECULAR ||
1373                 key->ts[s].alphaarg2 == D3DTA_SPECULAR)
1374                 ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR);
1375 
1376             if (key->ts[s].alphaarg0 == D3DTA_TEXTURE ||
1377                 key->ts[s].alphaarg1 == D3DTA_TEXTURE ||
1378                 key->ts[s].alphaarg2 == D3DTA_TEXTURE ||
1379                 key->ts[s].colorop == D3DTOP_BLENDTEXTUREALPHA ||
1380                 key->ts[s].colorop == D3DTOP_BLENDTEXTUREALPHAPM) {
1381                 ps.s[s] = ureg_DECL_sampler(ureg, s);
1382                 ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE);
1383             }
1384         }
1385     }
1386     if (key->specular)
1387         ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR);
1388 
1389     oCol = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
1390 
1391     /* Run stages.
1392      */
1393     for (s = 0; s < 8; ++s) {
1394         unsigned colorarg[3];
1395         unsigned alphaarg[3];
1396         const uint8_t used_c = ps_d3dtop_args_mask(key->ts[s].colorop);
1397         const uint8_t used_a = ps_d3dtop_args_mask(key->ts[s].alphaop);
1398         struct ureg_dst dst;
1399         struct ureg_src arg[3];
1400 
1401         if (key->ts[s].colorop == D3DTOP_DISABLE) {
1402             assert (key->ts[s].alphaop == D3DTOP_DISABLE);
1403             continue;
1404         }
1405         ps.stage.index = s;
1406 
1407         DBG("STAGE[%u]: colorop=%s alphaop=%s\n", s,
1408             nine_D3DTOP_to_str(key->ts[s].colorop),
1409             nine_D3DTOP_to_str(key->ts[s].alphaop));
1410 
1411         if (!ureg_src_is_undef(ps.s[s])) {
1412             unsigned target;
1413             struct ureg_src texture_coord = ps.vT[s];
1414             struct ureg_dst delta;
1415             switch (key->ts[s].textarget) {
1416             case 0: target = TGSI_TEXTURE_1D; break;
1417             case 1: target = TGSI_TEXTURE_2D; break;
1418             case 2: target = TGSI_TEXTURE_3D; break;
1419             case 3: target = TGSI_TEXTURE_CUBE; break;
1420             /* this is a 2 bit bitfield, do I really need a default case ? */
1421             }
1422 
1423             /* Modify coordinates */
1424             if (s >= 1 &&
1425                 (key->ts[s-1].colorop == D3DTOP_BUMPENVMAP ||
1426                  key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE)) {
1427                 delta = ureg_DECL_temporary(ureg);
1428                 /* Du' = D3DTSS_BUMPENVMAT00(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT10(stage s-1)*t(s-1)G */
1429                 ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _X(ps.rTex), _XXXX(_CONST(8 + s - 1)));
1430                 ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _Y(ps.rTex), _ZZZZ(_CONST(8 + s - 1)), ureg_src(delta));
1431                 /* Dv' = D3DTSS_BUMPENVMAT01(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT11(stage s-1)*t(s-1)G */
1432                 ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _X(ps.rTex), _YYYY(_CONST(8 + s - 1)));
1433                 ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _Y(ps.rTex), _WWWW(_CONST(8 + s - 1)), ureg_src(delta));
1434                 texture_coord = ureg_src(ureg_DECL_temporary(ureg));
1435                 ureg_MOV(ureg, ureg_writemask(ureg_dst(texture_coord), ureg_dst(ps.vT[s]).WriteMask), ps.vT[s]);
1436                 ureg_ADD(ureg, ureg_writemask(ureg_dst(texture_coord), TGSI_WRITEMASK_XY), texture_coord, ureg_src(delta));
1437                 /* Prepare luminance multiplier
1438                  * t(s)RGBA = t(s)RGBA * clamp[(t(s-1)B * D3DTSS_BUMPENVLSCALE(stage s-1)) + D3DTSS_BUMPENVLOFFSET(stage s-1)] */
1439                 if (key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE) {
1440                     struct ureg_src bumpenvlscale = ((s-1) & 1) ? _ZZZZ(_CONST(16 + (s-1) / 2)) : _XXXX(_CONST(16 + (s-1) / 2));
1441                     struct ureg_src bumpenvloffset = ((s-1) & 1) ? _WWWW(_CONST(16 + (s-1) / 2)) : _YYYY(_CONST(16 + (s-1) / 2));
1442 
1443                     ureg_MAD(ureg, ureg_saturate(ureg_writemask(delta, TGSI_WRITEMASK_X)), _Z(ps.rTex), bumpenvlscale, bumpenvloffset);
1444                 }
1445             }
1446             if (key->projected & (3 << (s *2))) {
1447                 unsigned dim = 1 + ((key->projected >> (2 * s)) & 3);
1448                 if (dim == 4)
1449                     ureg_TXP(ureg, ps.rTex, target, texture_coord, ps.s[s]);
1450                 else {
1451                     struct ureg_dst tmp = ureg_DECL_temporary(ureg);
1452                     ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(texture_coord, dim-1));
1453                     ureg_MUL(ureg, ps.rTmp, _X(tmp), texture_coord);
1454                     ureg_TEX(ureg, ps.rTex, target, ps.rTmpSrc, ps.s[s]);
1455                     ureg_release_temporary(ureg, tmp);
1456                 }
1457             } else {
1458                 ureg_TEX(ureg, ps.rTex, target, texture_coord, ps.s[s]);
1459             }
1460             if (s >= 1 && key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE)
1461                 ureg_MUL(ureg, ps.rTex, ureg_src(ps.rTex), _X(delta));
1462         }
1463 
1464         if (key->ts[s].colorop == D3DTOP_BUMPENVMAP ||
1465             key->ts[s].colorop == D3DTOP_BUMPENVMAPLUMINANCE)
1466             continue;
1467 
1468         dst = ps_get_ts_dst(&ps, key->ts[s].resultarg ? D3DTA_TEMP : D3DTA_CURRENT);
1469 
1470         if (ps.stage.index_pre_mod == ps.stage.index) {
1471             ps.rMod = ureg_DECL_temporary(ureg);
1472             ureg_MUL(ureg, ps.rMod, ps.rCurSrc, ps.rTexSrc);
1473         }
1474 
1475         colorarg[0] = (key->ts[s].colorarg0 | (((key->colorarg_b4[0] >> s) & 0x1) << 4) | ((key->colorarg_b5[0] >> s) << 5)) & 0x3f;
1476         colorarg[1] = (key->ts[s].colorarg1 | (((key->colorarg_b4[1] >> s) & 0x1) << 4) | ((key->colorarg_b5[1] >> s) << 5)) & 0x3f;
1477         colorarg[2] = (key->ts[s].colorarg2 | (((key->colorarg_b4[2] >> s) & 0x1) << 4) | ((key->colorarg_b5[2] >> s) << 5)) & 0x3f;
1478         alphaarg[0] = (key->ts[s].alphaarg0 | ((key->alphaarg_b4[0] >> s) << 4)) & 0x1f;
1479         alphaarg[1] = (key->ts[s].alphaarg1 | ((key->alphaarg_b4[1] >> s) << 4)) & 0x1f;
1480         alphaarg[2] = (key->ts[s].alphaarg2 | ((key->alphaarg_b4[2] >> s) << 4)) & 0x1f;
1481 
1482         if (key->ts[s].colorop != key->ts[s].alphaop ||
1483             colorarg[0] != alphaarg[0] ||
1484             colorarg[1] != alphaarg[1] ||
1485             colorarg[2] != alphaarg[2])
1486             dst.WriteMask = TGSI_WRITEMASK_XYZ;
1487 
1488         /* Special DOTPRODUCT behaviour (see wine tests) */
1489         if (key->ts[s].colorop == D3DTOP_DOTPRODUCT3)
1490             dst.WriteMask = TGSI_WRITEMASK_XYZW;
1491 
1492         if (used_c & 0x1) arg[0] = ps_get_ts_arg(&ps, colorarg[0]);
1493         if (used_c & 0x2) arg[1] = ps_get_ts_arg(&ps, colorarg[1]);
1494         if (used_c & 0x4) arg[2] = ps_get_ts_arg(&ps, colorarg[2]);
1495         ps_do_ts_op(&ps, key->ts[s].colorop, dst, arg);
1496 
1497         if (dst.WriteMask != TGSI_WRITEMASK_XYZW) {
1498             dst.WriteMask = TGSI_WRITEMASK_W;
1499 
1500             if (used_a & 0x1) arg[0] = ps_get_ts_arg(&ps, alphaarg[0]);
1501             if (used_a & 0x2) arg[1] = ps_get_ts_arg(&ps, alphaarg[1]);
1502             if (used_a & 0x4) arg[2] = ps_get_ts_arg(&ps, alphaarg[2]);
1503             ps_do_ts_op(&ps, key->ts[s].alphaop, dst, arg);
1504         }
1505     }
1506 
1507     if (key->specular)
1508         ureg_ADD(ureg, ureg_writemask(ps.rCur, TGSI_WRITEMASK_XYZ), ps.rCurSrc, ps.vC[1]);
1509 
1510     /* Fog.
1511      */
1512     if (key->fog_mode) {
1513         struct ureg_dst rFog = ureg_writemask(ps.rTmp, TGSI_WRITEMASK_X);
1514         struct ureg_src vPos;
1515         if (device->screen->get_param(device->screen,
1516                                       PIPE_CAP_FS_POSITION_IS_SYSVAL)) {
1517             vPos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0);
1518         } else {
1519             vPos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
1520                                       TGSI_INTERPOLATE_LINEAR);
1521         }
1522 
1523         /* Source is either W or Z.
1524          * When we use vs ff,
1525          * Z is when an orthogonal projection matrix is detected,
1526          * W (WFOG) else.
1527          * Z is used for programmable vs.
1528          * Note: Tests indicate that the projection matrix coefficients do
1529          * actually affect pixel fog (and not vertex fog) when vs ff is used,
1530          * which justifies taking the position's w instead of taking the z coordinate
1531          * before the projection in the vs shader.
1532          */
1533         if (!key->fog_source)
1534             ureg_MOV(ureg, rFog, _ZZZZ(vPos));
1535         else
1536             /* Position's w is 1/w */
1537             ureg_RCP(ureg, rFog, _WWWW(vPos));
1538 
1539         if (key->fog_mode == D3DFOG_EXP) {
1540             ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22)));
1541             ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f));
1542             ureg_EX2(ureg, rFog, _X(rFog));
1543         } else
1544         if (key->fog_mode == D3DFOG_EXP2) {
1545             ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22)));
1546             ureg_MUL(ureg, rFog, _X(rFog), _X(rFog));
1547             ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f));
1548             ureg_EX2(ureg, rFog, _X(rFog));
1549         } else
1550         if (key->fog_mode == D3DFOG_LINEAR) {
1551             ureg_ADD(ureg, rFog, _XXXX(_CONST(22)), ureg_negate(_X(rFog)));
1552             ureg_MUL(ureg, ureg_saturate(rFog), _X(rFog), _YYYY(_CONST(22)));
1553         }
1554         ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _X(rFog), ps.rCurSrc, _CONST(21));
1555         ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc);
1556     } else
1557     if (key->fog) {
1558         struct ureg_src vFog = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 16, TGSI_INTERPOLATE_PERSPECTIVE);
1559         ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _XXXX(vFog), ps.rCurSrc, _CONST(21));
1560         ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc);
1561     } else {
1562         ureg_MOV(ureg, oCol, ps.rCurSrc);
1563     }
1564 
1565     ureg_END(ureg);
1566     nine_ureg_tgsi_dump(ureg, FALSE);
1567     return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL);
1568 }
1569 
1570 static struct NineVertexShader9 *
nine_ff_get_vs(struct NineDevice9 * device)1571 nine_ff_get_vs(struct NineDevice9 *device)
1572 {
1573     const struct nine_context *context = &device->context;
1574     struct NineVertexShader9 *vs;
1575     struct vs_build_ctx bld;
1576     struct nine_ff_vs_key key;
1577     unsigned s, i;
1578     boolean has_indexes = false;
1579     boolean has_weights = false;
1580     int8_t input_texture_coord[8];
1581 
1582     assert(sizeof(key) <= sizeof(key.value32));
1583 
1584     memset(&key, 0, sizeof(key));
1585     memset(&bld, 0, sizeof(bld));
1586     memset(&input_texture_coord, 0, sizeof(input_texture_coord));
1587 
1588     bld.key = &key;
1589 
1590     /* FIXME: this shouldn't be NULL, but it is on init */
1591     if (context->vdecl) {
1592         key.color0in_one = 1;
1593         key.color1in_zero = 1;
1594         for (i = 0; i < context->vdecl->nelems; i++) {
1595             uint16_t usage = context->vdecl->usage_map[i];
1596             if (usage == NINE_DECLUSAGE_POSITIONT)
1597                 key.position_t = 1;
1598             else if (usage == NINE_DECLUSAGE_i(COLOR, 0))
1599                 key.color0in_one = 0;
1600             else if (usage == NINE_DECLUSAGE_i(COLOR, 1))
1601                 key.color1in_zero = 0;
1602             else if (usage == NINE_DECLUSAGE_i(BLENDINDICES, 0)) {
1603                 has_indexes = true;
1604                 key.passthrough |= 1 << usage;
1605             } else if (usage == NINE_DECLUSAGE_i(BLENDWEIGHT, 0)) {
1606                 has_weights = true;
1607                 key.passthrough |= 1 << usage;
1608             } else if (usage == NINE_DECLUSAGE_i(NORMAL, 0)) {
1609                 key.has_normal = 1;
1610                 key.passthrough |= 1 << usage;
1611             } else if (usage == NINE_DECLUSAGE_PSIZE)
1612                 key.vertexpointsize = 1;
1613             else if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) {
1614                 s = usage / NINE_DECLUSAGE_COUNT;
1615                 if (s < 8)
1616                     input_texture_coord[s] = nine_decltype_get_dim(context->vdecl->decls[i].Type);
1617                 else
1618                     DBG("FF given texture coordinate >= 8. Ignoring\n");
1619             } else if (usage < NINE_DECLUSAGE_NONE)
1620                 key.passthrough |= 1 << usage;
1621         }
1622     }
1623     /* ff vs + ps 3.0: some elements are passed to the ps (wine test).
1624      * We do restrict to indices 0 */
1625     key.passthrough &= ~((1 << NINE_DECLUSAGE_POSITION) | (1 << NINE_DECLUSAGE_PSIZE) |
1626                          (1 << NINE_DECLUSAGE_TEXCOORD) | (1 << NINE_DECLUSAGE_POSITIONT) |
1627                          (1 << NINE_DECLUSAGE_TESSFACTOR) | (1 << NINE_DECLUSAGE_SAMPLE));
1628     if (!key.position_t)
1629         key.passthrough = 0;
1630     key.pointscale = !!context->rs[D3DRS_POINTSCALEENABLE];
1631 
1632     key.lighting = !!context->rs[D3DRS_LIGHTING] &&  context->ff.num_lights_active;
1633     key.darkness = !!context->rs[D3DRS_LIGHTING] && !context->ff.num_lights_active;
1634     if (key.position_t) {
1635         key.darkness = 0; /* |= key.lighting; */ /* XXX ? */
1636         key.lighting = 0;
1637     }
1638     if ((key.lighting | key.darkness) && context->rs[D3DRS_COLORVERTEX]) {
1639         uint32_t mask = (key.color0in_one ? 0 : 1) | (key.color1in_zero ? 0 : 2);
1640         key.mtl_diffuse = context->rs[D3DRS_DIFFUSEMATERIALSOURCE] & mask;
1641         key.mtl_ambient = context->rs[D3DRS_AMBIENTMATERIALSOURCE] & mask;
1642         key.mtl_specular = context->rs[D3DRS_SPECULARMATERIALSOURCE] & mask;
1643         key.mtl_emissive = context->rs[D3DRS_EMISSIVEMATERIALSOURCE] & mask;
1644     }
1645     key.fog = !!context->rs[D3DRS_FOGENABLE];
1646     key.fog_mode = (!key.position_t && context->rs[D3DRS_FOGENABLE]) ? context->rs[D3DRS_FOGVERTEXMODE] : 0;
1647     if (key.fog_mode)
1648         key.fog_range = context->rs[D3DRS_RANGEFOGENABLE];
1649 
1650     key.localviewer = !!context->rs[D3DRS_LOCALVIEWER];
1651     key.normalizenormals = !!context->rs[D3DRS_NORMALIZENORMALS];
1652     key.ucp = !!context->rs[D3DRS_CLIPPLANEENABLE];
1653 
1654     if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
1655         key.vertexblend_indexed = !!context->rs[D3DRS_INDEXEDVERTEXBLENDENABLE] && has_indexes;
1656 
1657         switch (context->rs[D3DRS_VERTEXBLEND]) {
1658         case D3DVBF_0WEIGHTS: key.vertexblend = key.vertexblend_indexed; break;
1659         case D3DVBF_1WEIGHTS: key.vertexblend = 2; break;
1660         case D3DVBF_2WEIGHTS: key.vertexblend = 3; break;
1661         case D3DVBF_3WEIGHTS: key.vertexblend = 4; break;
1662         case D3DVBF_TWEENING: key.vertextween = 1; break;
1663         default:
1664             assert(!"invalid D3DVBF");
1665             break;
1666         }
1667         if (!has_weights && context->rs[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS)
1668             key.vertexblend = 0; /* TODO: if key.vertexblend_indexed, perhaps it should use 1.0 as weight, or revert to D3DVBF_0WEIGHTS */
1669     }
1670 
1671     for (s = 0; s < 8; ++s) {
1672         unsigned gen = (context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1;
1673         unsigned idx = context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] & 7;
1674         unsigned dim;
1675 
1676         if (key.position_t && gen > NINED3DTSS_TCI_PASSTHRU)
1677             gen = NINED3DTSS_TCI_PASSTHRU;
1678 
1679         if (!input_texture_coord[idx] && gen == NINED3DTSS_TCI_PASSTHRU)
1680             gen = NINED3DTSS_TCI_DISABLE;
1681 
1682         key.tc_gen |= gen << (s * 3);
1683         key.tc_idx |= idx << (s * 3);
1684         key.tc_dim_input |= ((input_texture_coord[idx]-1) & 0x3) << (s * 2);
1685 
1686         dim = context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7;
1687         if (dim > 4)
1688             dim = input_texture_coord[idx];
1689         if (dim == 1) /* NV behaviour */
1690             dim = 0;
1691         key.tc_dim_output |= dim << (s * 3);
1692     }
1693 
1694     DBG("VS ff key hash: %x\n", nine_ff_vs_key_hash(&key));
1695     vs = util_hash_table_get(device->ff.ht_vs, &key);
1696     if (vs)
1697         return vs;
1698     NineVertexShader9_new(device, &vs, NULL, nine_ff_build_vs(device, &bld));
1699 
1700     nine_ff_prune_vs(device);
1701     if (vs) {
1702         unsigned n;
1703 
1704         memcpy(&vs->ff_key, &key, sizeof(vs->ff_key));
1705 
1706         _mesa_hash_table_insert(device->ff.ht_vs, &vs->ff_key, vs);
1707         device->ff.num_vs++;
1708 
1709         vs->num_inputs = bld.num_inputs;
1710         for (n = 0; n < bld.num_inputs; ++n)
1711             vs->input_map[n].ndecl = bld.input[n];
1712 
1713         vs->position_t = key.position_t;
1714         vs->point_size = key.vertexpointsize | key.pointscale;
1715     }
1716     return vs;
1717 }
1718 
1719 #define GET_D3DTS(n) nine_state_access_transform(&context->ff, D3DTS_##n, FALSE)
1720 #define IS_D3DTS_DIRTY(s,n) ((s)->ff.changed.transform[(D3DTS_##n) / 32] & (1 << ((D3DTS_##n) % 32)))
1721 
1722 static struct NinePixelShader9 *
nine_ff_get_ps(struct NineDevice9 * device)1723 nine_ff_get_ps(struct NineDevice9 *device)
1724 {
1725     struct nine_context *context = &device->context;
1726     D3DMATRIX *projection_matrix = GET_D3DTS(PROJECTION);
1727     struct NinePixelShader9 *ps;
1728     struct nine_ff_ps_key key;
1729     unsigned s;
1730     uint8_t sampler_mask = 0;
1731 
1732     assert(sizeof(key) <= sizeof(key.value32));
1733 
1734     memset(&key, 0, sizeof(key));
1735     for (s = 0; s < 8; ++s) {
1736         key.ts[s].colorop = context->ff.tex_stage[s][D3DTSS_COLOROP];
1737         key.ts[s].alphaop = context->ff.tex_stage[s][D3DTSS_ALPHAOP];
1738         const uint8_t used_c = ps_d3dtop_args_mask(key.ts[s].colorop);
1739         const uint8_t used_a = ps_d3dtop_args_mask(key.ts[s].alphaop);
1740         /* MSDN says D3DTOP_DISABLE disables this and all subsequent stages.
1741          * ALPHAOP cannot be enabled if COLOROP is disabled.
1742          * Verified on Windows. */
1743         if (key.ts[s].colorop == D3DTOP_DISABLE) {
1744             key.ts[s].alphaop = D3DTOP_DISABLE; /* DISABLE == 1, avoid degenerate keys */
1745             break;
1746         }
1747 
1748         if (!context->texture[s].enabled &&
1749             ((context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE &&
1750               used_c & 0x1) ||
1751              (context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE &&
1752               used_c & 0x2) ||
1753              (context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE &&
1754               used_c & 0x4))) {
1755             /* Tested on Windows: Invalid texture read disables the stage
1756              * and the subsequent ones, but only for colorop. For alpha,
1757              * it's as if the texture had alpha of 1.0, which is what
1758              * has our dummy texture in that case. Invalid color also
1759              * disabled the following alpha stages. */
1760             key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
1761             break;
1762         }
1763 
1764         if (context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE ||
1765             context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE ||
1766             context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE ||
1767             context->ff.tex_stage[s][D3DTSS_ALPHAARG0] == D3DTA_TEXTURE ||
1768             context->ff.tex_stage[s][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE ||
1769             context->ff.tex_stage[s][D3DTSS_ALPHAARG2] == D3DTA_TEXTURE)
1770             sampler_mask |= (1 << s);
1771 
1772         if (key.ts[s].colorop != D3DTOP_DISABLE) {
1773             if (used_c & 0x1) key.ts[s].colorarg0 = context->ff.tex_stage[s][D3DTSS_COLORARG0] & 0x7;
1774             if (used_c & 0x2) key.ts[s].colorarg1 = context->ff.tex_stage[s][D3DTSS_COLORARG1] & 0x7;
1775             if (used_c & 0x4) key.ts[s].colorarg2 = context->ff.tex_stage[s][D3DTSS_COLORARG2] & 0x7;
1776             if (used_c & 0x1) key.colorarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 4) & 0x1) << s;
1777             if (used_c & 0x1) key.colorarg_b5[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 5) & 0x1) << s;
1778             if (used_c & 0x2) key.colorarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 4) & 0x1) << s;
1779             if (used_c & 0x2) key.colorarg_b5[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 5) & 0x1) << s;
1780             if (used_c & 0x4) key.colorarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 4) & 0x1) << s;
1781             if (used_c & 0x4) key.colorarg_b5[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 5) & 0x1) << s;
1782         }
1783         if (key.ts[s].alphaop != D3DTOP_DISABLE) {
1784             if (used_a & 0x1) key.ts[s].alphaarg0 = context->ff.tex_stage[s][D3DTSS_ALPHAARG0] & 0x7;
1785             if (used_a & 0x2) key.ts[s].alphaarg1 = context->ff.tex_stage[s][D3DTSS_ALPHAARG1] & 0x7;
1786             if (used_a & 0x4) key.ts[s].alphaarg2 = context->ff.tex_stage[s][D3DTSS_ALPHAARG2] & 0x7;
1787             if (used_a & 0x1) key.alphaarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG0] >> 4) & 0x1) << s;
1788             if (used_a & 0x2) key.alphaarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG1] >> 4) & 0x1) << s;
1789             if (used_a & 0x4) key.alphaarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG2] >> 4) & 0x1) << s;
1790         }
1791         key.ts[s].resultarg = context->ff.tex_stage[s][D3DTSS_RESULTARG] == D3DTA_TEMP;
1792 
1793         if (context->texture[s].enabled) {
1794             switch (context->texture[s].type) {
1795             case D3DRTYPE_TEXTURE:       key.ts[s].textarget = 1; break;
1796             case D3DRTYPE_VOLUMETEXTURE: key.ts[s].textarget = 2; break;
1797             case D3DRTYPE_CUBETEXTURE:   key.ts[s].textarget = 3; break;
1798             default:
1799                 assert(!"unexpected texture type");
1800                 break;
1801             }
1802         } else {
1803             key.ts[s].textarget = 1;
1804         }
1805     }
1806 
1807     /* Note: If colorop is D3DTOP_DISABLE for the first stage
1808      * (which implies alphaop is too), nothing particular happens,
1809      * that is, current is equal to diffuse (which is the case anyway,
1810      * because it is how it is initialized).
1811      * Special case seems if alphaop is D3DTOP_DISABLE and not colorop,
1812      * because then if the resultarg is TEMP, then diffuse alpha is written
1813      * to it. */
1814     if (key.ts[0].colorop != D3DTOP_DISABLE &&
1815         key.ts[0].alphaop == D3DTOP_DISABLE &&
1816         key.ts[0].resultarg != 0) {
1817         key.ts[0].alphaop = D3DTOP_SELECTARG1;
1818         key.ts[0].alphaarg1 = D3DTA_DIFFUSE;
1819     }
1820     /* When no alpha stage writes to current, diffuse alpha is taken.
1821      * Since we initialize current to diffuse, we have the behaviour. */
1822 
1823     /* Last stage always writes to Current */
1824     if (s >= 1)
1825         key.ts[s-1].resultarg = 0;
1826 
1827     key.projected = nine_ff_get_projected_key_ff(context);
1828     key.specular = !!context->rs[D3DRS_SPECULARENABLE];
1829 
1830     for (; s < 8; ++s)
1831         key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
1832     if (context->rs[D3DRS_FOGENABLE])
1833         key.fog_mode = context->rs[D3DRS_FOGTABLEMODE];
1834     key.fog = !!context->rs[D3DRS_FOGENABLE];
1835     /* Pixel fog (with WFOG advertised): source is either Z or W.
1836      * W is the source if vs ff is used, and the
1837      * projection matrix is not orthogonal.
1838      * Tests on Win 10 seem to indicate _34
1839      * and _33 are checked against 0, 1. */
1840     if (key.fog_mode && key.fog)
1841         key.fog_source = !context->programmable_vs &&
1842             !(projection_matrix->_34 == 0.0f &&
1843               projection_matrix->_44 == 1.0f);
1844 
1845     DBG("PS ff key hash: %x\n", nine_ff_ps_key_hash(&key));
1846     ps = util_hash_table_get(device->ff.ht_ps, &key);
1847     if (ps)
1848         return ps;
1849     NinePixelShader9_new(device, &ps, NULL, nine_ff_build_ps(device, &key));
1850 
1851     nine_ff_prune_ps(device);
1852     if (ps) {
1853         memcpy(&ps->ff_key, &key, sizeof(ps->ff_key));
1854 
1855         _mesa_hash_table_insert(device->ff.ht_ps, &ps->ff_key, ps);
1856         device->ff.num_ps++;
1857 
1858         ps->rt_mask = 0x1;
1859         ps->sampler_mask = sampler_mask;
1860     }
1861     return ps;
1862 }
1863 
1864 static void
nine_ff_load_vs_transforms(struct NineDevice9 * device)1865 nine_ff_load_vs_transforms(struct NineDevice9 *device)
1866 {
1867     struct nine_context *context = &device->context;
1868     D3DMATRIX T;
1869     D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const;
1870     unsigned i;
1871 
1872     /* TODO: make this nicer, and only upload the ones we need */
1873     /* TODO: use ff.vs_const as storage of W, V, P matrices */
1874 
1875     if (IS_D3DTS_DIRTY(context, WORLD) ||
1876         IS_D3DTS_DIRTY(context, VIEW) ||
1877         IS_D3DTS_DIRTY(context, PROJECTION)) {
1878         /* WVP, WV matrices */
1879         nine_d3d_matrix_matrix_mul(&M[1], GET_D3DTS(WORLD), GET_D3DTS(VIEW));
1880         nine_d3d_matrix_matrix_mul(&M[0], &M[1], GET_D3DTS(PROJECTION));
1881 
1882         /* normal matrix == transpose(inverse(WV)) */
1883         nine_d3d_matrix_inverse(&T, &M[1]);
1884         nine_d3d_matrix_transpose(&M[4], &T);
1885 
1886         /* P matrix */
1887         M[2] = *GET_D3DTS(PROJECTION);
1888 
1889         /* V and W matrix */
1890         nine_d3d_matrix_inverse(&M[3], GET_D3DTS(VIEW));
1891         M[40] = M[1];
1892     }
1893 
1894     if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
1895         /* load other world matrices */
1896         for (i = 1; i <= 8; ++i) {
1897             nine_d3d_matrix_matrix_mul(&M[40 + i], GET_D3DTS(WORLDMATRIX(i)), GET_D3DTS(VIEW));
1898         }
1899     }
1900 
1901     device->ff.vs_const[30 * 4] = asfloat(context->rs[D3DRS_TWEENFACTOR]);
1902 }
1903 
1904 static void
nine_ff_load_lights(struct NineDevice9 * device)1905 nine_ff_load_lights(struct NineDevice9 *device)
1906 {
1907     struct nine_context *context = &device->context;
1908     struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
1909     unsigned l;
1910 
1911     if (context->changed.group & NINE_STATE_FF_MATERIAL) {
1912         const D3DMATERIAL9 *mtl = &context->ff.material;
1913 
1914         memcpy(&dst[20], &mtl->Diffuse, 4 * sizeof(float));
1915         memcpy(&dst[21], &mtl->Ambient, 4 * sizeof(float));
1916         memcpy(&dst[22], &mtl->Specular, 4 * sizeof(float));
1917         dst[23].x = mtl->Power;
1918         memcpy(&dst[24], &mtl->Emissive, 4 * sizeof(float));
1919         d3dcolor_to_rgba(&dst[25].x, context->rs[D3DRS_AMBIENT]);
1920         dst[19].x = dst[25].x * mtl->Ambient.r + mtl->Emissive.r;
1921         dst[19].y = dst[25].y * mtl->Ambient.g + mtl->Emissive.g;
1922         dst[19].z = dst[25].z * mtl->Ambient.b + mtl->Emissive.b;
1923     }
1924 
1925     if (!(context->changed.group & NINE_STATE_FF_LIGHTING))
1926         return;
1927 
1928     for (l = 0; l < context->ff.num_lights_active; ++l) {
1929         const D3DLIGHT9 *light = &context->ff.light[context->ff.active_light[l]];
1930 
1931         dst[32 + l * 8].x = light->Type;
1932         dst[32 + l * 8].y = light->Attenuation0;
1933         dst[32 + l * 8].z = light->Attenuation1;
1934         dst[32 + l * 8].w = light->Attenuation2;
1935         memcpy(&dst[33 + l * 8].x, &light->Diffuse, sizeof(light->Diffuse));
1936         memcpy(&dst[34 + l * 8].x, &light->Specular, sizeof(light->Specular));
1937         memcpy(&dst[35 + l * 8].x, &light->Ambient, sizeof(light->Ambient));
1938         nine_d3d_vector4_matrix_mul((D3DVECTOR *)&dst[36 + l * 8].x, &light->Position, GET_D3DTS(VIEW));
1939         nine_d3d_vector3_matrix_mul((D3DVECTOR *)&dst[37 + l * 8].x, &light->Direction, GET_D3DTS(VIEW));
1940         dst[36 + l * 8].w = light->Type == D3DLIGHT_DIRECTIONAL ? 1e9f : light->Range;
1941         dst[37 + l * 8].w = light->Falloff;
1942         dst[38 + l * 8].x = cosf(light->Theta * 0.5f);
1943         dst[38 + l * 8].y = cosf(light->Phi * 0.5f);
1944         dst[38 + l * 8].z = 1.0f / (dst[38 + l * 8].x - dst[38 + l * 8].y);
1945         dst[39 + l * 8].w = (float)((l + 1) == context->ff.num_lights_active);
1946     }
1947 }
1948 
1949 static void
nine_ff_load_point_and_fog_params(struct NineDevice9 * device)1950 nine_ff_load_point_and_fog_params(struct NineDevice9 *device)
1951 {
1952     struct nine_context *context = &device->context;
1953     struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
1954 
1955     if (!(context->changed.group & NINE_STATE_FF_VS_OTHER))
1956         return;
1957     dst[26].x = asfloat(context->rs[D3DRS_POINTSIZE_MIN]);
1958     dst[26].y = asfloat(context->rs[D3DRS_POINTSIZE_MAX]);
1959     dst[26].z = asfloat(context->rs[D3DRS_POINTSIZE]);
1960     dst[26].w = asfloat(context->rs[D3DRS_POINTSCALE_A]);
1961     dst[27].x = asfloat(context->rs[D3DRS_POINTSCALE_B]);
1962     dst[27].y = asfloat(context->rs[D3DRS_POINTSCALE_C]);
1963     dst[28].x = asfloat(context->rs[D3DRS_FOGEND]);
1964     dst[28].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART]));
1965     if (isinf(dst[28].y))
1966         dst[28].y = 0.0f;
1967     dst[28].z = asfloat(context->rs[D3DRS_FOGDENSITY]);
1968 }
1969 
1970 static void
nine_ff_load_tex_matrices(struct NineDevice9 * device)1971 nine_ff_load_tex_matrices(struct NineDevice9 *device)
1972 {
1973     struct nine_context *context = &device->context;
1974     D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const;
1975     unsigned s;
1976 
1977     if (!(context->ff.changed.transform[0] & 0xff0000))
1978         return;
1979     for (s = 0; s < 8; ++s) {
1980         if (IS_D3DTS_DIRTY(context, TEXTURE0 + s))
1981             nine_d3d_matrix_transpose(&M[32 + s], nine_state_access_transform(&context->ff, D3DTS_TEXTURE0 + s, FALSE));
1982     }
1983 }
1984 
1985 static void
nine_ff_load_ps_params(struct NineDevice9 * device)1986 nine_ff_load_ps_params(struct NineDevice9 *device)
1987 {
1988     struct nine_context *context = &device->context;
1989     struct fvec4 *dst = (struct fvec4 *)device->ff.ps_const;
1990     unsigned s;
1991 
1992     if (!(context->changed.group & NINE_STATE_FF_PS_CONSTS))
1993         return;
1994 
1995     for (s = 0; s < 8; ++s)
1996         d3dcolor_to_rgba(&dst[s].x, context->ff.tex_stage[s][D3DTSS_CONSTANT]);
1997 
1998     for (s = 0; s < 8; ++s) {
1999         dst[8 + s].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT00]);
2000         dst[8 + s].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT01]);
2001         dst[8 + s].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT10]);
2002         dst[8 + s].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT11]);
2003         if (s & 1) {
2004             dst[16 + s / 2].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]);
2005             dst[16 + s / 2].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]);
2006         } else {
2007             dst[16 + s / 2].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]);
2008             dst[16 + s / 2].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]);
2009         }
2010     }
2011 
2012     d3dcolor_to_rgba(&dst[20].x, context->rs[D3DRS_TEXTUREFACTOR]);
2013     d3dcolor_to_rgba(&dst[21].x, context->rs[D3DRS_FOGCOLOR]);
2014     dst[22].x = asfloat(context->rs[D3DRS_FOGEND]);
2015     dst[22].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART]));
2016     dst[22].z = asfloat(context->rs[D3DRS_FOGDENSITY]);
2017 }
2018 
2019 static void
nine_ff_load_viewport_info(struct NineDevice9 * device)2020 nine_ff_load_viewport_info(struct NineDevice9 *device)
2021 {
2022     D3DVIEWPORT9 *viewport = &device->context.viewport;
2023     struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
2024     float diffZ = viewport->MaxZ - viewport->MinZ;
2025 
2026     /* Note: the other functions avoids to fill the const again if nothing changed.
2027      * But we don't have much to fill, and adding code to allow that may be complex
2028      * so just fill it always */
2029     dst[100].x = 2.0f / (float)(viewport->Width);
2030     dst[100].y = 2.0f / (float)(viewport->Height);
2031     dst[100].z = (diffZ == 0.0f) ? 0.0f : (1.0f / diffZ);
2032     dst[100].w = (float)(viewport->Width);
2033     dst[101].x = (float)(viewport->X);
2034     dst[101].y = (float)(viewport->Y);
2035     dst[101].z = (float)(viewport->MinZ);
2036 }
2037 
2038 void
nine_ff_update(struct NineDevice9 * device)2039 nine_ff_update(struct NineDevice9 *device)
2040 {
2041     struct nine_context *context = &device->context;
2042     struct pipe_constant_buffer cb;
2043 
2044     DBG("vs=%p ps=%p\n", context->vs, context->ps);
2045 
2046     /* NOTE: the only reference belongs to the hash table */
2047     if (!context->programmable_vs) {
2048         device->ff.vs = nine_ff_get_vs(device);
2049         context->changed.group |= NINE_STATE_VS;
2050     }
2051     if (!context->ps) {
2052         device->ff.ps = nine_ff_get_ps(device);
2053         context->changed.group |= NINE_STATE_PS;
2054     }
2055 
2056     if (!context->programmable_vs) {
2057         nine_ff_load_vs_transforms(device);
2058         nine_ff_load_tex_matrices(device);
2059         nine_ff_load_lights(device);
2060         nine_ff_load_point_and_fog_params(device);
2061         nine_ff_load_viewport_info(device);
2062 
2063         memset(context->ff.changed.transform, 0, sizeof(context->ff.changed.transform));
2064 
2065         cb.buffer_offset = 0;
2066         cb.buffer = NULL;
2067         cb.user_buffer = device->ff.vs_const;
2068         cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float);
2069 
2070         context->pipe_data.cb_vs_ff = cb;
2071         context->commit |= NINE_STATE_COMMIT_CONST_VS;
2072 
2073         context->changed.group &= ~NINE_STATE_FF_VS;
2074     }
2075 
2076     if (!context->ps) {
2077         nine_ff_load_ps_params(device);
2078 
2079         cb.buffer_offset = 0;
2080         cb.buffer = NULL;
2081         cb.user_buffer = device->ff.ps_const;
2082         cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float);
2083 
2084         context->pipe_data.cb_ps_ff = cb;
2085         context->commit |= NINE_STATE_COMMIT_CONST_PS;
2086 
2087         context->changed.group &= ~NINE_STATE_FF_PS;
2088     }
2089 }
2090 
2091 
2092 boolean
nine_ff_init(struct NineDevice9 * device)2093 nine_ff_init(struct NineDevice9 *device)
2094 {
2095     device->ff.ht_vs = _mesa_hash_table_create(NULL, nine_ff_vs_key_hash,
2096                                                nine_ff_vs_key_comp);
2097     device->ff.ht_ps = _mesa_hash_table_create(NULL, nine_ff_ps_key_hash,
2098                                                nine_ff_ps_key_comp);
2099 
2100     device->ff.ht_fvf = _mesa_hash_table_create(NULL, nine_ff_fvf_key_hash,
2101                                                 nine_ff_fvf_key_comp);
2102 
2103     device->ff.vs_const = CALLOC(NINE_FF_NUM_VS_CONST, 4 * sizeof(float));
2104     device->ff.ps_const = CALLOC(NINE_FF_NUM_PS_CONST, 4 * sizeof(float));
2105 
2106     return device->ff.ht_vs && device->ff.ht_ps &&
2107         device->ff.ht_fvf &&
2108         device->ff.vs_const && device->ff.ps_const;
2109 }
2110 
nine_ff_ht_delete_cb(void * key,void * value,void * data)2111 static enum pipe_error nine_ff_ht_delete_cb(void *key, void *value, void *data)
2112 {
2113     NineUnknown_Unbind(NineUnknown(value));
2114     return PIPE_OK;
2115 }
2116 
2117 void
nine_ff_fini(struct NineDevice9 * device)2118 nine_ff_fini(struct NineDevice9 *device)
2119 {
2120     if (device->ff.ht_vs) {
2121         util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL);
2122         _mesa_hash_table_destroy(device->ff.ht_vs, NULL);
2123     }
2124     if (device->ff.ht_ps) {
2125         util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL);
2126         _mesa_hash_table_destroy(device->ff.ht_ps, NULL);
2127     }
2128     if (device->ff.ht_fvf) {
2129         util_hash_table_foreach(device->ff.ht_fvf, nine_ff_ht_delete_cb, NULL);
2130         _mesa_hash_table_destroy(device->ff.ht_fvf, NULL);
2131     }
2132     device->ff.vs = NULL; /* destroyed by unbinding from hash table */
2133     device->ff.ps = NULL;
2134 
2135     FREE(device->ff.vs_const);
2136     FREE(device->ff.ps_const);
2137 }
2138 
2139 static void
nine_ff_prune_vs(struct NineDevice9 * device)2140 nine_ff_prune_vs(struct NineDevice9 *device)
2141 {
2142     struct nine_context *context = &device->context;
2143 
2144     if (device->ff.num_vs > 1024) {
2145         /* could destroy the bound one here, so unbind */
2146         context->pipe->bind_vs_state(context->pipe, NULL);
2147         util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL);
2148         _mesa_hash_table_clear(device->ff.ht_vs, NULL);
2149         device->ff.num_vs = 0;
2150         context->changed.group |= NINE_STATE_VS;
2151     }
2152 }
2153 static void
nine_ff_prune_ps(struct NineDevice9 * device)2154 nine_ff_prune_ps(struct NineDevice9 *device)
2155 {
2156     struct nine_context *context = &device->context;
2157 
2158     if (device->ff.num_ps > 1024) {
2159         /* could destroy the bound one here, so unbind */
2160         context->pipe->bind_fs_state(context->pipe, NULL);
2161         util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL);
2162         _mesa_hash_table_clear(device->ff.ht_ps, NULL);
2163         device->ff.num_ps = 0;
2164         context->changed.group |= NINE_STATE_PS;
2165     }
2166 }
2167 
2168 /* ========================================================================== */
2169 
2170 /* Matrix multiplication:
2171  *
2172  * in memory: 0 1 2 3 (row major)
2173  *            4 5 6 7
2174  *            8 9 a b
2175  *            c d e f
2176  *
2177  *    cA cB cC cD
2178  * r0             = (r0 * cA) (r0 * cB) . .
2179  * r1             = (r1 * cA) (r1 * cB)
2180  * r2             = (r2 * cA) .
2181  * r3             = (r3 * cA) .
2182  *
2183  *               r: (11) (12) (13) (14)
2184  *                  (21) (22) (23) (24)
2185  *                  (31) (32) (33) (34)
2186  *                  (41) (42) (43) (44)
2187  * l: (11 12 13 14)
2188  *    (21 22 23 24)
2189  *    (31 32 33 34)
2190  *    (41 42 43 44)
2191  *
2192  * v: (x  y  z  1 )
2193  *
2194  * t.xyzw = MUL(v.xxxx, r[0]);
2195  * t.xyzw = MAD(v.yyyy, r[1], t.xyzw);
2196  * t.xyzw = MAD(v.zzzz, r[2], t.xyzw);
2197  * v.xyzw = MAD(v.wwww, r[3], t.xyzw);
2198  *
2199  * v.x = DP4(v, c[0]);
2200  * v.y = DP4(v, c[1]);
2201  * v.z = DP4(v, c[2]);
2202  * v.w = DP4(v, c[3]) = 1
2203  */
2204 
2205 /*
2206 static void
2207 nine_D3DMATRIX_print(const D3DMATRIX *M)
2208 {
2209     DBG("\n(%f %f %f %f)\n"
2210         "(%f %f %f %f)\n"
2211         "(%f %f %f %f)\n"
2212         "(%f %f %f %f)\n",
2213         M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3],
2214         M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3],
2215         M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3],
2216         M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]);
2217 }
2218 */
2219 
2220 static inline float
nine_DP4_row_col(const D3DMATRIX * A,int r,const D3DMATRIX * B,int c)2221 nine_DP4_row_col(const D3DMATRIX *A, int r, const D3DMATRIX *B, int c)
2222 {
2223     return A->m[r][0] * B->m[0][c] +
2224            A->m[r][1] * B->m[1][c] +
2225            A->m[r][2] * B->m[2][c] +
2226            A->m[r][3] * B->m[3][c];
2227 }
2228 
2229 static inline float
nine_DP4_vec_col(const D3DVECTOR * v,const D3DMATRIX * M,int c)2230 nine_DP4_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c)
2231 {
2232     return v->x * M->m[0][c] +
2233            v->y * M->m[1][c] +
2234            v->z * M->m[2][c] +
2235            1.0f * M->m[3][c];
2236 }
2237 
2238 static inline float
nine_DP3_vec_col(const D3DVECTOR * v,const D3DMATRIX * M,int c)2239 nine_DP3_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c)
2240 {
2241     return v->x * M->m[0][c] +
2242            v->y * M->m[1][c] +
2243            v->z * M->m[2][c];
2244 }
2245 
2246 void
nine_d3d_matrix_matrix_mul(D3DMATRIX * D,const D3DMATRIX * L,const D3DMATRIX * R)2247 nine_d3d_matrix_matrix_mul(D3DMATRIX *D, const D3DMATRIX *L, const D3DMATRIX *R)
2248 {
2249     D->_11 = nine_DP4_row_col(L, 0, R, 0);
2250     D->_12 = nine_DP4_row_col(L, 0, R, 1);
2251     D->_13 = nine_DP4_row_col(L, 0, R, 2);
2252     D->_14 = nine_DP4_row_col(L, 0, R, 3);
2253 
2254     D->_21 = nine_DP4_row_col(L, 1, R, 0);
2255     D->_22 = nine_DP4_row_col(L, 1, R, 1);
2256     D->_23 = nine_DP4_row_col(L, 1, R, 2);
2257     D->_24 = nine_DP4_row_col(L, 1, R, 3);
2258 
2259     D->_31 = nine_DP4_row_col(L, 2, R, 0);
2260     D->_32 = nine_DP4_row_col(L, 2, R, 1);
2261     D->_33 = nine_DP4_row_col(L, 2, R, 2);
2262     D->_34 = nine_DP4_row_col(L, 2, R, 3);
2263 
2264     D->_41 = nine_DP4_row_col(L, 3, R, 0);
2265     D->_42 = nine_DP4_row_col(L, 3, R, 1);
2266     D->_43 = nine_DP4_row_col(L, 3, R, 2);
2267     D->_44 = nine_DP4_row_col(L, 3, R, 3);
2268 }
2269 
2270 void
nine_d3d_vector4_matrix_mul(D3DVECTOR * d,const D3DVECTOR * v,const D3DMATRIX * M)2271 nine_d3d_vector4_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M)
2272 {
2273     d->x = nine_DP4_vec_col(v, M, 0);
2274     d->y = nine_DP4_vec_col(v, M, 1);
2275     d->z = nine_DP4_vec_col(v, M, 2);
2276 }
2277 
2278 void
nine_d3d_vector3_matrix_mul(D3DVECTOR * d,const D3DVECTOR * v,const D3DMATRIX * M)2279 nine_d3d_vector3_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M)
2280 {
2281     d->x = nine_DP3_vec_col(v, M, 0);
2282     d->y = nine_DP3_vec_col(v, M, 1);
2283     d->z = nine_DP3_vec_col(v, M, 2);
2284 }
2285 
2286 void
nine_d3d_matrix_transpose(D3DMATRIX * D,const D3DMATRIX * M)2287 nine_d3d_matrix_transpose(D3DMATRIX *D, const D3DMATRIX *M)
2288 {
2289     unsigned i, j;
2290     for (i = 0; i < 4; ++i)
2291     for (j = 0; j < 4; ++j)
2292         D->m[i][j] = M->m[j][i];
2293 }
2294 
2295 #define _M_ADD_PROD_1i_2j_3k_4l(i,j,k,l) do {            \
2296     float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \
2297     if (t > 0.0f) pos += t; else neg += t; } while(0)
2298 
2299 #define _M_SUB_PROD_1i_2j_3k_4l(i,j,k,l) do {            \
2300     float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \
2301     if (t > 0.0f) neg -= t; else pos -= t; } while(0)
2302 float
nine_d3d_matrix_det(const D3DMATRIX * M)2303 nine_d3d_matrix_det(const D3DMATRIX *M)
2304 {
2305     float pos = 0.0f;
2306     float neg = 0.0f;
2307 
2308     _M_ADD_PROD_1i_2j_3k_4l(1, 2, 3, 4);
2309     _M_ADD_PROD_1i_2j_3k_4l(1, 3, 4, 2);
2310     _M_ADD_PROD_1i_2j_3k_4l(1, 4, 2, 3);
2311 
2312     _M_ADD_PROD_1i_2j_3k_4l(2, 1, 4, 3);
2313     _M_ADD_PROD_1i_2j_3k_4l(2, 3, 1, 4);
2314     _M_ADD_PROD_1i_2j_3k_4l(2, 4, 3, 1);
2315 
2316     _M_ADD_PROD_1i_2j_3k_4l(3, 1, 2, 4);
2317     _M_ADD_PROD_1i_2j_3k_4l(3, 2, 4, 1);
2318     _M_ADD_PROD_1i_2j_3k_4l(3, 4, 1, 2);
2319 
2320     _M_ADD_PROD_1i_2j_3k_4l(4, 1, 3, 2);
2321     _M_ADD_PROD_1i_2j_3k_4l(4, 2, 1, 3);
2322     _M_ADD_PROD_1i_2j_3k_4l(4, 3, 2, 1);
2323 
2324     _M_SUB_PROD_1i_2j_3k_4l(1, 2, 4, 3);
2325     _M_SUB_PROD_1i_2j_3k_4l(1, 3, 2, 4);
2326     _M_SUB_PROD_1i_2j_3k_4l(1, 4, 3, 2);
2327 
2328     _M_SUB_PROD_1i_2j_3k_4l(2, 1, 3, 4);
2329     _M_SUB_PROD_1i_2j_3k_4l(2, 3, 4, 1);
2330     _M_SUB_PROD_1i_2j_3k_4l(2, 4, 1, 3);
2331 
2332     _M_SUB_PROD_1i_2j_3k_4l(3, 1, 4, 2);
2333     _M_SUB_PROD_1i_2j_3k_4l(3, 2, 1, 4);
2334     _M_SUB_PROD_1i_2j_3k_4l(3, 4, 2, 1);
2335 
2336     _M_SUB_PROD_1i_2j_3k_4l(4, 1, 2, 3);
2337     _M_SUB_PROD_1i_2j_3k_4l(4, 2, 3, 1);
2338     _M_SUB_PROD_1i_2j_3k_4l(4, 3, 1, 2);
2339 
2340     return pos + neg;
2341 }
2342 
2343 /* XXX: Probably better to just use src/mesa/math/m_matrix.c because
2344  * I have no idea where this code came from.
2345  */
2346 void
nine_d3d_matrix_inverse(D3DMATRIX * D,const D3DMATRIX * M)2347 nine_d3d_matrix_inverse(D3DMATRIX *D, const D3DMATRIX *M)
2348 {
2349     int i, k;
2350     float det;
2351 
2352     D->m[0][0] =
2353         M->m[1][1] * M->m[2][2] * M->m[3][3] -
2354         M->m[1][1] * M->m[3][2] * M->m[2][3] -
2355         M->m[1][2] * M->m[2][1] * M->m[3][3] +
2356         M->m[1][2] * M->m[3][1] * M->m[2][3] +
2357         M->m[1][3] * M->m[2][1] * M->m[3][2] -
2358         M->m[1][3] * M->m[3][1] * M->m[2][2];
2359 
2360     D->m[0][1] =
2361        -M->m[0][1] * M->m[2][2] * M->m[3][3] +
2362         M->m[0][1] * M->m[3][2] * M->m[2][3] +
2363         M->m[0][2] * M->m[2][1] * M->m[3][3] -
2364         M->m[0][2] * M->m[3][1] * M->m[2][3] -
2365         M->m[0][3] * M->m[2][1] * M->m[3][2] +
2366         M->m[0][3] * M->m[3][1] * M->m[2][2];
2367 
2368     D->m[0][2] =
2369         M->m[0][1] * M->m[1][2] * M->m[3][3] -
2370         M->m[0][1] * M->m[3][2] * M->m[1][3] -
2371         M->m[0][2] * M->m[1][1] * M->m[3][3] +
2372         M->m[0][2] * M->m[3][1] * M->m[1][3] +
2373         M->m[0][3] * M->m[1][1] * M->m[3][2] -
2374         M->m[0][3] * M->m[3][1] * M->m[1][2];
2375 
2376     D->m[0][3] =
2377        -M->m[0][1] * M->m[1][2] * M->m[2][3] +
2378         M->m[0][1] * M->m[2][2] * M->m[1][3] +
2379         M->m[0][2] * M->m[1][1] * M->m[2][3] -
2380         M->m[0][2] * M->m[2][1] * M->m[1][3] -
2381         M->m[0][3] * M->m[1][1] * M->m[2][2] +
2382         M->m[0][3] * M->m[2][1] * M->m[1][2];
2383 
2384     D->m[1][0] =
2385        -M->m[1][0] * M->m[2][2] * M->m[3][3] +
2386         M->m[1][0] * M->m[3][2] * M->m[2][3] +
2387         M->m[1][2] * M->m[2][0] * M->m[3][3] -
2388         M->m[1][2] * M->m[3][0] * M->m[2][3] -
2389         M->m[1][3] * M->m[2][0] * M->m[3][2] +
2390         M->m[1][3] * M->m[3][0] * M->m[2][2];
2391 
2392     D->m[1][1] =
2393         M->m[0][0] * M->m[2][2] * M->m[3][3] -
2394         M->m[0][0] * M->m[3][2] * M->m[2][3] -
2395         M->m[0][2] * M->m[2][0] * M->m[3][3] +
2396         M->m[0][2] * M->m[3][0] * M->m[2][3] +
2397         M->m[0][3] * M->m[2][0] * M->m[3][2] -
2398         M->m[0][3] * M->m[3][0] * M->m[2][2];
2399 
2400     D->m[1][2] =
2401        -M->m[0][0] * M->m[1][2] * M->m[3][3] +
2402         M->m[0][0] * M->m[3][2] * M->m[1][3] +
2403         M->m[0][2] * M->m[1][0] * M->m[3][3] -
2404         M->m[0][2] * M->m[3][0] * M->m[1][3] -
2405         M->m[0][3] * M->m[1][0] * M->m[3][2] +
2406         M->m[0][3] * M->m[3][0] * M->m[1][2];
2407 
2408     D->m[1][3] =
2409         M->m[0][0] * M->m[1][2] * M->m[2][3] -
2410         M->m[0][0] * M->m[2][2] * M->m[1][3] -
2411         M->m[0][2] * M->m[1][0] * M->m[2][3] +
2412         M->m[0][2] * M->m[2][0] * M->m[1][3] +
2413         M->m[0][3] * M->m[1][0] * M->m[2][2] -
2414         M->m[0][3] * M->m[2][0] * M->m[1][2];
2415 
2416     D->m[2][0] =
2417         M->m[1][0] * M->m[2][1] * M->m[3][3] -
2418         M->m[1][0] * M->m[3][1] * M->m[2][3] -
2419         M->m[1][1] * M->m[2][0] * M->m[3][3] +
2420         M->m[1][1] * M->m[3][0] * M->m[2][3] +
2421         M->m[1][3] * M->m[2][0] * M->m[3][1] -
2422         M->m[1][3] * M->m[3][0] * M->m[2][1];
2423 
2424     D->m[2][1] =
2425        -M->m[0][0] * M->m[2][1] * M->m[3][3] +
2426         M->m[0][0] * M->m[3][1] * M->m[2][3] +
2427         M->m[0][1] * M->m[2][0] * M->m[3][3] -
2428         M->m[0][1] * M->m[3][0] * M->m[2][3] -
2429         M->m[0][3] * M->m[2][0] * M->m[3][1] +
2430         M->m[0][3] * M->m[3][0] * M->m[2][1];
2431 
2432     D->m[2][2] =
2433         M->m[0][0] * M->m[1][1] * M->m[3][3] -
2434         M->m[0][0] * M->m[3][1] * M->m[1][3] -
2435         M->m[0][1] * M->m[1][0] * M->m[3][3] +
2436         M->m[0][1] * M->m[3][0] * M->m[1][3] +
2437         M->m[0][3] * M->m[1][0] * M->m[3][1] -
2438         M->m[0][3] * M->m[3][0] * M->m[1][1];
2439 
2440     D->m[2][3] =
2441        -M->m[0][0] * M->m[1][1] * M->m[2][3] +
2442         M->m[0][0] * M->m[2][1] * M->m[1][3] +
2443         M->m[0][1] * M->m[1][0] * M->m[2][3] -
2444         M->m[0][1] * M->m[2][0] * M->m[1][3] -
2445         M->m[0][3] * M->m[1][0] * M->m[2][1] +
2446         M->m[0][3] * M->m[2][0] * M->m[1][1];
2447 
2448     D->m[3][0] =
2449        -M->m[1][0] * M->m[2][1] * M->m[3][2] +
2450         M->m[1][0] * M->m[3][1] * M->m[2][2] +
2451         M->m[1][1] * M->m[2][0] * M->m[3][2] -
2452         M->m[1][1] * M->m[3][0] * M->m[2][2] -
2453         M->m[1][2] * M->m[2][0] * M->m[3][1] +
2454         M->m[1][2] * M->m[3][0] * M->m[2][1];
2455 
2456     D->m[3][1] =
2457         M->m[0][0] * M->m[2][1] * M->m[3][2] -
2458         M->m[0][0] * M->m[3][1] * M->m[2][2] -
2459         M->m[0][1] * M->m[2][0] * M->m[3][2] +
2460         M->m[0][1] * M->m[3][0] * M->m[2][2] +
2461         M->m[0][2] * M->m[2][0] * M->m[3][1] -
2462         M->m[0][2] * M->m[3][0] * M->m[2][1];
2463 
2464     D->m[3][2] =
2465        -M->m[0][0] * M->m[1][1] * M->m[3][2] +
2466         M->m[0][0] * M->m[3][1] * M->m[1][2] +
2467         M->m[0][1] * M->m[1][0] * M->m[3][2] -
2468         M->m[0][1] * M->m[3][0] * M->m[1][2] -
2469         M->m[0][2] * M->m[1][0] * M->m[3][1] +
2470         M->m[0][2] * M->m[3][0] * M->m[1][1];
2471 
2472     D->m[3][3] =
2473         M->m[0][0] * M->m[1][1] * M->m[2][2] -
2474         M->m[0][0] * M->m[2][1] * M->m[1][2] -
2475         M->m[0][1] * M->m[1][0] * M->m[2][2] +
2476         M->m[0][1] * M->m[2][0] * M->m[1][2] +
2477         M->m[0][2] * M->m[1][0] * M->m[2][1] -
2478         M->m[0][2] * M->m[2][0] * M->m[1][1];
2479 
2480     det =
2481         M->m[0][0] * D->m[0][0] +
2482         M->m[1][0] * D->m[0][1] +
2483         M->m[2][0] * D->m[0][2] +
2484         M->m[3][0] * D->m[0][3];
2485 
2486     if (fabsf(det) < 1e-30) {/* non inversible */
2487         *D = *M; /* wine tests */
2488         return;
2489     }
2490 
2491     det = 1.0 / det;
2492 
2493     for (i = 0; i < 4; i++)
2494     for (k = 0; k < 4; k++)
2495         D->m[i][k] *= det;
2496 
2497 #if defined(DEBUG) || !defined(NDEBUG)
2498     {
2499         D3DMATRIX I;
2500 
2501         nine_d3d_matrix_matrix_mul(&I, D, M);
2502 
2503         for (i = 0; i < 4; ++i)
2504         for (k = 0; k < 4; ++k)
2505             if (fabsf(I.m[i][k] - (float)(i == k)) > 1e-3)
2506                 DBG("Matrix inversion check FAILED !\n");
2507     }
2508 #endif
2509 }
2510