Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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