s_fragprog.c revision f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3
1865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/*
2865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Mesa 3-D graphics library
3865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Version:  6.5.2
4865f88afc0d59d886fb2ad50429e584ecf17fa81Brian *
5865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6865f88afc0d59d886fb2ad50429e584ecf17fa81Brian *
7865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Permission is hereby granted, free of charge, to any person obtaining a
8865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * copy of this software and associated documentation files (the "Software"),
9865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * to deal in the Software without restriction, including without limitation
10865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * and/or sell copies of the Software, and to permit persons to whom the
12865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Software is furnished to do so, subject to the following conditions:
13865f88afc0d59d886fb2ad50429e584ecf17fa81Brian *
14865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * The above copyright notice and this permission notice shall be included
15865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * in all copies or substantial portions of the Software.
16865f88afc0d59d886fb2ad50429e584ecf17fa81Brian *
17865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
24865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
25865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "glheader.h"
26865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "colormac.h"
27865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "context.h"
28865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "prog_instruction.h"
29865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "prog_parameter.h"
30865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "prog_print.h"
31865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "program.h"
32865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
33c968d3d410a1897ecbb41d3557adaef69a4c627aBrian#include "s_fragprog.h"
34865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#include "s_span.h"
357aece10039ad4786d7f85d61ec8614b9f287ea23Brian#include "slang_library_noise.h"
36865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
37865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
38865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/* See comments below for info about this */
39865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#define LAMBDA_ZERO 1
40865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
41865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/* debug predicate */
42865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#define DEBUG_FRAG 0
43865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
44865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
45865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
46865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Virtual machine state used during execution of a fragment programs.
47865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
48865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstruct fp_machine
49865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
50f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   /** Fragment Input attributes */
51f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*Attribs)[MAX_WIDTH][4];
52f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLuint CurFrag; /**< Index into Attribs arrays */
53f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
54865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat Temporaries[MAX_PROGRAM_TEMPS][4];
55865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat Outputs[FRAG_RESULT_MAX][4];
56865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint CondCodes[4];  /**< COND_* value for x/y/z/w */
57865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
58865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
59865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint StackDepth; /**< Index/ptr to top of CallStack[] */
60865f88afc0d59d886fb2ad50429e584ecf17fa81Brian};
61865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
62865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
63865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#if FEATURE_MESA_program_debug
64865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic struct fp_machine *CurrentMachine = NULL;
65865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
66865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
67865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * For GL_MESA_program_debug.
68865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Return current value (4*GLfloat) of a fragment program register.
69865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Called via ctx->Driver.GetFragmentProgramRegister().
70865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
71865f88afc0d59d886fb2ad50429e584ecf17fa81Brianvoid
72865f88afc0d59d886fb2ad50429e584ecf17fa81Brian_swrast_get_program_register(GLcontext *ctx, enum register_file file,
73865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                             GLuint index, GLfloat val[4])
74865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
75865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (CurrentMachine) {
76865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      switch (file) {
77865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_INPUT:
78f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         COPY_4V(val, CurrentMachine->Attribs[index][CurrentMachine->CurFrag]);
79865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         break;
80865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_OUTPUT:
81865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         COPY_4V(val, CurrentMachine->Outputs[index]);
82865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         break;
83865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_TEMPORARY:
84865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         COPY_4V(val, CurrentMachine->Temporaries[index]);
85865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         break;
86865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      default:
87865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         _mesa_problem(NULL,
88865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                       "bad register file in _swrast_get_program_register");
89865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
90865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
91865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
92865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#endif /* FEATURE_MESA_program_debug */
93865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
94865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
95865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
96865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Fetch a texel.
97865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
98865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
99865f88afc0d59d886fb2ad50429e584ecf17fa81Brianfetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
100865f88afc0d59d886fb2ad50429e584ecf17fa81Brian             GLuint unit, GLfloat color[4] )
101865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
102865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLchan rgba[4];
103865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
104865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
105865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* XXX use a float-valued TextureSample routine here!!! */
106865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
107865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                               1, (const GLfloat (*)[4]) texcoord,
108865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                               &lambda, &rgba);
109865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[0] = CHAN_TO_FLOAT(rgba[0]);
110865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[1] = CHAN_TO_FLOAT(rgba[1]);
111865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[2] = CHAN_TO_FLOAT(rgba[2]);
112865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[3] = CHAN_TO_FLOAT(rgba[3]);
113865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
114865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
115865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
116865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
117865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Fetch a texel with the given partial derivatives to compute a level
118865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * of detail in the mipmap.
119865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
120865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
121865f88afc0d59d886fb2ad50429e584ecf17fa81Brianfetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
122865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   const GLfloat texdx[4], const GLfloat texdy[4],
123865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   GLuint unit, GLfloat color[4] )
124865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
125865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   SWcontext *swrast = SWRAST_CONTEXT(ctx);
126865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
127865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
128865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const GLfloat texW = (GLfloat) texImg->WidthScale;
129865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const GLfloat texH = (GLfloat) texImg->HeightScale;
130865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLchan rgba[4];
131865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
132865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
133865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                         texdx[1], texdy[1], /* dt/dx, dt/dy */
134865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                         texdx[3], texdy[2], /* dq/dx, dq/dy */
135865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                         texW, texH,
136865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                         texcoord[0], texcoord[1], texcoord[3],
137865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                         1.0F / texcoord[3]);
138865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
139865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
140865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                               1, (const GLfloat (*)[4]) texcoord,
141865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                               &lambda, &rgba);
142865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[0] = CHAN_TO_FLOAT(rgba[0]);
143865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[1] = CHAN_TO_FLOAT(rgba[1]);
144865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[2] = CHAN_TO_FLOAT(rgba[2]);
145865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   color[3] = CHAN_TO_FLOAT(rgba[3]);
146865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
147865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
148865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
149865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
150865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Return a pointer to the 4-element float vector specified by the given
151865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * source register.
152865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
153865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic INLINE const GLfloat *
154865f88afc0d59d886fb2ad50429e584ecf17fa81Brianget_register_pointer( GLcontext *ctx,
155865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      const struct prog_src_register *source,
156865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      const struct fp_machine *machine,
157865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      const struct gl_fragment_program *program )
158865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
159ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian   /* XXX relative addressing... */
160865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   switch (source->File) {
161865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_TEMPORARY:
162865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < MAX_PROGRAM_TEMPS);
163865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return machine->Temporaries[source->Index];
164865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_INPUT:
165865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < FRAG_ATTRIB_MAX);
166f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      return machine->Attribs[source->Index][machine->CurFrag];
167865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_OUTPUT:
168865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* This is only for PRINT */
169865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < FRAG_RESULT_MAX);
170865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return machine->Outputs[source->Index];
171865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_LOCAL_PARAM:
172865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
173865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return program->Base.LocalParams[source->Index];
174865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_ENV_PARAM:
175865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_PARAMS);
176865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return ctx->FragmentProgram.Parameters[source->Index];
177865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_STATE_VAR:
178865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* Fallthrough */
179865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_CONSTANT:
180865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* Fallthrough */
181865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_UNIFORM:
182865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* Fallthrough */
183865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case PROGRAM_NAMED_PARAM:
184865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      ASSERT(source->Index < (GLint) program->Base.Parameters->NumParameters);
185865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return program->Base.Parameters->ParameterValues[source->Index];
186865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   default:
187865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      _mesa_problem(ctx, "Invalid input register file %d in fp "
188865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    "get_register_pointer", source->File);
189865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return NULL;
190865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
191865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
192865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
193865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
194865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
195865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Fetch a 4-element float vector from the given source register.
196865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Apply swizzling and negating as needed.
197865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
198865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
199865f88afc0d59d886fb2ad50429e584ecf17fa81Brianfetch_vector4( GLcontext *ctx,
200865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct prog_src_register *source,
201865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct fp_machine *machine,
202865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct gl_fragment_program *program,
203865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat result[4] )
204865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
205865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
206865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ASSERT(src);
207865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
208223d7cb3c785ad58c869a3ee0fbf2f1d42c3310dBrian   if (source->Swizzle == SWIZZLE_NOOP) {
209865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* no swizzling */
210865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      COPY_4V(result, src);
211865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
212865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   else {
213f673b24017b8b5e850a1be5c04bd28cefa811329Brian      ASSERT(GET_SWZ(source->Swizzle, 0) <= 3);
214f673b24017b8b5e850a1be5c04bd28cefa811329Brian      ASSERT(GET_SWZ(source->Swizzle, 1) <= 3);
215f673b24017b8b5e850a1be5c04bd28cefa811329Brian      ASSERT(GET_SWZ(source->Swizzle, 2) <= 3);
216f673b24017b8b5e850a1be5c04bd28cefa811329Brian      ASSERT(GET_SWZ(source->Swizzle, 3) <= 3);
217865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = src[GET_SWZ(source->Swizzle, 0)];
218865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = src[GET_SWZ(source->Swizzle, 1)];
219865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = src[GET_SWZ(source->Swizzle, 2)];
220865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = src[GET_SWZ(source->Swizzle, 3)];
221865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
222865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
223865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateBase) {
224865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
225865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = -result[1];
226865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = -result[2];
227865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = -result[3];
228865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
229865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->Abs) {
230865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = FABSF(result[0]);
231865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = FABSF(result[1]);
232865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = FABSF(result[2]);
233865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = FABSF(result[3]);
234865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
235865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateAbs) {
236865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
237865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = -result[1];
238865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = -result[2];
239865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = -result[3];
240865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
241865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
242865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
243865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
244865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
245865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Fetch the derivative with respect to X for the given register.
246865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \return GL_TRUE if it was easily computed or GL_FALSE if we
247865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * need to execute another instance of the program (ugh)!
248865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
249865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic GLboolean
250865f88afc0d59d886fb2ad50429e584ecf17fa81Brianfetch_vector4_deriv( GLcontext *ctx,
251865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     const struct prog_src_register *source,
252865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     const SWspan *span,
253865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     char xOrY, GLint column, GLfloat result[4] )
254865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
255865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat src[4];
256865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
257865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ASSERT(xOrY == 'X' || xOrY == 'Y');
258865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
259865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   switch (source->Index) {
260865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_WPOS:
261865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
262865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = 1.0;
263865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = 0.0;
264865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dzdx / ctx->DrawBuffer->_DepthMaxF;
265865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->dwdx;
266865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
267865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
268865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = 0.0;
269865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = 1.0;
270865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dzdy / ctx->DrawBuffer->_DepthMaxF;
271865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->dwdy;
272865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
273865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      break;
274865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_COL0:
275865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
276865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->drdx * (1.0F / CHAN_MAXF);
277865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->dgdx * (1.0F / CHAN_MAXF);
278865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dbdx * (1.0F / CHAN_MAXF);
279865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->dadx * (1.0F / CHAN_MAXF);
280865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
281865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
282865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->drdy * (1.0F / CHAN_MAXF);
283865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->dgdy * (1.0F / CHAN_MAXF);
284865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dbdy * (1.0F / CHAN_MAXF);
285865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->dady * (1.0F / CHAN_MAXF);
286865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
287865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      break;
288865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_COL1:
289865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
290865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->dsrdx * (1.0F / CHAN_MAXF);
291865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->dsgdx * (1.0F / CHAN_MAXF);
292865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dsbdx * (1.0F / CHAN_MAXF);
293865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = 0.0; /* XXX need this */
294865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
295865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
296865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->dsrdy * (1.0F / CHAN_MAXF);
297865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->dsgdy * (1.0F / CHAN_MAXF);
298865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->dsbdy * (1.0F / CHAN_MAXF);
299865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = 0.0; /* XXX need this */
300865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
301865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      break;
302865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_FOGC:
303865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
304865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->dfogdx;
305865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = 0.0;
306865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = 0.0;
307865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = 0.0;
308865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
309865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
310865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->dfogdy;
311865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = 0.0;
312865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = 0.0;
313865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = 0.0;
314865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
315865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      break;
316865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX0:
317865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX1:
318865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX2:
319865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX3:
320865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX4:
321865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX5:
322865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX6:
323865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case FRAG_ATTRIB_TEX7:
324865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
325865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         const GLuint u = source->Index - FRAG_ATTRIB_TEX0;
326865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         /* this is a little tricky - I think I've got it right */
327865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         const GLfloat invQ = 1.0f / (span->tex[u][3]
328865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                      + span->texStepX[u][3] * column);
329865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->texStepX[u][0] * invQ;
330865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->texStepX[u][1] * invQ;
331865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->texStepX[u][2] * invQ;
332865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->texStepX[u][3] * invQ;
333865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
334865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
335865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         const GLuint u = source->Index - FRAG_ATTRIB_TEX0;
336865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         /* Tricky, as above, but in Y direction */
337865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         const GLfloat invQ = 1.0f / (span->tex[u][3] + span->texStepY[u][3]);
338865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[0] = span->texStepY[u][0] * invQ;
339865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[1] = span->texStepY[u][1] * invQ;
340865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[2] = span->texStepY[u][2] * invQ;
341865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         src[3] = span->texStepY[u][3] * invQ;
342865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
343865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      break;
344865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   default:
345865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return GL_FALSE;
346865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
347865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
348865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   result[0] = src[GET_SWZ(source->Swizzle, 0)];
349865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   result[1] = src[GET_SWZ(source->Swizzle, 1)];
350865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   result[2] = src[GET_SWZ(source->Swizzle, 2)];
351865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   result[3] = src[GET_SWZ(source->Swizzle, 3)];
352865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
353865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateBase) {
354865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
355865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = -result[1];
356865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = -result[2];
357865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = -result[3];
358865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
359865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->Abs) {
360865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = FABSF(result[0]);
361865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = FABSF(result[1]);
362865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = FABSF(result[2]);
363865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = FABSF(result[3]);
364865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
365865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateAbs) {
366865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
367865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[1] = -result[1];
368865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[2] = -result[2];
369865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[3] = -result[3];
370865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
371865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   return GL_TRUE;
372865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
373865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
374865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
375865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
376865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * As above, but only return result[0] element.
377865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
378865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
379865f88afc0d59d886fb2ad50429e584ecf17fa81Brianfetch_vector1( GLcontext *ctx,
380865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct prog_src_register *source,
381865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct fp_machine *machine,
382865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct gl_fragment_program *program,
383865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat result[4] )
384865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
385865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
386865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ASSERT(src);
387865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
388865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   result[0] = src[GET_SWZ(source->Swizzle, 0)];
389865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
390865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateBase) {
391865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
392865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
393865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->Abs) {
394865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = FABSF(result[0]);
395865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
396865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (source->NegateAbs) {
397865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      result[0] = -result[0];
398865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
399865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
400865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
401865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
402865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
403865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Test value against zero and return GT, LT, EQ or UN if NaN.
404865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
405865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic INLINE GLuint
406865f88afc0d59d886fb2ad50429e584ecf17fa81Briangenerate_cc( float value )
407865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
408865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (value != value)
409865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return COND_UN;  /* NaN */
410865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (value > 0.0F)
411865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return COND_GT;
412865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (value < 0.0F)
413865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      return COND_LT;
414865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   return COND_EQ;
415865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
416865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
417865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
418865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
419865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Test if the ccMaskRule is satisfied by the given condition code.
420865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Used to mask destination writes according to the current condition code.
421865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
422865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic INLINE GLboolean
423865f88afc0d59d886fb2ad50429e584ecf17fa81Briantest_cc(GLuint condCode, GLuint ccMaskRule)
424865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
425865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   switch (ccMaskRule) {
426865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_EQ: return (condCode == COND_EQ);
427865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_NE: return (condCode != COND_EQ);
428865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_LT: return (condCode == COND_LT);
429865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);
430865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_LE: return (condCode == COND_LT || condCode == COND_EQ);
431865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_GT: return (condCode == COND_GT);
432865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_TR: return GL_TRUE;
433865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   case COND_FL: return GL_FALSE;
434865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   default:      return GL_TRUE;
435865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
436865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
437865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
438865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
439865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
440865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Store 4 floats into a register.  Observe the instructions saturate and
441865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * set-condition-code flags.
442865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
443865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
444865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstore_vector4( const struct prog_instruction *inst,
445865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               struct fp_machine *machine,
446865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLfloat value[4] )
447865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
448865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const struct prog_dst_register *dest = &(inst->DstReg);
449865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE;
450865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat *dstReg;
451865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat dummyReg[4];
452865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLfloat clampedValue[4];
453865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint writeMask = dest->WriteMask;
454865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
455865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   switch (dest->File) {
456865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_OUTPUT:
457865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         dstReg = machine->Outputs[dest->Index];
458865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         break;
459865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_TEMPORARY:
460865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         dstReg = machine->Temporaries[dest->Index];
461865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         break;
462865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      case PROGRAM_WRITE_ONLY:
463865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         dstReg = dummyReg;
464865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         return;
465865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      default:
466865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         _mesa_problem(NULL, "bad register file in store_vector4(fp)");
467865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         return;
468865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
469865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
470865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#if 0
471865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (value[0] > 1.0e10 ||
472865f88afc0d59d886fb2ad50429e584ecf17fa81Brian       IS_INF_OR_NAN(value[0]) ||
473865f88afc0d59d886fb2ad50429e584ecf17fa81Brian       IS_INF_OR_NAN(value[1]) ||
474865f88afc0d59d886fb2ad50429e584ecf17fa81Brian       IS_INF_OR_NAN(value[2]) ||
475865f88afc0d59d886fb2ad50429e584ecf17fa81Brian       IS_INF_OR_NAN(value[3])  )
476865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]);
477865f88afc0d59d886fb2ad50429e584ecf17fa81Brian#endif
478865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
479865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (clamp) {
480865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F);
481865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F);
482865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F);
483865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F);
484865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      value = clampedValue;
485865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
486865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
487865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (dest->CondMask != COND_TR) {
488865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* condition codes may turn off some writes */
489865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_X) {
490865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 0)],
491865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      dest->CondMask))
492865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            writeMask &= ~WRITEMASK_X;
493865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
494865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_Y) {
495865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 1)],
496865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      dest->CondMask))
497865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            writeMask &= ~WRITEMASK_Y;
498865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
499865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_Z) {
500865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 2)],
501865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      dest->CondMask))
502865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            writeMask &= ~WRITEMASK_Z;
503865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
504865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_W) {
505865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 3)],
506865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                      dest->CondMask))
507865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            writeMask &= ~WRITEMASK_W;
508865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
509865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
510865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
511865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (writeMask & WRITEMASK_X)
512865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      dstReg[0] = value[0];
513865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (writeMask & WRITEMASK_Y)
514865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      dstReg[1] = value[1];
515865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (writeMask & WRITEMASK_Z)
516865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      dstReg[2] = value[2];
517865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (writeMask & WRITEMASK_W)
518865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      dstReg[3] = value[3];
519865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
520865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (inst->CondUpdate) {
521865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_X)
522865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         machine->CondCodes[0] = generate_cc(value[0]);
523865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_Y)
524865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         machine->CondCodes[1] = generate_cc(value[1]);
525865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_Z)
526865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         machine->CondCodes[2] = generate_cc(value[2]);
527865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (writeMask & WRITEMASK_W)
528865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         machine->CondCodes[3] = generate_cc(value[3]);
529865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
530865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
531865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
532865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
533865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
534865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Initialize a new machine state instance from an existing one, adding
535865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * the partial derivatives onto the input registers.
536865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Used to implement DDX and DDY instructions in non-trivial cases.
537865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
538865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
539865f88afc0d59d886fb2ad50429e584ecf17fa81Brianinit_machine_deriv( GLcontext *ctx,
540865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    const struct fp_machine *machine,
541865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    const struct gl_fragment_program *program,
542865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    const SWspan *span, char xOrY,
543865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    struct fp_machine *dMachine )
544865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
545865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint u, v;
546865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
547865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ASSERT(xOrY == 'X' || xOrY == 'Y');
548865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
549865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* copy existing machine */
550865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   _mesa_memcpy(dMachine, machine, sizeof(struct fp_machine));
551865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
552865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
553865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* Clear temporary registers (undefined for ARB_f_p) */
554865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      _mesa_bzero( (void*) machine->Temporaries,
555865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
556865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
557865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
558865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* Add derivatives */
559ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian   if (program->Base.InputsRead & FRAG_BIT_WPOS) {
560f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat *wpos = machine->Attribs[FRAG_ATTRIB_WPOS][machine->CurFrag];
561865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
562865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[0] += 1.0F;
563865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[1] += 0.0F;
564865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[2] += span->dzdx;
565865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[3] += span->dwdx;
566865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
567865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
568865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[0] += 0.0F;
569865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[1] += 1.0F;
570865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[2] += span->dzdy;
571865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         wpos[3] += span->dwdy;
572865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
573865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
574ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian   if (program->Base.InputsRead & FRAG_BIT_COL0) {
575f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat *col0 = machine->Attribs[FRAG_ATTRIB_COL0][machine->CurFrag];
576865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
577865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[0] += span->drdx * (1.0F / CHAN_MAXF);
578865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[1] += span->dgdx * (1.0F / CHAN_MAXF);
579865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[2] += span->dbdx * (1.0F / CHAN_MAXF);
580865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[3] += span->dadx * (1.0F / CHAN_MAXF);
581865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
582865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
583865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[0] += span->drdy * (1.0F / CHAN_MAXF);
584865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[1] += span->dgdy * (1.0F / CHAN_MAXF);
585865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[2] += span->dbdy * (1.0F / CHAN_MAXF);
586865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col0[3] += span->dady * (1.0F / CHAN_MAXF);
587865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
588865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
589ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian   if (program->Base.InputsRead & FRAG_BIT_COL1) {
590f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat *col1 = machine->Attribs[FRAG_ATTRIB_COL1][machine->CurFrag];
591865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
592865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[0] += span->dsrdx * (1.0F / CHAN_MAXF);
593865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[1] += span->dsgdx * (1.0F / CHAN_MAXF);
594865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[2] += span->dsbdx * (1.0F / CHAN_MAXF);
595865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[3] += 0.0; /*XXX fix */
596865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
597865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
598865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[0] += span->dsrdy * (1.0F / CHAN_MAXF);
599865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[1] += span->dsgdy * (1.0F / CHAN_MAXF);
600865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[2] += span->dsbdy * (1.0F / CHAN_MAXF);
601865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         col1[3] += 0.0; /*XXX fix */
602865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
603865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
604ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian   if (program->Base.InputsRead & FRAG_BIT_FOGC) {
605f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat *fogc = machine->Attribs[FRAG_ATTRIB_FOGC][machine->CurFrag];
606865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (xOrY == 'X') {
607865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         fogc[0] += span->dfogdx;
608865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
609865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      else {
610865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         fogc[0] += span->dfogdy;
611865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
612865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
613865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
614ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian      if (program->Base.InputsRead & FRAG_BIT_TEX(u)) {
615f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat *tex = machine->Attribs[FRAG_ATTRIB_TEX0 + u][machine->CurFrag];
616865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         /* XXX perspective-correct interpolation */
617865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (xOrY == 'X') {
618865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[0] += span->texStepX[u][0];
619865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[1] += span->texStepX[u][1];
620865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[2] += span->texStepX[u][2];
621865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[3] += span->texStepX[u][3];
622865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         }
623865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         else {
624865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[0] += span->texStepY[u][0];
625865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[1] += span->texStepY[u][1];
626865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[2] += span->texStepY[u][2];
627865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            tex[3] += span->texStepY[u][3];
628865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         }
629865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
630865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
631865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
632865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   for (v = 0; v < ctx->Const.MaxVarying; v++) {
633ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian      if (program->Base.InputsRead & FRAG_BIT_VAR(v)) {
634f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat *var = machine->Attribs[FRAG_ATTRIB_VAR0 + v][machine->CurFrag];
635ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian         if (xOrY == 'X') {
636ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[0] += span->varStepX[v][0];
637ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[1] += span->varStepX[v][1];
638ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[2] += span->varStepX[v][2];
639ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[3] += span->varStepX[v][3];
640ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian         }
641ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian         else {
642ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[0] += span->varStepY[v][0];
643ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[1] += span->varStepY[v][1];
644ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[2] += span->varStepY[v][2];
645ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian            var[3] += span->varStepY[v][3];
646ff13f0ea4d5e88ac86bf5d97373ca419ad4226e5Brian         }
647865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
648865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
649865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
650865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* init condition codes */
651865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   dMachine->CondCodes[0] = COND_EQ;
652865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   dMachine->CondCodes[1] = COND_EQ;
653865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   dMachine->CondCodes[2] = COND_EQ;
654865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   dMachine->CondCodes[3] = COND_EQ;
655865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
656865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
657865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
658865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
659865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Execute the given vertex program.
660865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * NOTE: we do everything in single-precision floating point; we don't
661865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * currently observe the single/half/fixed-precision qualifiers.
662865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param ctx - rendering context
663865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param program - the fragment program to execute
664865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param machine - machine state (register file)
665865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param maxInst - max number of instructions to execute
666865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
667865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
668865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic GLboolean
669865f88afc0d59d886fb2ad50429e584ecf17fa81Brianexecute_program( GLcontext *ctx,
670865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                 const struct gl_fragment_program *program, GLuint maxInst,
671865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                 struct fp_machine *machine, const SWspan *span,
672865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                 GLuint column )
673865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
674f673b24017b8b5e850a1be5c04bd28cefa811329Brian   const GLuint MAX_EXEC = 10000;
675d22079217c5a1954a07afb1193d06eecb2decbb6Brian   GLuint pc, total = 0;
676865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
677865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (DEBUG_FRAG) {
678865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      printf("execute fragment program --------------------\n");
679865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
680865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
681865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   for (pc = 0; pc < maxInst; pc++) {
682865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      const struct prog_instruction *inst = program->Base.Instructions + pc;
683865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
684865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (ctx->FragmentProgram.CallbackEnabled &&
685865f88afc0d59d886fb2ad50429e584ecf17fa81Brian          ctx->FragmentProgram.Callback) {
686865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         ctx->FragmentProgram.CurrentPosition = inst->StringPos;
687865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         ctx->FragmentProgram.Callback(program->Base.Target,
688865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                       ctx->FragmentProgram.CallbackData);
689865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
690865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
691865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (DEBUG_FRAG) {
692865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         _mesa_print_instruction(inst);
693865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
694865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
695865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      switch (inst->Opcode) {
696865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_ABS:
697865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
698865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
699865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
700865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = FABSF(a[0]);
701865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = FABSF(a[1]);
702865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = FABSF(a[2]);
703865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = FABSF(a[3]);
704865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
705865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
706865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
707865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_ADD:
708865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
709865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
710865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
711865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
712865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] + b[0];
713865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] + b[1];
714865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] + b[2];
715865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] + b[3];
716865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
717865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
718865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n",
719865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
720865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3],
721865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3]);
722865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
723865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
724865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
725865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_BRA: /* conditional branch */
726865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
7270031ea7d85ae8990872c2181d038fb97b566dc2bBrian               /* NOTE: The branch is conditional! */
728865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint swizzle = inst->DstReg.CondSwizzle;
729865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint condMask = inst->DstReg.CondMask;
730865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
731865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
732865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
733865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
734865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  /* take branch */
735865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  pc = inst->BranchTarget;
736d22079217c5a1954a07afb1193d06eecb2decbb6Brian                  /*
737d22079217c5a1954a07afb1193d06eecb2decbb6Brian                  printf("Take branch to %u\n", pc);
738d22079217c5a1954a07afb1193d06eecb2decbb6Brian                  */
739865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
740865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
741865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
742865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_CAL: /* Call subroutine */
743865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
744865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* NOTE: The call is conditional! */
745865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint swizzle = inst->DstReg.CondSwizzle;
746865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint condMask = inst->DstReg.CondMask;
747865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
748865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
749865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
750865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
751865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
752865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
753865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  }
754865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  machine->CallStack[machine->StackDepth++] = pc + 1;
755865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  pc = inst->BranchTarget;
756865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
757865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
758865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
759865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_CMP:
760865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
761865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], c[4], result[4];
762865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
763865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
764865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, c );
765865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] < 0.0F ? b[0] : c[0];
766865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] < 0.0F ? b[1] : c[1];
767865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] < 0.0F ? b[2] : c[2];
768865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] < 0.0F ? b[3] : c[3];
769865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
770865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
771865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
772865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_COS:
773865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
774865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
775865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
776865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3]
777865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = (GLfloat) _mesa_cos(a[0]);
778865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
779865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
780865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
781865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DDX: /* Partial derivative with respect to X */
782865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
783865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], aNext[4], result[4];
784865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               struct fp_machine dMachine;
785865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (!fetch_vector4_deriv(ctx, &inst->SrcReg[0], span, 'X',
786865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                        column, result)) {
787865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  /* This is tricky.  Make a copy of the current machine state,
788865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   * increment the input registers by the dx or dy partial
789865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   * derivatives, then re-execute the program up to the
790865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   * preceeding instruction, then fetch the source register.
791865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   * Finally, find the difference in the register values for
792865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   * the original and derivative runs.
793865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   */
794865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
795865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  init_machine_deriv(ctx, machine, program, span,
796865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                     'X', &dMachine);
797865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  execute_program(ctx, program, pc, &dMachine, span, column);
798865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  fetch_vector4( ctx, &inst->SrcReg[0], &dMachine, program, aNext );
799865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[0] = aNext[0] - a[0];
800865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[1] = aNext[1] - a[1];
801865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[2] = aNext[2] - a[2];
802865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[3] = aNext[3] - a[3];
803865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
804865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
805865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
806865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
807865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DDY: /* Partial derivative with respect to Y */
808865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
809865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], aNext[4], result[4];
810865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               struct fp_machine dMachine;
811865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (!fetch_vector4_deriv(ctx, &inst->SrcReg[0], span, 'Y',
812865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                        column, result)) {
813865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  init_machine_deriv(ctx, machine, program, span,
814865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                     'Y', &dMachine);
815865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
816865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  execute_program(ctx, program, pc, &dMachine, span, column);
817865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  fetch_vector4( ctx, &inst->SrcReg[0], &dMachine, program, aNext );
818865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[0] = aNext[0] - a[0];
819865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[1] = aNext[1] - a[1];
820865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[2] = aNext[2] - a[2];
821865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[3] = aNext[3] - a[3];
822865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
823865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
824865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
825865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
826865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DP3:
827865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
828865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
829865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
830865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
831865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] = DOT3(a, b);
832865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
833865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
834865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
835865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
836865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
837865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
838865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
839865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DP4:
840865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
841865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
842865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
843865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
844865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] = DOT4(a,b);
845865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
846865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
847865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
848865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], a[0], a[1], a[2], a[3],
849865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3]);
850865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
851865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
852865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
853865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DPH:
854865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
855865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
856865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
857865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
858865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] =
859865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + b[3];
860865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
861865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
862865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
863865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_DST: /* Distance vector */
864865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
865865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
866865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
867865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
868865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = 1.0F;
869865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] * b[1];
870865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2];
871865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = b[3];
872865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
873865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
874865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
875865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_EX2: /* Exponential base 2 */
876865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
877865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
878865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
879865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] =
880865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  (GLfloat) _mesa_pow(2.0, a[0]);
881865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
882865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
883865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
884865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_FLR:
885865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
886865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
887865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
888865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = FLOORF(a[0]);
889865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = FLOORF(a[1]);
890865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = FLOORF(a[2]);
891865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = FLOORF(a[3]);
892865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
893865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
894865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
895865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_FRC:
896865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
897865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
898865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
899865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] - FLOORF(a[0]);
900865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] - FLOORF(a[1]);
901865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] - FLOORF(a[2]);
902865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] - FLOORF(a[3]);
903865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
904865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
905865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
9065ae49cf3ed53fda6a904d7e90feef78495ae6903Brian         case OPCODE_IF:
9075ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            {
9085ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               const GLuint swizzle = inst->DstReg.CondSwizzle;
9095ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               const GLuint condMask = inst->DstReg.CondMask;
9105ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
9115ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
9125ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
9135ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
9145ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  /* do if-clause (just continue execution) */
9155ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               }
9165ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               else {
9175ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  /* do else-clause, or go to endif */
9185ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  GLint ifDepth = 1;
9195ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  do {
9205ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     pc++;
9215ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     inst = program->Base.Instructions + pc;
9225ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     if (inst->Opcode == OPCODE_END) {
9235ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        /* mal-formed program! */
9245ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        abort();
9255ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     }
9265ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     else if (inst->Opcode == OPCODE_IF) {
9275ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        ifDepth++;
9285ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     }
9295ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     else if (inst->Opcode == OPCODE_ELSE) {
9305ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        if (ifDepth == 0) {
9315ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                           /* ok, continue normal execution */
9325ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                           break;
9335ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        }
9345ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     }
9355ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     else if (inst->Opcode == OPCODE_ENDIF) {
9365ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        ifDepth--;
9375ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        if (ifDepth == 0) {
9385ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                           /* ok, continue normal execution */
9395ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                           break;
9405ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        }
9415ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     }
9425ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     assert(ifDepth >= 0);
9435ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  } while (pc < maxInst);
9445ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               }
9455ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            }
9465ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            break;
9475ae49cf3ed53fda6a904d7e90feef78495ae6903Brian         case OPCODE_ELSE:
9485ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            {
9495ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               /* find/goto ENDIF */
9505ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               GLint ifDepth = 1;
9515ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               do {
9525ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  pc++;
9535ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  inst = program->Base.Instructions + pc;
9545ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  if (inst->Opcode == OPCODE_END) {
9555ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     /* mal-formed program! */
9565ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     abort();
9575ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  }
9585ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  else if (inst->Opcode == OPCODE_IF) {
9595ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     ifDepth++;
9605ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  }
9615ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  else if (inst->Opcode == OPCODE_ENDIF) {
9625ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     ifDepth--;
9635ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                     if (ifDepth == 0)
9645ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                        break;
9655ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  }
9665ae49cf3ed53fda6a904d7e90feef78495ae6903Brian                  assert(ifDepth >= 0);
9675ae49cf3ed53fda6a904d7e90feef78495ae6903Brian               } while (pc < maxInst);
9685ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            }
9695ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            break;
9705ae49cf3ed53fda6a904d7e90feef78495ae6903Brian         case OPCODE_ENDIF:
9715ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            /* nothing */
9725ae49cf3ed53fda6a904d7e90feef78495ae6903Brian            break;
9730bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian         case OPCODE_INT: /* float to int */
9740bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian            {
9750bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               GLfloat a[4], result[4];
9760bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
9770bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               result[0] = (GLfloat) (GLint) a[0];
9780bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               result[1] = (GLfloat) (GLint) a[1];
9790bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               result[2] = (GLfloat) (GLint) a[2];
9800bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               result[3] = (GLfloat) (GLint) a[3];
9810bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian               store_vector4( inst, machine, result );
9820bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian            }
9830bad236cfbaabfc0ed4f20088e64fa89f81934ceBrian            break;
984865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_KIL_NV: /* NV_f_p only */
985865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
986865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint swizzle = inst->DstReg.CondSwizzle;
987865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint condMask = inst->DstReg.CondMask;
988865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
989865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
990865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
991865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
992865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  return GL_FALSE;
993865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
994865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
995865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
996865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_KIL: /* ARB_f_p only */
997865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
998865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4];
999865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1000865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
1001865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  return GL_FALSE;
1002865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1003865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1004865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1005865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_LG2:  /* log base 2 */
1006865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1007865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1008865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1009865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] = LOG2(a[0]);
1010865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1011865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1012865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1013865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_LIT:
1014865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1015865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLfloat epsilon = 1.0F / 256.0F; /* from NV VP spec */
1016865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1017865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1018865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[0] = MAX2(a[0], 0.0F);
1019865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[1] = MAX2(a[1], 0.0F);
1020865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* XXX ARB version clamps a[3], NV version doesn't */
1021865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon));
1022865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = 1.0F;
1023865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[0];
1024865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* XXX we could probably just use pow() here */
1025865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (a[0] > 0.0F) {
1026865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (a[1] == 0.0 && a[3] == 0.0)
1027865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[2] = 1.0;
1028865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  else
1029865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[2] = EXPF(a[3] * LOGF(a[1]));
1030865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1031865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else {
1032865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  result[2] = 0.0;
1033865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1034865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = 1.0F;
1035865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1036865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1037865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("LIT (%g %g %g %g) : (%g %g %g %g)\n",
1038865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1039865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3]);
1040865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1041865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1042865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1043865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_LRP:
1044865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1045865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], c[4], result[4];
1046865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1047865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1048865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, c );
1049865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0];
1050865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1];
1051865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2];
1052865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3];
1053865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1054865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1055865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("LRP (%g %g %g %g) = (%g %g %g %g), "
1056865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         "(%g %g %g %g), (%g %g %g %g)\n",
1057865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1058865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3],
1059865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3],
1060865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         c[0], c[1], c[2], c[3]);
1061865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1062865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1063865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1064865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_MAD:
1065865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1066865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], c[4], result[4];
1067865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1068865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1069865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, c );
1070865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] * b[0] + c[0];
1071865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] * b[1] + c[1];
1072865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] * b[2] + c[2];
1073865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] * b[3] + c[3];
1074865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1075865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1076865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("MAD (%g %g %g %g) = (%g %g %g %g) * "
1077865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         "(%g %g %g %g) + (%g %g %g %g)\n",
1078865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1079865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3],
1080865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3],
1081865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         c[0], c[1], c[2], c[3]);
1082865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1083865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1084865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1085865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_MAX:
1086865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1087865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1088865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1089865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1090865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = MAX2(a[0], b[0]);
1091865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = MAX2(a[1], b[1]);
1092865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = MAX2(a[2], b[2]);
1093865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = MAX2(a[3], b[3]);
1094865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1095865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1096865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
1097865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1098865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3],
1099865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3]);
1100865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1101865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1102865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1103865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_MIN:
1104865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1105865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1106865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1107865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1108865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = MIN2(a[0], b[0]);
1109865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = MIN2(a[1], b[1]);
1110865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = MIN2(a[2], b[2]);
1111865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = MIN2(a[3], b[3]);
1112865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1113865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1114865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1115865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_MOV:
1116865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1117865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat result[4];
1118865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, result );
1119865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1120865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1121865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("MOV (%g %g %g %g)\n",
1122865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3]);
1123865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1124865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1125865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1126865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_MUL:
1127865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1128865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1129865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1130865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1131865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] * b[0];
1132865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] * b[1];
1133865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] * b[2];
1134865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] * b[3];
1135865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1136865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1137865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
1138865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1139865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3],
1140865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         b[0], b[1], b[2], b[3]);
1141865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1142865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1143865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
11447aece10039ad4786d7f85d61ec8614b9f287ea23Brian         case OPCODE_NOISE1:
11457aece10039ad4786d7f85d61ec8614b9f287ea23Brian            {
11467aece10039ad4786d7f85d61ec8614b9f287ea23Brian               GLfloat a[4], result[4];
11477aece10039ad4786d7f85d61ec8614b9f287ea23Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
11487aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[0] =
11497aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[1] =
11507aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[2] =
11517aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[3] = _slang_library_noise1(a[0]);
11527aece10039ad4786d7f85d61ec8614b9f287ea23Brian               store_vector4( inst, machine, result );
11537aece10039ad4786d7f85d61ec8614b9f287ea23Brian            }
11547aece10039ad4786d7f85d61ec8614b9f287ea23Brian            break;
11557aece10039ad4786d7f85d61ec8614b9f287ea23Brian         case OPCODE_NOISE2:
11567aece10039ad4786d7f85d61ec8614b9f287ea23Brian            {
11577aece10039ad4786d7f85d61ec8614b9f287ea23Brian               GLfloat a[4], result[4];
11587aece10039ad4786d7f85d61ec8614b9f287ea23Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
11597aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[0] =
11607aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[1] =
11617aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[2] =
11627aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[3] = _slang_library_noise2(a[0], a[1]);
11637aece10039ad4786d7f85d61ec8614b9f287ea23Brian               store_vector4( inst, machine, result );
11647aece10039ad4786d7f85d61ec8614b9f287ea23Brian            }
11657aece10039ad4786d7f85d61ec8614b9f287ea23Brian            break;
11667aece10039ad4786d7f85d61ec8614b9f287ea23Brian         case OPCODE_NOISE3:
11677aece10039ad4786d7f85d61ec8614b9f287ea23Brian            {
11687aece10039ad4786d7f85d61ec8614b9f287ea23Brian               GLfloat a[4], result[4];
11697aece10039ad4786d7f85d61ec8614b9f287ea23Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
11707aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[0] =
11717aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[1] =
11727aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[2] =
11737aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[3] = _slang_library_noise3(a[0], a[1], a[2]);
11747aece10039ad4786d7f85d61ec8614b9f287ea23Brian               store_vector4( inst, machine, result );
11757aece10039ad4786d7f85d61ec8614b9f287ea23Brian            }
11767aece10039ad4786d7f85d61ec8614b9f287ea23Brian            break;
11777aece10039ad4786d7f85d61ec8614b9f287ea23Brian         case OPCODE_NOISE4:
11787aece10039ad4786d7f85d61ec8614b9f287ea23Brian            {
11797aece10039ad4786d7f85d61ec8614b9f287ea23Brian               GLfloat a[4], result[4];
11807aece10039ad4786d7f85d61ec8614b9f287ea23Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
11817aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[0] =
11827aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[1] =
11837aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[2] =
11847aece10039ad4786d7f85d61ec8614b9f287ea23Brian               result[3] = _slang_library_noise4(a[0], a[1], a[2], a[3]);
11857aece10039ad4786d7f85d61ec8614b9f287ea23Brian               store_vector4( inst, machine, result );
11867aece10039ad4786d7f85d61ec8614b9f287ea23Brian            }
11877aece10039ad4786d7f85d61ec8614b9f287ea23Brian            break;
11880031ea7d85ae8990872c2181d038fb97b566dc2bBrian         case OPCODE_NOP:
11890031ea7d85ae8990872c2181d038fb97b566dc2bBrian            break;
1190865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */
1191865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1192865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1193865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLhalfNV hx, hy;
1194865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint *rawResult = (GLuint *) result;
1195865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint twoHalves;
1196865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1197865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               hx = _mesa_float_to_half(a[0]);
1198865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               hy = _mesa_float_to_half(a[1]);
1199865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               twoHalves = hx | (hy << 16);
1200865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3]
1201865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = twoHalves;
1202865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1203865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1204865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1205865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_PK2US: /* pack two GLushorts into one 32-bit float */
1206865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1207865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1208865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint usx, usy, *rawResult = (GLuint *) result;
1209865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1210865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[0] = CLAMP(a[0], 0.0F, 1.0F);
1211865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[1] = CLAMP(a[1], 0.0F, 1.0F);
1212865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               usx = IROUND(a[0] * 65535.0F);
1213865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               usy = IROUND(a[1] * 65535.0F);
1214865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3]
1215865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = usx | (usy << 16);
1216865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1217865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1218865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1219865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_PK4B: /* pack four GLbytes into one 32-bit float */
1220865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1221865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1222865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result;
1223865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1224865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[0] = CLAMP(a[0], -128.0F / 127.0F, 1.0F);
1225865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F);
1226865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[2] = CLAMP(a[2], -128.0F / 127.0F, 1.0F);
1227865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[3] = CLAMP(a[3], -128.0F / 127.0F, 1.0F);
1228865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubx = IROUND(127.0F * a[0] + 128.0F);
1229865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               uby = IROUND(127.0F * a[1] + 128.0F);
1230865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubz = IROUND(127.0F * a[2] + 128.0F);
1231865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubw = IROUND(127.0F * a[3] + 128.0F);
1232865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3]
1233865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
1234865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1235865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1236865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1237865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_PK4UB: /* pack four GLubytes into one 32-bit float */
1238865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1239865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1240865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result;
1241865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1242865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[0] = CLAMP(a[0], 0.0F, 1.0F);
1243865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[1] = CLAMP(a[1], 0.0F, 1.0F);
1244865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[2] = CLAMP(a[2], 0.0F, 1.0F);
1245865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[3] = CLAMP(a[3], 0.0F, 1.0F);
1246865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubx = IROUND(255.0F * a[0]);
1247865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               uby = IROUND(255.0F * a[1]);
1248865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubz = IROUND(255.0F * a[2]);
1249865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               ubw = IROUND(255.0F * a[3]);
1250865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3]
1251865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
1252865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1253865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1254865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1255865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_POW:
1256865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1257865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1258865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1259865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[1], machine, program, b );
1260865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3]
1261865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = (GLfloat)_mesa_pow(a[0], b[0]);
1262865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1263865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1264865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1265865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_RCP:
1266865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1267865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1268865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1269865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1270865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (a[0] == 0)
1271865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     printf("RCP(0)\n");
1272865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  else if (IS_INF_OR_NAN(a[0]))
1273865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     printf("RCP(inf)\n");
1274865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1275865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] = 1.0F / a[0];
1276865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1277865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1278865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1279865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_RET: /* return from subroutine */
1280865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1281865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* NOTE: The return is conditional! */
1282865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint swizzle = inst->DstReg.CondSwizzle;
1283865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint condMask = inst->DstReg.CondMask;
1284865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
1285865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
1286865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
1287865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
1288865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (machine->StackDepth == 0) {
1289865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
1290865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  }
1291865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  pc = machine->CallStack[--machine->StackDepth];
1292865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1293865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1294865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1295865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_RFL: /* reflection vector */
1296865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1297865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat axis[4], dir[4], result[4], tmpX, tmpW;
1298865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, axis );
1299865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, dir );
1300865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               tmpW = DOT3(axis, axis);
1301865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               tmpX = (2.0F * DOT3(axis, dir)) / tmpW;
1302865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = tmpX * axis[0] - dir[0];
1303865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = tmpX * axis[1] - dir[1];
1304865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = tmpX * axis[2] - dir[2];
1305865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* result[3] is never written! XXX enforce in parser! */
1306865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1307865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1308865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1309865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_RSQ: /* 1 / sqrt() */
1310865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1311865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1312865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1313865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               a[0] = FABSF(a[0]);
1314865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3] = INV_SQRTF(a[0]);
1315865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1316865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1317865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
1318865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1319865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1320865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1321865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SCS: /* sine and cos */
1322865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1323865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1324865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1325223d7cb3c785ad58c869a3ee0fbf2f1d42c3310dBrian               result[0] = (GLfloat) _mesa_cos(a[0]);
1326223d7cb3c785ad58c869a3ee0fbf2f1d42c3310dBrian               result[1] = (GLfloat) _mesa_sin(a[0]);
1327865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = 0.0;  /* undefined! */
1328865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = 0.0;  /* undefined! */
1329865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1330865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1331865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1332865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SEQ: /* set on equal */
1333865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1334865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1335865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1336865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1337865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] == b[0]) ? 1.0F : 0.0F;
1338865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] == b[1]) ? 1.0F : 0.0F;
1339865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] == b[2]) ? 1.0F : 0.0F;
1340865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] == b[3]) ? 1.0F : 0.0F;
1341865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1342865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1343865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1344865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SFL: /* set false, operands ignored */
1345865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1346865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               static const GLfloat result[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
1347865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1348865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1349865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1350865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SGE: /* set on greater or equal */
1351865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1352865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1353865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1354865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1355865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F;
1356865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F;
1357865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F;
1358865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F;
1359865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1360865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1361865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1362865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SGT: /* set on greater */
1363865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1364865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1365865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1366865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1367865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] > b[0]) ? 1.0F : 0.0F;
1368865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] > b[1]) ? 1.0F : 0.0F;
1369865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
1370865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
1371865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1372865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1373865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1374865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SIN:
1375865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1376865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1377865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1378865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[1] = result[2] = result[3]
1379865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  = (GLfloat) _mesa_sin(a[0]);
1380865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1381865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1382865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1383865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SLE: /* set on less or equal */
1384865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1385865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1386865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1387865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1388865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] <= b[0]) ? 1.0F : 0.0F;
1389865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] <= b[1]) ? 1.0F : 0.0F;
1390865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] <= b[2]) ? 1.0F : 0.0F;
1391865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] <= b[3]) ? 1.0F : 0.0F;
1392865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1393865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1394865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1395865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SLT: /* set on less */
1396865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1397865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1398865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1399865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1400865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] < b[0]) ? 1.0F : 0.0F;
1401865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] < b[1]) ? 1.0F : 0.0F;
1402865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] < b[2]) ? 1.0F : 0.0F;
1403865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] < b[3]) ? 1.0F : 0.0F;
1404865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1405865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1406865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1407865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SNE: /* set on not equal */
1408865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1409865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1410865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1411865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1412865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (a[0] != b[0]) ? 1.0F : 0.0F;
1413865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (a[1] != b[1]) ? 1.0F : 0.0F;
1414865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (a[2] != b[2]) ? 1.0F : 0.0F;
1415865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (a[3] != b[3]) ? 1.0F : 0.0F;
1416865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1417865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1418865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1419865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_STR: /* set true, operands ignored */
1420865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1421865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F };
1422865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1423865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1424865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1425865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SUB:
1426865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1427865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1428865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1429865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1430865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] - b[0];
1431865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] - b[1];
1432865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] - b[2];
1433865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] - b[3];
1434865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1435865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1436865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
1437865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         result[0], result[1], result[2], result[3],
1438865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
1439865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1440865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1441865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1442865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_SWZ: /* extended swizzle */
1443865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1444865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const struct prog_src_register *source = &inst->SrcReg[0];
1445865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLfloat *src = get_register_pointer(ctx, source,
1446865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                                         machine, program);
1447865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat result[4];
1448865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLuint i;
1449865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               for (i = 0; i < 4; i++) {
1450865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  const GLuint swz = GET_SWZ(source->Swizzle, i);
1451865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (swz == SWIZZLE_ZERO)
1452865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[i] = 0.0;
1453865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  else if (swz == SWIZZLE_ONE)
1454865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[i] = 1.0;
1455865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  else {
1456865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     ASSERT(swz >= 0);
1457865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     ASSERT(swz <= 3);
1458865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[i] = src[swz];
1459865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  }
1460865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  if (source->NegateBase & (1 << i))
1461865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                     result[i] = -result[i];
1462865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1463865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1464865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1465865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1466865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_TEX: /* Both ARB and NV frag prog */
1467865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Texel lookup */
1468865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1469865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* Note: only use the precomputed lambda value when we're
1470865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * sampling texture unit [K] with texcoord[K].
1471865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * Otherwise, the lambda value may have no relation to the
1472865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * instruction's texcoord or texture image.  Using the wrong
1473865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * lambda is usually bad news.
1474865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * The rest of the time, just use zero (until we get a more
1475865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                * sophisticated way of computing lambda).
1476865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                */
1477865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat coord[4], color[4], lambda;
1478865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
1479865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
1480865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = span->array->lambda[inst->TexSrcUnit][column];
1481865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else
1482865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = 0.0;
1483865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4(ctx, &inst->SrcReg[0], machine, program, coord);
1484865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_texel( ctx, coord, lambda, inst->TexSrcUnit, color );
1485865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (DEBUG_FRAG) {
1486865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g], "
1487865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         "lod %f\n",
1488865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         color[0], color[1], color[2], color[3],
1489865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         inst->TexSrcUnit,
1490865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                         coord[0], coord[1], coord[2], coord[3], lambda);
1491865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1492865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, color );
1493865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1494865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1495865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_TXB: /* GL_ARB_fragment_program only */
1496865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Texel lookup with LOD bias */
1497865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
149841a4e828d9e06e42bba78166975cb283674c0d9fBrian               const struct gl_texture_unit *texUnit
149941a4e828d9e06e42bba78166975cb283674c0d9fBrian                  = &ctx->Texture.Unit[inst->TexSrcUnit];
1500865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat coord[4], color[4], lambda, bias;
1501865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
1502865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
1503865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = span->array->lambda[inst->TexSrcUnit][column];
1504865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else
1505865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = 0.0;
1506865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4(ctx, &inst->SrcReg[0], machine, program, coord);
1507865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               /* coord[3] is the bias to add to lambda */
150841a4e828d9e06e42bba78166975cb283674c0d9fBrian               bias = texUnit->LodBias + coord[3];
150941a4e828d9e06e42bba78166975cb283674c0d9fBrian               if (texUnit->_Current)
151041a4e828d9e06e42bba78166975cb283674c0d9fBrian                  bias += texUnit->_Current->LodBias;
1511865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_texel(ctx, coord, lambda + bias, inst->TexSrcUnit, color);
1512865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, color );
1513865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1514865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1515865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_TXD: /* GL_NV_fragment_program only */
1516865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Texture lookup w/ partial derivatives for LOD */
1517865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1518865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
1519865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
1520865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, dtdx );
1521865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, dtdy );
1522865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_texel_deriv( ctx, texcoord, dtdx, dtdy, inst->TexSrcUnit,
1523865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                                  color );
1524865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, color );
1525865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1526865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1527865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_TXP: /* GL_ARB_fragment_program only */
1528865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Texture lookup w/ projective divide */
1529865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1530865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat texcoord[4], color[4], lambda;
1531865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
1532865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
1533865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = span->array->lambda[inst->TexSrcUnit][column];
1534865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else
1535865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = 0.0;
1536865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4(ctx, &inst->SrcReg[0], machine, program,texcoord);
1537865f88afc0d59d886fb2ad50429e584ecf17fa81Brian	       /* Not so sure about this test - if texcoord[3] is
1538865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		* zero, we'd probably be fine except for an ASSERT in
1539865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		* IROUND_POS() which gets triggered by the inf values created.
1540865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		*/
1541865f88afc0d59d886fb2ad50429e584ecf17fa81Brian	       if (texcoord[3] != 0.0) {
1542865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		  texcoord[0] /= texcoord[3];
1543865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		  texcoord[1] /= texcoord[3];
1544865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		  texcoord[2] /= texcoord[3];
1545865f88afc0d59d886fb2ad50429e584ecf17fa81Brian	       }
1546865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_texel( ctx, texcoord, lambda, inst->TexSrcUnit, color );
1547865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, color );
1548865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1549865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1550865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_TXP_NV: /* GL_NV_fragment_program only */
1551865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Texture lookup w/ projective divide */
1552865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1553865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat texcoord[4], color[4], lambda;
1554865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
1555865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
1556865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = span->array->lambda[inst->TexSrcUnit][column];
1557865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else
1558865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  lambda = 0.0;
1559865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4(ctx, &inst->SrcReg[0], machine, program,texcoord);
1560865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
1561865f88afc0d59d886fb2ad50429e584ecf17fa81Brian		   texcoord[3] != 0.0) {
1562865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  texcoord[0] /= texcoord[3];
1563865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  texcoord[1] /= texcoord[3];
1564865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  texcoord[2] /= texcoord[3];
1565865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1566865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_texel( ctx, texcoord, lambda, inst->TexSrcUnit, color );
1567865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, color );
1568865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1569865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1570865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_UP2H: /* unpack two 16-bit floats */
1571865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1572865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1573865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint *rawBits = (const GLuint *) a;
1574865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLhalfNV hx, hy;
1575865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1576865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               hx = rawBits[0] & 0xffff;
1577865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               hy = rawBits[0] >> 16;
1578865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[2] = _mesa_half_to_float(hx);
1579865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = result[3] = _mesa_half_to_float(hy);
1580865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1581865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1582865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1583865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_UP2US: /* unpack two GLushorts */
1584865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1585865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1586865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint *rawBits = (const GLuint *) a;
1587865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLushort usx, usy;
1588865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1589865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               usx = rawBits[0] & 0xffff;
1590865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               usy = rawBits[0] >> 16;
1591865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = result[2] = usx * (1.0f / 65535.0f);
1592865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = result[3] = usy * (1.0f / 65535.0f);
1593865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1594865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1595865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1596865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_UP4B: /* unpack four GLbytes */
1597865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1598865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1599865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint *rawBits = (const GLuint *) a;
1600865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1601865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = (((rawBits[0] >>  0) & 0xff) - 128) / 127.0F;
1602865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = (((rawBits[0] >>  8) & 0xff) - 128) / 127.0F;
1603865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F;
1604865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F;
1605865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1606865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1607865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1608865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_UP4UB: /* unpack four GLubytes */
1609865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1610865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], result[4];
1611865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLuint *rawBits = (const GLuint *) a;
1612865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
1613865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = ((rawBits[0] >>  0) & 0xff) / 255.0F;
1614865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = ((rawBits[0] >>  8) & 0xff) / 255.0F;
1615865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = ((rawBits[0] >> 16) & 0xff) / 255.0F;
1616865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = ((rawBits[0] >> 24) & 0xff) / 255.0F;
1617865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1618865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1619865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1620865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_XPD: /* cross product */
1621865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1622865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], result[4];
1623865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1624865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1625865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[1] * b[2] - a[2] * b[1];
1626865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[2] * b[0] - a[0] * b[2];
1627865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[0] * b[1] - a[1] * b[0];
1628865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = 1.0;
1629865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1630865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1631865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1632865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_X2D: /* 2-D matrix transform */
1633865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1634865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               GLfloat a[4], b[4], c[4], result[4];
1635865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
1636865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
1637865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, c );
1638865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[0] = a[0] + b[0] * c[0] + b[1] * c[1];
1639865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[1] = a[1] + b[0] * c[2] + b[1] * c[3];
1640865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[2] = a[2] + b[0] * c[0] + b[1] * c[1];
1641865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               result[3] = a[3] + b[0] * c[2] + b[1] * c[3];
1642865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               store_vector4( inst, machine, result );
1643865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1644865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1645865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_PRINT:
1646865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            {
1647865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (inst->SrcReg[0].File != -1) {
1648865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  GLfloat a[4];
1649865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
1650865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  _mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
1651865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                               a[0], a[1], a[2], a[3]);
1652865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1653865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else {
1654865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  _mesa_printf("%s\n", (const char *) inst->Data);
1655865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               }
1656865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1657865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            break;
1658865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         case OPCODE_END:
1659865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            return GL_TRUE;
1660865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         default:
1661865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            _mesa_problem(ctx, "Bad opcode %d in _mesa_exec_fragment_program",
1662865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                          inst->Opcode);
1663865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            return GL_TRUE; /* return value doesn't matter */
1664d22079217c5a1954a07afb1193d06eecb2decbb6Brian
1665d22079217c5a1954a07afb1193d06eecb2decbb6Brian      }
1666d22079217c5a1954a07afb1193d06eecb2decbb6Brian      total++;
1667d22079217c5a1954a07afb1193d06eecb2decbb6Brian      if (total > MAX_EXEC) {
1668d22079217c5a1954a07afb1193d06eecb2decbb6Brian         _mesa_problem(ctx, "Infinite loop detected in fragment program");
1669f673b24017b8b5e850a1be5c04bd28cefa811329Brian         return GL_TRUE;
1670d22079217c5a1954a07afb1193d06eecb2decbb6Brian         abort();
1671865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
1672865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
1673865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   return GL_TRUE;
1674865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
1675865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1676865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1677865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
1678865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Initialize the virtual fragment program machine state prior to running
1679865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * fragment program on a fragment.  This involves initializing the input
1680865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * registers, condition codes, etc.
1681865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param machine  the virtual machine state to init
1682865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param program  the fragment program we're about to run
1683865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param span  the span of pixels we'll operate on
1684865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * \param col  which element (column) of the span we'll operate on
1685865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
1686865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
1687865f88afc0d59d886fb2ad50429e584ecf17fa81Brianinit_machine( GLcontext *ctx, struct fp_machine *machine,
1688865f88afc0d59d886fb2ad50429e584ecf17fa81Brian              const struct gl_fragment_program *program,
1689865f88afc0d59d886fb2ad50429e584ecf17fa81Brian              const SWspan *span, GLuint col )
1690865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
1691865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint inputsRead = program->Base.InputsRead;
1692865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1693865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (ctx->FragmentProgram.CallbackEnabled)
1694865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      inputsRead = ~0;
1695865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1696865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
1697865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      /* Clear temporary registers (undefined for ARB_f_p) */
1698865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      _mesa_bzero(machine->Temporaries,
1699865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
1700865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
1701865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1702f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   /* Setup pointer to input attributes */
1703f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   machine->Attribs = span->array->attribs;
1704f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   machine->CurFrag = col;
1705865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1706865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* init condition codes */
1707865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   machine->CondCodes[0] = COND_EQ;
1708865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   machine->CondCodes[1] = COND_EQ;
1709865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   machine->CondCodes[2] = COND_EQ;
1710865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   machine->CondCodes[3] = COND_EQ;
1711865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1712865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* init call stack */
1713865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   machine->StackDepth = 0;
1714865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
1715865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1716865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1717865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
1718865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Run fragment program on the pixels in span from 'start' to 'end' - 1.
1719865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
1720865f88afc0d59d886fb2ad50429e584ecf17fa81Brianstatic void
1721865f88afc0d59d886fb2ad50429e584ecf17fa81Brianrun_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end)
1722865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
1723865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
1724865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   struct fp_machine machine;
1725865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   GLuint i;
1726865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1727865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   CurrentMachine = &machine;
1728865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1729865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   for (i = start; i < end; i++) {
1730865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      if (span->array->mask[i]) {
1731865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         init_machine(ctx, &machine, program, span, i);
1732865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1733865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         if (execute_program(ctx, program, ~0, &machine, span, i)) {
1734865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Store result color */
1735f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian            COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i],
1736865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                    machine.Outputs[FRAG_RESULT_COLR]);
1737865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1738865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* Store result depth/z */
1739865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) {
1740865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               const GLfloat depth = machine.Outputs[FRAG_RESULT_DEPR][2];
1741865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               if (depth <= 0.0)
1742865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  span->array->z[i] = 0;
1743865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else if (depth >= 1.0)
1744865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  span->array->z[i] = ctx->DrawBuffer->_DepthMax;
1745865f88afc0d59d886fb2ad50429e584ecf17fa81Brian               else
1746865f88afc0d59d886fb2ad50429e584ecf17fa81Brian                  span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF);
1747865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            }
1748865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         }
1749865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         else {
1750865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            /* killed fragment */
1751865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            span->array->mask[i] = GL_FALSE;
1752865f88afc0d59d886fb2ad50429e584ecf17fa81Brian            span->writeAll = GL_FALSE;
1753865f88afc0d59d886fb2ad50429e584ecf17fa81Brian         }
1754865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      }
1755865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
1756865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1757865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   CurrentMachine = NULL;
1758865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
1759865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1760865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1761865f88afc0d59d886fb2ad50429e584ecf17fa81Brian/**
1762865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * Execute the current fragment program for all the fragments
1763865f88afc0d59d886fb2ad50429e584ecf17fa81Brian * in the given span.
1764865f88afc0d59d886fb2ad50429e584ecf17fa81Brian */
1765865f88afc0d59d886fb2ad50429e584ecf17fa81Brianvoid
1766865f88afc0d59d886fb2ad50429e584ecf17fa81Brian_swrast_exec_fragment_program( GLcontext *ctx, SWspan *span )
1767865f88afc0d59d886fb2ad50429e584ecf17fa81Brian{
1768865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
1769865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1770865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   /* incoming colors should be floats */
1771865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ASSERT(span->array->ChanType == GL_FLOAT);
1772865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1773865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */
1774865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1775865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   run_program(ctx, span, 0, span->end);
1776865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1777865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) {
1778865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      span->interpMask &= ~SPAN_Z;
1779865f88afc0d59d886fb2ad50429e584ecf17fa81Brian      span->arrayMask |= SPAN_Z;
1780865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   }
1781865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1782865f88afc0d59d886fb2ad50429e584ecf17fa81Brian   ctx->_CurrentProgram = 0;
1783865f88afc0d59d886fb2ad50429e584ecf17fa81Brian}
1784865f88afc0d59d886fb2ad50429e584ecf17fa81Brian
1785