t_vp_build.c revision dba21ed913da2222e3b55fc8ba724ca93acbabf1
1f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/*
2f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Mesa 3-D graphics library
3de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul * Version:  6.5
4f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
5564b2aa2ef8d5b859bb51d39024373a4865e93e9Brian Paul * Copyright (C) 2006  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"
3660a7200c0de7fc2925430b466739b4021087d14cBrian Paul#include "program.h"
3760a7200c0de7fc2925430b466739b4021087d14cBrian Paul#include "prog_instruction.h"
3860a7200c0de7fc2925430b466739b4021087d14cBrian Paul#include "prog_parameter.h"
3960a7200c0de7fc2925430b466739b4021087d14cBrian Paul#include "prog_print.h"
4060a7200c0de7fc2925430b466739b4021087d14cBrian Paul#include "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
4607e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *src,
461f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg )
462f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
463f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->File = reg.file;
464f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Index = reg.idx;
465f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->Swizzle = reg.swz;
46616d1024f27695bd9ceb86ffcdda960396a23ed2cAapo Tahkola   src->NegateBase = reg.negate ? NEGATE_XYZW : 0;
4677e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   src->Abs = 0;
4687e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   src->NegateAbs = 0;
469f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   src->RelAddr = 0;
470f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
471f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4727e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
473f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		      struct ureg reg, GLuint mask )
474f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
475f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->File = reg.file;
476f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->Index = reg.idx;
4775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* allow zero as a shorthand for xyzw */
4785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
4797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondMask = COND_TR;
4807e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondSwizzle = 0;
4817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   dst->CondSrc = 0;
482f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   dst->pad = 0;
483f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
484f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
4857e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void debug_insn( struct prog_instruction *inst, const char *fn,
4865f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			GLuint line )
487f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
488729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell   if (DISASSEM) {
489729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      static const char *last_fn;
490f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
491729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      if (fn != last_fn) {
492729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell	 last_fn = fn;
493729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell	 _mesa_printf("%s:\n", fn);
494729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      }
495f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
496729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell      _mesa_printf("%d:\t", line);
497de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul      _mesa_print_instruction(inst);
498729cccba5d20e3b34e7168ffff7515f52c72c26eKeith Whitwell   }
499f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
500f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
501f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
502f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_op3fn(struct tnl_program *p,
503f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint op,
504f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg dest,
505f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint mask,
506f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src0,
507f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src1,
508f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       struct ureg src2,
509f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       const char *fn,
510f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		       GLuint line)
511f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
512f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
513de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
514f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5152fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   if (p->program->Base.NumInstructions > MAX_INSN) {
516a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_problem(0, "Out of instructions in emit_op3fn\n");
5172fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell      return;
5182fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell   }
5192fcaf7a529f1e8bbdfbea6c8d9d6703adf5f17baKeith Whitwell
5209580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   inst->Opcode = (enum prog_opcode) op;
521dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->StringPos = 0;
522dbeea25bb834479a29712100888c862348112018Keith Whitwell   inst->Data = 0;
523f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
524f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
525f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
526f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
527f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
528f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   emit_dst( &inst->DstReg, dest, mask );
529f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
530f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   debug_insn(inst, fn, line);
531f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
532f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
533f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op3(p, op, dst, mask, src0, src1, src2) \
5355f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
5365f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5375f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op2(p, op, dst, mask, src0, src1) \
5385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
5395f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell#define emit_op1(p, op, dst, mask, src0) \
5415f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
542f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
543f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
544f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg make_temp( struct tnl_program *p, struct ureg reg )
545f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
546f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (reg.file == PROGRAM_TEMPORARY &&
547f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       !(p->temp_reserved & (1<<reg.idx)))
548f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return reg;
549f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
550f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg temp = get_temp(p);
5517e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, temp, 0, reg);
552f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return temp;
553f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
554f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
555f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
556f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
557f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Currently no tracking performed of input/output/register size or
558f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * active elements.  Could be used to reduce these operations, as
559f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * could the matrix type.
560f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
561f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec4( struct tnl_program *p,
562f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
563f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
564f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
565f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
5667e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
5677e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
5687e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
5697e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
5705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
5715f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
57247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell/* This version is much easier to implement if writemasks are not
57347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * supported natively on the target or (like SSE), the target doesn't
57447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell * have a clean/obvious dotproduct implementation.
57547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell */
5765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void emit_transpose_matrix_transform_vec4( struct tnl_program *p,
5775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg dest,
5785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  const struct ureg *mat,
5795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						  struct ureg src)
5805f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
5815f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp;
5825f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
5845f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = get_temp(p);
5855f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   else
5865f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      tmp = dest;
587f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
5887e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
5897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
5907e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
5917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
5925f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
5935f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   if (dest.file != PROGRAM_TEMPORARY)
5945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, tmp);
595f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
596f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
597f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_matrix_transform_vec3( struct tnl_program *p,
598f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg dest,
599f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					const struct ureg *mat,
600f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell					struct ureg src)
601f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
6027e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
6037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
6047e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
605f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
606f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
607f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
608f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void emit_normalize_vec3( struct tnl_program *p,
609f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg dest,
610f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell				 struct ureg src )
611f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
612f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg tmp = get_temp(p);
6137e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, src, src);
6147e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
6157e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, dest, 0, src, tmp);
616f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, tmp);
617f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
618f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
61910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwellstatic void emit_passthrough( struct tnl_program *p,
62010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint input,
62110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      GLuint output )
62210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell{
62310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   struct ureg out = register_output(p, output);
6247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
62510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell}
62610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
627f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position( struct tnl_program *p )
628f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
629f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position)) {
630f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg pos = register_input( p, VERT_ATTRIB_POS );
631f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg modelview[4];
632f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
633f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position = reserve_temp(p);
634f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
63510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (PREFER_DP4) {
636fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	 register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
637fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul                                 0, modelview );
63810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
63910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
64010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
64110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      else {
642fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	 register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
64310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell				 STATE_MATRIX_TRANSPOSE, modelview );
64410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
64510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
64610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
647f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
648f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
649f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position;
650f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
651f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
652f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
653f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_position_normalized( struct tnl_program *p )
654f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
655f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_position_normalized)) {
656f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg eye = get_eye_position(p);
657f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_position_normalized = reserve_temp(p);
658f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_normalize_vec3(p, p->eye_position_normalized, eye);
659f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
660f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
661f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_position_normalized;
662f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
663f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
664f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
665f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_eye_normal( struct tnl_program *p )
666f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
667f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (is_undef(p->eye_normal)) {
668f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
669f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg mvinv[3];
670f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
671fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
6725f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      STATE_MATRIX_INVTRANS, mvinv );
673f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
674f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->eye_normal = reserve_temp(p);
675f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
676f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Transform to eye space:
677f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
678f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
679f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
680f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* Normalize/Rescale:
681f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
682a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->normalize) {
683f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
684f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
685a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      else if (p->state->rescale_normals) {
6865f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 struct ureg rescale = register_param2(p, STATE_INTERNAL,
6875f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_NORMAL_SCALE);
6885f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
6897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2( p, OPCODE_MUL, p->eye_normal, 0, normal,
6905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell		   swizzle1(rescale, X));
691f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
692f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
693f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
694f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   return p->eye_normal;
695f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
696f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
697f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
698f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
699f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_hpos( struct tnl_program *p )
700f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
701f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg pos = register_input( p, VERT_ATTRIB_POS );
702f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
703f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg mvp[4];
704f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
70510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   if (PREFER_DP4) {
706fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
707fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul			      0, mvp );
70810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_matrix_transform_vec4( p, hpos, mvp, pos );
70910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
71010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   else {
711fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
71210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell			      STATE_MATRIX_TRANSPOSE, mvp );
71310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
71410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
715f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
716f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
717f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
718f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic GLuint material_attrib( GLuint side, GLuint property )
719f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
720f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell   return ((property - STATE_AMBIENT) * 2 +
7215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	   side);
722f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
723f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
724c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell/* Get a bitmask of which material values vary on a per-vertex basis.
725c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell */
726f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void set_material_flags( struct tnl_program *p )
727f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
728f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->color_materials = 0;
729f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p->materials = 0;
730f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
731a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->light_color_material) {
732f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      p->materials =
733a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 p->color_materials = p->state->light_color_material_mask;
734f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
735f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
736a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p->materials |= p->state->light_material_mask;
737f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
738f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
739f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_material( struct tnl_program *p, GLuint side,
7415f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint property )
742f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
743f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
744f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
745f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->color_materials & (1<<attrib))
746f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_input(p, VERT_ATTRIB_COLOR0);
747f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else if (p->materials & (1<<attrib))
748f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell      return register_input( p, attrib + _TNL_ATTRIB_MAT_FRONT_AMBIENT );
749f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
750f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param3( p, STATE_MATERIAL, side, property );
751f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
752f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
753f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell#define SCENE_COLOR_BITS(side) (( MAT_BIT_FRONT_EMISSION | \
754f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell				   MAT_BIT_FRONT_AMBIENT | \
755f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell				   MAT_BIT_FRONT_DIFFUSE) << (side))
756f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
757f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Either return a precalculated constant value or emit code to
758f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * calculate these values dynamically in the case where material calls
759f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * are present between begin/end pairs.
760f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell *
761f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * Probably want to shift this to the program compilation phase - if
762f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * we always emitted the calculation here, a smart compiler could
763f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * detect that it was constant (given a certain set of inputs), and
764f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * lift it out of the main loop.  That way the programs created here
765f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * would be independent of the vertex_buffer details.
766f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
767f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
768f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
769f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & SCENE_COLOR_BITS(side)) {
7705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg lm_ambient = register_param1(p, STATE_LIGHTMODEL_AMBIENT);
771f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_emission = get_material(p, side, STATE_EMISSION);
772f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
773f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
774f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = make_temp(p, material_diffuse);
7757e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op3(p, OPCODE_MAD, tmp,  WRITEMASK_XYZ, lm_ambient,
7765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       material_ambient, material_emission);
777f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
778f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
779f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
780f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param2( p, STATE_LIGHTMODEL_SCENECOLOR, side );
781f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
782f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
783f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
7845f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg get_lightprod( struct tnl_program *p, GLuint light,
7855f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint side, GLuint property )
786f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
787f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint attrib = material_attrib(side, property);
788f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (p->materials & (1<<attrib)) {
7895f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg light_value =
7905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 register_param3(p, STATE_LIGHT, light, property);
791f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg material_value = get_material(p, side, property);
792f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
7937e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, tmp,  0, light_value, material_value);
794f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return tmp;
795f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
796f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else
797f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      return register_param4(p, STATE_LIGHTPROD, light, side, property);
798f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
799f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
8005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic struct ureg calculate_light_attenuation( struct tnl_program *p,
8015f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						GLuint i,
8025f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg VPpli,
8035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell						struct ureg dist )
8045f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
8055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg attenuation = register_param3(p, STATE_LIGHT, i,
8065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					     STATE_ATTENUATION);
8075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg att = get_temp(p);
8085f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8095f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate spot attenuation:
8105f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
811a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (!p->state->unit[i].light_spotcutoff_is_180) {
81254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
81354dac2c84310536cce962101de29546d3eb80175Roland Scheidegger						  STATE_SPOT_DIR_NORMALIZED, i);
8145f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg spot = get_temp(p);
8155f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      struct ureg slt = get_temp(p);
81654dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
81754dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm);
81854dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
8197e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
8207e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
8215f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8225f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, spot);
8235f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      release_temp(p, slt);
8245f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8255f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8265f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Calculate distance attenuation:
8275f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
828a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->unit[i].light_attenuated) {
8295f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/d,d,d,1/d */
8317e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
8325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1,d,d*d,1/d */
8337e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
8345f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      /* 1/dist-atten */
8357e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
8365f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
837a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (!p->state->unit[i].light_spotcutoff_is_180) {
8385f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8397e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_RCP, dist, 0, dist);
8405f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* spot-atten * dist-atten */
8417e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MUL, att, 0, dist, att);
8425f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      } else {
8435f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	 /* dist-atten */
8447e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_RCP, att, 0, dist);
8455f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell      }
8465f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   }
8475f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8485f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   return att;
8495f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
8505f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
8515f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
852f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
853f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
854f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
855f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell/* Need to add some addtional parameters to allow lighting in object
85623d31efc167f09d47635352f697ffcb087d3ebbdBrian Paul * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
857f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell * space lighting.
858f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell */
859f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_lighting( struct tnl_program *p )
860f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
861a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean twoside = p->state->light_twoside;
862a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   const GLboolean separate = p->state->separate_specular;
863f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint nr_lights = 0, count = 0;
864f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg normal = get_eye_normal(p);
865f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg lit = get_temp(p);
866f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg dots = get_temp(p);
867f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _col0 = undef, _col1 = undef;
868f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg _bfc0 = undef, _bfc1 = undef;
869f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i;
870f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
871f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++)
872a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled)
873f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 nr_lights++;
874f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
875f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   set_material_flags(p);
876f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
877f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   {
878f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 0, STATE_SHININESS);
8797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, dots,  WRITEMASK_W, swizzle1(shininess,X));
880f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
881f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
882f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _col0 = make_temp(p, get_scenecolor(p, 0));
883f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
884f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = make_temp(p, get_identity_param(p));
885f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
886f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _col1 = _col0;
887f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
888f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
889f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
890f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   if (twoside) {
891f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg shininess = get_material(p, 1, STATE_SHININESS);
8927e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
8935f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       negate(swizzle1(shininess,X)));
894f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, shininess);
895f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
896f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      _bfc0 = make_temp(p, get_scenecolor(p, 1));
897f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      if (separate)
898f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = make_temp(p, get_identity_param(p));
899f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      else
900f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 _bfc1 = _bfc0;
901f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
902f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
90310432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
90410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   /* If no lights, still need to emit the scenecolor.
90510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell    */
90610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      {
90710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
9087e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res0, 0, _col0);
90910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
91010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
91110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (separate) {
91210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
9137e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res1, 0, _col1);
91410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
91510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
91610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside) {
91710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
9187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
91910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
92010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
92110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      if (twoside && separate) {
92210432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
9237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
92410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
92510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
926f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell   if (nr_lights == 0) {
92710432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      release_temps(p);
92810432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      return;
92910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell   }
93010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
93110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell
932f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   for (i = 0; i < MAX_LIGHTS; i++) {
933a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      if (p->state->unit[i].light_enabled) {
934f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg half = undef;
935f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg att = undef, VPpli = undef;
936f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
937f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 count++;
938f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
939a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].light_eyepos3_is_zero) {
94047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	    /* Can used precomputed constants in this case.
94147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	     * Attenuation never applies to infinite lights.
942f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9435f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    VPpli = register_param3(p, STATE_LIGHT, i,
9445f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				    STATE_POSITION_NORMALIZED);
94561ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            if (p->state->light_local_viewer) {
94661ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                struct ureg eye_hat = get_eye_position_normalized(p);
94761ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                half = get_temp(p);
94861ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
94961ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao                emit_normalize_vec3(p, half, half);
95061ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            } else {
95123d31efc167f09d47635352f697ffcb087d3ebbdBrian Paul                half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR);
95261ec23cc63a040a2edf1bc466917e85362514c89Xiang, Haihao            }
953f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
954f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 else {
9555f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg Ppli = register_param3(p, STATE_LIGHT, i,
9565f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell					       STATE_POSITION);
957f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg V = get_eye_position(p);
9585f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg dist = get_temp(p);
959f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
960f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    VPpli = get_temp(p);
961f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    half = get_temp(p);
962f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
963f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calulate VPpli vector
964f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9657e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
966f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9675f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    /* Normalize VPpli.  The dist value also used in
968f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     * attenuation below.
969f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
9707e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
9717e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_RSQ, dist, 0, dist);
9727e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
973f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
974f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
975f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate  attenuation:
976f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
977a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (!p->state->unit[i].light_spotcutoff_is_180 ||
978a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		p->state->unit[i].light_attenuated) {
979a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       att = calculate_light_attenuation(p, i, VPpli, dist);
980f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
981f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
982f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
983f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    /* Calculate viewer direction, or use infinite viewer:
984f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	     */
985a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    if (p->state->light_local_viewer) {
986f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg eye_hat = get_eye_position_normalized(p);
9877e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
988f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
989f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else {
9905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
9917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
992f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
993f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
994f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    emit_normalize_vec3(p, half, half);
995f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
9965f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    release_temp(p, dist);
997f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
998f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
999f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Calculate dot products:
1000f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
10017e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
10027e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
1003f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1004f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1005f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Front face lighting:
1006f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
1007f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 {
1008f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT);
1009f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE);
1010f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR);
1011f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
1012f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	    GLuint mask0, mask1;
1013f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10147e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_LIT, lit, 0, dots);
1015f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1016f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
10177e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
1018f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
101947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1020f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1021f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1022f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = WRITEMASK_XYZ;
1023f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1024f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_COL0 );
1025f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL1 );
1026f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1027f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1028f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = 0;
1029f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1030f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _col0;
1031f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_COL0 );
1032f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1033f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1034f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask0 = 0;
1035f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask1 = 0;
1036f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _col0;
1037f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _col1;
1038f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1039f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10407e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
10417e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
10427e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
1043f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1044f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1045f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1046f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1047f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1048f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1049f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 /* Back face lighting:
1050f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	  */
1051f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (twoside) {
1052f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT);
1053f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE);
1054f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
1055f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg res0, res1;
1056f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	    GLuint mask0, mask1;
1057f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10587e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op1(p, OPCODE_LIT, lit, 0, negate(swizzle(dots,X,Y,W,Z)));
1059f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1060f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (!is_undef(att))
10617e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
1062f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1063f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (count == nr_lights) {
1064f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       if (separate) {
1065f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = WRITEMASK_XYZ;
1066f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1067f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = register_output( p, VERT_RESULT_BFC0 );
1068f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC1 );
1069f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1070f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       else {
1071f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask0 = 0;
1072f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell		  mask1 = WRITEMASK_XYZ;
1073f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res0 = _bfc0;
1074f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  res1 = register_output( p, VERT_RESULT_BFC0 );
1075f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1076f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    } else {
1077f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res0 = _bfc0;
1078f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       res1 = _bfc1;
1079f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask0 = 0;
1080f6e7cfb60d3c4ceb2242cbc57c7e87c3c8e362feKeith Whitwell	       mask1 = 0;
1081f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1082f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
10837e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
10847e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
10857e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	    emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
1086f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1087f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, ambient);
1088f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, diffuse);
1089f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    release_temp(p, specular);
1090f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1091f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1092f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, half);
1093f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, VPpli);
1094f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temp(p, att);
1095f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1096f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1097f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1098f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temps( p );
1099f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1100f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1101f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1102f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_fog( struct tnl_program *p )
1103f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1104f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg fog = register_output(p, VERT_RESULT_FOGC);
1105f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg input;
11065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
1107a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->fog_source_is_depth) {
1108f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(get_eye_position(p), Z);
1109f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1110f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1111f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
1112f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1113f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1114a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->tnl_do_vertex_fog) {
111599dfca1e7fb32157135511bded07376ebb25acb3Roland Scheidegger      struct ureg params = register_param2(p, STATE_INTERNAL,
111699dfca1e7fb32157135511bded07376ebb25acb3Roland Scheidegger					   STATE_FOG_PARAMS_OPTIMIZED);
1117f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      struct ureg tmp = get_temp(p);
1118f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1119a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      switch (p->state->fog_mode) {
1120a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_LINEAR: {
1121f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg id = get_identity_param(p);
112254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op3(p, OPCODE_MAD, tmp, 0, input, swizzle1(params,X), swizzle1(params,Y));
11237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
11247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
1125f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1126f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1127a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP:
11287e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op1(p, OPCODE_ABS, tmp, 0, input);
112954dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,Z));
113054dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
1131f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1132a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      case FOG_EXP2:
113354dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));
11347e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp);
113554dac2c84310536cce962101de29546d3eb80175Roland Scheidegger	 emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
1136f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 break;
1137f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1138f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1139f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      release_temp(p, tmp);
1140f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1141f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   else {
1142f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      /* results = incoming fog coords (compute fog per-fragment later)
1143f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       *
1144f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       * KW:  Is it really necessary to do anything in this case?
1145f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell       */
11467e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_op1(p, OPCODE_MOV, fog, WRITEMASK_X, input);
1147f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1148f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
11495f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11505f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_reflect_texgen( struct tnl_program *p,
11515f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  struct ureg dest,
11525f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				  GLuint writemask )
11535f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11545f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
11555f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
11565f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
1157f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
11585f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
11597e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
11605f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
11617e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
11625f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
11637e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
1164ab377ce414ba5ca286bab0ddc8e80769bcb88656Keith Whitwell
1165ab377ce414ba5ca286bab0ddc8e80769bcb88656Keith Whitwell   release_temp(p, tmp);
11665f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
11675f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11685f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwellstatic void build_sphere_texgen( struct tnl_program *p,
11695f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 struct ureg dest,
11705f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell				 GLuint writemask )
11715f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell{
11725f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg normal = get_eye_normal(p);
11735f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg eye_hat = get_eye_position_normalized(p);
11745f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg tmp = get_temp(p);
117596582f4f28851f55f6726d1bba8a7f2616c327a4Keith Whitwell   struct ureg half = register_scalar_const(p, .5);
11765f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg r = get_temp(p);
11775f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg inv_m = get_temp(p);
11785f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg id = get_identity_param(p);
11795f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11805f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* Could share the above calculations, but it would be
11815f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * a fairly odd state for someone to set (both sphere and
11825f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflection active for different texture coordinate
11835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * components.  Of course - if two texture units enable
11845f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * reflect and/or sphere, things start to tilt in favour
11855f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    * of seperating this out:
11865f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell    */
11875f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
11885f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* n.u */
11897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
11905f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2n.u */
11917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
11925f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* (-2n.u)n + u */
11937e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
11945f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r + 0,0,1 */
11957e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
11965f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* rx^2 + ry^2 + (rz+1)^2 */
11977e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
11985f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 2/m */
11997e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
12005f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* 1/m */
12017e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
12025f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   /* r/m + 1/2 */
12037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
12045f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell
12055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, tmp);
12065f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, r);
12075f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   release_temp(p, inv_m);
12085f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell}
1209f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1210f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1211f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_texture_transform( struct tnl_program *p )
1212f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1213f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   GLuint i, j;
1214f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1215a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
1216f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1217e713c21bd09468887faceebcba9a62a406321c07Brian Paul      if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
1218c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 continue;
1219c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1220c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      if (p->state->unit[i].texgen_enabled ||
1221c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	  p->state->unit[i].texmat_enabled) {
1222c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1223c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
122410432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
1225f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 struct ureg out_texgen = undef;
1226f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1227a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 if (p->state->unit[i].texgen_enabled) {
1228f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint copy_mask = 0;
1229f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint sphere_mask = 0;
1230f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint reflect_mask = 0;
1231f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint normal_mask = 0;
1232f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    GLuint modes[4];
1233f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1234f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (texmat_enabled)
1235f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = get_temp(p);
1236f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    else
1237f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       out_texgen = out;
1238f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1239a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[0] = p->state->unit[i].texgen_mode0;
1240a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[1] = p->state->unit[i].texgen_mode1;
1241a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[2] = p->state->unit[i].texgen_mode2;
1242a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	    modes[3] = p->state->unit[i].texgen_mode3;
1243f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1244f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    for (j = 0; j < 4; j++) {
1245a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       switch (modes[j]) {
1246a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_OBJ_LINEAR: {
1247a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg obj = register_input(p, VERT_ATTRIB_POS);
1248a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1249a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1250a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_OBJECT_S + j);
1251a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
12527e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul		  emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1253a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   obj, plane );
1254a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1255f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       }
1256a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_EYE_LINEAR: {
1257a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg eye = get_eye_position(p);
1258a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  struct ureg plane =
1259a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		     register_param3(p, STATE_TEXGEN, i,
1260a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell				     STATE_TEXGEN_EYE_S + j);
1261a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
12627e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul		  emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
1263a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   eye, plane );
1264a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1265a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1266a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_SPHERE_MAP:
1267a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  sphere_mask |= WRITEMASK_X << j;
1268a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1269a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_REFLECTION_MAP:
1270a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  reflect_mask |= WRITEMASK_X << j;
1271a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1272a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NORMAL_MAP:
1273a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  normal_mask |= WRITEMASK_X << j;
1274a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell		  break;
1275a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       case TXG_NONE:
1276f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell		  copy_mask |= WRITEMASK_X << j;
1277a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	       }
1278a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1279f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1280f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1281f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1282f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (sphere_mask) {
12835f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_sphere_texgen(p, out_texgen, sphere_mask);
1284f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1285f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1286f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (reflect_mask) {
12875f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	       build_reflect_texgen(p, out_texgen, reflect_mask);
1288f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1289f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1290f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (normal_mask) {
1291f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg normal = get_eye_normal(p);
12927e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
1293f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1294f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1295f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    if (copy_mask) {
1296f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	       struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
12977e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	       emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in );
1298f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    }
1299f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1300f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1301f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 if (texmat_enabled) {
1302f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	    struct ureg texmat[4];
13035f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell	    struct ureg in = (!is_undef(out_texgen) ?
13045f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      out_texgen :
13055f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell			      register_input(p, VERT_ATTRIB_TEX0+i));
130610432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    if (PREFER_DP4) {
1307fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	       register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
1308fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				       0, texmat );
130910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	       emit_matrix_transform_vec4( p, out, texmat, in );
131010432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
131110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    else {
1312fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul	       register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
1313fce8409cbbe6aa5309163f3d63894233b8833308Brian Paul				       STATE_MATRIX_TRANSPOSE, texmat );
13141c48986e540f573c63b98470f52338dba6353ceaKeith Whitwell	       emit_transpose_matrix_transform_vec4( p, out, texmat, in );
131510432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	    }
1316f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 }
1317f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1318f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell	 release_temps(p);
131910432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell      }
1320c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
132110432bcc0a2c89916bc98921bcf01e0fbb422dc5Keith Whitwell	 emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
1322f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell      }
1323f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   }
1324f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1325f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1326f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1327f069e5e412eebabe64286d35598173caac5c132eKeith Whitwellstatic void build_pointsize( struct tnl_program *p )
1328f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1329f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg eye = get_eye_position(p);
13305f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_size = register_param1(p, STATE_POINT_SIZE);
13315f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION);
13325f534aa1e2c53360bb1ae42fb196e41aa29d0d3dKeith Whitwell   struct ureg out = register_output(p, VERT_RESULT_PSIZ);
1333f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct ureg ut = get_temp(p);
1334f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1335a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   /* dist = |eyez| */
1336a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));
133754dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* p1 + dist * (p2 + dist * p3); */
1338a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
133954dac2c84310536cce962101de29546d3eb80175Roland Scheidegger		swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));
1340a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
134154dac2c84310536cce962101de29546d3eb80175Roland Scheidegger		ut, swizzle1(state_attenuation, X));
134254dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
134354dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* 1 / sqrt(factor) */
1344a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );
134554dac2c84310536cce962101de29546d3eb80175Roland Scheidegger
134654dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#if 1
134754dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* out = pointSize / sqrt(factor) */
134854dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
134954dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#else
135054dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   /* not sure, might make sense to do clamping here,
135154dac2c84310536cce962101de29546d3eb80175Roland Scheidegger      but it's not done in t_vb_points neither */
1352a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);
1353a6cc9ab493a2efa9a0ea91cddba0e85c8c8c83f1Roland Scheidegger   emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));
135454dac2c84310536cce962101de29546d3eb80175Roland Scheidegger   emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));
135554dac2c84310536cce962101de29546d3eb80175Roland Scheidegger#endif
1356f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1357f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   release_temp(p, ut);
1358f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1359f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1360a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void build_tnl_program( struct tnl_program *p )
1361a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{   /* Emit the program, starting with modelviewproject:
1362a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1363a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_hpos(p);
1364a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1365a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Lighting calculations:
1366a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1367c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
1368c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      if (p->state->light_global_enabled)
1369c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 build_lighting(p);
1370c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
1371c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
1372c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
1373c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1374c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
1375f31448f3c86697275bffe5363d473dd128cbd2acAapo Tahkola	    emit_passthrough(p, VERT_ATTRIB_COLOR1, VERT_RESULT_COL1);
1376c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1377c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   }
1378f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1379c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
1380c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       p->state->fog_mode != FOG_NONE)
1381a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_fog(p);
13825a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1383c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
1384a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_texture_transform(p);
13855a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1386a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (p->state->point_attenuated)
1387a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      build_pointsize(p);
13885a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1389a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Finish up:
1390a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
13917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_op1(p, OPCODE_END, undef, 0, undef);
13925a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1393a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* Disassemble:
1394a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1395a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (DISASSEM) {
1396a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      _mesa_printf ("\n");
1397a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
13985a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell}
13995a5b4436cb71575884f76bc079156f77e30d72a7Keith Whitwell
1400f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1401c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paulstatic void
1402c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paulcreate_new_program( const struct state_key *key,
1403122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                    struct gl_vertex_program *program,
1404c43f03e38dd4bfbcbc0cc8414e2bacfbffad08a1Brian Paul                    GLuint max_temps)
1405f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell{
1406f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   struct tnl_program p;
1407f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
140849d8cbe8d110e5c0a23300b5b82d110286bc3609Keith Whitwell   _mesa_memset(&p, 0, sizeof(p));
1409a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.state = key;
1410a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   p.program = program;
1411f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position = undef;
1412f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_position_normalized = undef;
1413f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.eye_normal = undef;
1414f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.identity = undef;
14153509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   p.temp_in_use = 0;
1416a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1417a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   if (max_temps >= sizeof(int) * 8)
14183509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell      p.temp_reserved = 0;
14193509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell   else
1420a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      p.temp_reserved = ~((1<<max_temps)-1);
14213509fd8c1b38d955a066a2bad429dbfba162fa30Keith Whitwell
1422002762b13aa58ca569a564bb64672e343611c9edBrian Paul   p.program->Base.Instructions = _mesa_alloc_instructions(MAX_INSN);
1423002762b13aa58ca569a564bb64672e343611c9edBrian Paul   p.program->Base.String = NULL;
1424f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumInstructions =
1425f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumTemporaries =
1426f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumParameters =
1427f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1428de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1429de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.InputsRead = 0;
1430de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.OutputsWritten = 0;
1431f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1432a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   build_tnl_program( &p );
1433a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1434f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1435a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic void *search_cache( struct tnl_cache *cache,
1436a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint hash,
1437a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   const void *key,
1438a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			   GLuint keysize)
1439a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
144037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c;
1441a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
144237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (c = cache->items[hash % cache->size]; c; c = c->next) {
1443aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0)
1444a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell	 return c->data;
1445a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1446a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1447a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return NULL;
1448a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1449a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
145037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkolastatic void rehash( struct tnl_cache *cache )
145137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola{
145237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item **items;
145337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c, *next;
145437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   GLuint size, i;
145537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
145637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   size = cache->size * 3;
14579580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   items = (struct tnl_cache_item**) _mesa_malloc(size * sizeof(*items));
145837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   _mesa_memset(items, 0, size * sizeof(*items));
145937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
146037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (i = 0; i < cache->size; i++)
146137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      for (c = cache->items[i]; c; c = next) {
146237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 next = c->next;
146337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 c->next = items[c->hash % size];
146437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 items[c->hash % size] = c;
146537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      }
146637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
146737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(cache->items);
146837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->items = items;
146937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->size = size;
147037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola}
147137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
147237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkolastatic void cache_item( struct tnl_cache *cache,
1473a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			GLuint hash,
1474a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *key,
1475a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell			void *data )
1476a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
14779580179dfb42d5b81ff6ec9704b82a556c7f1229Brian Paul   struct tnl_cache_item *c = (struct tnl_cache_item*) _mesa_malloc(sizeof(*c));
1478a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->hash = hash;
1479a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->key = key;
1480a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   c->data = data;
148137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
148237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   if (++cache->n_items > cache->size * 1.5)
148337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      rehash(cache);
148437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
148537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   c->next = cache->items[hash % cache->size];
148637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   cache->items[hash % cache->size] = c;
1487a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1488a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1489a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellstatic GLuint hash_key( struct state_key *key )
1490a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1491a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint *ikey = (GLuint *)key;
1492a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash = 0, i;
1493a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1494a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   /* I'm sure this can be improved on, but speed is important:
1495f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell    */
1496a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++)
1497a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell      hash ^= ikey[i];
1498f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1499a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   return hash;
1500a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1501f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1502a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
1503a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1504a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
1505a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   struct state_key *key;
1506a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   GLuint hash;
1507122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
1508f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell
1509dba21ed913da2222e3b55fc8ba724ca93acbabf1Nicolai Hähnle   if (!ctx->VertexProgram._Current ||
1510dba21ed913da2222e3b55fc8ba724ca93acbabf1Nicolai Hähnle       ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
1511c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* Grab all the relevent state and put it in a single structure:
1512c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1513c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      key = make_state_key(ctx);
1514c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      hash = hash_key(key);
1515c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1516c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* Look for an already-prepared program for this state:
1517c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1518a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
1519c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 search_cache( tnl->vp_cache, hash, key, sizeof(*key) );
1520a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1521c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      /* OK, we'll have to build a new one:
1522c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell       */
1523a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      if (!ctx->VertexProgram._TnlProgram) {
1524c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (0)
1525c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    _mesa_printf("Build new TNL program\n");
1526c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1527a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 ctx->VertexProgram._TnlProgram = (struct gl_vertex_program *)
1528c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
1529dbeea25bb834479a29712100888c862348112018Keith Whitwell
1530a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 create_new_program( key, ctx->VertexProgram._TnlProgram,
1531c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell			     ctx->Const.VertexProgram.MaxTemps );
1532dbeea25bb834479a29712100888c862348112018Keith Whitwell
1533c9515bf1aec3a3d934535a9d2893e90e8b903043Keith Whitwell	 if (ctx->Driver.ProgramStringNotify)
1534c9515bf1aec3a3d934535a9d2893e90e8b903043Keith Whitwell	    ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
1535a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul                                       &ctx->VertexProgram._TnlProgram->Base );
1536a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1537a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul	 cache_item(tnl->vp_cache, hash, key, ctx->VertexProgram._TnlProgram );
1538c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1539c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      else {
1540c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 FREE(key);
1541c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	 if (0)
1542c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell	    _mesa_printf("Found existing TNL program for key %x\n", hash);
1543c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1544a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul      ctx->VertexProgram._Current = ctx->VertexProgram._TnlProgram;
1545a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   }
1546a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1547c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* Tell the driver about the change.  Could define a new target for
1548c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    * this?
1549a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell    */
1550a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
1551122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul      ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
1552122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                            (struct gl_program *) ctx->VertexProgram._Current);
1553a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul   }
1554a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell}
1555a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
15569248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkolavoid _tnl_ProgramCacheInit( GLcontext *ctx )
15579248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola{
15589248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   TNLcontext *tnl = TNL_CONTEXT(ctx);
15599248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola
15609248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache = (struct tnl_cache *) MALLOC(sizeof(*tnl->vp_cache));
15619248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->size = 17;
15629248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->n_items = 0;
15639248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola   tnl->vp_cache->items = (struct tnl_cache_item**)
15649248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola      _mesa_calloc(tnl->vp_cache->size * sizeof(*tnl->vp_cache->items));
15659248882ca27b289180a76262aa3d9b26c0cb0e8bAapo Tahkola}
1566a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
1567a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwellvoid _tnl_ProgramCacheDestroy( GLcontext *ctx )
1568a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell{
1569a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell   TNLcontext *tnl = TNL_CONTEXT(ctx);
157037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   struct tnl_cache_item *c, *next;
157137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   GLuint i;
1572a8534885efb13ec7f071192c1504513cd90d07deKeith Whitwell
157337f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   for (i = 0; i < tnl->vp_cache->size; i++)
157437f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      for (c = tnl->vp_cache->items[i]; c; c = next) {
157537f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 next = c->next;
157637f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c->key);
157737f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c->data);
157837f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola	 FREE(c);
157937f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola      }
158037f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola
158137f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(tnl->vp_cache->items);
158237f2eaa316d507b729ca392b651ae18ef92efcacAapo Tahkola   FREE(tnl->vp_cache);
1583f069e5e412eebabe64286d35598173caac5c132eKeith Whitwell}
1584