t_vp_build.c revision 6dd98e9853a6984150aa47467112e016c40a4ab4
1f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/*
2f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Mesa 3-D graphics library
36dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul * Version:  7.1
4f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
56dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul * Copyright (C) 2007  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"
36c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian Paul#include "shader/program.h"
37c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian Paul#include "shader/prog_instruction.h"
38c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian Paul#include "shader/prog_parameter.h"
39c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian Paul#include "shader/prog_print.h"
40c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian Paul#include "shader/prog_statevars.h"
410c6723aee564a7b320ca122c3c9b003c863cc714Brian Paul#include "t_context.h" /* NOTE: very light dependency on this */
42f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#include "t_vp_build.h"
43f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
44f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
45a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstruct state_key {
46a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_global_enabled:1;
47a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_local_viewer:1;
48a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_twoside:1;
49a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_color_material:1;
50a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_color_material_mask:12;
51a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned light_material_mask:12;
52a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
53a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned normalize:1;
54a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned rescale_normals:1;
55a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned fog_source_is_depth:1;
56a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned tnl_do_vertex_fog:1;
57a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned separate_specular:1;
58a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned fog_mode:2;
59a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   unsigned point_attenuated:1;
601c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell   unsigned texture_enabled_global:1;
61c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   unsigned fragprog_inputs_read:12;
62a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
63a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct {
64a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_enabled:1;
65a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_eyepos3_is_zero:1;
66a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_spotcutoff_is_180:1;
67a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned light_attenuated:1;
68a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texunit_really_enabled:1;
69a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texmat_enabled:1;
70a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_enabled:4;
71a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode0:4;
72a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode1:4;
73a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode2:4;
74a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      unsigned texgen_mode3:4;
75a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   } unit[8];
76a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell};
77a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
78a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
79a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
80c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell#define FOG_NONE   0
81c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell#define FOG_LINEAR 1
82c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell#define FOG_EXP    2
83c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell#define FOG_EXP2   3
84a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
85a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
86a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
87a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   switch (mode) {
88a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
89a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EXP: return FOG_EXP;
90a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EXP2: return FOG_EXP2;
91c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   default: return FOG_NONE;
92a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
93a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
94a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
95a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_NONE           0
96a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_OBJ_LINEAR     1
97a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_EYE_LINEAR     2
98a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_SPHERE_MAP     3
99a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_REFLECTION_MAP 4
100a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define TXG_NORMAL_MAP     5
101a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
102a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint translate_texgen( GLboolean enabled, GLenum mode )
103a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
104a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!enabled)
105a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      return TXG_NONE;
106a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
107a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   switch (mode) {
108a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;
109a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_EYE_LINEAR: return TXG_EYE_LINEAR;
110a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_SPHERE_MAP: return TXG_SPHERE_MAP;
111a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;
112a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;
113a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   default: return TXG_NONE;
114a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
115a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
116a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
117a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic struct state_key *make_state_key( GLcontext *ctx )
118a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
119a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
120a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct vertex_buffer *VB = &tnl->vb;
121122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
122a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct state_key *key = CALLOC_STRUCT(state_key);
123a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint i;
124a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
125c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* This now relies on texenvprogram.c being active:
126c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    */
127c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   assert(fp);
128c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
129de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   key->fragprog_inputs_read = fp->Base.InputsRead;
130c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
131a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   key->separate_specular = (ctx->Light.Model.ColorControl ==
132a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			     GL_SEPARATE_SPECULAR_COLOR);
133a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
134a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Light.Enabled) {
135a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->light_global_enabled = 1;
136a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
137a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.Model.LocalViewer)
138a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_local_viewer = 1;
139a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
140a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Light.Model.TwoSide)
141a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_twoside = 1;
142a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
143f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell      if (ctx->Light.ColorMaterialEnabled) {
144a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->light_color_material = 1;
145f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	 key->light_color_material_mask = ctx->Light.ColorMaterialBitmask;
146f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell      }
147a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
14894b30dc390f1fdd526c080080830016fad3e2ee2Brian Paul      for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++)
149a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (VB->AttribPtr[i]->stride)
150f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	    key->light_material_mask |= 1<<(i-_TNL_ATTRIB_MAT_FRONT_AMBIENT);
151a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
152a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      for (i = 0; i < MAX_LIGHTS; i++) {
153a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 struct gl_light *light = &ctx->Light.Light[i];
154a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
155a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (light->Enabled) {
156a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    key->unit[i].light_enabled = 1;
157a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
158a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->EyePosition[3] == 0.0)
159a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_eyepos3_is_zero = 1;
160a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
161a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->SpotCutoff == 180.0)
162a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_spotcutoff_is_180 = 1;
163a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
164a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (light->ConstantAttenuation != 1.0 ||
165729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell		light->LinearAttenuation != 0.0 ||
166729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell		light->QuadraticAttenuation != 0.0)
167a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       key->unit[i].light_attenuated = 1;
168a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 }
169a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      }
170a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
171a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
172a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Transform.Normalize)
173a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->normalize = 1;
174f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
175a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Transform.RescaleNormals)
176a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->rescale_normals = 1;
177a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
178c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   key->fog_mode = translate_fog_mode(fp->FogOption);
179c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
180c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
181c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      key->fog_source_is_depth = 1;
182c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
183c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (tnl->_DoVertexFog)
184c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      key->tnl_do_vertex_fog = 1;
185a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
186a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (ctx->Point._Attenuated)
187a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      key->point_attenuated = 1;
188a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1891c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell   if (ctx->Texture._TexGenEnabled ||
1901c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell       ctx->Texture._TexMatEnabled ||
1911c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell       ctx->Texture._EnabledUnits)
1921c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell      key->texture_enabled_global = 1;
1931c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell
194a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
195a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
196a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
197a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (texUnit->_ReallyEnabled)
198a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texunit_really_enabled = 1;
199a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
200a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
201a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texmat_enabled = 1;
202a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
203a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (texUnit->TexGenEnabled) {
204a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_enabled = 1;
205a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
206a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode0 =
207a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<0),
208a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeS );
209a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode1 =
210a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<1),
211a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeT );
212a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode2 =
213a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<2),
214a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeR );
215a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 key->unit[i].texgen_mode3 =
216a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    translate_texgen( texUnit->TexGenEnabled & (1<<3),
217a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			      texUnit->GenModeQ );
218a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      }
219a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
220a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
221a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return key;
222a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
223a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
224a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
225a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
226f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Very useful debugging tool - produces annotated listing of
227f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * generated program with line/function references for each
228f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * instruction back into this file:
229f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
230729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell#define DISASSEM (MESA_VERBOSE&VERBOSE_DISASSEM)
23110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
23210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell/* Should be tunable by the driver - do we want to do matrix
23310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell * multiplications with DP4's or with MUL/MAD's?  SSE works better
23410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell * with the latter, drivers may differ.
23510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell */
236a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell#define PREFER_DP4 0
237f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
238821b3dd562c0ec4560e50f29084c32653cf18c9dAapo Tahkola#define MAX_INSN 256
2392fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell
240f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Use uregs to represent registers internally, translate to Mesa's
241f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * expected formats on emit.
242f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
243f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * NOTE: These are passed by value extensively in this file rather
244f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * than as usual by pointer reference.  If this disturbs you, try
245f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * remembering they are just 32bits in size.
246f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
247f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * GCC is smart enough to deal with these dword-sized structures in
248f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * much the same way as if I had defined them as dwords and was using
249f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * macros to access and set the fields.  This is much nicer and easier
250f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * to evolve.
251f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
252f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct ureg {
253f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint file:4;
25461e694f270d8a4a03a3245b5e6eea805915ed74bBrian Paul   GLint idx:8;      /* relative addressing may be negative */
255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint negate:1;
256f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint swz:12;
257f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint pad:7;
258f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
259f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
260f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
261f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstruct tnl_program {
262a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const struct state_key *state;
263122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_vertex_program *program;
264f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
2653509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   GLuint temp_in_use;
266f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint temp_reserved;
267f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
268f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position;
269f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_position_normalized;
270f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye_normal;
271f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg identity;
272f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
273f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint materials;
274f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint color_materials;
275f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
276f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
277f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
278564b2aa2ef8d5b859bb51d39024373a4865e93e9Brian Paulstatic const struct ureg undef = {
279a89b099c74c0129c975d3f7ba1cdccc6a8d6b6beAlan Hourihane   PROGRAM_UNDEFINED,
280f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   ~0,
281f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0,
283f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   0
284f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell};
285f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
286f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Local shorthand:
287f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
288f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define X    SWIZZLE_X
289f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Y    SWIZZLE_Y
290f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define Z    SWIZZLE_Z
291f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define W    SWIZZLE_W
292f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
293f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
294f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Construct a ureg:
295f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
29660a6a0eb51a6cafc9f65bff8028510e0788cf311Brian Paulstatic struct ureg make_ureg(GLuint file, GLint idx)
297f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
298f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg reg;
299f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.file = file;
300f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.idx = idx;
301f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate = 0;
302f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = SWIZZLE_NOOP;
303f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.pad = 0;
304f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
305f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
306f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
307f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
308f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
309f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg negate( struct ureg reg )
310f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
311f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.negate ^= 1;
312f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
313f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
314f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
315f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
319f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, y),
320f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, z),
321f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			   GET_SWZ(reg.swz, w));
322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
323f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return reg;
324f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
325f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
326f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
327f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
328f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return swizzle(reg, x, x, x, x);
329f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
330f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
331f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_temp( struct tnl_program *p )
332f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
333b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   int bit = _mesa_ffs( ~p->temp_in_use );
334f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (!bit) {
335b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
336b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
337f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
338f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
339564b2aa2ef8d5b859bb51d39024373a4865e93e9Brian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
340c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      p->program->Base.NumTemporaries = bit;
341c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
3423509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
343f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_TEMPORARY, bit-1);
344f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
345f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
346f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg reserve_temp( struct tnl_program *p )
347f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
348f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg temp = get_temp( p );
349f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->temp_reserved |= 1<<temp.idx;
350f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return temp;
351f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
352f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
353f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temp( struct tnl_program *p, struct ureg reg )
354f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
355f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY) {
3563509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p->temp_in_use &= ~(1<<reg.idx);
3573509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p->temp_in_use |= p->temp_reserved; /* can't release reserved temps */
358f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
359f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
360f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
361f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void release_temps( struct tnl_program *p )
362f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
3633509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p->temp_in_use = p->temp_reserved;
364f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
365f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
366f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
367f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
368f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_input( struct tnl_program *p, GLuint input )
369f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
370de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p->program->Base.InputsRead |= (1<<input);
371f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_INPUT, input);
372f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
373f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
374f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_output( struct tnl_program *p, GLuint output )
375f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
376de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p->program->Base.OutputsWritten |= (1<<output);
377f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_OUTPUT, output);
378f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
379f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
380f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg register_const4f( struct tnl_program *p,
381f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s0,
382f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s1,
383f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s2,
384f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell			      GLfloat s3)
385f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
386f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLfloat values[4];
38760a6a0eb51a6cafc9f65bff8028510e0788cf311Brian Paul   GLint idx;
388a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   GLuint swizzle;
389f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[0] = s0;
390f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[1] = s1;
391f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[2] = s2;
392f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   values[3] = s3;
393a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
394a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul                                     &swizzle );
395a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   ASSERT(swizzle == SWIZZLE_NOOP);
396f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
397f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
398f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
399f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
40096582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
401f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
402f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
403f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
404f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLboolean is_undef( struct ureg reg )
405f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
406a89b099c74c0129c975d3f7ba1cdccc6a8d6b6beAlan Hourihane   return reg.file == PROGRAM_UNDEFINED;
407f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
408f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
409f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_identity_param( struct tnl_program *p )
410f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
411f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->identity))
412f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->identity = register_const4f(p, 0,0,0,1);
413f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
414f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->identity;
415f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
416f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
417fce8409cbbe6aa5309163f3d63894233b8833308Brian Paulstatic struct ureg register_param5(struct tnl_program *p,
418f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s0,
419f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s1,
420f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s2,
421f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				   GLint s3,
422fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul                                   GLint s4)
423f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
424fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul   gl_state_index tokens[STATE_LENGTH];
42560a6a0eb51a6cafc9f65bff8028510e0788cf311Brian Paul   GLint idx;
426f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[0] = s0;
427f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[1] = s1;
428f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[2] = s2;
429f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[3] = s3;
430f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   tokens[4] = s4;
431de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
432f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
433f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
434f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
435f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
436fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
437fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
438fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
439fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
440f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
441f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
442fce8409cbbe6aa5309163f3d63894233b8833308Brian Paulstatic void register_matrix_param5( struct tnl_program *p,
443fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				    GLint s0, /* modelview, projection, etc */
444fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				    GLint s1, /* texture matrix number */
445fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				    GLint s2, /* first row */
446fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				    GLint s3, /* last row */
447fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				    GLint s4, /* inverse, transpose, etc */
448f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				    struct ureg *matrix )
449f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
450564b2aa2ef8d5b859bb51d39024373a4865e93e9Brian Paul   GLint i;
451f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
452f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   /* This is a bit sad as the support is there to pull the whole
453f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    * matrix out in one go:
454f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
455fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul   for (i = 0; i <= s3 - s2; i++)
456fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      matrix[i] = register_param5( p, s0, s1, i, i, s4 );
457f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
458f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
459f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4606dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul/**
4616dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul * Convert a ureg source register to a prog_src_register.
4626dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul */
4637e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *src,
464f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg )
465f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
4666dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul   assert(reg.file != PROGRAM_OUTPUT);
467f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->File = reg.file;
468f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Index = reg.idx;
469f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Swizzle = reg.swz;
47016d1024f27695bd9ceb86ffcdda960396a23ed2cAapo Tahkola   src->NegateBase = reg.negate ? NEGATE_XYZW : 0;
4717e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   src->Abs = 0;
4727e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   src->NegateAbs = 0;
473f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->RelAddr = 0;
474f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
475f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4766dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul/**
4776dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul * Convert a ureg dest register to a prog_dst_register.
4786dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul */
4797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
480f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg, GLuint mask )
481f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
4826dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul   /* Check for legal output register type.  UNDEFINED will occur in
4836dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul    * instruction that don't produce a result (like END).
4846dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul    */
4856dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul   assert(reg.file == PROGRAM_TEMPORARY ||
4866dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul          reg.file == PROGRAM_OUTPUT ||
4876dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul          reg.file == PROGRAM_UNDEFINED);
488f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->File = reg.file;
489f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->Index = reg.idx;
4905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* allow zero as a shorthand for xyzw */
4915f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
4927e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondMask = COND_TR;
4937e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondSwizzle = 0;
4947e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondSrc = 0;
495f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->pad = 0;
496f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
497f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4987e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void debug_insn( struct prog_instruction *inst, const char *fn,
4995f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			GLuint line )
500f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
501729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell   if (DISASSEM) {
502729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      static const char *last_fn;
503f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
504729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      if (fn != last_fn) {
505729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell	 last_fn = fn;
506729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell	 _mesa_printf("%s:\n", fn);
507729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      }
508f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
509729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      _mesa_printf("%d:\t", line);
510de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul      _mesa_print_instruction(inst);
511729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell   }
512f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
513f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
514f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
515f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_op3fn(struct tnl_program *p,
516f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint op,
517f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg dest,
518f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint mask,
519f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src0,
520f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src1,
521f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src2,
522f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       const char *fn,
523f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint line)
524f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
525f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
526de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
527f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5282fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   if (p->program->Base.NumInstructions > MAX_INSN) {
529a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_problem(0, "Out of instructions in emit_op3fn\n");
5302fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell      return;
5312fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   }
5322fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell
5339580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   inst->Opcode = (enum prog_opcode) op;
534dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->StringPos = 0;
535dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->Data = 0;
536f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
537f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
538f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
539f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
540f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
541f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_dst( &inst->DstReg, dest, mask );
542f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
543f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   debug_insn(inst, fn, line);
544f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
545f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
546f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5475f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op3(p, op, dst, mask, src0, src1, src2) \
5485f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
5495f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5505f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op2(p, op, dst, mask, src0, src1) \
5515f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
5525f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op1(p, op, dst, mask, src0) \
5545f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
555f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
556f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
557f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_temp( struct tnl_program *p, struct ureg reg )
558f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
559f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY &&
560f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       !(p->temp_reserved & (1<<reg.idx)))
561f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return reg;
562f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
563f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg temp = get_temp(p);
5647e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, temp, 0, reg);
565f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return temp;
566f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
567f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
568f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
569f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
570f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Currently no tracking performed of input/output/register size or
571f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * active elements.  Could be used to reduce these operations, as
572f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * could the matrix type.
573f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
574f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec4( struct tnl_program *p,
575f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
576f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
577f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
578f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
5797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
5807e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
5817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
5827e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
5835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
5845f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
58547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell/* This version is much easier to implement if writemasks are not
58647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * supported natively on the target or (like SSE), the target doesn't
58747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * have a clean/obvious dotproduct implementation.
58847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell */
5895f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void emit_transpose_matrix_transform_vec4( struct tnl_program *p,
5905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg dest,
5915f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  const struct ureg *mat,
5925f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg src)
5935f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
5945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp;
5955f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5965f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
5975f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = get_temp(p);
5985f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   else
5995f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = dest;
600f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
6017e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
6027e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
6037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
6047e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
6055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
6065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
6075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, tmp);
608f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
609f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
610f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec3( struct tnl_program *p,
611f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
612f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
613f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
614f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
6157e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
6167e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
6177e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
618f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
619f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
620f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
621f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_normalize_vec3( struct tnl_program *p,
622f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg dest,
623f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg src )
624f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
625f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg tmp = get_temp(p);
6267e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, src, src);
6277e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
6287e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, dest, 0, src, tmp);
629f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, tmp);
630f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
631f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
63210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwellstatic void emit_passthrough( struct tnl_program *p,
63310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint input,
63410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint output )
63510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell{
63610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   struct ureg out = register_output(p, output);
6377e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
63810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell}
63910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
640f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position( struct tnl_program *p )
641f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
642f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position)) {
643f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg pos = register_input( p, VERT_ATTRIB_POS );
644f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg modelview[4];
645f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
646f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position = reserve_temp(p);
647f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
64810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (PREFER_DP4) {
649fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	 register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
650fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul                                 0, modelview );
65110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
65210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
65310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
65410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      else {
655fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	 register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
65610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				 STATE_MATRIX_TRANSPOSE, modelview );
65710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
65810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
65910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
660f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
661f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
662f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position;
663f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
664f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
665f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
666f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position_normalized( struct tnl_program *p )
667f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
668f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position_normalized)) {
669f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg eye = get_eye_position(p);
670f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position_normalized = reserve_temp(p);
671f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_normalize_vec3(p, p->eye_position_normalized, eye);
672f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
673f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
674f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position_normalized;
675f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
676f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
677f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
678f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_normal( struct tnl_program *p )
679f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
680f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_normal)) {
681f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
682f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg mvinv[3];
683f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
684fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
6855f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      STATE_MATRIX_INVTRANS, mvinv );
686f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
687f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_normal = reserve_temp(p);
688f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
689f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Transform to eye space:
690f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
691f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
692f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
693f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Normalize/Rescale:
694f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
695a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->normalize) {
696f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
697f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
698a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      else if (p->state->rescale_normals) {
6995f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 struct ureg rescale = register_param2(p, STATE_INTERNAL,
7005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_NORMAL_SCALE);
7015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
7027e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2( p, OPCODE_MUL, p->eye_normal, 0, normal,
7035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell		   swizzle1(rescale, X));
704f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
705f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
706f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
707f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_normal;
708f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
709f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
710f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
711f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
712f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_hpos( struct tnl_program *p )
713f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
714f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg pos = register_input( p, VERT_ATTRIB_POS );
715f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
716f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg mvp[4];
717f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
71810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   if (PREFER_DP4) {
719fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
720fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul			      0, mvp );
72110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_matrix_transform_vec4( p, hpos, mvp, pos );
72210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
72310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   else {
724fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
72510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      STATE_MATRIX_TRANSPOSE, mvp );
72610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
72710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
728f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
729f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
730f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
731f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLuint material_attrib( GLuint side, GLuint property )
732f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
733f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell   return ((property - STATE_AMBIENT) * 2 +
7345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	   side);
735f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
736f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
737c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell/* Get a bitmask of which material values vary on a per-vertex basis.
738c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell */
739f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void set_material_flags( struct tnl_program *p )
740f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
741f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->color_materials = 0;
742f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->materials = 0;
743f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
744a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->light_color_material) {
745f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->materials =
746a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 p->color_materials = p->state->light_color_material_mask;
747f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
748f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
749a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p->materials |= p->state->light_material_mask;
750f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
751f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
752f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_material( struct tnl_program *p, GLuint side,
7545f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint property )
755f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
756f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
757f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
758f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->color_materials & (1<<attrib))
759f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input(p, VERT_ATTRIB_COLOR0);
760f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else if (p->materials & (1<<attrib))
761f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell      return register_input( p, attrib + _TNL_ATTRIB_MAT_FRONT_AMBIENT );
762f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
763f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param3( p, STATE_MATERIAL, side, property );
764f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
765f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
766f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell#define SCENE_COLOR_BITS(side) (( MAT_BIT_FRONT_EMISSION | \
767f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell				   MAT_BIT_FRONT_AMBIENT | \
768f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell				   MAT_BIT_FRONT_DIFFUSE) << (side))
769f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
770f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Either return a precalculated constant value or emit code to
771f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * calculate these values dynamically in the case where material calls
772f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * are present between begin/end pairs.
773f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
774f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Probably want to shift this to the program compilation phase - if
775f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * we always emitted the calculation here, a smart compiler could
776f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * detect that it was constant (given a certain set of inputs), and
777f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * lift it out of the main loop.  That way the programs created here
778f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * would be independent of the vertex_buffer details.
779f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
780f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
781f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
782f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & SCENE_COLOR_BITS(side)) {
7835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg lm_ambient = register_param1(p, STATE_LIGHTMODEL_AMBIENT);
784f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_emission = get_material(p, side, STATE_EMISSION);
785f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
786f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
787f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = make_temp(p, material_diffuse);
7887e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op3(p, OPCODE_MAD, tmp,  WRITEMASK_XYZ, lm_ambient,
7895f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       material_ambient, material_emission);
790f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
791f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
792f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
793f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param2( p, STATE_LIGHTMODEL_SCENECOLOR, side );
794f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
795f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
796f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7975f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_lightprod( struct tnl_program *p, GLuint light,
7985f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint side, GLuint property )
799f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
800f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
801f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & (1<<attrib)) {
8025f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg light_value =
8035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 register_param3(p, STATE_LIGHT, light, property);
804f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_value = get_material(p, side, property);
805f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
8067e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, tmp,  0, light_value, material_value);
807f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
808f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
809f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
810f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param4(p, STATE_LIGHTPROD, light, side, property);
811f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
812f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
8135f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg calculate_light_attenuation( struct tnl_program *p,
8145f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						GLuint i,
8155f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg VPpli,
8165f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg dist )
8175f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
8185f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg attenuation = register_param3(p, STATE_LIGHT, i,
8195f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					     STATE_ATTENUATION);
8205f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg att = get_temp(p);
8215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8225f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate spot attenuation:
8235f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
824a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!p->state->unit[i].light_spotcutoff_is_180) {
82554dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
82654dac2c84310536cce962101de29546d3eb80175Roland Scheidegger						  STATE_SPOT_DIR_NORMALIZED, i);
8275f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg spot = get_temp(p);
8285f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg slt = get_temp(p);
82954dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
83054dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm);
83154dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
8327e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
8337e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
8345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8355f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, spot);
8365f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, slt);
8375f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8395f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate distance attenuation:
8405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
841a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->unit[i].light_attenuated) {
8425f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8435f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/d,d,d,1/d */
8447e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
8455f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1,d,d*d,1/d */
8467e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
8475f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/dist-atten */
8487e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
8495f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
850a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (!p->state->unit[i].light_spotcutoff_is_180) {
8515f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8527e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_RCP, dist, 0, dist);
8535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* spot-atten * dist-atten */
8547e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MUL, att, 0, dist, att);
8555f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      } else {
8565f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8577e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_RCP, att, 0, dist);
8585f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      }
8595f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8605f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8615f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   return att;
8625f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
8635f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8645f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
865f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
866f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
867f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
868f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Need to add some addtional parameters to allow lighting in object
86923d31efc167f09d47635352f697ffcb087d3ebbdBrian Paul * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
870f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space lighting.
871f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
872f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_lighting( struct tnl_program *p )
873f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
874a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean twoside = p->state->light_twoside;
875a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean separate = p->state->separate_specular;
876f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr_lights = 0, count = 0;
877f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg normal = get_eye_normal(p);
878f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg lit = get_temp(p);
879f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg dots = get_temp(p);
880f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _col0 = undef, _col1 = undef;
881f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _bfc0 = undef, _bfc1 = undef;
882f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
883f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
884f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++)
885a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled)
886f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 nr_lights++;
887f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
888f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   set_material_flags(p);
889f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
890f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   {
891f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 0, STATE_SHININESS);
8927e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, dots,  WRITEMASK_W, swizzle1(shininess,X));
893f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
894f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
895f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _col0 = make_temp(p, get_scenecolor(p, 0));
896f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
897f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = make_temp(p, get_identity_param(p));
898f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
899f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = _col0;
900f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
901f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
902f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
903f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (twoside) {
904f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 1, STATE_SHININESS);
9057e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
9065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       negate(swizzle1(shininess,X)));
907f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
908f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
909f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _bfc0 = make_temp(p, get_scenecolor(p, 1));
910f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
911f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = make_temp(p, get_identity_param(p));
912f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
913f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = _bfc0;
914f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
915f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
91610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
91710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   /* If no lights, still need to emit the scenecolor.
91810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell    */
91910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      {
92010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
9217e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res0, 0, _col0);
92210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
92310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
92410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (separate) {
92510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
9267e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res1, 0, _col1);
92710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
92810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
92910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside) {
93010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
9317e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
93210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
93310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
93410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside && separate) {
93510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
9367e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
93710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
93810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
939f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell   if (nr_lights == 0) {
94010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      release_temps(p);
94110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      return;
94210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
94310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
94410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
945f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++) {
946a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled) {
947f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg half = undef;
948f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg att = undef, VPpli = undef;
949f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
950f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 count++;
951f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
952a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].light_eyepos3_is_zero) {
95347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	    /* Can used precomputed constants in this case.
95447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	     * Attenuation never applies to infinite lights.
955f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9565f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    VPpli = register_param3(p, STATE_LIGHT, i,
9575f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				    STATE_POSITION_NORMALIZED);
95861ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            if (p->state->light_local_viewer) {
95961ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                struct ureg eye_hat = get_eye_position_normalized(p);
96061ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                half = get_temp(p);
96161ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
96261ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                emit_normalize_vec3(p, half, half);
96361ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            } else {
96423d31efc167f09d47635352f697ffcb087d3ebbdBrian Paul                half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
96561ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            }
966f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
967f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 else {
9685f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg Ppli = register_param3(p, STATE_LIGHT, i,
9695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_POSITION);
970f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg V = get_eye_position(p);
9715f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg dist = get_temp(p);
9726dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul	    struct ureg tmpPpli = get_temp(p);
973f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
974f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    VPpli = get_temp(p);
975f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = get_temp(p);
976f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9776dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul            /* In homogeneous object coordinates
9786dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul             */
9796dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul            emit_op1(p, OPCODE_RCP, dist, 0, swizzle1(Ppli, W));
9806dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul            emit_op2(p, OPCODE_MUL, tmpPpli, 0, Ppli, dist);
981214347fdb4c30dc8bac5d4b9a823458709bc53eaXiang, Haihao
9826dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul	    /* Calculate VPpli vector
983f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9846dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul	    emit_op2(p, OPCODE_SUB, VPpli, 0, tmpPpli, V);
985f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9865f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    /* Normalize VPpli.  The dist value also used in
987f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * attenuation below.
988f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
9907e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_RSQ, dist, 0, dist);
9917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
992f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
993f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
994f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate  attenuation:
995f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
996a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (!p->state->unit[i].light_spotcutoff_is_180 ||
997a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		p->state->unit[i].light_attenuated) {
998a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       att = calculate_light_attenuation(p, i, VPpli, dist);
999f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1000f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1001f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1002f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate viewer direction, or use infinite viewer:
1003f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
1004a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (p->state->light_local_viewer) {
1005f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
10067e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
1007f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1008f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else {
10095f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
10107e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
1011f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1012f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1013f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_normalize_vec3(p, half, half);
1014f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10155f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    release_temp(p, dist);
10166dd98e9853a6984150aa47467112e016c40a4ab4Brian Paul	    release_temp(p, tmpPpli);
1017f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1018f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1019f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Calculate dot products:
1020f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
10217e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
10227e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
1023f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1024f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1025f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Front face lighting:
1026f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
1027f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 {
1028f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT);
1029f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE);
1030f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR);
1031f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
1032f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	    GLuint mask0, mask1;
1033f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10347e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_LIT, lit, 0, dots);
1035f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1036f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
10377e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
1038f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
103947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1040f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1041f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1042f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = WRITEMASK_XYZ;
1043f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1044f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_COL0 );
1045f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL1 );
1046f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1047f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1048f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = 0;
1049f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1050f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _col0;
1051f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL0 );
1052f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1053f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1054f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask0 = 0;
1055f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask1 = 0;
1056f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _col0;
1057f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _col1;
1058f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1059f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10607e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
10617e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
10627e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
1063f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1064f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1065f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1066f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1067f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1068f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1069f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Back face lighting:
1070f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
1071f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (twoside) {
1072f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT);
1073f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE);
1074f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
1075f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
1076f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	    GLuint mask0, mask1;
1077f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10787e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
1079f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1080f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
10817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
1082f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1083f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1084f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1085f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = WRITEMASK_XYZ;
1086f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1087f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_BFC0 );
1088f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC1 );
1089f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1090f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1091f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = 0;
1092f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1093f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _bfc0;
1094f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC0 );
1095f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1096f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1097f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _bfc0;
1098f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _bfc1;
1099f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask0 = 0;
1100f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask1 = 0;
1101f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1102f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
11037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
11047e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
11057e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
1106f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1107f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1108f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1109f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1110f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1111f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1112f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, half);
1113f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, VPpli);
1114f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, att);
1115f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1116f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1117f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1118f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temps( p );
1119f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1120f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1121f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1122f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_fog( struct tnl_program *p )
1123f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1124f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg fog = register_output(p, VERT_RESULT_FOGC);
1125f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg input;
112674a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger   GLuint useabs = p->state->fog_source_is_depth && p->state->fog_mode &&
112774a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger		   (p->state->fog_mode != FOG_EXP2);
112874a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger
1129a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->fog_source_is_depth) {
1130f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(get_eye_position(p), Z);
1131f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1132f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1133f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
1134f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1135f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
113674a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger   if (p->state->fog_mode && p->state->tnl_do_vertex_fog) {
113799dfca1e7fb32157135511bded07376ebb25acb3Roland Scheidegger      struct ureg params = register_param2(p, STATE_INTERNAL,
113899dfca1e7fb32157135511bded07376ebb25acb3Roland Scheidegger					   STATE_FOG_PARAMS_OPTIMIZED);
1139f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
1140f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
114174a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger      if (useabs) {
114274a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger	 emit_op1(p, OPCODE_ABS, tmp, 0, input);
114374a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger      }
114474a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger
1145a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      switch (p->state->fog_mode) {
1146a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_LINEAR: {
1147f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg id = get_identity_param(p);
114874a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger	 emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input,
114974a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger			swizzle1(params,X), swizzle1(params,Y));
11507e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
11517e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
1152f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1153f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1154a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP:
115574a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger	 emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input,
115674a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger			swizzle1(params,Z));
115754dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
1158f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1159a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP2:
116054dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));
116174a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger	 emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp);
116254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
1163f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1164f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
116574a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger
1166f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, tmp);
1167f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1168f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1169f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* results = incoming fog coords (compute fog per-fragment later)
1170f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       *
1171f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       * KW:  Is it really necessary to do anything in this case?
1172f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
117374a30c351fe98f41150dfe81a6aba05087997206Roland Scheidegger      emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input);
1174f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1175f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
11765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_reflect_texgen( struct tnl_program *p,
11785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  struct ureg dest,
11795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint writemask )
11805f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11815f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
11825f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
11835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
1184f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
11855f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
11867e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
11875f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
11887e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
11895f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
11907e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
1191ab377ce414ba5ca286bab0ddc8e80769bcb88656Keith Whitwell
1192ab377ce414ba5ca286bab0ddc8e80769bcb88656Keith Whitwell   release_temp(p, tmp);
11935f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
11945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11955f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_sphere_texgen( struct tnl_program *p,
11965f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 struct ureg dest,
11975f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint writemask )
11985f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11995f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
12005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
12015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
120296582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell   struct ureg half = register_scalar_const(p, .5);
12035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg r = get_temp(p);
12045f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg inv_m = get_temp(p);
12055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg id = get_identity_param(p);
12065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
12075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Could share the above calculations, but it would be
12085f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * a fairly odd state for someone to set (both sphere and
12095f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflection active for different texture coordinate
12105f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * components.  Of course - if two texture units enable
12115f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflect and/or sphere, things start to tilt in favour
12125f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * of seperating this out:
12135f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
12145f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
12155f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
12167e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
12175f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
12187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
12195f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
12207e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
12215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r + 0,0,1 */
12227e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
12235f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* rx^2 + ry^2 + (rz+1)^2 */
12247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
12255f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2/m */
12267e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
12275f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 1/m */
12287e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
12295f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r/m + 1/2 */
12307e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
12315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
12325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, tmp);
12335f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, r);
12345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, inv_m);
12355f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
1236f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1237f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1238f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_texture_transform( struct tnl_program *p )
1239f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1240f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i, j;
1241f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1242a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
1243f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1244e713c21bd09468887faceebcba9a62a406321c07Brian Paul      if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
1245c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 continue;
1246c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1247c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      if (p->state->unit[i].texgen_enabled ||
1248c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	  p->state->unit[i].texmat_enabled) {
1249c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1250c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
125110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
1252f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg out_texgen = undef;
1253f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1254a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].texgen_enabled) {
1255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint copy_mask = 0;
1256f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint sphere_mask = 0;
1257f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint reflect_mask = 0;
1258f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint normal_mask = 0;
1259f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint modes[4];
1260f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1261f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (texmat_enabled)
1262f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = get_temp(p);
1263f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else
1264f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = out;
1265f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1266a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[0] = p->state->unit[i].texgen_mode0;
1267a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[1] = p->state->unit[i].texgen_mode1;
1268a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[2] = p->state->unit[i].texgen_mode2;
1269a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[3] = p->state->unit[i].texgen_mode3;
1270f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1271f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    for (j = 0; j < 4; j++) {
1272a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       switch (modes[j]) {
1273a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_OBJ_LINEAR: {
1274a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg obj = register_input(p, VERT_ATTRIB_POS);
1275a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1276a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1277a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_OBJECT_S + j);
1278a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
12797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul		  emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1280a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   obj, plane );
1281a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1283a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_EYE_LINEAR: {
1284a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg eye = get_eye_position(p);
1285a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1286a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1287a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_EYE_S + j);
1288a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
12897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul		  emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1290a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   eye, plane );
1291a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1292a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1293a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_SPHERE_MAP:
1294a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  sphere_mask |= WRITEMASK_X << j;
1295a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1296a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_REFLECTION_MAP:
1297a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  reflect_mask |= WRITEMASK_X << j;
1298a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1299a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NORMAL_MAP:
1300a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  normal_mask |= WRITEMASK_X << j;
1301a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1302a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NONE:
1303f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  copy_mask |= WRITEMASK_X << j;
1304a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1305a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1306f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1307f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1308f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1309f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (sphere_mask) {
13105f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_sphere_texgen(p, out_texgen, sphere_mask);
1311f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1312f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1313f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (reflect_mask) {
13145f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_reflect_texgen(p, out_texgen, reflect_mask);
1315f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (normal_mask) {
1318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
13197e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
1320f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1321f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (copy_mask) {
1323f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
13247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in );
1325f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1326f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1327f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1328f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (texmat_enabled) {
1329f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg texmat[4];
13305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg in = (!is_undef(out_texgen) ?
13315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      out_texgen :
13325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      register_input(p, VERT_ATTRIB_TEX0+i));
133310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    if (PREFER_DP4) {
1334fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	       register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
1335fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				       0, texmat );
133610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       emit_matrix_transform_vec4( p, out, texmat, in );
133710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
133810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    else {
1339fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	       register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
1340fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				       STATE_MATRIX_TRANSPOSE, texmat );
13411c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell	       emit_transpose_matrix_transform_vec4( p, out, texmat, in );
134210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
1343f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1344f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1345f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temps(p);
134610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
1347c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
134810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
1349f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1350f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1351f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1352f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1353f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1354f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_pointsize( struct tnl_program *p )
1355f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1356f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye = get_eye_position(p);
13575f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_size = register_param1(p, STATE_POINT_SIZE);
13585f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION);
13595f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg out = register_output(p, VERT_RESULT_PSIZ);
1360f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg ut = get_temp(p);
1361f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1362a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   /* dist = |eyez| */
1363a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));
136454dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* p1 + dist * (p2 + dist * p3); */
1365a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
136654dac2c84310536cce962101de29546d3eb80175Roland Scheidegger		swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));
1367a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
136854dac2c84310536cce962101de29546d3eb80175Roland Scheidegger		ut, swizzle1(state_attenuation, X));
136954dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
137054dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* 1 / sqrt(factor) */
1371a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );
137254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
137354dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#if 1
137454dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* out = pointSize / sqrt(factor) */
137554dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
137654dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#else
137754dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* not sure, might make sense to do clamping here,
137854dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      but it's not done in t_vb_points neither */
1379a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);
1380a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));
138154dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));
138254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#endif
1383f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1384f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, ut);
1385f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1386f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1387a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void build_tnl_program( struct tnl_program *p )
1388a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{   /* Emit the program, starting with modelviewproject:
1389a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1390a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_hpos(p);
1391a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1392a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Lighting calculations:
1393a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1394c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
1395c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      if (p->state->light_global_enabled)
1396c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 build_lighting(p);
1397c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
1398c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
1399c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
1400c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1401c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
1402f31448f3c86697275bffe5363d473dd128cbd2acAapo Tahkola	    emit_passthrough(p, VERT_ATTRIB_COLOR1, VERT_RESULT_COL1);
1403c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1404c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   }
1405f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1406c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
1407c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       p->state->fog_mode != FOG_NONE)
1408a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_fog(p);
14095a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1410c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
1411a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_texture_transform(p);
14125a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1413a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->point_attenuated)
1414a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_pointsize(p);
14155a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1416a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Finish up:
1417a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
14187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_END, undef, 0, undef);
14195a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1420a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Disassemble:
1421a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1422a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (DISASSEM) {
1423a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_printf ("\n");
1424a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
14255a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell}
14265a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1427f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1428c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paulstatic void
1429c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paulcreate_new_program( const struct state_key *key,
1430122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                    struct gl_vertex_program *program,
1431c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paul                    GLuint max_temps)
1432f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1433f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct tnl_program p;
1434f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
143549d8cbe8d110e5c0a23300b5b82d110286bc3609Keith Whitwell   _mesa_memset(&p, 0, sizeof(p));
1436a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.state = key;
1437a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.program = program;
1438f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position = undef;
1439f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position_normalized = undef;
1440f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_normal = undef;
1441f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.identity = undef;
14423509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p.temp_in_use = 0;
1443a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1444a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (max_temps >= sizeof(int) * 8)
14453509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p.temp_reserved = 0;
14463509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   else
1447a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      p.temp_reserved = ~((1<<max_temps)-1);
14483509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell
1449002762b13aa58ca569a564bb64672e343611c9edBrian Paul   p.program->Base.Instructions = _mesa_alloc_instructions(MAX_INSN);
1450002762b13aa58ca569a564bb64672e343611c9edBrian Paul   p.program->Base.String = NULL;
1451f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumInstructions =
1452f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumTemporaries =
1453f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumParameters =
1454f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1455de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1456de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.InputsRead = 0;
1457de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.OutputsWritten = 0;
1458f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1459a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_tnl_program( &p );
1460a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1461f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1462a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void *search_cache( struct tnl_cache *cache,
1463a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint hash,
1464a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   const void *key,
1465a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint keysize)
1466a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
146737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c;
1468a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
146937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (c = cache->items[hash % cache->size]; c; c = c->next) {
1470aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0)
1471a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 return c->data;
1472a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1473a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1474a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return NULL;
1475a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1476a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
147737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkolastatic void rehash( struct tnl_cache *cache )
147837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola{
147937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item **items;
148037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c, *next;
148137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   GLuint size, i;
148237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
148337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   size = cache->size * 3;
14849580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   items = (struct tnl_cache_item**) _mesa_malloc(size * sizeof(*items));
148537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   _mesa_memset(items, 0, size * sizeof(*items));
148637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
148737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (i = 0; i < cache->size; i++)
148837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      for (c = cache->items[i]; c; c = next) {
148937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 next = c->next;
149037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 c->next = items[c->hash % size];
149137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 items[c->hash % size] = c;
149237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      }
149337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
149437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(cache->items);
149537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->items = items;
149637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->size = size;
149737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola}
149837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
149937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkolastatic void cache_item( struct tnl_cache *cache,
1500a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			GLuint hash,
1501a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *key,
1502a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *data )
1503a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
15049580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   struct tnl_cache_item *c = (struct tnl_cache_item*) _mesa_malloc(sizeof(*c));
1505a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->hash = hash;
1506a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->key = key;
1507a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->data = data;
150837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
150937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   if (++cache->n_items > cache->size * 1.5)
151037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      rehash(cache);
151137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
151237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   c->next = cache->items[hash % cache->size];
151337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->items[hash % cache->size] = c;
1514a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1515a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1516a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint hash_key( struct state_key *key )
1517a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1518a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint *ikey = (GLuint *)key;
1519a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash = 0, i;
1520a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1521a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* I'm sure this can be improved on, but speed is important:
1522f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1523a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++)
1524a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      hash ^= ikey[i];
1525f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1526a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return hash;
1527a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1528f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1529a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
1530a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1531a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
1532a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct state_key *key;
1533a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash;
1534122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
1535f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1536dba21ed913da2222e3b55fc8ba724ca93acbabf1Nicolai Hähnle   if (!ctx->VertexProgram._Current ||
1537dba21ed913da2222e3b55fc8ba724ca93acbabf1Nicolai Hähnle       ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
1538c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* Grab all the relevent state and put it in a single structure:
1539c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1540c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      key = make_state_key(ctx);
1541c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      hash = hash_key(key);
1542c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1543c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* Look for an already-prepared program for this state:
1544c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1545a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
1546c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
1547a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1548c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* OK, we'll have to build a new one:
1549c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1550a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      if (!ctx->VertexProgram._TnlProgram) {
1551c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (0)
1552c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    _mesa_printf("Build new TNL program\n");
1553c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1554a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
1555c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
1556dbeea25bb834479a29712100888c862348112018Keith Whitwell
1557a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 create_new_program( key, ctx->VertexProgram._TnlProgram,
1558c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell			     ctx->Const.VertexProgram.MaxTemps );
1559dbeea25bb834479a29712100888c862348112018Keith Whitwell
1560c9515bf1aec3a3d934535a9d2893e90e8b903043Keith Whitwell	 if (ctx->Driver.ProgramStringNotify)
1561c9515bf1aec3a3d934535a9d2893e90e8b903043Keith Whitwell	    ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
1562a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul                                       &ctx->VertexProgram._TnlProgram->Base );
1563a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1564a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 cache_item(tnl->vp_cache, hash, key, ctx->VertexProgram._TnlProgram );
1565c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1566c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
1567c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 FREE(key);
1568c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (0)
1569c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    _mesa_printf("Found existing TNL program for key %x\n", hash);
1570c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1571a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      ctx->VertexProgram._Current = ctx->VertexProgram._TnlProgram;
1572a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1573a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1574c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* Tell the driver about the change.  Could define a new target for
1575c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    * this?
1576a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1577a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
1578122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul      ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
1579122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                            (struct gl_program *) ctx->VertexProgram._Current);
1580a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   }
1581a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1582a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
15839248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkolavoid _tnl_ProgramCacheInit( GLcontext *ctx )
15849248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola{
15859248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   TNLcontext *tnl = TNL_CONTEXT(ctx);
15869248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola
15879248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache = (struct tnl_cache *) MALLOC(sizeof(*tnl->vp_cache));
15889248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->size = 17;
15899248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->n_items = 0;
15909248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->items = (struct tnl_cache_item**)
15919248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola      _mesa_calloc(tnl->vp_cache->size * sizeof(*tnl->vp_cache->items));
15929248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola}
1593a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1594a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_ProgramCacheDestroy( GLcontext *ctx )
1595a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1596a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
159737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c, *next;
159837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   GLuint i;
1599a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
160037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (i = 0; i < tnl->vp_cache->size; i++)
160137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      for (c = tnl->vp_cache->items[i]; c; c = next) {
160237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 next = c->next;
160337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c->key);
160437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c->data);
160537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c);
160637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      }
160737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
160837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(tnl->vp_cache->items);
160937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(tnl->vp_cache);
1610f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1611