t_vp_build.c revision a8534885efb13ec7f071192c1504513cd90d07de
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
205f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell * WHETHER IN
22f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
25f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
26f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/**
27f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * \file t_vp_build.c
28f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Create a vertex program to execute the current fixed function T&L pipeline.
29f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * \author Keith Whitwell
30f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
31f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
32f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
33f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "glheader.h"
34f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "macros.h"
35f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "enums.h"
36f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "t_context.h"
37f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "t_vp_build.h"
38f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
39f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/program.h"
40f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/nvvertprog.h"
41f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "shader/arbvertparse.h"
42f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
43a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstruct state_key {
44a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_global_enabled:1;
45a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_local_viewer:1;
46a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_twoside:1;
47a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_color_material:1;
48a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_color_material_mask:12;
49a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_material_mask:12;
50a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
51a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned normalize:1;
52a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned rescale_normals:1;
53a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned fog_source_is_depth:1;
54a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned tnl_do_vertex_fog:1;
55a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned separate_specular:1;
56a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned fog_enabled:1;
57a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned fog_mode:2;
58a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned point_attenuated:1;
59a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned nr_tex:4;
60a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned texgen_enabled_global:1;
61a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
62a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct {
63a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_enabled:1;
64a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_eyepos3_is_zero:1;
65a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_spotcutoff_is_180:1;
66a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_attenuated:1;
67a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texunit_really_enabled:1;
68a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texmat_enabled:1;
69a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_enabled:4;
70a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode0:4;
71a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode1:4;
72a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode2:4;
73a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode3:4;
74a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   } unit[8];
75a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell};
76a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
77a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
78a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
79a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define FOG_LINEAR   0
80a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define FOG_EXP      1
81a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define FOG_EXP2     2
82a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define FOG_UNKNOWN  3
83a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
84a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
85a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
86a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   switch (mode) {
87a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
88a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EXP: return FOG_EXP;
89a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EXP2: return FOG_EXP2;
90a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   default: return FOG_UNKNOWN;
91a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
92a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
93a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
94a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_NONE           0
95a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_OBJ_LINEAR     1
96a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_EYE_LINEAR     2
97a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_SPHERE_MAP     3
98a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_REFLECTION_MAP 4
99a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_NORMAL_MAP     5
100a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
101a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint translate_texgen( GLboolean enabled, GLenum mode )
102a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
103a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!enabled)
104a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      return TXG_NONE;
105a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
106a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   switch (mode) {
107a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;
108a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EYE_LINEAR: return TXG_EYE_LINEAR;
109a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_SPHERE_MAP: return TXG_SPHERE_MAP;
110a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;
111a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;
112a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   default: return TXG_NONE;
113a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
114a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
115a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
116a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic struct state_key *make_state_key( GLcontext *ctx )
117a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
118a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
119a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct vertex_buffer *VB = &tnl->vb;
120a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct state_key *key = CALLOC_STRUCT(state_key);
121a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint i;
122a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
123a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   key->separate_specular = (ctx->Light.Model.ColorControl ==
124a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			     GL_SEPARATE_SPECULAR_COLOR);
125a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
126a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Light.Enabled) {
127a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->light_global_enabled = 1;
128a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
129a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.Model.LocalViewer)
130a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_local_viewer = 1;
131a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
132a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.Model.TwoSide)
133a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_twoside = 1;
134a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
135a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.ColorMaterialEnabled)
136a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_color_material = 1;
137a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
138a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.ColorMaterialBitmask)
139a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_color_material_mask = 1;
140a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
141a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; i < _TNL_ATTRIB_INDEX ; i++)
142a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (VB->AttribPtr[i]->stride)
143a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    key->light_material_mask |= 1<<i;
144a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
145a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      for (i = 0; i < MAX_LIGHTS; i++) {
146a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 struct gl_light *light = &ctx->Light.Light[i];
147a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
148a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (light->Enabled) {
149a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    key->unit[i].light_enabled = 1;
150a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
151a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->EyePosition[3] == 0.0)
152a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_eyepos3_is_zero = 1;
153a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
154a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->SpotCutoff == 180.0)
155a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_spotcutoff_is_180 = 1;
156a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
157a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->ConstantAttenuation != 1.0 ||
158a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		light->LinearAttenuation != 1.0 ||
159a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		light->QuadraticAttenuation != 1.0)
160a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_attenuated = 1;
161a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 }
162a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      }
163a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
164a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
165a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Transform.Normalize)
166a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->normalize = 1;
167f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
168a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Transform.RescaleNormals)
169a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->rescale_normals = 1;
170a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
171a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Fog.Enabled)
172a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->fog_enabled = 1;
173a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
174a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (key->fog_enabled) {
175a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
176a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->fog_source_is_depth = 1;
177a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
178a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (tnl->_DoVertexFog)
179a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->tnl_do_vertex_fog = 1;
180a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
181a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
182a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
183a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
184a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Point._Attenuated)
185a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->point_attenuated = 1;
186a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
187a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Texture._TexGenEnabled)
188a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->texgen_enabled_global = 1;
189a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
190a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
191a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
192a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
193a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (texUnit->_ReallyEnabled)
194a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texunit_really_enabled = 1;
195a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
196a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
197a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texmat_enabled = 1;
198a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
199a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (texUnit->TexGenEnabled) {
200a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_enabled = 1;
201a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
202a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode0 =
203a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<0),
204a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeS );
205a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode1 =
206a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<1),
207a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeT );
208a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode2 =
209a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<2),
210a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeR );
211a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode3 =
212a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<3),
213a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeQ );
214a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      }
215a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
216a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
217a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return key;
218a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
219a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
220a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
221a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
222f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Very useful debugging tool - produces annotated listing of
223f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * generated program with line/function references for each
224f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * instruction back into this file:
225f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
2265f430c9976c71d7167f9327623e1df5fce53a970Keith Whitwell#define DISASSEM 0
22710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
22810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell/* Should be tunable by the driver - do we want to do matrix
22910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell * multiplications with DP4's or with MUL/MAD's?  SSE works better
23010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell * with the latter, drivers may differ.
23110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell */
232a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define PREFER_DP4 0
233f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
2342fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell#define MAX_INSN 200
2352fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell
236f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Use uregs to represent registers internally, translate to Mesa's
237f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * expected formats on emit.
238f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
239f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * NOTE: These are passed by value extensively in this file rather
240f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * than as usual by pointer reference.  If this disturbs you, try
241f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * remembering they are just 32bits in size.
242f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
243f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * GCC is smart enough to deal with these dword-sized structures in
244f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * much the same way as if I had defined them as dwords and was using
245f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * macros to access and set the fields.  This is much nicer and easier
246f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * to evolve.
247f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
248f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct ureg {
249f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint file:4;
250f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx:8;
251f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint negate:1;
252f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint swz:12;
253f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint pad:7;
254f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
256f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
257f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct tnl_program {
258a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const struct state_key *state;
259f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct vertex_program *program;
260f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
2613509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   GLuint temp_in_use;
262f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint temp_reserved;
263f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
264f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position;
265f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position_normalized;
266f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_normal;
267f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg identity;
268f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
269f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint materials;
270f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint color_materials;
271f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
272f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
273f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
274f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellconst static struct ureg undef = {
275f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   ~0,
276f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   ~0,
277f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
278f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
279f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0
280f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
281f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Local shorthand:
283f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
284f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define X    SWIZZLE_X
285f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Y    SWIZZLE_Y
286f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Z    SWIZZLE_Z
287f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define W    SWIZZLE_W
288f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
289f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
290f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Construct a ureg:
291f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
292f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
293f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
294f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg reg;
295f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.file = file;
296f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.idx = idx;
297f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate = 0;
298f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = SWIZZLE_NOOP;
299f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.pad = 0;
300f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
301f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
302f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
303f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
304f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
305f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg negate( struct ureg reg )
306f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
307f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate ^= 1;
308f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
309f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
310f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
311f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
312f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
313f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
314f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
315f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, y),
316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, z),
317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, w));
318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
319f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
320f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
321f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
323f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
324f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return swizzle(reg, x, x, x, x);
325f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
326f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
327f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_temp( struct tnl_program *p )
328f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
3293509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   int bit = ffs( ~p->temp_in_use );
330f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (!bit) {
331f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      fprintf(stderr, "%s: out of temporaries\n", __FILE__);
332f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      exit(1);
333f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
334f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
3353509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
336f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_TEMPORARY, bit-1);
337f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
338f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
339f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg reserve_temp( struct tnl_program *p )
340f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
341f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg temp = get_temp( p );
342f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->temp_reserved |= 1<<temp.idx;
343f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return temp;
344f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
345f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
346f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temp( struct tnl_program *p, struct ureg reg )
347f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
348f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY) {
3493509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p->temp_in_use &= ~(1<<reg.idx);
3503509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p->temp_in_use |= p->temp_reserved; /* can't release reserved temps */
351f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
352f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
353f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
354f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temps( struct tnl_program *p )
355f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
3563509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p->temp_in_use = p->temp_reserved;
357f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
358f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
359f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
360f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
361f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_input( struct tnl_program *p, GLuint input )
362f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
363f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->program->InputsRead |= (1<<input);
364f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_INPUT, input);
365f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
366f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
367f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_output( struct tnl_program *p, GLuint output )
368f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
369f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->program->OutputsWritten |= (1<<output);
370f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_OUTPUT, output);
371f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
372f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
373f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_const4f( struct tnl_program *p,
374f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s0,
375f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s1,
376f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s2,
377f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s3)
378f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
379f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLfloat values[4];
380f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx;
381f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[0] = s0;
382f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[1] = s1;
383f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[2] = s2;
384f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[3] = s3;
385f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
386f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
387f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
388f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
389f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
39096582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
391f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
392f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
393f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
394f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLboolean is_undef( struct ureg reg )
395f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
396f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg.file == 0xf;
397f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
398f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
399f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_identity_param( struct tnl_program *p )
400f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
401f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->identity))
402f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->identity = register_const4f(p, 0,0,0,1);
403f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
404f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->identity;
405f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
406f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
407f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_param6( struct tnl_program *p,
408f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s0,
409f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s1,
410f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s2,
411f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s3,
412f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s4,
413f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s5)
414f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
415f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLint tokens[6];
416f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint idx;
417f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[0] = s0;
418f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[1] = s1;
419f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[2] = s2;
420f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[3] = s3;
421f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[4] = s4;
422f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[5] = s5;
423f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   idx = _mesa_add_state_reference( p->program->Parameters, tokens );
424f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
425f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
426f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
427f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
428f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
429f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
430f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
431f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
432f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
433f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
434f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void register_matrix_param6( struct tnl_program *p,
435f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s0,
436f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s1,
437f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s2,
438f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s3,
439f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s4,
440f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    GLint s5,
441f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    struct ureg *matrix )
442f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
443f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
444f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
445f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* This is a bit sad as the support is there to pull the whole
446f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    * matrix out in one go:
447f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
448f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i <= s4 - s3; i++)
449f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
450f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
451f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
452f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
453f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_arg( struct vp_src_register *src,
454f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg )
455f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
456f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->File = reg.file;
457f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Index = reg.idx;
458f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Swizzle = reg.swz;
459f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Negate = reg.negate;
460f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->RelAddr = 0;
461f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->pad = 0;
462f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
463f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
464f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_dst( struct vp_dst_register *dst,
465f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg, GLuint mask )
466f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
467f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->File = reg.file;
468f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->Index = reg.idx;
4695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* allow zero as a shorthand for xyzw */
4705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
471f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->pad = 0;
472f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
473f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4745f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void debug_insn( struct vp_instruction *inst, const char *fn,
4755f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			GLuint line )
476f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
477f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#if DISASSEM
478f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   static const char *last_fn;
479f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
480f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (fn != last_fn) {
481f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      last_fn = fn;
482f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _mesa_printf("%s:\n", fn);
483f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
484f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
485f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   _mesa_printf("%d:\t", line);
486f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   _mesa_debug_vp_inst(1, inst);
487f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#endif
488f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
489f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
490f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
491f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_op3fn(struct tnl_program *p,
492f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint op,
493f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg dest,
494f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint mask,
495f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src0,
496f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src1,
497f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src2,
498f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       const char *fn,
499f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint line)
500f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
501f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
502f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct vp_instruction *inst = &p->program->Instructions[nr];
503f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5042fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   if (p->program->Base.NumInstructions > MAX_INSN) {
505a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_problem(0, "Out of instructions in emit_op3fn\n");
5062fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell      return;
5072fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   }
5082fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell
509f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   inst->Opcode = op;
510dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->StringPos = 0;
511dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->Data = 0;
512f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
513f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
514f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
515f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
516f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
517f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_dst( &inst->DstReg, dest, mask );
518f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
519f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   debug_insn(inst, fn, line);
520f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
521f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
522f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
523f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5245f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op3(p, op, dst, mask, src0, src1, src2) \
5255f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
5265f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5275f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op2(p, op, dst, mask, src0, src1) \
5285f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
5295f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op1(p, op, dst, mask, src0) \
5315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
532f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
533f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
534f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_temp( struct tnl_program *p, struct ureg reg )
535f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
536f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY &&
537f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       !(p->temp_reserved & (1<<reg.idx)))
538f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return reg;
539f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
540f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg temp = get_temp(p);
541f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, temp, 0, reg);
542f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return temp;
543f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
544f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
545f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
546f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
547f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Currently no tracking performed of input/output/register size or
548f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * active elements.  Could be used to reduce these operations, as
549f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * could the matrix type.
550f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
551f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec4( struct tnl_program *p,
552f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
553f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
554f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
555f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
556f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
557f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
558f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
559f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
5605f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
5615f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
56247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell/* This version is much easier to implement if writemasks are not
56347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * supported natively on the target or (like SSE), the target doesn't
56447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * have a clean/obvious dotproduct implementation.
56547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell */
5665f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void emit_transpose_matrix_transform_vec4( struct tnl_program *p,
5675f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg dest,
5685f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  const struct ureg *mat,
5695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg src)
5705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
5715f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp;
5725f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5735f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
5745f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = get_temp(p);
5755f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   else
5765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = dest;
577f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
5795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3(p, VP_OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
5805f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3(p, VP_OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
5815f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3(p, VP_OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
5825f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
5845f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, tmp);
585f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
586f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
587f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec3( struct tnl_program *p,
588f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
589f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
590f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
591f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
592f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
593f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
594f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
595f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
596f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
597f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
598f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_normalize_vec3( struct tnl_program *p,
599f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg dest,
600f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg src )
601f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
602f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg tmp = get_temp(p);
603f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, tmp, 0, src, src);
604f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp);
605f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, dest, 0, src, tmp);
606f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, tmp);
607f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
608f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
60910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwellstatic void emit_passthrough( struct tnl_program *p,
61010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint input,
61110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint output )
61210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell{
61310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   struct ureg out = register_output(p, output);
61410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   emit_op1(p, VP_OPCODE_MOV, out, 0, register_input(p, input));
61510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell}
61610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
617f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position( struct tnl_program *p )
618f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
619f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position)) {
620f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg pos = register_input( p, VERT_ATTRIB_POS );
621f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg modelview[4];
622f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
623f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position = reserve_temp(p);
624f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
62510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (PREFER_DP4) {
62610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3,
62710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				 STATE_MATRIX, modelview );
62810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
62910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
63010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
63110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      else {
63210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3,
63310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				 STATE_MATRIX_TRANSPOSE, modelview );
63410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
63510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
63610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
637f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
638f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
639f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position;
640f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
641f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
642f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
643f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position_normalized( struct tnl_program *p )
644f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
645f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position_normalized)) {
646f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg eye = get_eye_position(p);
647f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position_normalized = reserve_temp(p);
648f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_normalize_vec3(p, p->eye_position_normalized, eye);
649f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
650f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
651f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position_normalized;
652f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
653f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
654f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
655f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_normal( struct tnl_program *p )
656f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
657f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_normal)) {
658f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
659f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg mvinv[3];
660f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
6615f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2,
6625f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      STATE_MATRIX_INVTRANS, mvinv );
663f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
664f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_normal = reserve_temp(p);
665f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
666f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Transform to eye space:
667f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
668f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
669f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
670f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Normalize/Rescale:
671f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
672a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->normalize) {
673f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
674f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
675a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      else if (p->state->rescale_normals) {
6765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 struct ureg rescale = register_param2(p, STATE_INTERNAL,
6775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_NORMAL_SCALE);
6785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
6795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op2( p, VP_OPCODE_MUL, p->eye_normal, 0, normal,
6805f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell		   swizzle1(rescale, X));
681f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
682f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
683f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
684f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_normal;
685f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
686f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
687f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
688f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
689f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_hpos( struct tnl_program *p )
690f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
691f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg pos = register_input( p, VERT_ATTRIB_POS );
692f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
693f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg mvp[4];
694f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
69510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   if (PREFER_DP4) {
69610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3,
69710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      STATE_MATRIX, mvp );
69810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_matrix_transform_vec4( p, hpos, mvp, pos );
69910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
70010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   else {
70110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3,
70210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      STATE_MATRIX_TRANSPOSE, mvp );
70310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
70410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
705f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
706f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
707f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
708f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLuint material_attrib( GLuint side, GLuint property )
709f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
7105f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   return (_TNL_ATTRIB_MAT_FRONT_AMBIENT +
7115f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	   (property - STATE_AMBIENT) * 2 +
7125f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	   side);
713f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
714f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
715f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void set_material_flags( struct tnl_program *p )
716f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
717f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->color_materials = 0;
718f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->materials = 0;
719f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
720a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->light_color_material) {
721f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->materials =
722a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 p->color_materials = p->state->light_color_material_mask;
723f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
724f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
725a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p->materials |= p->state->light_material_mask;
726f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
727f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
728f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7295f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_material( struct tnl_program *p, GLuint side,
7305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint property )
731f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
732f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
733f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
734f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->color_materials & (1<<attrib))
735f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input(p, VERT_ATTRIB_COLOR0);
736f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else if (p->materials & (1<<attrib))
737f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input( p, attrib );
738f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
739f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param3( p, STATE_MATERIAL, side, property );
740f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
741f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
742f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define SCENE_COLOR_BITS(side) (( _TNL_BIT_MAT_FRONT_EMISSION | \
743f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   _TNL_BIT_MAT_FRONT_AMBIENT | \
744f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   _TNL_BIT_MAT_FRONT_DIFFUSE) << (side))
745f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
746f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Either return a precalculated constant value or emit code to
747f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * calculate these values dynamically in the case where material calls
748f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * are present between begin/end pairs.
749f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
750f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Probably want to shift this to the program compilation phase - if
751f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * we always emitted the calculation here, a smart compiler could
752f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * detect that it was constant (given a certain set of inputs), and
753f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * lift it out of the main loop.  That way the programs created here
754f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * would be independent of the vertex_buffer details.
755f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
756f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
757f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
758f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & SCENE_COLOR_BITS(side)) {
7595f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg lm_ambient = register_param1(p, STATE_LIGHTMODEL_AMBIENT);
760f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_emission = get_material(p, side, STATE_EMISSION);
761f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
762f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
763f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = make_temp(p, material_diffuse);
7645f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op3(p, VP_OPCODE_MAD, tmp,  WRITEMASK_XYZ, lm_ambient,
7655f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       material_ambient, material_emission);
766f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
767f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
768f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
769f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param2( p, STATE_LIGHTMODEL_SCENECOLOR, side );
770f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
771f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
772f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7735f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_lightprod( struct tnl_program *p, GLuint light,
7745f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint side, GLuint property )
775f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
776f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
777f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & (1<<attrib)) {
7785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg light_value =
7795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 register_param3(p, STATE_LIGHT, light, property);
780f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_value = get_material(p, side, property);
781f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
782f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op2(p, VP_OPCODE_MUL, tmp,  0, light_value, material_value);
783f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
784f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
785f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
786f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param4(p, STATE_LIGHTPROD, light, side, property);
787f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
788f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7895f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg calculate_light_attenuation( struct tnl_program *p,
7905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						GLuint i,
7915f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg VPpli,
7925f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg dist )
7935f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
7945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg attenuation = register_param3(p, STATE_LIGHT, i,
7955f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					     STATE_ATTENUATION);
7965f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg att = get_temp(p);
7975f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
7985f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate spot attenuation:
7995f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
800a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!p->state->unit[i].light_spotcutoff_is_180) {
8015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg spot_dir = register_param3(p, STATE_LIGHT, i,
8025f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					     STATE_SPOT_DIRECTION);
8035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg spot = get_temp(p);
8045f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg slt = get_temp(p);
8055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_normalize_vec3( p, spot, spot_dir ); /* XXX: precompute! */
8075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_DP3, spot, 0, negate(VPpli), spot_dir);
8085f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_SLT, slt, 0, swizzle1(spot_dir,W), spot);
8095f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
8105f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_MUL, att, 0, slt, spot);
8115f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8125f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, spot);
8135f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, slt);
8145f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8155f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8165f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate distance attenuation:
8175f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
818a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->unit[i].light_attenuated) {
8195f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8205f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/d,d,d,1/d */
8215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op1(p, VP_OPCODE_RCP, dist, WRITEMASK_YZ, dist);
8225f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1,d,d*d,1/d */
8235f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
8245f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/dist-atten */
8255f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op2(p, VP_OPCODE_DP3, dist, 0, attenuation, dist);
8265f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
827a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (!p->state->unit[i].light_spotcutoff_is_180) {
8285f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8295f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op1(p, VP_OPCODE_RCP, dist, 0, dist);
8305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* spot-atten * dist-atten */
8315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, att, 0, dist, att);
8325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      } else {
8335f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op1(p, VP_OPCODE_RCP, att, 0, dist);
8355f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      }
8365f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8375f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   return att;
8395f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
8405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8415f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
842f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
843f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
844f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
845f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Need to add some addtional parameters to allow lighting in object
846f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
847f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space lighting.
848f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
849f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_lighting( struct tnl_program *p )
850f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
851a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean twoside = p->state->light_twoside;
852a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean separate = p->state->separate_specular;
853f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr_lights = 0, count = 0;
854f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg normal = get_eye_normal(p);
855f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg lit = get_temp(p);
856f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg dots = get_temp(p);
857f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _col0 = undef, _col1 = undef;
858f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _bfc0 = undef, _bfc1 = undef;
859f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
860f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
861f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++)
862a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled)
863f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 nr_lights++;
864f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
865f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   set_material_flags(p);
866f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
867f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   {
868f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 0, STATE_SHININESS);
869f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, dots,  WRITEMASK_W, swizzle1(shininess,X));
870f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
871f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
872f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _col0 = make_temp(p, get_scenecolor(p, 0));
873f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
874f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = make_temp(p, get_identity_param(p));
875f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
876f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = _col0;
877f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
878f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
879f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
880f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (twoside) {
881f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 1, STATE_SHININESS);
8825f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, dots, WRITEMASK_Z,
8835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       negate(swizzle1(shininess,X)));
884f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
885f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
886f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _bfc0 = make_temp(p, get_scenecolor(p, 1));
887f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
888f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = make_temp(p, get_identity_param(p));
889f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
890f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = _bfc0;
891f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
892f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
89310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
89410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   /* If no lights, still need to emit the scenecolor.
89510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell    */
89610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   if (nr_lights == 0) {
89710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      {
89810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
89910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_op1(p, VP_OPCODE_MOV, res0, 0, _col0);
90010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
90110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
90210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (separate) {
90310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
90410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_op1(p, VP_OPCODE_MOV, res1, 0, _col1);
90510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
90610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
90710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside) {
90810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
90910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_op1(p, VP_OPCODE_MOV, res0, 0, _bfc0);
91010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
91110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
91210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside && separate) {
91310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
91410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_op1(p, VP_OPCODE_MOV, res1, 0, _bfc1);
91510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
91610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
91710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      release_temps(p);
91810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      return;
91910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
92010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
92110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
922f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++) {
923a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled) {
924f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg half = undef;
925f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg att = undef, VPpli = undef;
926f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
927f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 count++;
928f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
929a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].light_eyepos3_is_zero) {
93047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	    /* Can used precomputed constants in this case.
93147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	     * Attenuation never applies to infinite lights.
932f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9335f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    VPpli = register_param3(p, STATE_LIGHT, i,
9345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				    STATE_POSITION_NORMALIZED);
935f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
936f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
937f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 else {
9385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg Ppli = register_param3(p, STATE_LIGHT, i,
9395f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_POSITION);
940f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg V = get_eye_position(p);
9415f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg dist = get_temp(p);
942f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
943f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    VPpli = get_temp(p);
944f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = get_temp(p);
945f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
946f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calulate VPpli vector
947f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
948f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op2(p, VP_OPCODE_SUB, VPpli, 0, Ppli, V);
949f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9505f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    /* Normalize VPpli.  The dist value also used in
951f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * attenuation below.
952f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    emit_op2(p, VP_OPCODE_DP3, dist, 0, VPpli, VPpli);
9545f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    emit_op1(p, VP_OPCODE_RSQ, dist, 0, dist);
9555f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    emit_op2(p, VP_OPCODE_MUL, VPpli, 0, VPpli, dist);
956f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
957f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
958f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate  attenuation:
959f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
960a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (!p->state->unit[i].light_spotcutoff_is_180 ||
961a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		p->state->unit[i].light_attenuated) {
962a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       att = calculate_light_attenuation(p, i, VPpli, dist);
963f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
964f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
965f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
966f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate viewer direction, or use infinite viewer:
967f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
968a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (p->state->light_local_viewer) {
969f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
970f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_SUB, half, 0, VPpli, eye_hat);
971f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
972f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else {
9735f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
974f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_ADD, half, 0, VPpli, z_dir);
975f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
976f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
977f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_normalize_vec3(p, half, half);
978f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    release_temp(p, dist);
980f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
981f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
982f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Calculate dot products:
983f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
984f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
985f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
986f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
987f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
988f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Front face lighting:
989f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
990f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 {
991f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT);
992f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE);
993f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR);
994f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
995f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
996f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op1(p, VP_OPCODE_LIT, lit, 0, dots);
997f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
998f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
999f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
1000f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
100147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1002f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1003f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1004f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_COL0 );
1005f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL1 );
1006f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1007f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1008f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _col0;
1009f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL0 );
1010f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1011f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1012f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _col0;
1013f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _col1;
1014f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1015f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1016f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
1017f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res0, 0, swizzle1(lit,Y), diffuse, _col0);
1018f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res1, 0, swizzle1(lit,Z), specular, _col1);
1019f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1020f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1021f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1022f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1023f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1024f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1025f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Back face lighting:
1026f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
1027f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (twoside) {
1028f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT);
1029f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE);
1030f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
1031f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
1032f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1033f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op1(p, VP_OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
1034f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1035f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
1036f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att);
1037f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1038f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1039f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1040f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_BFC0 );
1041f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC1 );
1042f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1043f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1044f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _bfc0;
1045f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC0 );
1046f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1047f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1048f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _bfc0;
1049f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _bfc1;
1050f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1051f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1052f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1053f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
1054f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res0, 0, swizzle1(lit,Y), diffuse, _bfc0);
1055f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_op3(p, VP_OPCODE_MAD, res1, 0, swizzle1(lit,Z), specular, _bfc1);
1056f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1057f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1058f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1059f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1060f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1061f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1062f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, half);
1063f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, VPpli);
1064f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, att);
1065f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1066f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1067f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1068f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temps( p );
1069f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1070f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1071f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1072f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_fog( struct tnl_program *p )
1073f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1074f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg fog = register_output(p, VERT_RESULT_FOGC);
1075f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg input;
10765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
1077a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->fog_source_is_depth) {
1078f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(get_eye_position(p), Z);
1079f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1080f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1081f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
1082f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1083f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1084a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->tnl_do_vertex_fog) {
1085f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg params = register_param1(p, STATE_FOG_PARAMS);
1086f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
1087f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1088a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      switch (p->state->fog_mode) {
1089a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_LINEAR: {
1090f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg id = get_identity_param(p);
1091f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_SUB, tmp, 0, swizzle1(params,Z), input);
1092f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,W));
1093f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
10945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op2(p, VP_OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
1095f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1096f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1097a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP:
1098f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op1(p, VP_OPCODE_ABS, tmp, 0, input);
1099f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, swizzle1(params,X));
11005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X,
11015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell		  register_const1f(p, M_E), negate(tmp));
1102f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1103a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP2:
1104f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, input, swizzle1(params,X));
1105f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_op2(p, VP_OPCODE_MUL, tmp, 0, tmp, tmp);
11065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 emit_op2(p, VP_OPCODE_POW, fog, WRITEMASK_X,
11075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell		  register_const1f(p, M_E), negate(tmp));
1108f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1109f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1110f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1111f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, tmp);
1112f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1113f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1114f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* results = incoming fog coords (compute fog per-fragment later)
1115f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       *
1116f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       * KW:  Is it really necessary to do anything in this case?
1117f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
1118f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_op1(p, VP_OPCODE_MOV, fog, WRITEMASK_X, input);
1119f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1120f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
11215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11225f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_reflect_texgen( struct tnl_program *p,
11235f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  struct ureg dest,
11245f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint writemask )
11255f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11265f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
11275f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
11285f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
1129f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
11305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
11315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat);
11325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
11335f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp);
11345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
11355f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3(p, VP_OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
11365f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
11375f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_sphere_texgen( struct tnl_program *p,
11395f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 struct ureg dest,
11405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint writemask )
11415f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11425f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
11435f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
11445f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
114596582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell   struct ureg half = register_scalar_const(p, .5);
11465f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg r = get_temp(p);
11475f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg inv_m = get_temp(p);
11485f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg id = get_identity_param(p);
11495f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11505f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Could share the above calculations, but it would be
11515f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * a fairly odd state for someone to set (both sphere and
11525f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflection active for different texture coordinate
11535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * components.  Of course - if two texture units enable
11545f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflect and/or sphere, things start to tilt in favour
11555f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * of seperating this out:
11565f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
11575f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11585f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
11595f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, tmp, 0, normal, eye_hat);
11605f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
11615f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_ADD, tmp, 0, tmp, tmp);
11625f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
11635f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3(p, VP_OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
11645f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r + 0,0,1 */
11655f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
11665f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* rx^2 + ry^2 + (rz+1)^2 */
11675f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, tmp, 0, tmp, tmp);
11685f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2/m */
11695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op1(p, VP_OPCODE_RSQ, tmp, 0, tmp);
11705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 1/m */
117196582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell   emit_op2(p, VP_OPCODE_MUL, inv_m, 0, tmp, half);
11725f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r/m + 1/2 */
117396582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell   emit_op3(p, VP_OPCODE_MAD, dest, writemask, r, inv_m, half);
11745f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11755f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, tmp);
11765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, r);
11775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, inv_m);
11785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
1179f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1180f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1181f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_texture_transform( struct tnl_program *p )
1182f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1183f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i, j;
1184f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1185a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
1186a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
1187f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1188a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].texgen_enabled || texmat_enabled) {
118910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
1190f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg out_texgen = undef;
1191f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1192a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].texgen_enabled) {
1193f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint copy_mask = 0;
1194f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint sphere_mask = 0;
1195f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint reflect_mask = 0;
1196f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint normal_mask = 0;
1197f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint modes[4];
1198f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1199f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (texmat_enabled)
1200f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = get_temp(p);
1201f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else
1202f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = out;
1203f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1204a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[0] = p->state->unit[i].texgen_mode0;
1205a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[1] = p->state->unit[i].texgen_mode1;
1206a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[2] = p->state->unit[i].texgen_mode2;
1207a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[3] = p->state->unit[i].texgen_mode3;
1208f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1209f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    for (j = 0; j < 4; j++) {
1210a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       switch (modes[j]) {
1211a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_OBJ_LINEAR: {
1212a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg obj = register_input(p, VERT_ATTRIB_POS);
1213a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1214a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1215a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_OBJECT_S + j);
1216a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1217a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1218a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   obj, plane );
1219a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1220f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1221a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_EYE_LINEAR: {
1222a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg eye = get_eye_position(p);
1223a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1224a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1225a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_EYE_S + j);
1226a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1227a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  emit_op2(p, VP_OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1228a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   eye, plane );
1229a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1230a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1231a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_SPHERE_MAP:
1232a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  sphere_mask |= WRITEMASK_X << j;
1233a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1234a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_REFLECTION_MAP:
1235a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  reflect_mask |= WRITEMASK_X << j;
1236a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1237a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NORMAL_MAP:
1238a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  normal_mask |= WRITEMASK_X << j;
1239a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1240a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NONE:
1241f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  copy_mask |= WRITEMASK_X << j;
1242a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1243a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1244f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1245f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1246f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1247f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (sphere_mask) {
12485f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_sphere_texgen(p, out_texgen, sphere_mask);
1249f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1250f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1251f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (reflect_mask) {
12525f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_reflect_texgen(p, out_texgen, reflect_mask);
1253f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1254f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (normal_mask) {
1256f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
1257f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op1(p, VP_OPCODE_MOV, out_texgen, normal_mask, normal );
1258f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1259f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1260f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (copy_mask) {
1261f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
1262f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       emit_op1(p, VP_OPCODE_MOV, out_texgen, copy_mask, in );
1263f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1264f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1265f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1266f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (texmat_enabled) {
1267f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg texmat[4];
12685f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg in = (!is_undef(out_texgen) ?
12695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      out_texgen :
12705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      register_input(p, VERT_ATTRIB_TEX0+i));
127110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    if (PREFER_DP4) {
127210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i,
127310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				       0, 3, STATE_MATRIX, texmat );
127410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       emit_matrix_transform_vec4( p, out, texmat, in );
127510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
127610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    else {
127710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i,
127810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				       0, 3, STATE_MATRIX_TRANSPOSE, texmat );
127910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       emit_matrix_transform_vec4( p, out, texmat, in );
128010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
1281f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1283f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temps(p);
128410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
1285a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      else if (p->state->unit[i].texunit_really_enabled) {
128610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 /* KW: _ReallyEnabled isn't sufficient?  Need to know whether
128710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	  * this texture unit is referenced by the fragment shader.
128810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	  */
128910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
1290f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1291f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1292f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1293f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1294f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1295f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Seems like it could be tighter:
1296f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
1297f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_pointsize( struct tnl_program *p )
1298f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1299f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye = get_eye_position(p);
13005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_size = register_param1(p, STATE_POINT_SIZE);
13015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION);
13025f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg out = register_output(p, VERT_RESULT_PSIZ);
1303f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg ut = get_temp(p);
1304f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1305f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* 1, -Z, Z * Z, 1 */
1306f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_MOV, ut, 0, swizzle1(get_identity_param(p), W));
1307f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_YZ, ut, negate(swizzle1(eye, Z)));
1308f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, ut, WRITEMASK_Z, ut, negate(swizzle1(eye, Z)));
1309f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1310f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
13115f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* p1 +  p2 * dist + p3 * dist * dist, 0 */
1312f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_DP3, ut, 0, ut, state_attenuation);
1313f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1314f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* 1 / factor */
1315f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op1(p, VP_OPCODE_RCP, ut, 0, ut );
1316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* out = pointSize / factor */
1318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_op2(p, VP_OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
1319f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1320f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, ut);
1321f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1323a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void build_tnl_program( struct tnl_program *p )
1324a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{   /* Emit the program, starting with modelviewproject:
1325a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1326a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_hpos(p);
1327a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1328a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Lighting calculations:
1329a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1330a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->light_global_enabled)
1331a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_lighting(p);
1332a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   else
1333a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
1334f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1335a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->fog_enabled)
1336a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_fog(p);
13375a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1338a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->nr_tex)
1339a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_texture_transform(p);
13405a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1341a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->point_attenuated)
1342a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_pointsize(p);
13435a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1344a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Finish up:
1345a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1346a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   emit_op1(p, VP_OPCODE_END, undef, 0, undef);
13475a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1348a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Disassemble:
1349a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1350a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (DISASSEM) {
1351a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_printf ("\n");
1352a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
13535a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell}
13545a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1355f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1356a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid create_new_program( const struct state_key *key,
1357a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			 struct vertex_program *program,
1358a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			 GLuint max_temps)
1359f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1360f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct tnl_program p;
1361f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
136249d8cbe8d110e5c0a23300b5b82d110286bc3609Keith Whitwell   _mesa_memset(&p, 0, sizeof(p));
1363a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.state = key;
1364a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.program = program;
1365f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position = undef;
1366f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position_normalized = undef;
1367f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_normal = undef;
1368f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.identity = undef;
13693509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p.temp_in_use = 0;
1370a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1371a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (max_temps >= sizeof(int) * 8)
13723509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p.temp_reserved = 0;
13733509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   else
1374a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      p.temp_reserved = ~((1<<max_temps)-1);
13753509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell
13762fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   p.program->Instructions = MALLOC(sizeof(struct vp_instruction) * MAX_INSN);
1377f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.String = 0;
1378f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumInstructions =
1379f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumTemporaries =
1380f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumParameters =
1381f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1382a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.program->Parameters = _mesa_new_parameter_list();
1383f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->InputsRead = 0;
1384f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->OutputsWritten = 0;
1385f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1386a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_tnl_program( &p );
1387a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1388f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1389a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void *search_cache( struct tnl_cache *cache,
1390a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint hash,
1391a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   const void *key,
1392a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint keysize)
1393a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1394a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct tnl_cache *c;
1395a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1396a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (c = cache; c; c = c->next) {
1397a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
1398a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 return c->data;
1399a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1400a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1401a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return NULL;
1402a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1403a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1404a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void cache_item( struct tnl_cache **cache,
1405a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			GLuint hash,
1406a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *key,
1407a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *data )
1408a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1409a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct tnl_cache *c = MALLOC(sizeof(*c));
1410a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->hash = hash;
1411a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->key = key;
1412a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->data = data;
1413a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->next = *cache;
1414a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   *cache = c;
1415a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1416a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1417a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint hash_key( struct state_key *key )
1418a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1419a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint *ikey = (GLuint *)key;
1420a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash = 0, i;
1421a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1422a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* I'm sure this can be improved on, but speed is important:
1423f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1424a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++)
1425a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      hash ^= ikey[i];
1426f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1427a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return hash;
1428a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1429f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1430a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
1431a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1432a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
1433a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct state_key *key;
1434a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash;
1435f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1436a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->VertexProgram._Enabled)
1437a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      return;
1438f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1439a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Grab all the relevent state and put it in a single structure:
1440f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1441a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   key = make_state_key(ctx);
1442a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   hash = hash_key(key);
1443f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1444a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Look for an already-prepared program for this state:
1445f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1446a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   ctx->_TnlProgram = (struct vertex_program *)
1447a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      search_cache( tnl->vp_cache, hash, key, sizeof(key) );
1448a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1449a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* OK, we'll have to build a new one:
1450a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1451a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!ctx->_TnlProgram) {
1452a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (0)
1453a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 _mesa_printf("Build new TNL program\n");
1454dbeea25bb834479a29712100888c862348112018Keith Whitwell
1455a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      ctx->_TnlProgram = (struct vertex_program *)
1456a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
1457dbeea25bb834479a29712100888c862348112018Keith Whitwell
1458a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      create_new_program( key, ctx->_TnlProgram,
1459a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			  ctx->Const.MaxVertexProgramTemps );
1460a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1461a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      cache_item(&tnl->vp_cache, hash, key, ctx->_TnlProgram );
14625a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell   }
1463a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   else {
1464a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (0)
1465a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 _mesa_printf("Found existing TNL program for key %x\n", hash);
1466a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1467a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1468a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Need a BindProgram callback for the driver?
1469a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1470a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1471a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1472a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1473a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_ProgramCacheDestroy( GLcontext *ctx )
1474a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1475a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
1476a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct tnl_cache *a, *tmp;
1477a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1478a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (a = tnl->vp_cache ; a; a = tmp) {
1479a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      tmp = a->next;
1480a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      FREE(a->key);
1481a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      FREE(a->data);
1482a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      FREE(a);
1483dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
1484f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1485