Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / i915 / i915_fragprog.c
1 /**************************************************************************
2  * 
3  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27
28 #include "main/glheader.h"
29 #include "main/macros.h"
30 #include "main/enums.h"
31
32 #include "program/prog_instruction.h"
33 #include "program/prog_parameter.h"
34 #include "program/program.h"
35 #include "program/programopt.h"
36 #include "program/prog_print.h"
37
38 #include "tnl/tnl.h"
39 #include "tnl/t_context.h"
40
41 #include "intel_batchbuffer.h"
42
43 #include "i915_reg.h"
44 #include "i915_context.h"
45 #include "i915_program.h"
46
47 static const GLfloat sin_quad_constants[2][4] = {
48    {
49       2.0,
50       -1.0,
51       .5,
52       .75
53    },
54    {
55       4.0,
56       -4.0,
57       1.0 / (2.0 * M_PI),
58       .2225
59    }
60 };
61
62 static const GLfloat sin_constants[4] = { 1.0,
63    -1.0 / (3 * 2 * 1),
64    1.0 / (5 * 4 * 3 * 2 * 1),
65    -1.0 / (7 * 6 * 5 * 4 * 3 * 2 * 1)
66 };
67
68 /* 1, -1/2!, 1/4!, -1/6! */
69 static const GLfloat cos_constants[4] = { 1.0,
70    -1.0 / (2 * 1),
71    1.0 / (4 * 3 * 2 * 1),
72    -1.0 / (6 * 5 * 4 * 3 * 2 * 1)
73 };
74
75 /**
76  * Retrieve a ureg for the given source register.  Will emit
77  * constants, apply swizzling and negation as needed.
78  */
79 static GLuint
80 src_vector(struct i915_fragment_program *p,
81            const struct prog_src_register *source,
82            const struct gl_fragment_program *program)
83 {
84    GLuint src;
85
86    switch (source->File) {
87
88       /* Registers:
89        */
90    case PROGRAM_TEMPORARY:
91       if (source->Index >= I915_MAX_TEMPORARY) {
92          i915_program_error(p, "Exceeded max temporary reg: %d/%d",
93                             source->Index, I915_MAX_TEMPORARY);
94          return 0;
95       }
96       src = UREG(REG_TYPE_R, source->Index);
97       break;
98    case PROGRAM_INPUT:
99       switch (source->Index) {
100       case FRAG_ATTRIB_WPOS:
101          src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
102          break;
103       case FRAG_ATTRIB_COL0:
104          src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
105          break;
106       case FRAG_ATTRIB_COL1:
107          src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
108          src = swizzle(src, X, Y, Z, ONE);
109          break;
110       case FRAG_ATTRIB_FOGC:
111          src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W);
112          src = swizzle(src, W, ZERO, ZERO, ONE);
113          break;
114       case FRAG_ATTRIB_TEX0:
115       case FRAG_ATTRIB_TEX1:
116       case FRAG_ATTRIB_TEX2:
117       case FRAG_ATTRIB_TEX3:
118       case FRAG_ATTRIB_TEX4:
119       case FRAG_ATTRIB_TEX5:
120       case FRAG_ATTRIB_TEX6:
121       case FRAG_ATTRIB_TEX7:
122          src = i915_emit_decl(p, REG_TYPE_T,
123                               T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0),
124                               D0_CHANNEL_ALL);
125          break;
126
127       case FRAG_ATTRIB_VAR0:
128       case FRAG_ATTRIB_VAR0 + 1:
129       case FRAG_ATTRIB_VAR0 + 2:
130       case FRAG_ATTRIB_VAR0 + 3:
131       case FRAG_ATTRIB_VAR0 + 4:
132       case FRAG_ATTRIB_VAR0 + 5:
133       case FRAG_ATTRIB_VAR0 + 6:
134       case FRAG_ATTRIB_VAR0 + 7:
135          src = i915_emit_decl(p, REG_TYPE_T,
136                               T_TEX0 + (source->Index - FRAG_ATTRIB_VAR0),
137                               D0_CHANNEL_ALL);
138          break;
139
140       default:
141          i915_program_error(p, "Bad source->Index: %d", source->Index);
142          return 0;
143       }
144       break;
145
146    case PROGRAM_OUTPUT:
147       switch (source->Index) {
148       case FRAG_RESULT_COLOR:
149          src = UREG(REG_TYPE_OC, 0);
150          break;
151       case FRAG_RESULT_DEPTH:
152          src = UREG(REG_TYPE_OD, 0);
153          break;
154       default:
155          i915_program_error(p, "Bad source->Index: %d", source->Index);
156          return 0;
157       }
158       break;
159
160       /* Various paramters and env values.  All emitted to
161        * hardware as program constants.
162        */
163    case PROGRAM_LOCAL_PARAM:
164       src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]);
165       break;
166
167    case PROGRAM_ENV_PARAM:
168       src =
169          i915_emit_param4fv(p,
170                             p->ctx->FragmentProgram.Parameters[source->
171                                                                Index]);
172       break;
173
174    case PROGRAM_CONSTANT:
175    case PROGRAM_STATE_VAR:
176    case PROGRAM_NAMED_PARAM:
177    case PROGRAM_UNIFORM:
178       src =
179          i915_emit_param4fv(p,
180                             program->Base.Parameters->ParameterValues[source->
181                                                                       Index]);
182       break;
183
184    default:
185       i915_program_error(p, "Bad source->File: %d", source->File);
186       return 0;
187    }
188
189    src = swizzle(src,
190                  GET_SWZ(source->Swizzle, 0),
191                  GET_SWZ(source->Swizzle, 1),
192                  GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3));
193
194    if (source->Negate)
195       src = negate(src,
196                    GET_BIT(source->Negate, 0),
197                    GET_BIT(source->Negate, 1),
198                    GET_BIT(source->Negate, 2),
199                    GET_BIT(source->Negate, 3));
200
201    return src;
202 }
203
204
205 static GLuint
206 get_result_vector(struct i915_fragment_program *p,
207                   const struct prog_instruction *inst)
208 {
209    switch (inst->DstReg.File) {
210    case PROGRAM_OUTPUT:
211       switch (inst->DstReg.Index) {
212       case FRAG_RESULT_COLOR:
213       case FRAG_RESULT_DATA0:
214          return UREG(REG_TYPE_OC, 0);
215       case FRAG_RESULT_DEPTH:
216          p->depth_written = 1;
217          return UREG(REG_TYPE_OD, 0);
218       default:
219          i915_program_error(p, "Bad inst->DstReg.Index: %d",
220                             inst->DstReg.Index);
221          return 0;
222       }
223    case PROGRAM_TEMPORARY:
224       return UREG(REG_TYPE_R, inst->DstReg.Index);
225    default:
226       i915_program_error(p, "Bad inst->DstReg.File: %d", inst->DstReg.File);
227       return 0;
228    }
229 }
230
231 static GLuint
232 get_result_flags(const struct prog_instruction *inst)
233 {
234    GLuint flags = 0;
235
236    if (inst->SaturateMode == SATURATE_ZERO_ONE)
237       flags |= A0_DEST_SATURATE;
238    if (inst->DstReg.WriteMask & WRITEMASK_X)
239       flags |= A0_DEST_CHANNEL_X;
240    if (inst->DstReg.WriteMask & WRITEMASK_Y)
241       flags |= A0_DEST_CHANNEL_Y;
242    if (inst->DstReg.WriteMask & WRITEMASK_Z)
243       flags |= A0_DEST_CHANNEL_Z;
244    if (inst->DstReg.WriteMask & WRITEMASK_W)
245       flags |= A0_DEST_CHANNEL_W;
246
247    return flags;
248 }
249
250 static GLuint
251 translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit)
252 {
253    switch (bit) {
254    case TEXTURE_1D_INDEX:
255       return D0_SAMPLE_TYPE_2D;
256    case TEXTURE_2D_INDEX:
257       return D0_SAMPLE_TYPE_2D;
258    case TEXTURE_RECT_INDEX:
259       return D0_SAMPLE_TYPE_2D;
260    case TEXTURE_3D_INDEX:
261       return D0_SAMPLE_TYPE_VOLUME;
262    case TEXTURE_CUBE_INDEX:
263       return D0_SAMPLE_TYPE_CUBE;
264    default:
265       i915_program_error(p, "TexSrcBit: %d", bit);
266       return 0;
267    }
268 }
269
270 #define EMIT_TEX( OP )                                          \
271 do {                                                            \
272    GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget );      \
273    const struct gl_fragment_program *program = &p->FragProg;    \
274    GLuint unit = program->Base.SamplerUnits[inst->TexSrcUnit];  \
275    GLuint sampler = i915_emit_decl(p, REG_TYPE_S,               \
276                                    unit, dim);                  \
277    GLuint coord = src_vector( p, &inst->SrcReg[0], program);    \
278    /* Texel lookup */                                           \
279                                                                 \
280    i915_emit_texld( p, get_live_regs(p, inst),                                          \
281                get_result_vector( p, inst ),                    \
282                get_result_flags( inst ),                        \
283                sampler,                                         \
284                coord,                                           \
285                OP);                                             \
286 } while (0)
287
288 #define EMIT_ARITH( OP, N )                                             \
289 do {                                                                    \
290    i915_emit_arith( p,                                                  \
291                OP,                                                      \
292                get_result_vector( p, inst ),                            \
293                get_result_flags( inst ), 0,                     \
294                (N<1)?0:src_vector( p, &inst->SrcReg[0], program),       \
295                (N<2)?0:src_vector( p, &inst->SrcReg[1], program),       \
296                (N<3)?0:src_vector( p, &inst->SrcReg[2], program));      \
297 } while (0)
298
299 #define EMIT_1ARG_ARITH( OP ) EMIT_ARITH( OP, 1 )
300 #define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 )
301 #define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 )
302
303 /* 
304  * TODO: consider moving this into core 
305  */
306 static bool calc_live_regs( struct i915_fragment_program *p )
307 {
308     const struct gl_fragment_program *program = &p->FragProg;
309     GLuint regsUsed = ~((1 << I915_MAX_TEMPORARY) - 1);
310     uint8_t live_components[I915_MAX_TEMPORARY] = { 0, };
311     GLint i;
312    
313     for (i = program->Base.NumInstructions - 1; i >= 0; i--) {
314         struct prog_instruction *inst = &program->Base.Instructions[i];
315         int opArgs = _mesa_num_inst_src_regs(inst->Opcode);
316         int a;
317
318         /* Register is written to: unmark as live for this and preceeding ops */ 
319         if (inst->DstReg.File == PROGRAM_TEMPORARY) {
320             if (inst->DstReg.Index >= I915_MAX_TEMPORARY)
321                return false;
322
323             live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask;
324             if (live_components[inst->DstReg.Index] == 0)
325                 regsUsed &= ~(1 << inst->DstReg.Index);
326         }
327
328         for (a = 0; a < opArgs; a++) {
329             /* Register is read from: mark as live for this and preceeding ops */ 
330             if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) {
331                 unsigned c;
332
333                 if (inst->SrcReg[a].Index >= I915_MAX_TEMPORARY)
334                    return false;
335
336                 regsUsed |= 1 << inst->SrcReg[a].Index;
337
338                 for (c = 0; c < 4; c++) {
339                     const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c);
340
341                     if (field <= SWIZZLE_W)
342                         live_components[inst->SrcReg[a].Index] |= (1U << field);
343                 }
344             }
345         }
346
347         p->usedRegs[i] = regsUsed;
348     }
349
350     return true;
351 }
352
353 static GLuint get_live_regs( struct i915_fragment_program *p, 
354                              const struct prog_instruction *inst )
355 {
356     const struct gl_fragment_program *program = &p->FragProg;
357     GLuint nr = inst - program->Base.Instructions;
358
359     return p->usedRegs[nr];
360 }
361  
362
363 /* Possible concerns:
364  *
365  * SIN, COS -- could use another taylor step?
366  * LIT      -- results seem a little different to sw mesa
367  * LOG      -- different to mesa on negative numbers, but this is conformant.
368  * 
369  * Parse failures -- Mesa doesn't currently give a good indication
370  * internally whether a particular program string parsed or not.  This
371  * can lead to confusion -- hopefully we cope with it ok now.
372  *
373  */
374 static void
375 upload_program(struct i915_fragment_program *p)
376 {
377    const struct gl_fragment_program *program = &p->FragProg;
378    const struct prog_instruction *inst = program->Base.Instructions;
379
380    if (INTEL_DEBUG & DEBUG_WM)
381       _mesa_print_program(&program->Base);
382
383    /* Is this a parse-failed program?  Ensure a valid program is
384     * loaded, as the flagging of an error isn't sufficient to stop
385     * this being uploaded to hardware.
386     */
387    if (inst[0].Opcode == OPCODE_END) {
388       GLuint tmp = i915_get_utemp(p);
389       i915_emit_arith(p,
390                       A0_MOV,
391                       UREG(REG_TYPE_OC, 0),
392                       A0_DEST_CHANNEL_ALL, 0,
393                       swizzle(tmp, ONE, ZERO, ONE, ONE), 0, 0);
394       return;
395    }
396
397    if (program->Base.NumInstructions > I915_MAX_INSN) {
398       i915_program_error(p, "Exceeded max instructions (%d out of %d)",
399                          program->Base.NumInstructions, I915_MAX_INSN);
400       return;
401    }
402
403    /* Not always needed:
404     */
405    if (!calc_live_regs(p)) {
406       i915_program_error(p, "Could not allocate registers");
407       return;
408    }
409
410    while (1) {
411       GLuint src0, src1, src2, flags;
412       GLuint tmp = 0, dst, consts0 = 0, consts1 = 0;
413
414       switch (inst->Opcode) {
415       case OPCODE_ABS:
416          src0 = src_vector(p, &inst->SrcReg[0], program);
417          i915_emit_arith(p,
418                          A0_MAX,
419                          get_result_vector(p, inst),
420                          get_result_flags(inst), 0,
421                          src0, negate(src0, 1, 1, 1, 1), 0);
422          break;
423
424       case OPCODE_ADD:
425          EMIT_2ARG_ARITH(A0_ADD);
426          break;
427
428       case OPCODE_CMP:
429          src0 = src_vector(p, &inst->SrcReg[0], program);
430          src1 = src_vector(p, &inst->SrcReg[1], program);
431          src2 = src_vector(p, &inst->SrcReg[2], program);
432          i915_emit_arith(p, A0_CMP, get_result_vector(p, inst), get_result_flags(inst), 0, src0, src2, src1);   /* NOTE: order of src2, src1 */
433          break;
434
435       case OPCODE_COS:
436          src0 = src_vector(p, &inst->SrcReg[0], program);
437          tmp = i915_get_utemp(p);
438          consts0 = i915_emit_const4fv(p, sin_quad_constants[0]);
439          consts1 = i915_emit_const4fv(p, sin_quad_constants[1]);
440
441          /* Reduce range from repeating about [-pi,pi] to [-1,1] */
442          i915_emit_arith(p,
443                          A0_MAD,
444                          tmp, A0_DEST_CHANNEL_X, 0,
445                          src0,
446                          swizzle(consts1, Z, ZERO, ZERO, ZERO), /* 1/(2pi) */
447                          swizzle(consts0, W, ZERO, ZERO, ZERO)); /* .75 */
448
449          i915_emit_arith(p, A0_FRC, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
450
451          i915_emit_arith(p,
452                          A0_MAD,
453                          tmp, A0_DEST_CHANNEL_X, 0,
454                          tmp,
455                          swizzle(consts0, X, ZERO, ZERO, ZERO), /* 2 */
456                          swizzle(consts0, Y, ZERO, ZERO, ZERO)); /* -1 */
457
458          /* Compute COS with the same calculation used for SIN, but a
459           * different source range has been mapped to [-1,1] this time.
460           */
461
462          /* tmp.y = abs(tmp.x); {x, abs(x), 0, 0} */
463          i915_emit_arith(p,
464                          A0_MAX,
465                          tmp, A0_DEST_CHANNEL_Y, 0,
466                          swizzle(tmp, ZERO, X, ZERO, ZERO),
467                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0),
468                          0);
469
470          /* tmp.y = tmp.y * tmp.x; {x, x * abs(x), 0, 0} */
471          i915_emit_arith(p,
472                          A0_MUL,
473                          tmp, A0_DEST_CHANNEL_Y, 0,
474                          swizzle(tmp, ZERO, X, ZERO, ZERO),
475                          tmp,
476                          0);
477
478          /* tmp.x = tmp.xy DP sin_quad_constants[2].xy */
479          i915_emit_arith(p,
480                          A0_DP3,
481                          tmp, A0_DEST_CHANNEL_X, 0,
482                          tmp,
483                          swizzle(consts1, X, Y, ZERO, ZERO),
484                          0);
485
486          /* tmp.x now contains a first approximation (y).  Now, weight it
487           * against tmp.y**2 to get closer.
488           */
489          i915_emit_arith(p,
490                          A0_MAX,
491                          tmp, A0_DEST_CHANNEL_Y, 0,
492                          swizzle(tmp, ZERO, X, ZERO, ZERO),
493                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0),
494                          0);
495
496          /* tmp.y = tmp.x * tmp.y - tmp.x; {y, y * abs(y) - y, 0, 0} */
497          i915_emit_arith(p,
498                          A0_MAD,
499                          tmp, A0_DEST_CHANNEL_Y, 0,
500                          swizzle(tmp, ZERO, X, ZERO, ZERO),
501                          swizzle(tmp, ZERO, Y, ZERO, ZERO),
502                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0));
503
504          /* result = .2225 * tmp.y + tmp.x =.2225(y * abs(y) - y) + y= */
505          i915_emit_arith(p,
506                          A0_MAD,
507                          get_result_vector(p, inst),
508                          get_result_flags(inst), 0,
509                          swizzle(consts1, W, W, W, W),
510                          swizzle(tmp, Y, Y, Y, Y),
511                          swizzle(tmp, X, X, X, X));
512          break;
513
514       case OPCODE_DP2:
515          src0 = src_vector(p, &inst->SrcReg[0], program);
516          src1 = src_vector(p, &inst->SrcReg[1], program);
517          i915_emit_arith(p,
518                          A0_DP3,
519                          get_result_vector(p, inst),
520                          get_result_flags(inst), 0,
521                          swizzle(src0, X, Y, ZERO, ZERO),
522                          swizzle(src1, X, Y, ZERO, ZERO),
523                          0);
524          break;
525
526       case OPCODE_DP3:
527          EMIT_2ARG_ARITH(A0_DP3);
528          break;
529
530       case OPCODE_DP4:
531          EMIT_2ARG_ARITH(A0_DP4);
532          break;
533
534       case OPCODE_DPH:
535          src0 = src_vector(p, &inst->SrcReg[0], program);
536          src1 = src_vector(p, &inst->SrcReg[1], program);
537
538          i915_emit_arith(p,
539                          A0_DP4,
540                          get_result_vector(p, inst),
541                          get_result_flags(inst), 0,
542                          swizzle(src0, X, Y, Z, ONE), src1, 0);
543          break;
544
545       case OPCODE_DST:
546          src0 = src_vector(p, &inst->SrcReg[0], program);
547          src1 = src_vector(p, &inst->SrcReg[1], program);
548
549          /* result[0] = 1    * 1;
550           * result[1] = a[1] * b[1];
551           * result[2] = a[2] * 1;
552           * result[3] = 1    * b[3];
553           */
554          i915_emit_arith(p,
555                          A0_MUL,
556                          get_result_vector(p, inst),
557                          get_result_flags(inst), 0,
558                          swizzle(src0, ONE, Y, Z, ONE),
559                          swizzle(src1, ONE, Y, ONE, W), 0);
560          break;
561
562       case OPCODE_EX2:
563          src0 = src_vector(p, &inst->SrcReg[0], program);
564
565          i915_emit_arith(p,
566                          A0_EXP,
567                          get_result_vector(p, inst),
568                          get_result_flags(inst), 0,
569                          swizzle(src0, X, X, X, X), 0, 0);
570          break;
571
572       case OPCODE_FLR:
573          EMIT_1ARG_ARITH(A0_FLR);
574          break;
575
576       case OPCODE_TRUNC:
577          EMIT_1ARG_ARITH(A0_TRC);
578          break;
579
580       case OPCODE_FRC:
581          EMIT_1ARG_ARITH(A0_FRC);
582          break;
583
584       case OPCODE_KIL:
585          src0 = src_vector(p, &inst->SrcReg[0], program);
586          tmp = i915_get_utemp(p);
587
588          i915_emit_texld(p, get_live_regs(p, inst),
589                          tmp, A0_DEST_CHANNEL_ALL,   /* use a dummy dest reg */
590                          0, src0, T0_TEXKILL);
591          break;
592
593       case OPCODE_KIL_NV:
594          if (inst->DstReg.CondMask == COND_TR) {
595             tmp = i915_get_utemp(p);
596
597             /* The KIL instruction discards the fragment if any component of
598              * the source is < 0.  Emit an immediate operand of {-1}.xywz.
599              */
600             i915_emit_texld(p, get_live_regs(p, inst),
601                             tmp, A0_DEST_CHANNEL_ALL,
602                             0, /* use a dummy dest reg */
603                             negate(swizzle(tmp, ONE, ONE, ONE, ONE),
604                                    1, 1, 1, 1),
605                             T0_TEXKILL);
606          } else {
607             p->error = 1;
608             i915_program_error(p, "Unsupported KIL_NV condition code: %d",
609                                inst->DstReg.CondMask);
610          }
611          break;
612
613       case OPCODE_LG2:
614          src0 = src_vector(p, &inst->SrcReg[0], program);
615
616          i915_emit_arith(p,
617                          A0_LOG,
618                          get_result_vector(p, inst),
619                          get_result_flags(inst), 0,
620                          swizzle(src0, X, X, X, X), 0, 0);
621          break;
622
623       case OPCODE_LIT:
624          src0 = src_vector(p, &inst->SrcReg[0], program);
625          tmp = i915_get_utemp(p);
626
627          /* tmp = max( a.xyzw, a.00zw )
628           * XXX: Clamp tmp.w to -128..128
629           * tmp.y = log(tmp.y)
630           * tmp.y = tmp.w * tmp.y
631           * tmp.y = exp(tmp.y)
632           * result = cmp (a.11-x1, a.1x01, a.1xy1 )
633           */
634          i915_emit_arith(p, A0_MAX, tmp, A0_DEST_CHANNEL_ALL, 0,
635                          src0, swizzle(src0, ZERO, ZERO, Z, W), 0);
636
637          i915_emit_arith(p, A0_LOG, tmp, A0_DEST_CHANNEL_Y, 0,
638                          swizzle(tmp, Y, Y, Y, Y), 0, 0);
639
640          i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_Y, 0,
641                          swizzle(tmp, ZERO, Y, ZERO, ZERO),
642                          swizzle(tmp, ZERO, W, ZERO, ZERO), 0);
643
644          i915_emit_arith(p, A0_EXP, tmp, A0_DEST_CHANNEL_Y, 0,
645                          swizzle(tmp, Y, Y, Y, Y), 0, 0);
646
647          i915_emit_arith(p, A0_CMP,
648                          get_result_vector(p, inst),
649                          get_result_flags(inst), 0,
650                          negate(swizzle(tmp, ONE, ONE, X, ONE), 0, 0, 1, 0),
651                          swizzle(tmp, ONE, X, ZERO, ONE),
652                          swizzle(tmp, ONE, X, Y, ONE));
653
654          break;
655
656       case OPCODE_LRP:
657          src0 = src_vector(p, &inst->SrcReg[0], program);
658          src1 = src_vector(p, &inst->SrcReg[1], program);
659          src2 = src_vector(p, &inst->SrcReg[2], program);
660          flags = get_result_flags(inst);
661          tmp = i915_get_utemp(p);
662
663          /* b*a + c*(1-a)
664           *
665           * b*a + c - ca 
666           *
667           * tmp = b*a + c, 
668           * result = (-c)*a + tmp 
669           */
670          i915_emit_arith(p, A0_MAD, tmp,
671                          flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2);
672
673          i915_emit_arith(p, A0_MAD,
674                          get_result_vector(p, inst),
675                          flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp);
676          break;
677
678       case OPCODE_MAD:
679          EMIT_3ARG_ARITH(A0_MAD);
680          break;
681
682       case OPCODE_MAX:
683          EMIT_2ARG_ARITH(A0_MAX);
684          break;
685
686       case OPCODE_MIN:
687          src0 = src_vector(p, &inst->SrcReg[0], program);
688          src1 = src_vector(p, &inst->SrcReg[1], program);
689          tmp = i915_get_utemp(p);
690          flags = get_result_flags(inst);
691
692          i915_emit_arith(p,
693                          A0_MAX,
694                          tmp, flags & A0_DEST_CHANNEL_ALL, 0,
695                          negate(src0, 1, 1, 1, 1),
696                          negate(src1, 1, 1, 1, 1), 0);
697
698          i915_emit_arith(p,
699                          A0_MOV,
700                          get_result_vector(p, inst),
701                          flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0);
702          break;
703
704       case OPCODE_MOV:
705          EMIT_1ARG_ARITH(A0_MOV);
706          break;
707
708       case OPCODE_MUL:
709          EMIT_2ARG_ARITH(A0_MUL);
710          break;
711
712       case OPCODE_POW:
713          src0 = src_vector(p, &inst->SrcReg[0], program);
714          src1 = src_vector(p, &inst->SrcReg[1], program);
715          tmp = i915_get_utemp(p);
716          flags = get_result_flags(inst);
717
718          /* XXX: masking on intermediate values, here and elsewhere.
719           */
720          i915_emit_arith(p,
721                          A0_LOG,
722                          tmp, A0_DEST_CHANNEL_X, 0,
723                          swizzle(src0, X, X, X, X), 0, 0);
724
725          i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0);
726
727
728          i915_emit_arith(p,
729                          A0_EXP,
730                          get_result_vector(p, inst),
731                          flags, 0, swizzle(tmp, X, X, X, X), 0, 0);
732
733          break;
734
735       case OPCODE_RCP:
736          src0 = src_vector(p, &inst->SrcReg[0], program);
737
738          i915_emit_arith(p,
739                          A0_RCP,
740                          get_result_vector(p, inst),
741                          get_result_flags(inst), 0,
742                          swizzle(src0, X, X, X, X), 0, 0);
743          break;
744
745       case OPCODE_RSQ:
746
747          src0 = src_vector(p, &inst->SrcReg[0], program);
748
749          i915_emit_arith(p,
750                          A0_RSQ,
751                          get_result_vector(p, inst),
752                          get_result_flags(inst), 0,
753                          swizzle(src0, X, X, X, X), 0, 0);
754          break;
755
756       case OPCODE_SCS:
757          src0 = src_vector(p, &inst->SrcReg[0], program);
758          tmp = i915_get_utemp(p);
759
760          /* 
761           * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1
762           * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x
763           * t1 = MUL t0.xyyw t0.yz11    ; x^7 x^5 x^3 x
764           * scs.x = DP4 t1, sin_constants
765           * t1 = MUL t0.xxz1 t0.z111    ; x^6 x^4 x^2 1
766           * scs.y = DP4 t1, cos_constants
767           */
768          i915_emit_arith(p,
769                          A0_MUL,
770                          tmp, A0_DEST_CHANNEL_XY, 0,
771                          swizzle(src0, X, X, ONE, ONE),
772                          swizzle(src0, X, ONE, ONE, ONE), 0);
773
774          i915_emit_arith(p,
775                          A0_MUL,
776                          tmp, A0_DEST_CHANNEL_ALL, 0,
777                          swizzle(tmp, X, Y, X, Y),
778                          swizzle(tmp, X, X, ONE, ONE), 0);
779
780          if (inst->DstReg.WriteMask & WRITEMASK_Y) {
781             GLuint tmp1;
782
783             if (inst->DstReg.WriteMask & WRITEMASK_X)
784                tmp1 = i915_get_utemp(p);
785             else
786                tmp1 = tmp;
787
788             i915_emit_arith(p,
789                             A0_MUL,
790                             tmp1, A0_DEST_CHANNEL_ALL, 0,
791                             swizzle(tmp, X, Y, Y, W),
792                             swizzle(tmp, X, Z, ONE, ONE), 0);
793
794             i915_emit_arith(p,
795                             A0_DP4,
796                             get_result_vector(p, inst),
797                             A0_DEST_CHANNEL_Y, 0,
798                             swizzle(tmp1, W, Z, Y, X),
799                             i915_emit_const4fv(p, sin_constants), 0);
800          }
801
802          if (inst->DstReg.WriteMask & WRITEMASK_X) {
803             i915_emit_arith(p,
804                             A0_MUL,
805                             tmp, A0_DEST_CHANNEL_XYZ, 0,
806                             swizzle(tmp, X, X, Z, ONE),
807                             swizzle(tmp, Z, ONE, ONE, ONE), 0);
808
809             i915_emit_arith(p,
810                             A0_DP4,
811                             get_result_vector(p, inst),
812                             A0_DEST_CHANNEL_X, 0,
813                             swizzle(tmp, ONE, Z, Y, X),
814                             i915_emit_const4fv(p, cos_constants), 0);
815          }
816          break;
817
818       case OPCODE_SEQ:
819          tmp = i915_get_utemp(p);
820          flags = get_result_flags(inst);
821          dst = get_result_vector(p, inst);
822
823          /* tmp = src1 >= src2 */
824          i915_emit_arith(p,
825                          A0_SGE,
826                          tmp,
827                          flags, 0,
828                          src_vector(p, &inst->SrcReg[0], program),
829                          src_vector(p, &inst->SrcReg[1], program),
830                          0);
831          /* dst = src1 <= src2 */
832          i915_emit_arith(p,
833                          A0_SGE,
834                          dst,
835                          flags, 0,
836                          negate(src_vector(p, &inst->SrcReg[0], program),
837                                 1, 1, 1, 1),
838                          negate(src_vector(p, &inst->SrcReg[1], program),
839                                 1, 1, 1, 1),
840                          0);
841          /* dst = tmp && dst */
842          i915_emit_arith(p,
843                          A0_MUL,
844                          dst,
845                          flags, 0,
846                          dst,
847                          tmp,
848                          0);
849          break;
850
851       case OPCODE_SIN:
852          src0 = src_vector(p, &inst->SrcReg[0], program);
853          tmp = i915_get_utemp(p);
854          consts0 = i915_emit_const4fv(p, sin_quad_constants[0]);
855          consts1 = i915_emit_const4fv(p, sin_quad_constants[1]);
856
857          /* Reduce range from repeating about [-pi,pi] to [-1,1] */
858          i915_emit_arith(p,
859                          A0_MAD,
860                          tmp, A0_DEST_CHANNEL_X, 0,
861                          src0,
862                          swizzle(consts1, Z, ZERO, ZERO, ZERO), /* 1/(2pi) */
863                          swizzle(consts0, Z, ZERO, ZERO, ZERO)); /* .5 */
864
865          i915_emit_arith(p, A0_FRC, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
866
867          i915_emit_arith(p,
868                          A0_MAD,
869                          tmp, A0_DEST_CHANNEL_X, 0,
870                          tmp,
871                          swizzle(consts0, X, ZERO, ZERO, ZERO), /* 2 */
872                          swizzle(consts0, Y, ZERO, ZERO, ZERO)); /* -1 */
873
874          /* Compute sin using a quadratic and quartic.  It gives continuity
875           * that repeating the Taylor series lacks every 2*pi, and has
876           * reduced error.
877           *
878           * The idea was described at:
879           * http://www.devmaster.net/forums/showthread.php?t=5784
880           */
881
882          /* tmp.y = abs(tmp.x); {x, abs(x), 0, 0} */
883          i915_emit_arith(p,
884                          A0_MAX,
885                          tmp, A0_DEST_CHANNEL_Y, 0,
886                          swizzle(tmp, ZERO, X, ZERO, ZERO),
887                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0),
888                          0);
889
890          /* tmp.y = tmp.y * tmp.x; {x, x * abs(x), 0, 0} */
891          i915_emit_arith(p,
892                          A0_MUL,
893                          tmp, A0_DEST_CHANNEL_Y, 0,
894                          swizzle(tmp, ZERO, X, ZERO, ZERO),
895                          tmp,
896                          0);
897
898          /* tmp.x = tmp.xy DP sin_quad_constants[2].xy */
899          i915_emit_arith(p,
900                          A0_DP3,
901                          tmp, A0_DEST_CHANNEL_X, 0,
902                          tmp,
903                          swizzle(consts1, X, Y, ZERO, ZERO),
904                          0);
905
906          /* tmp.x now contains a first approximation (y).  Now, weight it
907           * against tmp.y**2 to get closer.
908           */
909          i915_emit_arith(p,
910                          A0_MAX,
911                          tmp, A0_DEST_CHANNEL_Y, 0,
912                          swizzle(tmp, ZERO, X, ZERO, ZERO),
913                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0),
914                          0);
915
916          /* tmp.y = tmp.x * tmp.y - tmp.x; {y, y * abs(y) - y, 0, 0} */
917          i915_emit_arith(p,
918                          A0_MAD,
919                          tmp, A0_DEST_CHANNEL_Y, 0,
920                          swizzle(tmp, ZERO, X, ZERO, ZERO),
921                          swizzle(tmp, ZERO, Y, ZERO, ZERO),
922                          negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0));
923
924          /* result = .2225 * tmp.y + tmp.x =.2225(y * abs(y) - y) + y= */
925          i915_emit_arith(p,
926                          A0_MAD,
927                          get_result_vector(p, inst),
928                          get_result_flags(inst), 0,
929                          swizzle(consts1, W, W, W, W),
930                          swizzle(tmp, Y, Y, Y, Y),
931                          swizzle(tmp, X, X, X, X));
932
933          break;
934
935       case OPCODE_SGE:
936          EMIT_2ARG_ARITH(A0_SGE);
937          break;
938
939       case OPCODE_SGT:
940          i915_emit_arith(p,
941                          A0_SLT,
942                          get_result_vector( p, inst ),
943                          get_result_flags( inst ), 0,
944                          negate(src_vector( p, &inst->SrcReg[0], program),
945                                 1, 1, 1, 1),
946                          negate(src_vector( p, &inst->SrcReg[1], program),
947                                 1, 1, 1, 1),
948                          0);
949          break;
950
951       case OPCODE_SLE:
952          i915_emit_arith(p,
953                          A0_SGE,
954                          get_result_vector( p, inst ),
955                          get_result_flags( inst ), 0,
956                          negate(src_vector( p, &inst->SrcReg[0], program),
957                                 1, 1, 1, 1),
958                          negate(src_vector( p, &inst->SrcReg[1], program),
959                                 1, 1, 1, 1),
960                          0);
961          break;
962
963       case OPCODE_SLT:
964          EMIT_2ARG_ARITH(A0_SLT);
965          break;
966
967       case OPCODE_SNE:
968          tmp = i915_get_utemp(p);
969          flags = get_result_flags(inst);
970          dst = get_result_vector(p, inst);
971
972          /* tmp = src1 < src2 */
973          i915_emit_arith(p,
974                          A0_SLT,
975                          tmp,
976                          flags, 0,
977                          src_vector(p, &inst->SrcReg[0], program),
978                          src_vector(p, &inst->SrcReg[1], program),
979                          0);
980          /* dst = src1 > src2 */
981          i915_emit_arith(p,
982                          A0_SLT,
983                          dst,
984                          flags, 0,
985                          negate(src_vector(p, &inst->SrcReg[0], program),
986                                 1, 1, 1, 1),
987                          negate(src_vector(p, &inst->SrcReg[1], program),
988                                 1, 1, 1, 1),
989                          0);
990          /* dst = tmp || dst */
991          i915_emit_arith(p,
992                          A0_ADD,
993                          dst,
994                          flags | A0_DEST_SATURATE, 0,
995                          dst,
996                          tmp,
997                          0);
998          break;
999
1000       case OPCODE_SSG:
1001          dst = get_result_vector(p, inst);
1002          flags = get_result_flags(inst);
1003          src0 = src_vector(p, &inst->SrcReg[0], program);
1004          tmp = i915_get_utemp(p);
1005
1006          /* tmp = (src < 0.0) */
1007          i915_emit_arith(p,
1008                          A0_SLT,
1009                          tmp,
1010                          flags, 0,
1011                          src0,
1012                          swizzle(src0, ZERO, ZERO, ZERO, ZERO),
1013                          0);
1014
1015          /* dst = (0.0 < src) */
1016          i915_emit_arith(p,
1017                          A0_SLT,
1018                          dst,
1019                          flags, 0,
1020                          swizzle(src0, ZERO, ZERO, ZERO, ZERO),
1021                          src0,
1022                          0);
1023
1024          /* dst = (src > 0.0) - (src < 0.0) */
1025          i915_emit_arith(p,
1026                          A0_ADD,
1027                          dst,
1028                          flags, 0,
1029                          dst,
1030                          negate(tmp, 1, 1, 1, 1),
1031                          0);
1032
1033          break;
1034
1035       case OPCODE_SUB:
1036          src0 = src_vector(p, &inst->SrcReg[0], program);
1037          src1 = src_vector(p, &inst->SrcReg[1], program);
1038
1039          i915_emit_arith(p,
1040                          A0_ADD,
1041                          get_result_vector(p, inst),
1042                          get_result_flags(inst), 0,
1043                          src0, negate(src1, 1, 1, 1, 1), 0);
1044          break;
1045
1046       case OPCODE_SWZ:
1047          EMIT_1ARG_ARITH(A0_MOV);       /* extended swizzle handled natively */
1048          break;
1049
1050       case OPCODE_TEX:
1051          EMIT_TEX(T0_TEXLD);
1052          break;
1053
1054       case OPCODE_TXB:
1055          EMIT_TEX(T0_TEXLDB);
1056          break;
1057
1058       case OPCODE_TXP:
1059          EMIT_TEX(T0_TEXLDP);
1060          break;
1061
1062       case OPCODE_XPD:
1063          /* Cross product:
1064           *      result.x = src0.y * src1.z - src0.z * src1.y;
1065           *      result.y = src0.z * src1.x - src0.x * src1.z;
1066           *      result.z = src0.x * src1.y - src0.y * src1.x;
1067           *      result.w = undef;
1068           */
1069          src0 = src_vector(p, &inst->SrcReg[0], program);
1070          src1 = src_vector(p, &inst->SrcReg[1], program);
1071          tmp = i915_get_utemp(p);
1072
1073          i915_emit_arith(p,
1074                          A0_MUL,
1075                          tmp, A0_DEST_CHANNEL_ALL, 0,
1076                          swizzle(src0, Z, X, Y, ONE),
1077                          swizzle(src1, Y, Z, X, ONE), 0);
1078
1079          i915_emit_arith(p,
1080                          A0_MAD,
1081                          get_result_vector(p, inst),
1082                          get_result_flags(inst), 0,
1083                          swizzle(src0, Y, Z, X, ONE),
1084                          swizzle(src1, Z, X, Y, ONE),
1085                          negate(tmp, 1, 1, 1, 0));
1086          break;
1087
1088       case OPCODE_END:
1089          return;
1090
1091       case OPCODE_BGNLOOP:
1092       case OPCODE_BGNSUB:
1093       case OPCODE_BRA:
1094       case OPCODE_BRK:
1095       case OPCODE_CAL:
1096       case OPCODE_CONT:
1097       case OPCODE_DDX:
1098       case OPCODE_DDY:
1099       case OPCODE_ELSE:
1100       case OPCODE_ENDIF:
1101       case OPCODE_ENDLOOP:
1102       case OPCODE_ENDSUB:
1103       case OPCODE_IF:
1104       case OPCODE_RET:
1105          p->error = 1;
1106          i915_program_error(p, "Unsupported opcode: %s",
1107                             _mesa_opcode_string(inst->Opcode));
1108          return;
1109
1110       case OPCODE_EXP:
1111       case OPCODE_LOG:
1112          /* These opcodes are claimed as GLSL, NV_vp, and ARB_vp in
1113           * prog_instruction.h, but apparently GLSL doesn't ever emit them.
1114           * Instead, it translates to EX2 or LG2.
1115           */
1116       case OPCODE_TXD:
1117       case OPCODE_TXL:
1118          /* These opcodes are claimed by GLSL in prog_instruction.h, but
1119           * only NV_vp/fp appears to emit them.
1120           */
1121       default:
1122          i915_program_error(p, "bad opcode: %s",
1123                             _mesa_opcode_string(inst->Opcode));
1124          return;
1125       }
1126
1127       inst++;
1128       i915_release_utemps(p);
1129    }
1130 }
1131
1132 /* Rather than trying to intercept and jiggle depth writes during
1133  * emit, just move the value into its correct position at the end of
1134  * the program:
1135  */
1136 static void
1137 fixup_depth_write(struct i915_fragment_program *p)
1138 {
1139    if (p->depth_written) {
1140       GLuint depth = UREG(REG_TYPE_OD, 0);
1141
1142       i915_emit_arith(p,
1143                       A0_MOV,
1144                       depth, A0_DEST_CHANNEL_W, 0,
1145                       swizzle(depth, X, Y, Z, Z), 0, 0);
1146    }
1147 }
1148
1149
1150 static void
1151 check_wpos(struct i915_fragment_program *p)
1152 {
1153    GLuint inputs = p->FragProg.Base.InputsRead;
1154    GLint i;
1155
1156    p->wpos_tex = -1;
1157
1158    for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
1159       if (inputs & (FRAG_BIT_TEX(i) | FRAG_BIT_VAR(i)))
1160          continue;
1161       else if (inputs & FRAG_BIT_WPOS) {
1162          p->wpos_tex = i;
1163          inputs &= ~FRAG_BIT_WPOS;
1164       }
1165    }
1166
1167    if (inputs & FRAG_BIT_WPOS) {
1168       i915_program_error(p, "No free texcoord for wpos value");
1169    }
1170 }
1171
1172
1173 static void
1174 translate_program(struct i915_fragment_program *p)
1175 {
1176    struct i915_context *i915 = I915_CONTEXT(p->ctx);
1177
1178    if (INTEL_DEBUG & DEBUG_WM) {
1179       printf("fp:\n");
1180       _mesa_print_program(&p->FragProg.Base);
1181       printf("\n");
1182    }
1183
1184    i915_init_program(i915, p);
1185    check_wpos(p);
1186    upload_program(p);
1187    fixup_depth_write(p);
1188    i915_fini_program(p);
1189
1190    p->translated = 1;
1191 }
1192
1193
1194 static void
1195 track_params(struct i915_fragment_program *p)
1196 {
1197    GLint i;
1198
1199    if (p->nr_params)
1200       _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters);
1201
1202    for (i = 0; i < p->nr_params; i++) {
1203       GLint reg = p->param[i].reg;
1204       COPY_4V(p->constant[reg], p->param[i].values);
1205    }
1206
1207    p->params_uptodate = 1;
1208    p->on_hardware = 0;          /* overkill */
1209 }
1210
1211
1212 static void
1213 i915BindProgram(struct gl_context * ctx, GLenum target, struct gl_program *prog)
1214 {
1215    if (target == GL_FRAGMENT_PROGRAM_ARB) {
1216       struct i915_context *i915 = I915_CONTEXT(ctx);
1217       struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
1218
1219       if (i915->current_program == p)
1220          return;
1221
1222       if (i915->current_program) {
1223          i915->current_program->on_hardware = 0;
1224          i915->current_program->params_uptodate = 0;
1225       }
1226
1227       i915->current_program = p;
1228
1229       assert(p->on_hardware == 0);
1230       assert(p->params_uptodate == 0);
1231
1232    }
1233 }
1234
1235 static struct gl_program *
1236 i915NewProgram(struct gl_context * ctx, GLenum target, GLuint id)
1237 {
1238    switch (target) {
1239    case GL_VERTEX_PROGRAM_ARB:
1240       return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
1241                                        target, id);
1242
1243    case GL_FRAGMENT_PROGRAM_ARB:{
1244          struct i915_fragment_program *prog =
1245             CALLOC_STRUCT(i915_fragment_program);
1246          if (prog) {
1247             i915_init_program(I915_CONTEXT(ctx), prog);
1248
1249             return _mesa_init_fragment_program(ctx, &prog->FragProg,
1250                                                target, id);
1251          }
1252          else
1253             return NULL;
1254       }
1255
1256    default:
1257       /* Just fallback:
1258        */
1259       return _mesa_new_program(ctx, target, id);
1260    }
1261 }
1262
1263 static void
1264 i915DeleteProgram(struct gl_context * ctx, struct gl_program *prog)
1265 {
1266    if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
1267       struct i915_context *i915 = I915_CONTEXT(ctx);
1268       struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
1269
1270       if (i915->current_program == p)
1271          i915->current_program = 0;
1272    }
1273
1274    _mesa_delete_program(ctx, prog);
1275 }
1276
1277
1278 static GLboolean
1279 i915IsProgramNative(struct gl_context * ctx, GLenum target, struct gl_program *prog)
1280 {
1281    if (target == GL_FRAGMENT_PROGRAM_ARB) {
1282       struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
1283
1284       if (!p->translated)
1285          translate_program(p);
1286
1287       return !p->error;
1288    }
1289    else
1290       return GL_TRUE;
1291 }
1292
1293 static GLboolean
1294 i915ProgramStringNotify(struct gl_context * ctx,
1295                         GLenum target, struct gl_program *prog)
1296 {
1297    if (target == GL_FRAGMENT_PROGRAM_ARB) {
1298       struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
1299       p->translated = 0;
1300    }
1301
1302    (void) _tnl_program_string(ctx, target, prog);
1303
1304    /* XXX check if program is legal, within limits */
1305    return GL_TRUE;
1306 }
1307
1308 void
1309 i915_update_program(struct gl_context *ctx)
1310 {
1311    struct intel_context *intel = intel_context(ctx);
1312    struct i915_context *i915 = i915_context(&intel->ctx);
1313    struct i915_fragment_program *fp =
1314       (struct i915_fragment_program *) ctx->FragmentProgram._Current;
1315
1316    if (i915->current_program != fp) {
1317       if (i915->current_program) {
1318          i915->current_program->on_hardware = 0;
1319          i915->current_program->params_uptodate = 0;
1320       }
1321
1322       i915->current_program = fp;
1323    }
1324
1325    if (!fp->translated)
1326       translate_program(fp);
1327
1328    FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, fp->error);
1329 }
1330
1331 void
1332 i915ValidateFragmentProgram(struct i915_context *i915)
1333 {
1334    struct gl_context *ctx = &i915->intel.ctx;
1335    struct intel_context *intel = intel_context(ctx);
1336    TNLcontext *tnl = TNL_CONTEXT(ctx);
1337    struct vertex_buffer *VB = &tnl->vb;
1338
1339    struct i915_fragment_program *p =
1340       (struct i915_fragment_program *) ctx->FragmentProgram._Current;
1341
1342    const GLuint inputsRead = p->FragProg.Base.InputsRead;
1343    GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
1344    GLuint s2 = S2_TEXCOORD_NONE;
1345    int i, offset = 0;
1346
1347    /* Important:
1348     */
1349    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
1350
1351    if (!p->translated)
1352       translate_program(p);
1353
1354    intel->vertex_attr_count = 0;
1355    intel->wpos_offset = 0;
1356    intel->coloroffset = 0;
1357    intel->specoffset = 0;
1358
1359    if (inputsRead & FRAG_BITS_TEX_ANY || p->wpos_tex != -1) {
1360       EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16);
1361    }
1362    else {
1363       EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12);
1364    }
1365
1366    if (inputsRead & FRAG_BIT_COL0) {
1367       intel->coloroffset = offset / 4;
1368       EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4);
1369    }
1370
1371    if (inputsRead & FRAG_BIT_COL1) {
1372        intel->specoffset = offset / 4;
1373        EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_4UB_4F_BGRA, S4_VFMT_SPEC_FOG, 4);
1374    }
1375
1376    if ((inputsRead & FRAG_BIT_FOGC)) {
1377       EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4);
1378    }
1379
1380    for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
1381       if (inputsRead & FRAG_BIT_TEX(i)) {
1382          int sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size;
1383
1384          s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
1385          s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
1386
1387          EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4);
1388       }
1389       else if (inputsRead & FRAG_BIT_VAR(i)) {
1390          int sz = VB->AttribPtr[_TNL_ATTRIB_GENERIC0 + i]->size;
1391
1392          s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
1393          s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
1394
1395          EMIT_ATTR(_TNL_ATTRIB_GENERIC0 + i, EMIT_SZ(sz), 0, sz * 4);
1396       }
1397       else if (i == p->wpos_tex) {
1398          int wpos_size = 4 * sizeof(float);
1399          /* If WPOS is required, duplicate the XYZ position data in an
1400           * unused texture coordinate:
1401           */
1402          s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
1403          s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(wpos_size));
1404
1405          intel->wpos_offset = offset;
1406          EMIT_PAD(wpos_size);
1407       }
1408    }
1409
1410    if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
1411        s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
1412       int k;
1413
1414       I915_STATECHANGE(i915, I915_UPLOAD_CTX);
1415
1416       /* Must do this *after* statechange, so as not to affect
1417        * buffered vertices reliant on the old state:
1418        */
1419       intel->vertex_size = _tnl_install_attrs(&intel->ctx,
1420                                               intel->vertex_attrs,
1421                                               intel->vertex_attr_count,
1422                                               intel->ViewportMatrix.m, 0);
1423
1424       assert(intel->prim.current_offset == intel->prim.start_offset);
1425       intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size;
1426       intel->prim.current_offset = intel->prim.start_offset;
1427
1428       intel->vertex_size >>= 2;
1429
1430       i915->state.Ctx[I915_CTXREG_LIS2] = s2;
1431       i915->state.Ctx[I915_CTXREG_LIS4] = s4;
1432
1433       k = intel->vtbl.check_vertex_size(intel, intel->vertex_size);
1434       assert(k);
1435    }
1436
1437    if (!p->params_uptodate)
1438       track_params(p);
1439
1440    if (!p->on_hardware)
1441       i915_upload_program(i915, p);
1442
1443    if (INTEL_DEBUG & DEBUG_WM) {
1444       printf("i915:\n");
1445       i915_disassemble_program(i915->state.Program, i915->state.ProgramSize);
1446    }
1447 }
1448
1449 void
1450 i915InitFragProgFuncs(struct dd_function_table *functions)
1451 {
1452    functions->BindProgram = i915BindProgram;
1453    functions->NewProgram = i915NewProgram;
1454    functions->DeleteProgram = i915DeleteProgram;
1455    functions->IsProgramNative = i915IsProgramNative;
1456    functions->ProgramStringNotify = i915ProgramStringNotify;
1457 }