t_vp_build.c revision f069e5e412eebabe64286d35598173caac5c132e
1f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/*
2f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Mesa 3-D graphics library
3f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Version:  6.3
4f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
5f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Copyright (C) 2005  Tungsten Graphics   All Rights Reserved.
6f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
7f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
8f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * copy of this software and associated documentation files (the "Software"),
9f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * to deal in the Software without restriction, including without limitation
10f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
12f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Software is furnished to do so, subject to the following conditions:
13f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
14f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * The above copyright notice and this permission notice shall be included
15f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * in all copies or substantial portions of the Software.
16f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
17f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
24f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
25f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/**
26f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * \file t_vp_build.c
27f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Create a vertex program to execute the current fixed function T&L pipeline.
28f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * \author Keith Whitwell
29f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
30f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
31f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
32f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include <strings.h>
33f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
34f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "glheader.h"
35f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "macros.h"
36f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "enums.h"
37f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "t_context.h"
38f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "t_vp_build.h"
39f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
40f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/program.h"
41f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/nvvertprog.h"
42f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/arbvertparse.h"
43f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
44f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
45f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Very useful debugging tool - produces annotated listing of
46f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * generated program with line/function references for each
47f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * instruction back into this file:
48f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
49f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define DISASSEM 1
50f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
51f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Use uregs to represent registers internally, translate to Mesa's
52f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * expected formats on emit.
53f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
54f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * NOTE: These are passed by value extensively in this file rather
55f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * than as usual by pointer reference.  If this disturbs you, try
56f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * remembering they are just 32bits in size.
57f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
58f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * GCC is smart enough to deal with these dword-sized structures in
59f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * much the same way as if I had defined them as dwords and was using
60f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * macros to access and set the fields.  This is much nicer and easier
61f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * to evolve.
62f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
63f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct ureg {
64f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint file:4;
65f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx:8;
66f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint negate:1;
67f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint swz:12;
68f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint pad:7;
69f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
70f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
71f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
72f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct tnl_program {
73f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLcontext *ctx;
74f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct vertex_program *program;
75f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
76f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint temp_flag;
77f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint temp_reserved;
78f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
79f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position;
80f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position_normalized;
81f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_normal;
82f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg identity;
83f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
84f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint materials;
85f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint color_materials;
86f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
87f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
88f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
89f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellconst static struct ureg undef = {
90f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   ~0,
91f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   ~0,
92f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
93f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
94f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0
95f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
96f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
97f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Local shorthand:
98f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
99f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define X    SWIZZLE_X
100f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Y    SWIZZLE_Y
101f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Z    SWIZZLE_Z
102f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define W    SWIZZLE_W
103f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
104f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
105f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Construct a ureg:
106f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
107f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
108f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
109f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg reg;
110f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.file = file;
111f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.idx = idx;
112f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate = 0;
113f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = SWIZZLE_NOOP;
114f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.pad = 0;
115f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
116f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
117f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
118f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
119f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
120f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg negate( struct ureg reg )
121f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
122f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate ^= 1;
123f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
124f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
125f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
126f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
127f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
128f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
129f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
130f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, y),
131f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, z),
132f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, w));
133f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
134f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
135f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
136f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
137f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
138f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
139f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return swizzle(reg, x, x, x, x);
140f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
141f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
142f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_temp( struct tnl_program *p )
143f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
144f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   int bit = ffs( ~p->temp_flag );
145f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (!bit) {
146f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      fprintf(stderr, "%s: out of temporaries\n", __FILE__);
147f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      exit(1);
148f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
149f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
150f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->temp_flag |= 1<<(bit-1);
151f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_TEMPORARY, bit-1);
152f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
153f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
154f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg reserve_temp( struct tnl_program *p )
155f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
156f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg temp = get_temp( p );
157f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->temp_reserved |= 1<<temp.idx;
158f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return temp;
159f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
160f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
161f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temp( struct tnl_program *p, struct ureg reg )
162f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
163f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY) {
164f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->temp_flag &= ~(1<<reg.idx);
165f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->temp_flag |= p->temp_reserved; /* can't release reserved temps */
166f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
167f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
168f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
169f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temps( struct tnl_program *p )
170f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
171f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->temp_flag = p->temp_reserved;
172f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
173f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
174f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
175f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
176f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_input( struct tnl_program *p, GLuint input )
177f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
178f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->program->InputsRead |= (1<<input);
179f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_INPUT, input);
180f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
181f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
182f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_output( struct tnl_program *p, GLuint output )
183f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
184f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->program->OutputsWritten |= (1<<output);
185f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_OUTPUT, output);
186f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
187f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
188f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_const4f( struct tnl_program *p,
189f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s0,
190f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s1,
191f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s2,
192f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s3)
193f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
194f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLfloat values[4];
195f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx;
196f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[0] = s0;
197f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[1] = s1;
198f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[2] = s2;
199f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[3] = s3;
200f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
201f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
202f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
203f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
204f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
205f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
206f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
207f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
208f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLboolean is_undef( struct ureg reg )
209f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
210f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg.file == 0xf;
211f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
212f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
213f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_identity_param( struct tnl_program *p )
214f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
215f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->identity))
216f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->identity = register_const4f(p, 0,0,0,1);
217f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
218f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->identity;
219f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
220f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
221f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_param6( struct tnl_program *p,
222f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s0,
223f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s1,
224f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s2,
225f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s3,
226f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s4,
227f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s5)
228f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
229f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLint tokens[6];
230f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx;
231f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[0] = s0;
232f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[1] = s1;
233f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[2] = s2;
234f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[3] = s3;
235f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[4] = s4;
236f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[5] = s5;
237f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   idx = _mesa_add_state_reference( p->program->Parameters, tokens );
238f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
239f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
240f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
241f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
242f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
243f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
244f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
245f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
246f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
247f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
248f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void register_matrix_param6( struct tnl_program *p,
249f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s0,
250f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s1,
251f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s2,
252f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s3,
253f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s4,
254f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s5,
255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    struct ureg *matrix )
256f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
257f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
258f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
259f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* This is a bit sad as the support is there to pull the whole
260f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    * matrix out in one go:
261f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
262f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i <= s4 - s3; i++)
263f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
264f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
265f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
266f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
267f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_arg( struct vp_src_register *src,
268f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg )
269f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
270f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->File = reg.file;
271f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Index = reg.idx;
272f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Swizzle = reg.swz;
273f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Negate = reg.negate;
274f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->RelAddr = 0;
275f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->pad = 0;
276f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
277f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
278f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_dst( struct vp_dst_register *dst,
279f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg, GLuint mask )
280f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
281f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->File = reg.file;
282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->Index = reg.idx;
283f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->WriteMask = mask ? mask : WRITEMASK_XYZW; /* allow zero as a shorthand for xyzw */
284f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->pad = 0;
285f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
286f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
287f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void debug_insn( struct vp_instruction *inst, const char *fn, GLuint line )
288f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
289f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#if DISASSEM
290f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   static const char *last_fn;
291f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
292f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (fn != last_fn) {
293f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      last_fn = fn;
294f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _mesa_printf("%s:\n", fn);
295f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
296f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
297f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   _mesa_printf("%d:\t", line);
298f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   _mesa_debug_vp_inst(1, inst);
299f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#endif
300f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
301f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
302f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
303f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_op3fn(struct tnl_program *p,
304f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint op,
305f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg dest,
306f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint mask,
307f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src0,
308f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src1,
309f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src2,
310f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       const char *fn,
311f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint line)
312f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
313f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
314f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct vp_instruction *inst = &p->program->Instructions[nr];
315f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   inst->Opcode = op;
317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
319f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
320f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
321f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_dst( &inst->DstReg, dest, mask );
323f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
324f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   debug_insn(inst, fn, line);
325f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
326f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
327f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
328f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
329f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define emit_op3(p, op, dst, mask, src0, src1, src2) emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
330f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define emit_op2(p, op, dst, mask, src0, src1) emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
331f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define emit_op1(p, op, dst, mask, src0)       emit_op3fn(p, op, dst, mask, src0, undef,    undef, __FUNCTION__, __LINE__)
332f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
333f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
334f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_temp( struct tnl_program *p, struct ureg reg )
335f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
336f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY &&
337f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       !(p->temp_reserved & (1<<reg.idx)))
338f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return reg;
339f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
340f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg temp = get_temp(p);
341f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, temp, 0, reg);
342f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return temp;
343f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
344f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
345f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
346f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
347f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Currently no tracking performed of input/output/register size or
348f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * active elements.  Could be used to reduce these operations, as
349f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * could the matrix type.
350f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
351f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec4( struct tnl_program *p,
352f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
353f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
354f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
355f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
356f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
357f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
358f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
359f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
360f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
361f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
362f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
363f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec3( struct tnl_program *p,
364f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
365f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
366f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
367f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
368f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
369f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
370f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
371f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
372f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
373f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
374f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_normalize_vec3( struct tnl_program *p,
375f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg dest,
376f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg src )
377f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
378f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg tmp = get_temp(p);
379f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, tmp, 0, src, src);
380f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp);
381f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, dest, 0, src, tmp);
382f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, tmp);
383f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
384f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
385f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position( struct tnl_program *p )
386f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
387f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position)) {
388f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg pos = register_input( p, VERT_ATTRIB_POS );
389f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg modelview[4];
390f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
391f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 0, modelview );
392f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position = reserve_temp(p);
393f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
394f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_matrix_transform_vec4( p, p->eye_position, modelview, pos );
395f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
396f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
397f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position;
398f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
399f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
400f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
401f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position_normalized( struct tnl_program *p )
402f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
403f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position_normalized)) {
404f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg eye = get_eye_position(p);
405f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position_normalized = reserve_temp(p);
406f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_normalize_vec3(p, p->eye_position_normalized, eye);
407f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
408f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
409f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position_normalized;
410f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
411f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
412f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
413f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_normal( struct tnl_program *p )
414f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
415f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_normal)) {
416f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
417f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg mvinv[3];
418f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
419f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2, STATE_MATRIX_INVTRANS, mvinv );
420f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
421f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_normal = reserve_temp(p);
422f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
423f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Transform to eye space:
424f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
425f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
426f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
427f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Normalize/Rescale:
428f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
429f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (p->ctx->Transform.Normalize) {
430f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
431f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
432f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else if (p->ctx->Transform.RescaleNormals) {
433f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg rescale = register_param2(p, STATE_INTERNAL, STATE_NORMAL_SCALE);
434f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2( p, VP_OPCODE_MUL, p->eye_normal, 0, normal, swizzle1(rescale, X));
435f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
436f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
437f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
438f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_normal;
439f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
440f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
441f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
442f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
443f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_hpos( struct tnl_program *p )
444f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
445f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg pos = register_input( p, VERT_ATTRIB_POS );
446f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
447f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg mvp[4];
448f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
449f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 0, mvp );
450f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_matrix_transform_vec4( p, hpos, mvp, pos );
451f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
452f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
453f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
454f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLuint material_attrib( GLuint side, GLuint property )
455f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
456f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return _TNL_ATTRIB_MAT_FRONT_AMBIENT + (property - STATE_AMBIENT) * 2 + side;
457f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
458f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
459f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void set_material_flags( struct tnl_program *p )
460f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
461f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLcontext *ctx = p->ctx;
462f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
463f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
464f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
465f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->color_materials = 0;
466f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->materials = 0;
467f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
468f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Light.ColorMaterialEnabled) {
469f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->materials =
470f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 p->color_materials =
471f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 ctx->Light.ColorMaterialBitmask << _TNL_ATTRIB_MAT_FRONT_AMBIENT;
472f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
473f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
474f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; i < _TNL_ATTRIB_INDEX ; i++)
475f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (tnl->vb.AttribPtr[i]->stride)
476f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 p->materials |= 1<<i;
477f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
478f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
479f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
480f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_material( struct tnl_program *p, GLuint side, GLuint property )
481f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
482f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
483f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
484f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->color_materials & (1<<attrib))
485f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input(p, VERT_ATTRIB_COLOR0);
486f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else if (p->materials & (1<<attrib))
487f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input( p, attrib );
488f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
489f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param3( p, STATE_MATERIAL, side, property );
490f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
491f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
492f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define SCENE_COLOR_BITS(side) (( _TNL_BIT_MAT_FRONT_EMISSION | \
493f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   _TNL_BIT_MAT_FRONT_AMBIENT | \
494f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   _TNL_BIT_MAT_FRONT_DIFFUSE) << (side))
495f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
496f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Either return a precalculated constant value or emit code to
497f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * calculate these values dynamically in the case where material calls
498f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * are present between begin/end pairs.
499f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
500f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Probably want to shift this to the program compilation phase - if
501f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * we always emitted the calculation here, a smart compiler could
502f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * detect that it was constant (given a certain set of inputs), and
503f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * lift it out of the main loop.  That way the programs created here
504f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * would be independent of the vertex_buffer details.
505f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
506f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
507f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
508f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & SCENE_COLOR_BITS(side)) {
509f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg lightmodel_ambient = register_param1(p, STATE_LIGHTMODEL_AMBIENT);
510f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_emission = get_material(p, side, STATE_EMISSION);
511f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
512f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
513f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = make_temp(p, material_diffuse);
514f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op3(p, VP_OPCODE_MAD, tmp,  WRITEMASK_XYZ, lightmodel_ambient, material_ambient, material_emission);
515f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
516f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
517f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
518f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param2( p, STATE_LIGHTMODEL_SCENECOLOR, side );
519f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
520f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
521f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
522f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_lightprod( struct tnl_program *p, GLuint light, GLuint side, GLuint property )
523f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
524f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
525f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & (1<<attrib)) {
526f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg light_value = register_param3(p, STATE_LIGHT, light, property);
527f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_value = get_material(p, side, property);
528f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
529f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op2(p, VP_OPCODE_MUL, tmp,  0, light_value, material_value);
530f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
531f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
532f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
533f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param4(p, STATE_LIGHTPROD, light, side, property);
534f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
535f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
536f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
537f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
538f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
539f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Need to add some addtional parameters to allow lighting in object
540f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
541f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space lighting.
542f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
543f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_lighting( struct tnl_program *p )
544f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
545f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLcontext *ctx = p->ctx;
546f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   const GLboolean twoside = ctx->Light.Model.TwoSide;
547f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   const GLboolean separate = (ctx->Light.Model.ColorControl ==
548f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			       GL_SEPARATE_SPECULAR_COLOR);
549f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr_lights = 0, count = 0;
550f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg normal = get_eye_normal(p);
551f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg lit = get_temp(p);
552f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg dots = get_temp(p);
553f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _col0 = undef, _col1 = undef;
554f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _bfc0 = undef, _bfc1 = undef;
555f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
556f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
557f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++)
558f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (ctx->Light.Light[i].Enabled)
559f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 nr_lights++;
560f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
561f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   set_material_flags(p);
562f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
563f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   {
564f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 0, STATE_SHININESS);
565f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, dots,  WRITEMASK_W, swizzle1(shininess,X));
566f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
567f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
568f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _col0 = make_temp(p, get_scenecolor(p, 0));
569f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
570f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = make_temp(p, get_identity_param(p));
571f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
572f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = _col0;
573f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
574f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
575f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
576f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (twoside) {
577f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 1, STATE_SHININESS);
578f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, dots,  WRITEMASK_Z, negate(swizzle1(shininess,X)));
579f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
580f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
581f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _bfc0 = make_temp(p, get_scenecolor(p, 1));
582f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
583f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = make_temp(p, get_identity_param(p));
584f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
585f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = _bfc0;
586f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
587f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
588f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++) {
589f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct gl_light *light = &ctx->Light.Light[i];
590f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
591f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (light->Enabled) {
592f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg half = undef;
593f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg att = undef, VPpli = undef;
594f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
595f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 count++;
596f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
597f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (light->EyePosition[3] == 0) {
598f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Can used precomputed constants in this case:
599f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
600f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    VPpli = register_param3(p, STATE_LIGHT, i, STATE_POSITION_NORMALIZED);
601f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
602f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
603f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Spot attenuation maybe applies to this case?  Could precompute if so? */
604f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
605f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 else {
606f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg Ppli = register_param3(p, STATE_LIGHT, i, STATE_POSITION);
607f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg V = get_eye_position(p);
608f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg dst = get_temp(p);
609f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
610f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    VPpli = get_temp(p);
611f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = get_temp(p);
612f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
613f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calulate VPpli vector
614f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
615f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op2(p, VP_OPCODE_SUB, VPpli, 0, Ppli, V);
616f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
617f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Normalize VPpli.  The dst value also used in
618f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * attenuation below.
619f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
620f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op2(p, VP_OPCODE_DP3, dst, 0, VPpli, VPpli);
621f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op1(p, VP_OPCODE_RSQ, dst, 0, dst);
622f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op2(p, VP_OPCODE_MUL, VPpli, 0, VPpli, dst);
623f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
624f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
625f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate  attenuation:
626f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
627f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (light->SpotCutoff != 180.0 ||
628f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		light->ConstantAttenuation != 1.0 ||
629f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		light->LinearAttenuation != 1.0 ||
630f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		light->QuadraticAttenuation != 1.0) {
631f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
632f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg attenuation = register_param3(p, STATE_LIGHT, i, STATE_ATTENUATION);
633f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       att = get_temp(p);
634f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
635f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       /* Calculate spot attenuation:
636f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		*/
637f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (light->SpotCutoff != 180.0F) {
638f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  struct ureg spot_dir = register_param3(p, STATE_LIGHT, i, STATE_SPOT_DIRECTION);
639f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  struct ureg spot = get_temp(p);
640f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  struct ureg slt = get_temp(p);
641f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
642f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_normalize_vec3( p, spot, spot_dir ); /* XXX: precompute! */
643f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_DP3, spot, 0, negate(VPpli), spot_dir);
644f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_SLT, slt, 0, swizzle1(spot_dir,W), spot);
645f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
646f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_MUL, att, 0, slt, spot);
647f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
648f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  release_temp(p, spot);
649f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  release_temp(p, slt);
650f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
651f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
652f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       /* Calculate distance attenuation:
653f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		*/
654f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (light->ConstantAttenuation != 1.0 ||
655f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		   light->LinearAttenuation != 1.0 ||
656f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		   light->QuadraticAttenuation != 1.0) {
657f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
658f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op1(p, VP_OPCODE_RCP, dst, WRITEMASK_YZ, dst); /* 1/d,d,d,1/d */
659f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_MUL, dst, WRITEMASK_XZ, dst, swizzle1(dst,Y)); /* 1,d,d*d,1/d */
660f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  emit_op2(p, VP_OPCODE_DP3, dst, 0, attenuation, dst); /* 1/dist-atten */
661f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
662f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  if (light->SpotCutoff != 180.0F) {
663f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     emit_op1(p, VP_OPCODE_RCP, dst, 0, dst); /* dist-atten */
664f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     emit_op2(p, VP_OPCODE_MUL, att, 0, dst, att);	/* spot-atten * dist-atten */
665f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  } else {
666f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     emit_op1(p, VP_OPCODE_RCP, att, 0, dst); /* dist-atten */
667f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  }
668f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
669f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
670f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
671f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
672f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate viewer direction, or use infinite viewer:
673f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
674f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (ctx->Light.Model.LocalViewer) {
675f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
676f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_SUB, half, 0, VPpli, eye_hat);
677f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
678f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else {
679f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); /* 0,0,1,0 */
680f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_ADD, half, 0, VPpli, z_dir);
681f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
682f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
683f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_normalize_vec3(p, half, half);
684f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
685f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, dst);
686f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
687f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
688f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Calculate dot products:
689f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
690f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
691f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
692f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
693f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
694f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Front face lighting:
695f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
696f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 {
697f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT);
698f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE);
699f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR);
700f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
701f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
702f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op1(p, VP_OPCODE_LIT, lit, 0, dots);
703f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
704f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
705f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
706f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
707f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
708f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
709f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
710f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_COL0 );
711f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL1 );
712f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
713f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
714f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _col0;
715f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL0 );
716f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
717f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
718f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _col0;
719f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _col1;
720f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
721f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
722f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
723f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res0, 0, swizzle1(lit,Y), diffuse, _col0);
724f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res1, 0, swizzle1(lit,Z), specular, _col1);
725f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
726f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
727f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
728f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
729f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
730f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
731f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Back face lighting:
732f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
733f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (twoside) {
734f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT);
735f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE);
736f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
737f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
738f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
739f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op1(p, VP_OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
740f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
741f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
742f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
743f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
744f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
745f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
746f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_BFC0 );
747f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC1 );
748f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
749f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
750f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _bfc0;
751f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC0 );
752f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
753f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
754f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _bfc0;
755f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _bfc1;
756f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
757f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
758f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
759f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
760f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res0, 0, swizzle1(lit,Y), diffuse, _bfc0);
761f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res1, 0, swizzle1(lit,Z), specular, _bfc1);
762f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
763f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
764f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
765f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
766f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
767f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
768f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, half);
769f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, VPpli);
770f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, att);
771f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
772f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
773f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
774f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temps( p );
775f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
776f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
777f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
778f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_fog( struct tnl_program *p )
779f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
780f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLcontext *ctx = p->ctx;
781f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
782f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg fog = register_output(p, VERT_RESULT_FOGC);
783f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg input;
784f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
785f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
786f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(get_eye_position(p), Z);
787f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
788f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
789f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
790f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
791f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
792f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (tnl->_DoVertexFog) {
793f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg params = register_param1(p, STATE_FOG_PARAMS);
794f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
795f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
796f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      switch (ctx->Fog.Mode) {
797f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      case GL_LINEAR: {
798f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg id = get_identity_param(p);
799f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_SUB, tmp, 0, swizzle1(params,Z), input);
800f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,W));
801f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
802f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W)); /* saturate */
803f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
804f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
805f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      case GL_EXP:
806f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op1(p, VP_OPCODE_ABS, tmp, 0, input);
807f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,X));
808f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X, register_const1f(p, M_E), negate(tmp));
809f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
810f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      case GL_EXP2:
811f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, input, swizzle1(params,X));
812f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, tmp);
813f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X, register_const1f(p, M_E), negate(tmp));
814f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
815f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
816f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
817f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, tmp);
818f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
819f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
820f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* results = incoming fog coords (compute fog per-fragment later)
821f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       *
822f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       * KW:  Is it really necessary to do anything in this case?
823f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
824f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, fog, WRITEMASK_X, input);
825f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
826f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
827f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
828f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
829f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
830f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_texture_transform( struct tnl_program *p )
831f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
832f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLcontext *ctx = p->ctx;
833f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i, j;
834f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
835f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
836f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
837f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      GLuint texmat_enabled = ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i);
838f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
839f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
840f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (texUnit->TexGenEnabled || texmat_enabled) {
841f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg out_texgen = undef;
842f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
843f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (texUnit->TexGenEnabled) {
844f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint copy_mask = 0;
845f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint sphere_mask = 0;
846f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint reflect_mask = 0;
847f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint normal_mask = 0;
848f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint modes[4];
849f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
850f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (texmat_enabled)
851f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = get_temp(p);
852f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else
853f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = out;
854f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
855f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    modes[0] = texUnit->GenModeS;
856f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    modes[1] = texUnit->GenModeT;
857f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    modes[2] = texUnit->GenModeR;
858f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    modes[3] = texUnit->GenModeQ;
859f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
860f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    for (j = 0; j < 4; j++) {
861f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (texUnit->TexGenEnabled & (1<<j)) {
862f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  switch (modes[j]) {
863f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  case GL_OBJECT_LINEAR: {
864f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     struct ureg obj = register_input(p, VERT_ATTRIB_POS);
865f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j);
866f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane );
867f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     break;
868f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  }
869f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  case GL_EYE_LINEAR: {
870f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     struct ureg eye = get_eye_position(p);
871f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j);
872f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane );
873f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     break;
874f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  }
875f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  case GL_SPHERE_MAP:
876f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     sphere_mask |= WRITEMASK_X << j;
877f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     break;
878f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  case GL_REFLECTION_MAP_NV:
879f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     reflect_mask |= WRITEMASK_X << j;
880f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     break;
881f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  case GL_NORMAL_MAP_NV:
882f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     normal_mask |= WRITEMASK_X << j;
883f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		     break;
884f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  }
885f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
886f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else
887f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  copy_mask |= WRITEMASK_X << j;
888f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
889f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
890f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
891f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (sphere_mask) {
892f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
893f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
894f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg tmp = get_temp(p);
895f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg half = register_const1f(p, .5);
896f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg r = get_temp(p);
897f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg inv_m = get_temp(p);
898f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
899f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat); /* n.u */
900f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp); /* 2n.u */
901f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op3(p, VP_OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat); /* (-2n.u)n + u */
902f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_ADD, tmp, 0, r, swizzle(get_identity_param(p),X,Y,W,Z)); /* r + 0,0,1 */
903f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_DP3, tmp, 0, tmp, tmp); /* rx^2 + ry^2 + (rz+1)^2 */
904f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp); /* 2/m */
905f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_MUL, inv_m, 0, tmp, swizzle1(half,X)); /* 1/m */
906f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op3(p, VP_OPCODE_MAD, out_texgen, sphere_mask, r, inv_m, swizzle1(half,X));	/* r/m + 1/2 */
907f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
908f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       release_temp(p, tmp);
909f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       release_temp(p, r);
910f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       release_temp(p, inv_m);
911f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
912f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
913f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Could duplicate the above calculations, but it would be
914f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * a fairly odd state for someone to set (both sphere and
915f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * reflection active for different texture coordinate
916f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * components.  Of course - if two texture units enable
917f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * reflect and/or sphere, things start to tilt in favour
918f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * of seperating this out:
919f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
920f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (reflect_mask) {
921f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
922f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
923f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg tmp = get_temp(p);
924f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
925f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat);
926f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp);
927f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op3(p, VP_OPCODE_MAD, out_texgen, reflect_mask, negate(tmp), normal, eye_hat);
928f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
929f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
930f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (normal_mask) {
931f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
932f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op1(p, VP_OPCODE_MOV, out_texgen, normal_mask, normal );
933f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
934f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
935f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (copy_mask) {
936f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
937f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op1(p, VP_OPCODE_MOV, out_texgen, copy_mask, in );
938f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
939f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
940f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
941f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (texmat_enabled) {
942f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg texmat[4];
943f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg in = !is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i);
944f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 0, 3, 0, texmat );
945f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_matrix_transform_vec4( p, out, texmat, in );
946f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
947f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
948f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temps(p);
949f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
950f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
951f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
952f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
953f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
954f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Seems like it could be tighter:
955f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
956f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_pointsize( struct tnl_program *p )
957f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
958f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye = get_eye_position(p);
959f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg state_size = register_param1( p, STATE_POINT_SIZE );
960f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg state_attenuation = register_param1( p, STATE_POINT_ATTENUATION );
961f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg out = register_output( p, VERT_RESULT_PSIZ );
962f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg ut = get_temp(p);
963f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
964f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* 1, -Z, Z * Z, 1 */
965f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_MOV, ut, 0, swizzle1(get_identity_param(p), W));
966f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_YZ, ut, negate(swizzle1(eye, Z)));
967f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_Z, ut, negate(swizzle1(eye, Z)));
968f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
969f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
970f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* p1 +  p2 * dst + p3 * dst * dst, 0 */
971f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, ut, 0, ut, state_attenuation);
972f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
973f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* 1 / factor */
974f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_RCP, ut, 0, ut );
975f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
976f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* out = pointSize / factor */
977f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
978f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
979f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, ut);
980f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
981f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
982f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
983f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
984f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellvoid _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
985f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
986f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct tnl_program p;
987f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
988f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->VertexProgram._Enabled)
989f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return;
990f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
991f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   memset(&p, 0, sizeof(p));
992f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.ctx = ctx;
993f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program = &ctx->_TnlProgram;
994f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
995f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position = undef;
996f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position_normalized = undef;
997f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_normal = undef;
998f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.identity = undef;
999f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1000f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.temp_flag = 0;
1001f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.temp_reserved = ~((1<<MAX_NV_VERTEX_PROGRAM_TEMPS)-1);
1002f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1003f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p.program->Instructions == NULL) {
1004f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p.program->Instructions = MALLOC(sizeof(struct vp_instruction) * 100);
1005f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1006f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1007f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* Initialize the arb_program struct */
1008f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.String = 0;
1009f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumInstructions =
1010f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumTemporaries =
1011f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumParameters =
1012f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1013f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p.program->Parameters)
1014f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _mesa_free_parameter_list(p.program->Parameters);
1015f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Parameters = _mesa_new_parameter_list ();
1016f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->InputsRead = 0;
1017f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->OutputsWritten = 0;
1018f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1019f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* Emit the program, starting with modelviewproject:
1020f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1021f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   build_hpos(&p);
1022f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1023f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* Lighting calculations:
1024f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1025f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Light.Enabled)
1026f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      build_lighting(&p);
1027f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1028f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Fog.Enabled)
1029f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      build_fog(&p);
1030f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1031f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Texture._TexGenEnabled || ctx->Texture._TexMatEnabled)
1032f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      build_texture_transform(&p);
1033f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1034f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (ctx->Point._Attenuated)
1035f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      build_pointsize(&p);
1036f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1037f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1038f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* Finish up:
1039f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1040f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(&p, VP_OPCODE_END, undef, 0, undef);
1041f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1042f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* Disassemble:
1043f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1044f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (DISASSEM) {
1045f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _mesa_printf ("\n");
1046f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1047f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1048