Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   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 "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. /**
  26.  * \file prog_execute.c
  27.  * Software interpreter for vertex/fragment programs.
  28.  * \author Brian Paul
  29.  */
  30.  
  31. /*
  32.  * NOTE: we do everything in single-precision floating point; we don't
  33.  * currently observe the single/half/fixed-precision qualifiers.
  34.  *
  35.  */
  36.  
  37.  
  38. #include "c99_math.h"
  39. #include "main/glheader.h"
  40. #include "main/macros.h"
  41. #include "prog_execute.h"
  42. #include "prog_instruction.h"
  43. #include "prog_parameter.h"
  44. #include "prog_print.h"
  45. #include "prog_noise.h"
  46.  
  47.  
  48. /* debug predicate */
  49. #define DEBUG_PROG 0
  50.  
  51.  
  52. /**
  53.  * Set x to positive or negative infinity.
  54.  */
  55. #define SET_POS_INFINITY(x)                  \
  56.    do {                                      \
  57.          fi_type fi;                         \
  58.          fi.i = 0x7F800000;                  \
  59.          x = fi.f;                           \
  60.    } while (0)
  61. #define SET_NEG_INFINITY(x)                  \
  62.    do {                                      \
  63.          fi_type fi;                         \
  64.          fi.i = 0xFF800000;                  \
  65.          x = fi.f;                           \
  66.    } while (0)
  67.  
  68. #define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits
  69.  
  70.  
  71. static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
  72.  
  73.  
  74. /**
  75.  * Return a pointer to the 4-element float vector specified by the given
  76.  * source register.
  77.  */
  78. static inline const GLfloat *
  79. get_src_register_pointer(const struct prog_src_register *source,
  80.                          const struct gl_program_machine *machine)
  81. {
  82.    const struct gl_program *prog = machine->CurProgram;
  83.    GLint reg = source->Index;
  84.  
  85.    if (source->RelAddr) {
  86.       /* add address register value to src index/offset */
  87.       reg += machine->AddressReg[0][0];
  88.       if (reg < 0) {
  89.          return ZeroVec;
  90.       }
  91.    }
  92.  
  93.    switch (source->File) {
  94.    case PROGRAM_TEMPORARY:
  95.       if (reg >= MAX_PROGRAM_TEMPS)
  96.          return ZeroVec;
  97.       return machine->Temporaries[reg];
  98.  
  99.    case PROGRAM_INPUT:
  100.       if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
  101.          if (reg >= VERT_ATTRIB_MAX)
  102.             return ZeroVec;
  103.          return machine->VertAttribs[reg];
  104.       }
  105.       else {
  106.          if (reg >= VARYING_SLOT_MAX)
  107.             return ZeroVec;
  108.          return machine->Attribs[reg][machine->CurElement];
  109.       }
  110.  
  111.    case PROGRAM_OUTPUT:
  112.       if (reg >= MAX_PROGRAM_OUTPUTS)
  113.          return ZeroVec;
  114.       return machine->Outputs[reg];
  115.  
  116.    case PROGRAM_STATE_VAR:
  117.       /* Fallthrough */
  118.    case PROGRAM_CONSTANT:
  119.       /* Fallthrough */
  120.    case PROGRAM_UNIFORM:
  121.       if (reg >= (GLint) prog->Parameters->NumParameters)
  122.          return ZeroVec;
  123.       return (GLfloat *) prog->Parameters->ParameterValues[reg];
  124.  
  125.    case PROGRAM_SYSTEM_VALUE:
  126.       assert(reg < (GLint) ARRAY_SIZE(machine->SystemValues));
  127.       return machine->SystemValues[reg];
  128.  
  129.    default:
  130.       _mesa_problem(NULL,
  131.          "Invalid src register file %d in get_src_register_pointer()",
  132.          source->File);
  133.       return ZeroVec;
  134.    }
  135. }
  136.  
  137.  
  138. /**
  139.  * Return a pointer to the 4-element float vector specified by the given
  140.  * destination register.
  141.  */
  142. static inline GLfloat *
  143. get_dst_register_pointer(const struct prog_dst_register *dest,
  144.                          struct gl_program_machine *machine)
  145. {
  146.    static GLfloat dummyReg[4];
  147.    GLint reg = dest->Index;
  148.  
  149.    if (dest->RelAddr) {
  150.       /* add address register value to src index/offset */
  151.       reg += machine->AddressReg[0][0];
  152.       if (reg < 0) {
  153.          return dummyReg;
  154.       }
  155.    }
  156.  
  157.    switch (dest->File) {
  158.    case PROGRAM_TEMPORARY:
  159.       if (reg >= MAX_PROGRAM_TEMPS)
  160.          return dummyReg;
  161.       return machine->Temporaries[reg];
  162.  
  163.    case PROGRAM_OUTPUT:
  164.       if (reg >= MAX_PROGRAM_OUTPUTS)
  165.          return dummyReg;
  166.       return machine->Outputs[reg];
  167.  
  168.    default:
  169.       _mesa_problem(NULL,
  170.          "Invalid dest register file %d in get_dst_register_pointer()",
  171.          dest->File);
  172.       return dummyReg;
  173.    }
  174. }
  175.  
  176.  
  177.  
  178. /**
  179.  * Fetch a 4-element float vector from the given source register.
  180.  * Apply swizzling and negating as needed.
  181.  */
  182. static void
  183. fetch_vector4(const struct prog_src_register *source,
  184.               const struct gl_program_machine *machine, GLfloat result[4])
  185. {
  186.    const GLfloat *src = get_src_register_pointer(source, machine);
  187.  
  188.    if (source->Swizzle == SWIZZLE_NOOP) {
  189.       /* no swizzling */
  190.       COPY_4V(result, src);
  191.    }
  192.    else {
  193.       assert(GET_SWZ(source->Swizzle, 0) <= 3);
  194.       assert(GET_SWZ(source->Swizzle, 1) <= 3);
  195.       assert(GET_SWZ(source->Swizzle, 2) <= 3);
  196.       assert(GET_SWZ(source->Swizzle, 3) <= 3);
  197.       result[0] = src[GET_SWZ(source->Swizzle, 0)];
  198.       result[1] = src[GET_SWZ(source->Swizzle, 1)];
  199.       result[2] = src[GET_SWZ(source->Swizzle, 2)];
  200.       result[3] = src[GET_SWZ(source->Swizzle, 3)];
  201.    }
  202.  
  203.    if (source->Abs) {
  204.       result[0] = fabsf(result[0]);
  205.       result[1] = fabsf(result[1]);
  206.       result[2] = fabsf(result[2]);
  207.       result[3] = fabsf(result[3]);
  208.    }
  209.    if (source->Negate) {
  210.       assert(source->Negate == NEGATE_XYZW);
  211.       result[0] = -result[0];
  212.       result[1] = -result[1];
  213.       result[2] = -result[2];
  214.       result[3] = -result[3];
  215.    }
  216.  
  217. #ifdef NAN_CHECK
  218.    assert(!IS_INF_OR_NAN(result[0]));
  219.    assert(!IS_INF_OR_NAN(result[0]));
  220.    assert(!IS_INF_OR_NAN(result[0]));
  221.    assert(!IS_INF_OR_NAN(result[0]));
  222. #endif
  223. }
  224.  
  225.  
  226. /**
  227.  * Fetch the derivative with respect to X or Y for the given register.
  228.  * XXX this currently only works for fragment program input attribs.
  229.  */
  230. static void
  231. fetch_vector4_deriv(struct gl_context * ctx,
  232.                     const struct prog_src_register *source,
  233.                     const struct gl_program_machine *machine,
  234.                     char xOrY, GLfloat result[4])
  235. {
  236.    if (source->File == PROGRAM_INPUT &&
  237.        source->Index < (GLint) machine->NumDeriv) {
  238.       const GLint col = machine->CurElement;
  239.       const GLfloat w = machine->Attribs[VARYING_SLOT_POS][col][3];
  240.       const GLfloat invQ = 1.0f / w;
  241.       GLfloat deriv[4];
  242.  
  243.       if (xOrY == 'X') {
  244.          deriv[0] = machine->DerivX[source->Index][0] * invQ;
  245.          deriv[1] = machine->DerivX[source->Index][1] * invQ;
  246.          deriv[2] = machine->DerivX[source->Index][2] * invQ;
  247.          deriv[3] = machine->DerivX[source->Index][3] * invQ;
  248.       }
  249.       else {
  250.          deriv[0] = machine->DerivY[source->Index][0] * invQ;
  251.          deriv[1] = machine->DerivY[source->Index][1] * invQ;
  252.          deriv[2] = machine->DerivY[source->Index][2] * invQ;
  253.          deriv[3] = machine->DerivY[source->Index][3] * invQ;
  254.       }
  255.  
  256.       result[0] = deriv[GET_SWZ(source->Swizzle, 0)];
  257.       result[1] = deriv[GET_SWZ(source->Swizzle, 1)];
  258.       result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
  259.       result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
  260.      
  261.       if (source->Abs) {
  262.          result[0] = fabsf(result[0]);
  263.          result[1] = fabsf(result[1]);
  264.          result[2] = fabsf(result[2]);
  265.          result[3] = fabsf(result[3]);
  266.       }
  267.       if (source->Negate) {
  268.          assert(source->Negate == NEGATE_XYZW);
  269.          result[0] = -result[0];
  270.          result[1] = -result[1];
  271.          result[2] = -result[2];
  272.          result[3] = -result[3];
  273.       }
  274.    }
  275.    else {
  276.       ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0);
  277.    }
  278. }
  279.  
  280.  
  281. /**
  282.  * As above, but only return result[0] element.
  283.  */
  284. static void
  285. fetch_vector1(const struct prog_src_register *source,
  286.               const struct gl_program_machine *machine, GLfloat result[4])
  287. {
  288.    const GLfloat *src = get_src_register_pointer(source, machine);
  289.  
  290.    result[0] = src[GET_SWZ(source->Swizzle, 0)];
  291.  
  292.    if (source->Abs) {
  293.       result[0] = fabsf(result[0]);
  294.    }
  295.    if (source->Negate) {
  296.       result[0] = -result[0];
  297.    }
  298. }
  299.  
  300.  
  301. /**
  302.  * Fetch texel from texture.  Use partial derivatives when possible.
  303.  */
  304. static inline void
  305. fetch_texel(struct gl_context *ctx,
  306.             const struct gl_program_machine *machine,
  307.             const struct prog_instruction *inst,
  308.             const GLfloat texcoord[4], GLfloat lodBias,
  309.             GLfloat color[4])
  310. {
  311.    const GLuint unit = machine->Samplers[inst->TexSrcUnit];
  312.  
  313.    /* Note: we only have the right derivatives for fragment input attribs.
  314.     */
  315.    if (machine->NumDeriv > 0 &&
  316.        inst->SrcReg[0].File == PROGRAM_INPUT &&
  317.        inst->SrcReg[0].Index == VARYING_SLOT_TEX0 + inst->TexSrcUnit) {
  318.       /* simple texture fetch for which we should have derivatives */
  319.       GLuint attr = inst->SrcReg[0].Index;
  320.       machine->FetchTexelDeriv(ctx, texcoord,
  321.                                machine->DerivX[attr],
  322.                                machine->DerivY[attr],
  323.                                lodBias, unit, color);
  324.    }
  325.    else {
  326.       machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
  327.    }
  328. }
  329.  
  330.  
  331. /**
  332.  * Test value against zero and return GT, LT, EQ or UN if NaN.
  333.  */
  334. static inline GLuint
  335. generate_cc(float value)
  336. {
  337.    if (value != value)
  338.       return COND_UN;           /* NaN */
  339.    if (value > 0.0F)
  340.       return COND_GT;
  341.    if (value < 0.0F)
  342.       return COND_LT;
  343.    return COND_EQ;
  344. }
  345.  
  346.  
  347. /**
  348.  * Test if the ccMaskRule is satisfied by the given condition code.
  349.  * Used to mask destination writes according to the current condition code.
  350.  */
  351. static inline GLboolean
  352. test_cc(GLuint condCode, GLuint ccMaskRule)
  353. {
  354.    switch (ccMaskRule) {
  355.    case COND_EQ: return (condCode == COND_EQ);
  356.    case COND_NE: return (condCode != COND_EQ);
  357.    case COND_LT: return (condCode == COND_LT);
  358.    case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);
  359.    case COND_LE: return (condCode == COND_LT || condCode == COND_EQ);
  360.    case COND_GT: return (condCode == COND_GT);
  361.    case COND_TR: return GL_TRUE;
  362.    case COND_FL: return GL_FALSE;
  363.    default:      return GL_TRUE;
  364.    }
  365. }
  366.  
  367.  
  368. /**
  369.  * Evaluate the 4 condition codes against a predicate and return GL_TRUE
  370.  * or GL_FALSE to indicate result.
  371.  */
  372. static inline GLboolean
  373. eval_condition(const struct gl_program_machine *machine,
  374.                const struct prog_instruction *inst)
  375. {
  376.    const GLuint swizzle = inst->DstReg.CondSwizzle;
  377.    const GLuint condMask = inst->DstReg.CondMask;
  378.    if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
  379.        test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
  380.        test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
  381.        test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
  382.       return GL_TRUE;
  383.    }
  384.    else {
  385.       return GL_FALSE;
  386.    }
  387. }
  388.  
  389.  
  390.  
  391. /**
  392.  * Store 4 floats into a register.  Observe the instructions saturate and
  393.  * set-condition-code flags.
  394.  */
  395. static void
  396. store_vector4(const struct prog_instruction *inst,
  397.               struct gl_program_machine *machine, const GLfloat value[4])
  398. {
  399.    const struct prog_dst_register *dstReg = &(inst->DstReg);
  400.    const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE;
  401.    GLuint writeMask = dstReg->WriteMask;
  402.    GLfloat clampedValue[4];
  403.    GLfloat *dst = get_dst_register_pointer(dstReg, machine);
  404.  
  405. #if 0
  406.    if (value[0] > 1.0e10 ||
  407.        IS_INF_OR_NAN(value[0]) ||
  408.        IS_INF_OR_NAN(value[1]) ||
  409.        IS_INF_OR_NAN(value[2]) || IS_INF_OR_NAN(value[3]))
  410.       printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]);
  411. #endif
  412.  
  413.    if (clamp) {
  414.       clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F);
  415.       clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F);
  416.       clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F);
  417.       clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F);
  418.       value = clampedValue;
  419.    }
  420.  
  421.    if (dstReg->CondMask != COND_TR) {
  422.       /* condition codes may turn off some writes */
  423.       if (writeMask & WRITEMASK_X) {
  424.          if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)],
  425.                       dstReg->CondMask))
  426.             writeMask &= ~WRITEMASK_X;
  427.       }
  428.       if (writeMask & WRITEMASK_Y) {
  429.          if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)],
  430.                       dstReg->CondMask))
  431.             writeMask &= ~WRITEMASK_Y;
  432.       }
  433.       if (writeMask & WRITEMASK_Z) {
  434.          if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)],
  435.                       dstReg->CondMask))
  436.             writeMask &= ~WRITEMASK_Z;
  437.       }
  438.       if (writeMask & WRITEMASK_W) {
  439.          if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)],
  440.                       dstReg->CondMask))
  441.             writeMask &= ~WRITEMASK_W;
  442.       }
  443.    }
  444.  
  445. #ifdef NAN_CHECK
  446.    assert(!IS_INF_OR_NAN(value[0]));
  447.    assert(!IS_INF_OR_NAN(value[0]));
  448.    assert(!IS_INF_OR_NAN(value[0]));
  449.    assert(!IS_INF_OR_NAN(value[0]));
  450. #endif
  451.  
  452.    if (writeMask & WRITEMASK_X)
  453.       dst[0] = value[0];
  454.    if (writeMask & WRITEMASK_Y)
  455.       dst[1] = value[1];
  456.    if (writeMask & WRITEMASK_Z)
  457.       dst[2] = value[2];
  458.    if (writeMask & WRITEMASK_W)
  459.       dst[3] = value[3];
  460.  
  461.    if (inst->CondUpdate) {
  462.       if (writeMask & WRITEMASK_X)
  463.          machine->CondCodes[0] = generate_cc(value[0]);
  464.       if (writeMask & WRITEMASK_Y)
  465.          machine->CondCodes[1] = generate_cc(value[1]);
  466.       if (writeMask & WRITEMASK_Z)
  467.          machine->CondCodes[2] = generate_cc(value[2]);
  468.       if (writeMask & WRITEMASK_W)
  469.          machine->CondCodes[3] = generate_cc(value[3]);
  470. #if DEBUG_PROG
  471.       printf("CondCodes=(%s,%s,%s,%s) for:\n",
  472.              _mesa_condcode_string(machine->CondCodes[0]),
  473.              _mesa_condcode_string(machine->CondCodes[1]),
  474.              _mesa_condcode_string(machine->CondCodes[2]),
  475.              _mesa_condcode_string(machine->CondCodes[3]));
  476. #endif
  477.    }
  478. }
  479.  
  480.  
  481. /**
  482.  * Execute the given vertex/fragment program.
  483.  *
  484.  * \param ctx  rendering context
  485.  * \param program  the program to execute
  486.  * \param machine  machine state (must be initialized)
  487.  * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
  488.  */
  489. GLboolean
  490. _mesa_execute_program(struct gl_context * ctx,
  491.                       const struct gl_program *program,
  492.                       struct gl_program_machine *machine)
  493. {
  494.    const GLuint numInst = program->NumInstructions;
  495.    const GLuint maxExec = 65536;
  496.    GLuint pc, numExec = 0;
  497.  
  498.    machine->CurProgram = program;
  499.  
  500.    if (DEBUG_PROG) {
  501.       printf("execute program %u --------------------\n", program->Id);
  502.    }
  503.  
  504.    if (program->Target == GL_VERTEX_PROGRAM_ARB) {
  505.       machine->EnvParams = ctx->VertexProgram.Parameters;
  506.    }
  507.    else {
  508.       machine->EnvParams = ctx->FragmentProgram.Parameters;
  509.    }
  510.  
  511.    for (pc = 0; pc < numInst; pc++) {
  512.       const struct prog_instruction *inst = program->Instructions + pc;
  513.  
  514.       if (DEBUG_PROG) {
  515.          _mesa_print_instruction(inst);
  516.       }
  517.  
  518.       switch (inst->Opcode) {
  519.       case OPCODE_ABS:
  520.          {
  521.             GLfloat a[4], result[4];
  522.             fetch_vector4(&inst->SrcReg[0], machine, a);
  523.             result[0] = fabsf(a[0]);
  524.             result[1] = fabsf(a[1]);
  525.             result[2] = fabsf(a[2]);
  526.             result[3] = fabsf(a[3]);
  527.             store_vector4(inst, machine, result);
  528.          }
  529.          break;
  530.       case OPCODE_ADD:
  531.          {
  532.             GLfloat a[4], b[4], result[4];
  533.             fetch_vector4(&inst->SrcReg[0], machine, a);
  534.             fetch_vector4(&inst->SrcReg[1], machine, b);
  535.             result[0] = a[0] + b[0];
  536.             result[1] = a[1] + b[1];
  537.             result[2] = a[2] + b[2];
  538.             result[3] = a[3] + b[3];
  539.             store_vector4(inst, machine, result);
  540.             if (DEBUG_PROG) {
  541.                printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n",
  542.                       result[0], result[1], result[2], result[3],
  543.                       a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
  544.             }
  545.          }
  546.          break;
  547.       case OPCODE_ARL:
  548.          {
  549.             GLfloat t[4];
  550.             fetch_vector4(&inst->SrcReg[0], machine, t);
  551.             machine->AddressReg[0][0] = IFLOOR(t[0]);
  552.             if (DEBUG_PROG) {
  553.                printf("ARL %d\n", machine->AddressReg[0][0]);
  554.             }
  555.          }
  556.          break;
  557.       case OPCODE_BGNLOOP:
  558.          /* no-op */
  559.          assert(program->Instructions[inst->BranchTarget].Opcode
  560.                 == OPCODE_ENDLOOP);
  561.          break;
  562.       case OPCODE_ENDLOOP:
  563.          /* subtract 1 here since pc is incremented by for(pc) loop */
  564.          assert(program->Instructions[inst->BranchTarget].Opcode
  565.                 == OPCODE_BGNLOOP);
  566.          pc = inst->BranchTarget - 1;   /* go to matching BNGLOOP */
  567.          break;
  568.       case OPCODE_BGNSUB:      /* begin subroutine */
  569.          break;
  570.       case OPCODE_ENDSUB:      /* end subroutine */
  571.          break;
  572.       case OPCODE_BRK:         /* break out of loop (conditional) */
  573.          assert(program->Instructions[inst->BranchTarget].Opcode
  574.                 == OPCODE_ENDLOOP);
  575.          if (eval_condition(machine, inst)) {
  576.             /* break out of loop */
  577.             /* pc++ at end of for-loop will put us after the ENDLOOP inst */
  578.             pc = inst->BranchTarget;
  579.          }
  580.          break;
  581.       case OPCODE_CONT:        /* continue loop (conditional) */
  582.          assert(program->Instructions[inst->BranchTarget].Opcode
  583.                 == OPCODE_ENDLOOP);
  584.          if (eval_condition(machine, inst)) {
  585.             /* continue at ENDLOOP */
  586.             /* Subtract 1 here since we'll do pc++ at end of for-loop */
  587.             pc = inst->BranchTarget - 1;
  588.          }
  589.          break;
  590.       case OPCODE_CAL:         /* Call subroutine (conditional) */
  591.          if (eval_condition(machine, inst)) {
  592.             /* call the subroutine */
  593.             if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
  594.                return GL_TRUE;  /* Per GL_NV_vertex_program2 spec */
  595.             }
  596.             machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */
  597.             /* Subtract 1 here since we'll do pc++ at end of for-loop */
  598.             pc = inst->BranchTarget - 1;
  599.          }
  600.          break;
  601.       case OPCODE_CMP:
  602.          {
  603.             GLfloat a[4], b[4], c[4], result[4];
  604.             fetch_vector4(&inst->SrcReg[0], machine, a);
  605.             fetch_vector4(&inst->SrcReg[1], machine, b);
  606.             fetch_vector4(&inst->SrcReg[2], machine, c);
  607.             result[0] = a[0] < 0.0F ? b[0] : c[0];
  608.             result[1] = a[1] < 0.0F ? b[1] : c[1];
  609.             result[2] = a[2] < 0.0F ? b[2] : c[2];
  610.             result[3] = a[3] < 0.0F ? b[3] : c[3];
  611.             store_vector4(inst, machine, result);
  612.             if (DEBUG_PROG) {
  613.                printf("CMP (%g %g %g %g) = (%g %g %g %g) < 0 ? (%g %g %g %g) : (%g %g %g %g)\n",
  614.                       result[0], result[1], result[2], result[3],
  615.                       a[0], a[1], a[2], a[3],
  616.                       b[0], b[1], b[2], b[3],
  617.                       c[0], c[1], c[2], c[3]);
  618.             }
  619.          }
  620.          break;
  621.       case OPCODE_COS:
  622.          {
  623.             GLfloat a[4], result[4];
  624.             fetch_vector1(&inst->SrcReg[0], machine, a);
  625.             result[0] = result[1] = result[2] = result[3]
  626.                = (GLfloat) cos(a[0]);
  627.             store_vector4(inst, machine, result);
  628.          }
  629.          break;
  630.       case OPCODE_DDX:         /* Partial derivative with respect to X */
  631.          {
  632.             GLfloat result[4];
  633.             fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
  634.                                 'X', result);
  635.             store_vector4(inst, machine, result);
  636.          }
  637.          break;
  638.       case OPCODE_DDY:         /* Partial derivative with respect to Y */
  639.          {
  640.             GLfloat result[4];
  641.             fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
  642.                                 'Y', result);
  643.             store_vector4(inst, machine, result);
  644.          }
  645.          break;
  646.       case OPCODE_DP2:
  647.          {
  648.             GLfloat a[4], b[4], result[4];
  649.             fetch_vector4(&inst->SrcReg[0], machine, a);
  650.             fetch_vector4(&inst->SrcReg[1], machine, b);
  651.             result[0] = result[1] = result[2] = result[3] = DOT2(a, b);
  652.             store_vector4(inst, machine, result);
  653.             if (DEBUG_PROG) {
  654.                printf("DP2 %g = (%g %g) . (%g %g)\n",
  655.                       result[0], a[0], a[1], b[0], b[1]);
  656.             }
  657.          }
  658.          break;
  659.       case OPCODE_DP3:
  660.          {
  661.             GLfloat a[4], b[4], result[4];
  662.             fetch_vector4(&inst->SrcReg[0], machine, a);
  663.             fetch_vector4(&inst->SrcReg[1], machine, b);
  664.             result[0] = result[1] = result[2] = result[3] = DOT3(a, b);
  665.             store_vector4(inst, machine, result);
  666.             if (DEBUG_PROG) {
  667.                printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
  668.                       result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
  669.             }
  670.          }
  671.          break;
  672.       case OPCODE_DP4:
  673.          {
  674.             GLfloat a[4], b[4], result[4];
  675.             fetch_vector4(&inst->SrcReg[0], machine, a);
  676.             fetch_vector4(&inst->SrcReg[1], machine, b);
  677.             result[0] = result[1] = result[2] = result[3] = DOT4(a, b);
  678.             store_vector4(inst, machine, result);
  679.             if (DEBUG_PROG) {
  680.                printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
  681.                       result[0], a[0], a[1], a[2], a[3],
  682.                       b[0], b[1], b[2], b[3]);
  683.             }
  684.          }
  685.          break;
  686.       case OPCODE_DPH:
  687.          {
  688.             GLfloat a[4], b[4], result[4];
  689.             fetch_vector4(&inst->SrcReg[0], machine, a);
  690.             fetch_vector4(&inst->SrcReg[1], machine, b);
  691.             result[0] = result[1] = result[2] = result[3] = DOT3(a, b) + b[3];
  692.             store_vector4(inst, machine, result);
  693.          }
  694.          break;
  695.       case OPCODE_DST:         /* Distance vector */
  696.          {
  697.             GLfloat a[4], b[4], result[4];
  698.             fetch_vector4(&inst->SrcReg[0], machine, a);
  699.             fetch_vector4(&inst->SrcReg[1], machine, b);
  700.             result[0] = 1.0F;
  701.             result[1] = a[1] * b[1];
  702.             result[2] = a[2];
  703.             result[3] = b[3];
  704.             store_vector4(inst, machine, result);
  705.          }
  706.          break;
  707.       case OPCODE_EXP:
  708.          {
  709.             GLfloat t[4], q[4], floor_t0;
  710.             fetch_vector1(&inst->SrcReg[0], machine, t);
  711.             floor_t0 = floorf(t[0]);
  712.             if (floor_t0 > FLT_MAX_EXP) {
  713.                SET_POS_INFINITY(q[0]);
  714.                SET_POS_INFINITY(q[2]);
  715.             }
  716.             else if (floor_t0 < FLT_MIN_EXP) {
  717.                q[0] = 0.0F;
  718.                q[2] = 0.0F;
  719.             }
  720.             else {
  721.                q[0] = ldexpf(1.0, (int) floor_t0);
  722.                /* Note: GL_NV_vertex_program expects
  723.                 * result.z = result.x * APPX(result.y)
  724.                 * We do what the ARB extension says.
  725.                 */
  726.                q[2] = (GLfloat) pow(2.0, t[0]);
  727.             }
  728.             q[1] = t[0] - floor_t0;
  729.             q[3] = 1.0F;
  730.             store_vector4( inst, machine, q );
  731.          }
  732.          break;
  733.       case OPCODE_EX2:         /* Exponential base 2 */
  734.          {
  735.             GLfloat a[4], result[4], val;
  736.             fetch_vector1(&inst->SrcReg[0], machine, a);
  737.             val = (GLfloat) pow(2.0, a[0]);
  738.             /*
  739.             if (IS_INF_OR_NAN(val))
  740.                val = 1.0e10;
  741.             */
  742.             result[0] = result[1] = result[2] = result[3] = val;
  743.             store_vector4(inst, machine, result);
  744.          }
  745.          break;
  746.       case OPCODE_FLR:
  747.          {
  748.             GLfloat a[4], result[4];
  749.             fetch_vector4(&inst->SrcReg[0], machine, a);
  750.             result[0] = floorf(a[0]);
  751.             result[1] = floorf(a[1]);
  752.             result[2] = floorf(a[2]);
  753.             result[3] = floorf(a[3]);
  754.             store_vector4(inst, machine, result);
  755.          }
  756.          break;
  757.       case OPCODE_FRC:
  758.          {
  759.             GLfloat a[4], result[4];
  760.             fetch_vector4(&inst->SrcReg[0], machine, a);
  761.             result[0] = a[0] - floorf(a[0]);
  762.             result[1] = a[1] - floorf(a[1]);
  763.             result[2] = a[2] - floorf(a[2]);
  764.             result[3] = a[3] - floorf(a[3]);
  765.             store_vector4(inst, machine, result);
  766.          }
  767.          break;
  768.       case OPCODE_IF:
  769.          {
  770.             GLboolean cond;
  771.             assert(program->Instructions[inst->BranchTarget].Opcode
  772.                    == OPCODE_ELSE ||
  773.                    program->Instructions[inst->BranchTarget].Opcode
  774.                    == OPCODE_ENDIF);
  775.             /* eval condition */
  776.             if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
  777.                GLfloat a[4];
  778.                fetch_vector1(&inst->SrcReg[0], machine, a);
  779.                cond = (a[0] != 0.0);
  780.             }
  781.             else {
  782.                cond = eval_condition(machine, inst);
  783.             }
  784.             if (DEBUG_PROG) {
  785.                printf("IF: %d\n", cond);
  786.             }
  787.             /* do if/else */
  788.             if (cond) {
  789.                /* do if-clause (just continue execution) */
  790.             }
  791.             else {
  792.                /* go to the instruction after ELSE or ENDIF */
  793.                assert(inst->BranchTarget >= 0);
  794.                pc = inst->BranchTarget;
  795.             }
  796.          }
  797.          break;
  798.       case OPCODE_ELSE:
  799.          /* goto ENDIF */
  800.          assert(program->Instructions[inst->BranchTarget].Opcode
  801.                 == OPCODE_ENDIF);
  802.          assert(inst->BranchTarget >= 0);
  803.          pc = inst->BranchTarget;
  804.          break;
  805.       case OPCODE_ENDIF:
  806.          /* nothing */
  807.          break;
  808.       case OPCODE_KIL_NV:      /* NV_f_p only (conditional) */
  809.          if (eval_condition(machine, inst)) {
  810.             return GL_FALSE;
  811.          }
  812.          break;
  813.       case OPCODE_KIL:         /* ARB_f_p only */
  814.          {
  815.             GLfloat a[4];
  816.             fetch_vector4(&inst->SrcReg[0], machine, a);
  817.             if (DEBUG_PROG) {
  818.                printf("KIL if (%g %g %g %g) <= 0.0\n",
  819.                       a[0], a[1], a[2], a[3]);
  820.             }
  821.  
  822.             if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
  823.                return GL_FALSE;
  824.             }
  825.          }
  826.          break;
  827.       case OPCODE_LG2:         /* log base 2 */
  828.          {
  829.             GLfloat a[4], result[4], val;
  830.             fetch_vector1(&inst->SrcReg[0], machine, a);
  831.             /* The fast LOG2 macro doesn't meet the precision requirements.
  832.              */
  833.             if (a[0] == 0.0F) {
  834.                val = -FLT_MAX;
  835.             }
  836.             else {
  837.                val = (float)(log(a[0]) * 1.442695F);
  838.             }
  839.             result[0] = result[1] = result[2] = result[3] = val;
  840.             store_vector4(inst, machine, result);
  841.          }
  842.          break;
  843.       case OPCODE_LIT:
  844.          {
  845.             const GLfloat epsilon = 1.0F / 256.0F;      /* from NV VP spec */
  846.             GLfloat a[4], result[4];
  847.             fetch_vector4(&inst->SrcReg[0], machine, a);
  848.             a[0] = MAX2(a[0], 0.0F);
  849.             a[1] = MAX2(a[1], 0.0F);
  850.             /* XXX ARB version clamps a[3], NV version doesn't */
  851.             a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon));
  852.             result[0] = 1.0F;
  853.             result[1] = a[0];
  854.             /* XXX we could probably just use pow() here */
  855.             if (a[0] > 0.0F) {
  856.                if (a[1] == 0.0 && a[3] == 0.0)
  857.                   result[2] = 1.0F;
  858.                else
  859.                   result[2] = (GLfloat) pow(a[1], a[3]);
  860.             }
  861.             else {
  862.                result[2] = 0.0F;
  863.             }
  864.             result[3] = 1.0F;
  865.             store_vector4(inst, machine, result);
  866.             if (DEBUG_PROG) {
  867.                printf("LIT (%g %g %g %g) : (%g %g %g %g)\n",
  868.                       result[0], result[1], result[2], result[3],
  869.                       a[0], a[1], a[2], a[3]);
  870.             }
  871.          }
  872.          break;
  873.       case OPCODE_LOG:
  874.          {
  875.             GLfloat t[4], q[4], abs_t0;
  876.             fetch_vector1(&inst->SrcReg[0], machine, t);
  877.             abs_t0 = fabsf(t[0]);
  878.             if (abs_t0 != 0.0F) {
  879.                if (IS_INF_OR_NAN(abs_t0))
  880.                {
  881.                   SET_POS_INFINITY(q[0]);
  882.                   q[1] = 1.0F;
  883.                   SET_POS_INFINITY(q[2]);
  884.                }
  885.                else {
  886.                   int exponent;
  887.                   GLfloat mantissa = frexpf(t[0], &exponent);
  888.                   q[0] = (GLfloat) (exponent - 1);
  889.                   q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */
  890.  
  891.                   /* The fast LOG2 macro doesn't meet the precision
  892.                    * requirements.
  893.                    */
  894.                   q[2] = (float)(log(t[0]) * 1.442695F);
  895.                }
  896.             }
  897.             else {
  898.                SET_NEG_INFINITY(q[0]);
  899.                q[1] = 1.0F;
  900.                SET_NEG_INFINITY(q[2]);
  901.             }
  902.             q[3] = 1.0;
  903.             store_vector4(inst, machine, q);
  904.          }
  905.          break;
  906.       case OPCODE_LRP:
  907.          {
  908.             GLfloat a[4], b[4], c[4], result[4];
  909.             fetch_vector4(&inst->SrcReg[0], machine, a);
  910.             fetch_vector4(&inst->SrcReg[1], machine, b);
  911.             fetch_vector4(&inst->SrcReg[2], machine, c);
  912.             result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0];
  913.             result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1];
  914.             result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2];
  915.             result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3];
  916.             store_vector4(inst, machine, result);
  917.             if (DEBUG_PROG) {
  918.                printf("LRP (%g %g %g %g) = (%g %g %g %g), "
  919.                       "(%g %g %g %g), (%g %g %g %g)\n",
  920.                       result[0], result[1], result[2], result[3],
  921.                       a[0], a[1], a[2], a[3],
  922.                       b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
  923.             }
  924.          }
  925.          break;
  926.       case OPCODE_MAD:
  927.          {
  928.             GLfloat a[4], b[4], c[4], result[4];
  929.             fetch_vector4(&inst->SrcReg[0], machine, a);
  930.             fetch_vector4(&inst->SrcReg[1], machine, b);
  931.             fetch_vector4(&inst->SrcReg[2], machine, c);
  932.             result[0] = a[0] * b[0] + c[0];
  933.             result[1] = a[1] * b[1] + c[1];
  934.             result[2] = a[2] * b[2] + c[2];
  935.             result[3] = a[3] * b[3] + c[3];
  936.             store_vector4(inst, machine, result);
  937.             if (DEBUG_PROG) {
  938.                printf("MAD (%g %g %g %g) = (%g %g %g %g) * "
  939.                       "(%g %g %g %g) + (%g %g %g %g)\n",
  940.                       result[0], result[1], result[2], result[3],
  941.                       a[0], a[1], a[2], a[3],
  942.                       b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
  943.             }
  944.          }
  945.          break;
  946.       case OPCODE_MAX:
  947.          {
  948.             GLfloat a[4], b[4], result[4];
  949.             fetch_vector4(&inst->SrcReg[0], machine, a);
  950.             fetch_vector4(&inst->SrcReg[1], machine, b);
  951.             result[0] = MAX2(a[0], b[0]);
  952.             result[1] = MAX2(a[1], b[1]);
  953.             result[2] = MAX2(a[2], b[2]);
  954.             result[3] = MAX2(a[3], b[3]);
  955.             store_vector4(inst, machine, result);
  956.             if (DEBUG_PROG) {
  957.                printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
  958.                       result[0], result[1], result[2], result[3],
  959.                       a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
  960.             }
  961.          }
  962.          break;
  963.       case OPCODE_MIN:
  964.          {
  965.             GLfloat a[4], b[4], result[4];
  966.             fetch_vector4(&inst->SrcReg[0], machine, a);
  967.             fetch_vector4(&inst->SrcReg[1], machine, b);
  968.             result[0] = MIN2(a[0], b[0]);
  969.             result[1] = MIN2(a[1], b[1]);
  970.             result[2] = MIN2(a[2], b[2]);
  971.             result[3] = MIN2(a[3], b[3]);
  972.             store_vector4(inst, machine, result);
  973.          }
  974.          break;
  975.       case OPCODE_MOV:
  976.          {
  977.             GLfloat result[4];
  978.             fetch_vector4(&inst->SrcReg[0], machine, result);
  979.             store_vector4(inst, machine, result);
  980.             if (DEBUG_PROG) {
  981.                printf("MOV (%g %g %g %g)\n",
  982.                       result[0], result[1], result[2], result[3]);
  983.             }
  984.          }
  985.          break;
  986.       case OPCODE_MUL:
  987.          {
  988.             GLfloat a[4], b[4], result[4];
  989.             fetch_vector4(&inst->SrcReg[0], machine, a);
  990.             fetch_vector4(&inst->SrcReg[1], machine, b);
  991.             result[0] = a[0] * b[0];
  992.             result[1] = a[1] * b[1];
  993.             result[2] = a[2] * b[2];
  994.             result[3] = a[3] * b[3];
  995.             store_vector4(inst, machine, result);
  996.             if (DEBUG_PROG) {
  997.                printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
  998.                       result[0], result[1], result[2], result[3],
  999.                       a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
  1000.             }
  1001.          }
  1002.          break;
  1003.       case OPCODE_NOISE1:
  1004.          {
  1005.             GLfloat a[4], result[4];
  1006.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1007.             result[0] =
  1008.                result[1] =
  1009.                result[2] =
  1010.                result[3] = _mesa_noise1(a[0]);
  1011.             store_vector4(inst, machine, result);
  1012.          }
  1013.          break;
  1014.       case OPCODE_NOISE2:
  1015.          {
  1016.             GLfloat a[4], result[4];
  1017.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1018.             result[0] =
  1019.                result[1] =
  1020.                result[2] = result[3] = _mesa_noise2(a[0], a[1]);
  1021.             store_vector4(inst, machine, result);
  1022.          }
  1023.          break;
  1024.       case OPCODE_NOISE3:
  1025.          {
  1026.             GLfloat a[4], result[4];
  1027.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1028.             result[0] =
  1029.                result[1] =
  1030.                result[2] =
  1031.                result[3] = _mesa_noise3(a[0], a[1], a[2]);
  1032.             store_vector4(inst, machine, result);
  1033.          }
  1034.          break;
  1035.       case OPCODE_NOISE4:
  1036.          {
  1037.             GLfloat a[4], result[4];
  1038.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1039.             result[0] =
  1040.                result[1] =
  1041.                result[2] =
  1042.                result[3] = _mesa_noise4(a[0], a[1], a[2], a[3]);
  1043.             store_vector4(inst, machine, result);
  1044.          }
  1045.          break;
  1046.       case OPCODE_NOP:
  1047.          break;
  1048.       case OPCODE_POW:
  1049.          {
  1050.             GLfloat a[4], b[4], result[4];
  1051.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1052.             fetch_vector1(&inst->SrcReg[1], machine, b);
  1053.             result[0] = result[1] = result[2] = result[3]
  1054.                = (GLfloat) pow(a[0], b[0]);
  1055.             store_vector4(inst, machine, result);
  1056.          }
  1057.          break;
  1058.  
  1059.       case OPCODE_RCP:
  1060.          {
  1061.             GLfloat a[4], result[4];
  1062.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1063.             if (DEBUG_PROG) {
  1064.                if (a[0] == 0)
  1065.                   printf("RCP(0)\n");
  1066.                else if (IS_INF_OR_NAN(a[0]))
  1067.                   printf("RCP(inf)\n");
  1068.             }
  1069.             result[0] = result[1] = result[2] = result[3] = 1.0F / a[0];
  1070.             store_vector4(inst, machine, result);
  1071.          }
  1072.          break;
  1073.       case OPCODE_RET:         /* return from subroutine (conditional) */
  1074.          if (eval_condition(machine, inst)) {
  1075.             if (machine->StackDepth == 0) {
  1076.                return GL_TRUE;  /* Per GL_NV_vertex_program2 spec */
  1077.             }
  1078.             /* subtract one because of pc++ in the for loop */
  1079.             pc = machine->CallStack[--machine->StackDepth] - 1;
  1080.          }
  1081.          break;
  1082.       case OPCODE_RSQ:         /* 1 / sqrt() */
  1083.          {
  1084.             GLfloat a[4], result[4];
  1085.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1086.             a[0] = fabsf(a[0]);
  1087.             result[0] = result[1] = result[2] = result[3] = 1.0f / sqrtf(a[0]);
  1088.             store_vector4(inst, machine, result);
  1089.             if (DEBUG_PROG) {
  1090.                printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
  1091.             }
  1092.          }
  1093.          break;
  1094.       case OPCODE_SCS:         /* sine and cos */
  1095.          {
  1096.             GLfloat a[4], result[4];
  1097.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1098.             result[0] = (GLfloat) cos(a[0]);
  1099.             result[1] = (GLfloat) sin(a[0]);
  1100.             result[2] = 0.0;    /* undefined! */
  1101.             result[3] = 0.0;    /* undefined! */
  1102.             store_vector4(inst, machine, result);
  1103.          }
  1104.          break;
  1105.       case OPCODE_SEQ:         /* set on equal */
  1106.          {
  1107.             GLfloat a[4], b[4], result[4];
  1108.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1109.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1110.             result[0] = (a[0] == b[0]) ? 1.0F : 0.0F;
  1111.             result[1] = (a[1] == b[1]) ? 1.0F : 0.0F;
  1112.             result[2] = (a[2] == b[2]) ? 1.0F : 0.0F;
  1113.             result[3] = (a[3] == b[3]) ? 1.0F : 0.0F;
  1114.             store_vector4(inst, machine, result);
  1115.             if (DEBUG_PROG) {
  1116.                printf("SEQ (%g %g %g %g) = (%g %g %g %g) == (%g %g %g %g)\n",
  1117.                       result[0], result[1], result[2], result[3],
  1118.                       a[0], a[1], a[2], a[3],
  1119.                       b[0], b[1], b[2], b[3]);
  1120.             }
  1121.          }
  1122.          break;
  1123.       case OPCODE_SGE:         /* set on greater or equal */
  1124.          {
  1125.             GLfloat a[4], b[4], result[4];
  1126.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1127.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1128.             result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F;
  1129.             result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F;
  1130.             result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F;
  1131.             result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F;
  1132.             store_vector4(inst, machine, result);
  1133.             if (DEBUG_PROG) {
  1134.                printf("SGE (%g %g %g %g) = (%g %g %g %g) >= (%g %g %g %g)\n",
  1135.                       result[0], result[1], result[2], result[3],
  1136.                       a[0], a[1], a[2], a[3],
  1137.                       b[0], b[1], b[2], b[3]);
  1138.             }
  1139.          }
  1140.          break;
  1141.       case OPCODE_SGT:         /* set on greater */
  1142.          {
  1143.             GLfloat a[4], b[4], result[4];
  1144.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1145.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1146.             result[0] = (a[0] > b[0]) ? 1.0F : 0.0F;
  1147.             result[1] = (a[1] > b[1]) ? 1.0F : 0.0F;
  1148.             result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
  1149.             result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
  1150.             store_vector4(inst, machine, result);
  1151.             if (DEBUG_PROG) {
  1152.                printf("SGT (%g %g %g %g) = (%g %g %g %g) > (%g %g %g %g)\n",
  1153.                       result[0], result[1], result[2], result[3],
  1154.                       a[0], a[1], a[2], a[3],
  1155.                       b[0], b[1], b[2], b[3]);
  1156.             }
  1157.          }
  1158.          break;
  1159.       case OPCODE_SIN:
  1160.          {
  1161.             GLfloat a[4], result[4];
  1162.             fetch_vector1(&inst->SrcReg[0], machine, a);
  1163.             result[0] = result[1] = result[2] = result[3]
  1164.                = (GLfloat) sin(a[0]);
  1165.             store_vector4(inst, machine, result);
  1166.          }
  1167.          break;
  1168.       case OPCODE_SLE:         /* set on less or equal */
  1169.          {
  1170.             GLfloat a[4], b[4], result[4];
  1171.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1172.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1173.             result[0] = (a[0] <= b[0]) ? 1.0F : 0.0F;
  1174.             result[1] = (a[1] <= b[1]) ? 1.0F : 0.0F;
  1175.             result[2] = (a[2] <= b[2]) ? 1.0F : 0.0F;
  1176.             result[3] = (a[3] <= b[3]) ? 1.0F : 0.0F;
  1177.             store_vector4(inst, machine, result);
  1178.             if (DEBUG_PROG) {
  1179.                printf("SLE (%g %g %g %g) = (%g %g %g %g) <= (%g %g %g %g)\n",
  1180.                       result[0], result[1], result[2], result[3],
  1181.                       a[0], a[1], a[2], a[3],
  1182.                       b[0], b[1], b[2], b[3]);
  1183.             }
  1184.          }
  1185.          break;
  1186.       case OPCODE_SLT:         /* set on less */
  1187.          {
  1188.             GLfloat a[4], b[4], result[4];
  1189.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1190.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1191.             result[0] = (a[0] < b[0]) ? 1.0F : 0.0F;
  1192.             result[1] = (a[1] < b[1]) ? 1.0F : 0.0F;
  1193.             result[2] = (a[2] < b[2]) ? 1.0F : 0.0F;
  1194.             result[3] = (a[3] < b[3]) ? 1.0F : 0.0F;
  1195.             store_vector4(inst, machine, result);
  1196.             if (DEBUG_PROG) {
  1197.                printf("SLT (%g %g %g %g) = (%g %g %g %g) < (%g %g %g %g)\n",
  1198.                       result[0], result[1], result[2], result[3],
  1199.                       a[0], a[1], a[2], a[3],
  1200.                       b[0], b[1], b[2], b[3]);
  1201.             }
  1202.          }
  1203.          break;
  1204.       case OPCODE_SNE:         /* set on not equal */
  1205.          {
  1206.             GLfloat a[4], b[4], result[4];
  1207.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1208.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1209.             result[0] = (a[0] != b[0]) ? 1.0F : 0.0F;
  1210.             result[1] = (a[1] != b[1]) ? 1.0F : 0.0F;
  1211.             result[2] = (a[2] != b[2]) ? 1.0F : 0.0F;
  1212.             result[3] = (a[3] != b[3]) ? 1.0F : 0.0F;
  1213.             store_vector4(inst, machine, result);
  1214.             if (DEBUG_PROG) {
  1215.                printf("SNE (%g %g %g %g) = (%g %g %g %g) != (%g %g %g %g)\n",
  1216.                       result[0], result[1], result[2], result[3],
  1217.                       a[0], a[1], a[2], a[3],
  1218.                       b[0], b[1], b[2], b[3]);
  1219.             }
  1220.          }
  1221.          break;
  1222.       case OPCODE_SSG:         /* set sign (-1, 0 or +1) */
  1223.          {
  1224.             GLfloat a[4], result[4];
  1225.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1226.             result[0] = (GLfloat) ((a[0] > 0.0F) - (a[0] < 0.0F));
  1227.             result[1] = (GLfloat) ((a[1] > 0.0F) - (a[1] < 0.0F));
  1228.             result[2] = (GLfloat) ((a[2] > 0.0F) - (a[2] < 0.0F));
  1229.             result[3] = (GLfloat) ((a[3] > 0.0F) - (a[3] < 0.0F));
  1230.             store_vector4(inst, machine, result);
  1231.          }
  1232.          break;
  1233.       case OPCODE_SUB:
  1234.          {
  1235.             GLfloat a[4], b[4], result[4];
  1236.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1237.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1238.             result[0] = a[0] - b[0];
  1239.             result[1] = a[1] - b[1];
  1240.             result[2] = a[2] - b[2];
  1241.             result[3] = a[3] - b[3];
  1242.             store_vector4(inst, machine, result);
  1243.             if (DEBUG_PROG) {
  1244.                printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
  1245.                       result[0], result[1], result[2], result[3],
  1246.                       a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
  1247.             }
  1248.          }
  1249.          break;
  1250.       case OPCODE_SWZ:         /* extended swizzle */
  1251.          {
  1252.             const struct prog_src_register *source = &inst->SrcReg[0];
  1253.             const GLfloat *src = get_src_register_pointer(source, machine);
  1254.             GLfloat result[4];
  1255.             GLuint i;
  1256.             for (i = 0; i < 4; i++) {
  1257.                const GLuint swz = GET_SWZ(source->Swizzle, i);
  1258.                if (swz == SWIZZLE_ZERO)
  1259.                   result[i] = 0.0;
  1260.                else if (swz == SWIZZLE_ONE)
  1261.                   result[i] = 1.0;
  1262.                else {
  1263.                   assert(swz <= 3);
  1264.                   result[i] = src[swz];
  1265.                }
  1266.                if (source->Negate & (1 << i))
  1267.                   result[i] = -result[i];
  1268.             }
  1269.             store_vector4(inst, machine, result);
  1270.          }
  1271.          break;
  1272.       case OPCODE_TEX:         /* Both ARB and NV frag prog */
  1273.          /* Simple texel lookup */
  1274.          {
  1275.             GLfloat texcoord[4], color[4];
  1276.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1277.  
  1278.             /* For TEX, texcoord.Q should not be used and its value should not
  1279.              * matter (at most, we pass coord.xyz to texture3D() in GLSL).
  1280.              * Set Q=1 so that FetchTexelDeriv() doesn't get a garbage value
  1281.              * which is effectively what happens when the texcoord swizzle
  1282.              * is .xyzz
  1283.              */
  1284.             texcoord[3] = 1.0f;
  1285.  
  1286.             fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
  1287.  
  1288.             if (DEBUG_PROG) {
  1289.                printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g]\n",
  1290.                       color[0], color[1], color[2], color[3],
  1291.                       inst->TexSrcUnit,
  1292.                       texcoord[0], texcoord[1], texcoord[2], texcoord[3]);
  1293.             }
  1294.             store_vector4(inst, machine, color);
  1295.          }
  1296.          break;
  1297.       case OPCODE_TXB:         /* GL_ARB_fragment_program only */
  1298.          /* Texel lookup with LOD bias */
  1299.          {
  1300.             GLfloat texcoord[4], color[4], lodBias;
  1301.  
  1302.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1303.  
  1304.             /* texcoord[3] is the bias to add to lambda */
  1305.             lodBias = texcoord[3];
  1306.  
  1307.             fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
  1308.  
  1309.             if (DEBUG_PROG) {
  1310.                printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]"
  1311.                       "  bias %g\n",
  1312.                       color[0], color[1], color[2], color[3],
  1313.                       inst->TexSrcUnit,
  1314.                       texcoord[0],
  1315.                       texcoord[1],
  1316.                       texcoord[2],
  1317.                       texcoord[3],
  1318.                       lodBias);
  1319.             }
  1320.  
  1321.             store_vector4(inst, machine, color);
  1322.          }
  1323.          break;
  1324.       case OPCODE_TXD:         /* GL_NV_fragment_program only */
  1325.          /* Texture lookup w/ partial derivatives for LOD */
  1326.          {
  1327.             GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
  1328.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1329.             fetch_vector4(&inst->SrcReg[1], machine, dtdx);
  1330.             fetch_vector4(&inst->SrcReg[2], machine, dtdy);
  1331.             machine->FetchTexelDeriv(ctx, texcoord, dtdx, dtdy,
  1332.                                      0.0, /* lodBias */
  1333.                                      inst->TexSrcUnit, color);
  1334.             store_vector4(inst, machine, color);
  1335.          }
  1336.          break;
  1337.       case OPCODE_TXL:
  1338.          /* Texel lookup with explicit LOD */
  1339.          {
  1340.             GLfloat texcoord[4], color[4], lod;
  1341.  
  1342.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1343.  
  1344.             /* texcoord[3] is the LOD */
  1345.             lod = texcoord[3];
  1346.  
  1347.             machine->FetchTexelLod(ctx, texcoord, lod,
  1348.                                    machine->Samplers[inst->TexSrcUnit], color);
  1349.  
  1350.             store_vector4(inst, machine, color);
  1351.          }
  1352.          break;
  1353.       case OPCODE_TXP:         /* GL_ARB_fragment_program only */
  1354.          /* Texture lookup w/ projective divide */
  1355.          {
  1356.             GLfloat texcoord[4], color[4];
  1357.  
  1358.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1359.             /* Not so sure about this test - if texcoord[3] is
  1360.              * zero, we'd probably be fine except for an assert in
  1361.              * IROUND_POS() which gets triggered by the inf values created.
  1362.              */
  1363.             if (texcoord[3] != 0.0) {
  1364.                texcoord[0] /= texcoord[3];
  1365.                texcoord[1] /= texcoord[3];
  1366.                texcoord[2] /= texcoord[3];
  1367.             }
  1368.  
  1369.             fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
  1370.  
  1371.             store_vector4(inst, machine, color);
  1372.          }
  1373.          break;
  1374.       case OPCODE_TXP_NV:      /* GL_NV_fragment_program only */
  1375.          /* Texture lookup w/ projective divide, as above, but do not
  1376.           * do the divide by w if sampling from a cube map.
  1377.           */
  1378.          {
  1379.             GLfloat texcoord[4], color[4];
  1380.  
  1381.             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
  1382.             if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
  1383.                 texcoord[3] != 0.0) {
  1384.                texcoord[0] /= texcoord[3];
  1385.                texcoord[1] /= texcoord[3];
  1386.                texcoord[2] /= texcoord[3];
  1387.             }
  1388.  
  1389.             fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
  1390.  
  1391.             store_vector4(inst, machine, color);
  1392.          }
  1393.          break;
  1394.       case OPCODE_TRUNC:       /* truncate toward zero */
  1395.          {
  1396.             GLfloat a[4], result[4];
  1397.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1398.             result[0] = (GLfloat) (GLint) a[0];
  1399.             result[1] = (GLfloat) (GLint) a[1];
  1400.             result[2] = (GLfloat) (GLint) a[2];
  1401.             result[3] = (GLfloat) (GLint) a[3];
  1402.             store_vector4(inst, machine, result);
  1403.          }
  1404.          break;
  1405.       case OPCODE_XPD:         /* cross product */
  1406.          {
  1407.             GLfloat a[4], b[4], result[4];
  1408.             fetch_vector4(&inst->SrcReg[0], machine, a);
  1409.             fetch_vector4(&inst->SrcReg[1], machine, b);
  1410.             result[0] = a[1] * b[2] - a[2] * b[1];
  1411.             result[1] = a[2] * b[0] - a[0] * b[2];
  1412.             result[2] = a[0] * b[1] - a[1] * b[0];
  1413.             result[3] = 1.0;
  1414.             store_vector4(inst, machine, result);
  1415.             if (DEBUG_PROG) {
  1416.                printf("XPD (%g %g %g %g) = (%g %g %g) X (%g %g %g)\n",
  1417.                       result[0], result[1], result[2], result[3],
  1418.                       a[0], a[1], a[2], b[0], b[1], b[2]);
  1419.             }
  1420.          }
  1421.          break;
  1422.       case OPCODE_END:
  1423.          return GL_TRUE;
  1424.       default:
  1425.          _mesa_problem(ctx, "Bad opcode %d in _mesa_execute_program",
  1426.                        inst->Opcode);
  1427.          return GL_TRUE;        /* return value doesn't matter */
  1428.       }
  1429.  
  1430.       numExec++;
  1431.       if (numExec > maxExec) {
  1432.          static GLboolean reported = GL_FALSE;
  1433.          if (!reported) {
  1434.             _mesa_problem(ctx, "Infinite loop detected in fragment program");
  1435.             reported = GL_TRUE;
  1436.          }
  1437.          return GL_TRUE;
  1438.       }
  1439.  
  1440.    } /* for pc */
  1441.  
  1442.    return GL_TRUE;
  1443. }
  1444.