13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 53464ebd5Sriastradh * 63464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 73464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 83464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 93464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 103464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 113464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 123464ebd5Sriastradh * 133464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 143464ebd5Sriastradh * in all copies or substantial portions of the Software. 153464ebd5Sriastradh * 163464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 173464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 233464ebd5Sriastradh */ 243464ebd5Sriastradh 253464ebd5Sriastradh/** 263464ebd5Sriastradh * \file prog_execute.c 273464ebd5Sriastradh * Software interpreter for vertex/fragment programs. 283464ebd5Sriastradh * \author Brian Paul 293464ebd5Sriastradh */ 303464ebd5Sriastradh 313464ebd5Sriastradh/* 323464ebd5Sriastradh * NOTE: we do everything in single-precision floating point; we don't 333464ebd5Sriastradh * currently observe the single/half/fixed-precision qualifiers. 343464ebd5Sriastradh * 353464ebd5Sriastradh */ 363464ebd5Sriastradh 373464ebd5Sriastradh 3801e04c3fSmrg#include "c99_math.h" 3901e04c3fSmrg#include "main/errors.h" 403464ebd5Sriastradh#include "main/glheader.h" 413464ebd5Sriastradh#include "main/macros.h" 4201e04c3fSmrg#include "main/mtypes.h" 433464ebd5Sriastradh#include "prog_execute.h" 443464ebd5Sriastradh#include "prog_instruction.h" 453464ebd5Sriastradh#include "prog_parameter.h" 463464ebd5Sriastradh#include "prog_print.h" 473464ebd5Sriastradh#include "prog_noise.h" 483464ebd5Sriastradh 493464ebd5Sriastradh 503464ebd5Sriastradh/* debug predicate */ 513464ebd5Sriastradh#define DEBUG_PROG 0 523464ebd5Sriastradh 533464ebd5Sriastradh 543464ebd5Sriastradh/** 553464ebd5Sriastradh * Set x to positive or negative infinity. 563464ebd5Sriastradh */ 573464ebd5Sriastradh#define SET_POS_INFINITY(x) \ 583464ebd5Sriastradh do { \ 593464ebd5Sriastradh fi_type fi; \ 603464ebd5Sriastradh fi.i = 0x7F800000; \ 613464ebd5Sriastradh x = fi.f; \ 623464ebd5Sriastradh } while (0) 633464ebd5Sriastradh#define SET_NEG_INFINITY(x) \ 643464ebd5Sriastradh do { \ 653464ebd5Sriastradh fi_type fi; \ 663464ebd5Sriastradh fi.i = 0xFF800000; \ 673464ebd5Sriastradh x = fi.f; \ 683464ebd5Sriastradh } while (0) 693464ebd5Sriastradh 703464ebd5Sriastradh#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits 713464ebd5Sriastradh 723464ebd5Sriastradh 733464ebd5Sriastradhstatic const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F }; 743464ebd5Sriastradh 753464ebd5Sriastradh 763464ebd5Sriastradh/** 773464ebd5Sriastradh * Return a pointer to the 4-element float vector specified by the given 783464ebd5Sriastradh * source register. 793464ebd5Sriastradh */ 80af69d88dSmrgstatic inline const GLfloat * 813464ebd5Sriastradhget_src_register_pointer(const struct prog_src_register *source, 823464ebd5Sriastradh const struct gl_program_machine *machine) 833464ebd5Sriastradh{ 843464ebd5Sriastradh const struct gl_program *prog = machine->CurProgram; 853464ebd5Sriastradh GLint reg = source->Index; 863464ebd5Sriastradh 873464ebd5Sriastradh if (source->RelAddr) { 883464ebd5Sriastradh /* add address register value to src index/offset */ 893464ebd5Sriastradh reg += machine->AddressReg[0][0]; 903464ebd5Sriastradh if (reg < 0) { 913464ebd5Sriastradh return ZeroVec; 923464ebd5Sriastradh } 933464ebd5Sriastradh } 943464ebd5Sriastradh 953464ebd5Sriastradh switch (source->File) { 963464ebd5Sriastradh case PROGRAM_TEMPORARY: 973464ebd5Sriastradh if (reg >= MAX_PROGRAM_TEMPS) 983464ebd5Sriastradh return ZeroVec; 993464ebd5Sriastradh return machine->Temporaries[reg]; 1003464ebd5Sriastradh 1013464ebd5Sriastradh case PROGRAM_INPUT: 1023464ebd5Sriastradh if (prog->Target == GL_VERTEX_PROGRAM_ARB) { 1033464ebd5Sriastradh if (reg >= VERT_ATTRIB_MAX) 1043464ebd5Sriastradh return ZeroVec; 1053464ebd5Sriastradh return machine->VertAttribs[reg]; 1063464ebd5Sriastradh } 1073464ebd5Sriastradh else { 108af69d88dSmrg if (reg >= VARYING_SLOT_MAX) 1093464ebd5Sriastradh return ZeroVec; 1103464ebd5Sriastradh return machine->Attribs[reg][machine->CurElement]; 1113464ebd5Sriastradh } 1123464ebd5Sriastradh 1133464ebd5Sriastradh case PROGRAM_OUTPUT: 1143464ebd5Sriastradh if (reg >= MAX_PROGRAM_OUTPUTS) 1153464ebd5Sriastradh return ZeroVec; 1163464ebd5Sriastradh return machine->Outputs[reg]; 1173464ebd5Sriastradh 1183464ebd5Sriastradh case PROGRAM_STATE_VAR: 1197ec681f3Smrg FALLTHROUGH; 1203464ebd5Sriastradh case PROGRAM_CONSTANT: 1217ec681f3Smrg FALLTHROUGH; 12201e04c3fSmrg case PROGRAM_UNIFORM: { 1233464ebd5Sriastradh if (reg >= (GLint) prog->Parameters->NumParameters) 1243464ebd5Sriastradh return ZeroVec; 1253464ebd5Sriastradh 1267ec681f3Smrg unsigned pvo = prog->Parameters->Parameters[reg].ValueOffset; 12701e04c3fSmrg return (GLfloat *) prog->Parameters->ParameterValues + pvo; 12801e04c3fSmrg } 1293464ebd5Sriastradh case PROGRAM_SYSTEM_VALUE: 13001e04c3fSmrg assert(reg < (GLint) ARRAY_SIZE(machine->SystemValues)); 1313464ebd5Sriastradh return machine->SystemValues[reg]; 1323464ebd5Sriastradh 1333464ebd5Sriastradh default: 1343464ebd5Sriastradh _mesa_problem(NULL, 1353464ebd5Sriastradh "Invalid src register file %d in get_src_register_pointer()", 1363464ebd5Sriastradh source->File); 137af69d88dSmrg return ZeroVec; 1383464ebd5Sriastradh } 1393464ebd5Sriastradh} 1403464ebd5Sriastradh 1413464ebd5Sriastradh 1423464ebd5Sriastradh/** 1433464ebd5Sriastradh * Return a pointer to the 4-element float vector specified by the given 1443464ebd5Sriastradh * destination register. 1453464ebd5Sriastradh */ 146af69d88dSmrgstatic inline GLfloat * 1473464ebd5Sriastradhget_dst_register_pointer(const struct prog_dst_register *dest, 1483464ebd5Sriastradh struct gl_program_machine *machine) 1493464ebd5Sriastradh{ 1503464ebd5Sriastradh static GLfloat dummyReg[4]; 1513464ebd5Sriastradh GLint reg = dest->Index; 1523464ebd5Sriastradh 1533464ebd5Sriastradh if (dest->RelAddr) { 1543464ebd5Sriastradh /* add address register value to src index/offset */ 1553464ebd5Sriastradh reg += machine->AddressReg[0][0]; 1563464ebd5Sriastradh if (reg < 0) { 1573464ebd5Sriastradh return dummyReg; 1583464ebd5Sriastradh } 1593464ebd5Sriastradh } 1603464ebd5Sriastradh 1613464ebd5Sriastradh switch (dest->File) { 1623464ebd5Sriastradh case PROGRAM_TEMPORARY: 1633464ebd5Sriastradh if (reg >= MAX_PROGRAM_TEMPS) 1643464ebd5Sriastradh return dummyReg; 1653464ebd5Sriastradh return machine->Temporaries[reg]; 1663464ebd5Sriastradh 1673464ebd5Sriastradh case PROGRAM_OUTPUT: 1683464ebd5Sriastradh if (reg >= MAX_PROGRAM_OUTPUTS) 1693464ebd5Sriastradh return dummyReg; 1703464ebd5Sriastradh return machine->Outputs[reg]; 1713464ebd5Sriastradh 1723464ebd5Sriastradh default: 1733464ebd5Sriastradh _mesa_problem(NULL, 1743464ebd5Sriastradh "Invalid dest register file %d in get_dst_register_pointer()", 1753464ebd5Sriastradh dest->File); 176af69d88dSmrg return dummyReg; 1773464ebd5Sriastradh } 1783464ebd5Sriastradh} 1793464ebd5Sriastradh 1803464ebd5Sriastradh 1813464ebd5Sriastradh 1823464ebd5Sriastradh/** 1833464ebd5Sriastradh * Fetch a 4-element float vector from the given source register. 1843464ebd5Sriastradh * Apply swizzling and negating as needed. 1853464ebd5Sriastradh */ 1863464ebd5Sriastradhstatic void 1873464ebd5Sriastradhfetch_vector4(const struct prog_src_register *source, 1883464ebd5Sriastradh const struct gl_program_machine *machine, GLfloat result[4]) 1893464ebd5Sriastradh{ 1903464ebd5Sriastradh const GLfloat *src = get_src_register_pointer(source, machine); 1913464ebd5Sriastradh 1923464ebd5Sriastradh if (source->Swizzle == SWIZZLE_NOOP) { 1933464ebd5Sriastradh /* no swizzling */ 1943464ebd5Sriastradh COPY_4V(result, src); 1953464ebd5Sriastradh } 1963464ebd5Sriastradh else { 19701e04c3fSmrg assert(GET_SWZ(source->Swizzle, 0) <= 3); 19801e04c3fSmrg assert(GET_SWZ(source->Swizzle, 1) <= 3); 19901e04c3fSmrg assert(GET_SWZ(source->Swizzle, 2) <= 3); 20001e04c3fSmrg assert(GET_SWZ(source->Swizzle, 3) <= 3); 2013464ebd5Sriastradh result[0] = src[GET_SWZ(source->Swizzle, 0)]; 2023464ebd5Sriastradh result[1] = src[GET_SWZ(source->Swizzle, 1)]; 2033464ebd5Sriastradh result[2] = src[GET_SWZ(source->Swizzle, 2)]; 2043464ebd5Sriastradh result[3] = src[GET_SWZ(source->Swizzle, 3)]; 2053464ebd5Sriastradh } 2063464ebd5Sriastradh 2073464ebd5Sriastradh if (source->Negate) { 20801e04c3fSmrg assert(source->Negate == NEGATE_XYZW); 2093464ebd5Sriastradh result[0] = -result[0]; 2103464ebd5Sriastradh result[1] = -result[1]; 2113464ebd5Sriastradh result[2] = -result[2]; 2123464ebd5Sriastradh result[3] = -result[3]; 2133464ebd5Sriastradh } 2143464ebd5Sriastradh 2153464ebd5Sriastradh#ifdef NAN_CHECK 2167ec681f3Smrg assert(!util_is_inf_or_nan(result[0])); 2177ec681f3Smrg assert(!util_is_inf_or_nan(result[0])); 2187ec681f3Smrg assert(!util_is_inf_or_nan(result[0])); 2197ec681f3Smrg assert(!util_is_inf_or_nan(result[0])); 2203464ebd5Sriastradh#endif 2213464ebd5Sriastradh} 2223464ebd5Sriastradh 2233464ebd5Sriastradh 2243464ebd5Sriastradh/** 2253464ebd5Sriastradh * Fetch the derivative with respect to X or Y for the given register. 2263464ebd5Sriastradh * XXX this currently only works for fragment program input attribs. 2273464ebd5Sriastradh */ 2283464ebd5Sriastradhstatic void 22901e04c3fSmrgfetch_vector4_deriv(const struct prog_src_register *source, 2303464ebd5Sriastradh const struct gl_program_machine *machine, 2313464ebd5Sriastradh char xOrY, GLfloat result[4]) 2323464ebd5Sriastradh{ 2333464ebd5Sriastradh if (source->File == PROGRAM_INPUT && 2343464ebd5Sriastradh source->Index < (GLint) machine->NumDeriv) { 2353464ebd5Sriastradh const GLint col = machine->CurElement; 236af69d88dSmrg const GLfloat w = machine->Attribs[VARYING_SLOT_POS][col][3]; 2373464ebd5Sriastradh const GLfloat invQ = 1.0f / w; 2383464ebd5Sriastradh GLfloat deriv[4]; 2393464ebd5Sriastradh 2403464ebd5Sriastradh if (xOrY == 'X') { 2413464ebd5Sriastradh deriv[0] = machine->DerivX[source->Index][0] * invQ; 2423464ebd5Sriastradh deriv[1] = machine->DerivX[source->Index][1] * invQ; 2433464ebd5Sriastradh deriv[2] = machine->DerivX[source->Index][2] * invQ; 2443464ebd5Sriastradh deriv[3] = machine->DerivX[source->Index][3] * invQ; 2453464ebd5Sriastradh } 2463464ebd5Sriastradh else { 2473464ebd5Sriastradh deriv[0] = machine->DerivY[source->Index][0] * invQ; 2483464ebd5Sriastradh deriv[1] = machine->DerivY[source->Index][1] * invQ; 2493464ebd5Sriastradh deriv[2] = machine->DerivY[source->Index][2] * invQ; 2503464ebd5Sriastradh deriv[3] = machine->DerivY[source->Index][3] * invQ; 2513464ebd5Sriastradh } 2523464ebd5Sriastradh 2533464ebd5Sriastradh result[0] = deriv[GET_SWZ(source->Swizzle, 0)]; 2543464ebd5Sriastradh result[1] = deriv[GET_SWZ(source->Swizzle, 1)]; 2553464ebd5Sriastradh result[2] = deriv[GET_SWZ(source->Swizzle, 2)]; 2563464ebd5Sriastradh result[3] = deriv[GET_SWZ(source->Swizzle, 3)]; 2573464ebd5Sriastradh 2583464ebd5Sriastradh if (source->Negate) { 25901e04c3fSmrg assert(source->Negate == NEGATE_XYZW); 2603464ebd5Sriastradh result[0] = -result[0]; 2613464ebd5Sriastradh result[1] = -result[1]; 2623464ebd5Sriastradh result[2] = -result[2]; 2633464ebd5Sriastradh result[3] = -result[3]; 2643464ebd5Sriastradh } 2653464ebd5Sriastradh } 2663464ebd5Sriastradh else { 2673464ebd5Sriastradh ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0); 2683464ebd5Sriastradh } 2693464ebd5Sriastradh} 2703464ebd5Sriastradh 2713464ebd5Sriastradh 2723464ebd5Sriastradh/** 2733464ebd5Sriastradh * As above, but only return result[0] element. 2743464ebd5Sriastradh */ 2753464ebd5Sriastradhstatic void 2763464ebd5Sriastradhfetch_vector1(const struct prog_src_register *source, 2773464ebd5Sriastradh const struct gl_program_machine *machine, GLfloat result[4]) 2783464ebd5Sriastradh{ 2793464ebd5Sriastradh const GLfloat *src = get_src_register_pointer(source, machine); 2803464ebd5Sriastradh 2813464ebd5Sriastradh result[0] = src[GET_SWZ(source->Swizzle, 0)]; 2823464ebd5Sriastradh 2833464ebd5Sriastradh if (source->Negate) { 2843464ebd5Sriastradh result[0] = -result[0]; 2853464ebd5Sriastradh } 2863464ebd5Sriastradh} 2873464ebd5Sriastradh 2883464ebd5Sriastradh 2893464ebd5Sriastradh/** 2903464ebd5Sriastradh * Fetch texel from texture. Use partial derivatives when possible. 2913464ebd5Sriastradh */ 292af69d88dSmrgstatic inline void 2933464ebd5Sriastradhfetch_texel(struct gl_context *ctx, 2943464ebd5Sriastradh const struct gl_program_machine *machine, 2953464ebd5Sriastradh const struct prog_instruction *inst, 2963464ebd5Sriastradh const GLfloat texcoord[4], GLfloat lodBias, 2973464ebd5Sriastradh GLfloat color[4]) 2983464ebd5Sriastradh{ 2993464ebd5Sriastradh const GLuint unit = machine->Samplers[inst->TexSrcUnit]; 3003464ebd5Sriastradh 3013464ebd5Sriastradh /* Note: we only have the right derivatives for fragment input attribs. 3023464ebd5Sriastradh */ 3033464ebd5Sriastradh if (machine->NumDeriv > 0 && 3043464ebd5Sriastradh inst->SrcReg[0].File == PROGRAM_INPUT && 305af69d88dSmrg inst->SrcReg[0].Index == VARYING_SLOT_TEX0 + inst->TexSrcUnit) { 3063464ebd5Sriastradh /* simple texture fetch for which we should have derivatives */ 3073464ebd5Sriastradh GLuint attr = inst->SrcReg[0].Index; 3083464ebd5Sriastradh machine->FetchTexelDeriv(ctx, texcoord, 3093464ebd5Sriastradh machine->DerivX[attr], 3103464ebd5Sriastradh machine->DerivY[attr], 3113464ebd5Sriastradh lodBias, unit, color); 3123464ebd5Sriastradh } 3133464ebd5Sriastradh else { 3143464ebd5Sriastradh machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color); 3153464ebd5Sriastradh } 3163464ebd5Sriastradh} 3173464ebd5Sriastradh 3183464ebd5Sriastradh 3193464ebd5Sriastradh/** 3203464ebd5Sriastradh * Store 4 floats into a register. Observe the instructions saturate and 3213464ebd5Sriastradh * set-condition-code flags. 3223464ebd5Sriastradh */ 3233464ebd5Sriastradhstatic void 3243464ebd5Sriastradhstore_vector4(const struct prog_instruction *inst, 3253464ebd5Sriastradh struct gl_program_machine *machine, const GLfloat value[4]) 3263464ebd5Sriastradh{ 3273464ebd5Sriastradh const struct prog_dst_register *dstReg = &(inst->DstReg); 32801e04c3fSmrg const GLboolean clamp = inst->Saturate; 3293464ebd5Sriastradh GLuint writeMask = dstReg->WriteMask; 3303464ebd5Sriastradh GLfloat clampedValue[4]; 3313464ebd5Sriastradh GLfloat *dst = get_dst_register_pointer(dstReg, machine); 3323464ebd5Sriastradh 3333464ebd5Sriastradh#if 0 3343464ebd5Sriastradh if (value[0] > 1.0e10 || 3357ec681f3Smrg util_is_inf_or_nan(value[0]) || 3367ec681f3Smrg util_is_inf_or_nan(value[1]) || 3377ec681f3Smrg util_is_inf_or_nan(value[2]) || util_is_inf_or_nan(value[3])) 3383464ebd5Sriastradh printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]); 3393464ebd5Sriastradh#endif 3403464ebd5Sriastradh 3413464ebd5Sriastradh if (clamp) { 3423464ebd5Sriastradh clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F); 3433464ebd5Sriastradh clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F); 3443464ebd5Sriastradh clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F); 3453464ebd5Sriastradh clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F); 3463464ebd5Sriastradh value = clampedValue; 3473464ebd5Sriastradh } 3483464ebd5Sriastradh 3493464ebd5Sriastradh#ifdef NAN_CHECK 3507ec681f3Smrg assert(!util_is_inf_or_nan(value[0])); 3517ec681f3Smrg assert(!util_is_inf_or_nan(value[0])); 3527ec681f3Smrg assert(!util_is_inf_or_nan(value[0])); 3537ec681f3Smrg assert(!util_is_inf_or_nan(value[0])); 3543464ebd5Sriastradh#endif 3553464ebd5Sriastradh 3563464ebd5Sriastradh if (writeMask & WRITEMASK_X) 3573464ebd5Sriastradh dst[0] = value[0]; 3583464ebd5Sriastradh if (writeMask & WRITEMASK_Y) 3593464ebd5Sriastradh dst[1] = value[1]; 3603464ebd5Sriastradh if (writeMask & WRITEMASK_Z) 3613464ebd5Sriastradh dst[2] = value[2]; 3623464ebd5Sriastradh if (writeMask & WRITEMASK_W) 3633464ebd5Sriastradh dst[3] = value[3]; 3643464ebd5Sriastradh} 3653464ebd5Sriastradh 3663464ebd5Sriastradh 3673464ebd5Sriastradh/** 3683464ebd5Sriastradh * Execute the given vertex/fragment program. 3693464ebd5Sriastradh * 3703464ebd5Sriastradh * \param ctx rendering context 3713464ebd5Sriastradh * \param program the program to execute 3723464ebd5Sriastradh * \param machine machine state (must be initialized) 3733464ebd5Sriastradh * \return GL_TRUE if program completed or GL_FALSE if program executed KIL. 3743464ebd5Sriastradh */ 3753464ebd5SriastradhGLboolean 3763464ebd5Sriastradh_mesa_execute_program(struct gl_context * ctx, 3773464ebd5Sriastradh const struct gl_program *program, 3783464ebd5Sriastradh struct gl_program_machine *machine) 3793464ebd5Sriastradh{ 38001e04c3fSmrg const GLuint numInst = program->arb.NumInstructions; 381af69d88dSmrg const GLuint maxExec = 65536; 3823464ebd5Sriastradh GLuint pc, numExec = 0; 3833464ebd5Sriastradh 3843464ebd5Sriastradh machine->CurProgram = program; 3853464ebd5Sriastradh 3863464ebd5Sriastradh if (DEBUG_PROG) { 3873464ebd5Sriastradh printf("execute program %u --------------------\n", program->Id); 3883464ebd5Sriastradh } 3893464ebd5Sriastradh 3903464ebd5Sriastradh if (program->Target == GL_VERTEX_PROGRAM_ARB) { 3913464ebd5Sriastradh machine->EnvParams = ctx->VertexProgram.Parameters; 3923464ebd5Sriastradh } 3933464ebd5Sriastradh else { 3943464ebd5Sriastradh machine->EnvParams = ctx->FragmentProgram.Parameters; 3953464ebd5Sriastradh } 3963464ebd5Sriastradh 3973464ebd5Sriastradh for (pc = 0; pc < numInst; pc++) { 39801e04c3fSmrg const struct prog_instruction *inst = program->arb.Instructions + pc; 3993464ebd5Sriastradh 4003464ebd5Sriastradh if (DEBUG_PROG) { 4013464ebd5Sriastradh _mesa_print_instruction(inst); 4023464ebd5Sriastradh } 4033464ebd5Sriastradh 4043464ebd5Sriastradh switch (inst->Opcode) { 4053464ebd5Sriastradh case OPCODE_ABS: 4063464ebd5Sriastradh { 4073464ebd5Sriastradh GLfloat a[4], result[4]; 4083464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 40901e04c3fSmrg result[0] = fabsf(a[0]); 41001e04c3fSmrg result[1] = fabsf(a[1]); 41101e04c3fSmrg result[2] = fabsf(a[2]); 41201e04c3fSmrg result[3] = fabsf(a[3]); 4133464ebd5Sriastradh store_vector4(inst, machine, result); 4143464ebd5Sriastradh } 4153464ebd5Sriastradh break; 4163464ebd5Sriastradh case OPCODE_ADD: 4173464ebd5Sriastradh { 4183464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 4193464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 4203464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 4213464ebd5Sriastradh result[0] = a[0] + b[0]; 4223464ebd5Sriastradh result[1] = a[1] + b[1]; 4233464ebd5Sriastradh result[2] = a[2] + b[2]; 4243464ebd5Sriastradh result[3] = a[3] + b[3]; 4253464ebd5Sriastradh store_vector4(inst, machine, result); 4263464ebd5Sriastradh if (DEBUG_PROG) { 4273464ebd5Sriastradh printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n", 4283464ebd5Sriastradh result[0], result[1], result[2], result[3], 4293464ebd5Sriastradh a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); 4303464ebd5Sriastradh } 4313464ebd5Sriastradh } 4323464ebd5Sriastradh break; 4333464ebd5Sriastradh case OPCODE_ARL: 4343464ebd5Sriastradh { 4353464ebd5Sriastradh GLfloat t[4]; 4363464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, t); 4377ec681f3Smrg machine->AddressReg[0][0] = util_ifloor(t[0]); 4383464ebd5Sriastradh if (DEBUG_PROG) { 4393464ebd5Sriastradh printf("ARL %d\n", machine->AddressReg[0][0]); 4403464ebd5Sriastradh } 4413464ebd5Sriastradh } 4423464ebd5Sriastradh break; 4433464ebd5Sriastradh case OPCODE_BGNLOOP: 4443464ebd5Sriastradh /* no-op */ 44501e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 4463464ebd5Sriastradh == OPCODE_ENDLOOP); 4473464ebd5Sriastradh break; 4483464ebd5Sriastradh case OPCODE_ENDLOOP: 4493464ebd5Sriastradh /* subtract 1 here since pc is incremented by for(pc) loop */ 45001e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 4513464ebd5Sriastradh == OPCODE_BGNLOOP); 4523464ebd5Sriastradh pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */ 4533464ebd5Sriastradh break; 4543464ebd5Sriastradh case OPCODE_BGNSUB: /* begin subroutine */ 4553464ebd5Sriastradh break; 4563464ebd5Sriastradh case OPCODE_ENDSUB: /* end subroutine */ 4573464ebd5Sriastradh break; 4583464ebd5Sriastradh case OPCODE_BRK: /* break out of loop (conditional) */ 45901e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 4603464ebd5Sriastradh == OPCODE_ENDLOOP); 46101e04c3fSmrg /* break out of loop */ 46201e04c3fSmrg /* pc++ at end of for-loop will put us after the ENDLOOP inst */ 46301e04c3fSmrg pc = inst->BranchTarget; 4643464ebd5Sriastradh break; 4653464ebd5Sriastradh case OPCODE_CONT: /* continue loop (conditional) */ 46601e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 4673464ebd5Sriastradh == OPCODE_ENDLOOP); 46801e04c3fSmrg /* continue at ENDLOOP */ 46901e04c3fSmrg /* Subtract 1 here since we'll do pc++ at end of for-loop */ 47001e04c3fSmrg pc = inst->BranchTarget - 1; 4713464ebd5Sriastradh break; 4723464ebd5Sriastradh case OPCODE_CAL: /* Call subroutine (conditional) */ 47301e04c3fSmrg /* call the subroutine */ 47401e04c3fSmrg if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) { 47501e04c3fSmrg return GL_TRUE; /* Per GL_NV_vertex_program2 spec */ 4763464ebd5Sriastradh } 47701e04c3fSmrg machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */ 47801e04c3fSmrg /* Subtract 1 here since we'll do pc++ at end of for-loop */ 47901e04c3fSmrg pc = inst->BranchTarget - 1; 4803464ebd5Sriastradh break; 4813464ebd5Sriastradh case OPCODE_CMP: 4823464ebd5Sriastradh { 4833464ebd5Sriastradh GLfloat a[4], b[4], c[4], result[4]; 4843464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 4853464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 4863464ebd5Sriastradh fetch_vector4(&inst->SrcReg[2], machine, c); 4873464ebd5Sriastradh result[0] = a[0] < 0.0F ? b[0] : c[0]; 4883464ebd5Sriastradh result[1] = a[1] < 0.0F ? b[1] : c[1]; 4893464ebd5Sriastradh result[2] = a[2] < 0.0F ? b[2] : c[2]; 4903464ebd5Sriastradh result[3] = a[3] < 0.0F ? b[3] : c[3]; 4913464ebd5Sriastradh store_vector4(inst, machine, result); 4923464ebd5Sriastradh if (DEBUG_PROG) { 4933464ebd5Sriastradh printf("CMP (%g %g %g %g) = (%g %g %g %g) < 0 ? (%g %g %g %g) : (%g %g %g %g)\n", 4943464ebd5Sriastradh result[0], result[1], result[2], result[3], 4953464ebd5Sriastradh a[0], a[1], a[2], a[3], 4963464ebd5Sriastradh b[0], b[1], b[2], b[3], 4973464ebd5Sriastradh c[0], c[1], c[2], c[3]); 4983464ebd5Sriastradh } 4993464ebd5Sriastradh } 5003464ebd5Sriastradh break; 5013464ebd5Sriastradh case OPCODE_COS: 5023464ebd5Sriastradh { 5033464ebd5Sriastradh GLfloat a[4], result[4]; 5043464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 5053464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] 50601e04c3fSmrg = cosf(a[0]); 5073464ebd5Sriastradh store_vector4(inst, machine, result); 5083464ebd5Sriastradh } 5093464ebd5Sriastradh break; 5103464ebd5Sriastradh case OPCODE_DDX: /* Partial derivative with respect to X */ 5113464ebd5Sriastradh { 5123464ebd5Sriastradh GLfloat result[4]; 51301e04c3fSmrg fetch_vector4_deriv(&inst->SrcReg[0], machine, 'X', result); 5143464ebd5Sriastradh store_vector4(inst, machine, result); 5153464ebd5Sriastradh } 5163464ebd5Sriastradh break; 5173464ebd5Sriastradh case OPCODE_DDY: /* Partial derivative with respect to Y */ 5183464ebd5Sriastradh { 5193464ebd5Sriastradh GLfloat result[4]; 52001e04c3fSmrg fetch_vector4_deriv(&inst->SrcReg[0], machine, 'Y', result); 5213464ebd5Sriastradh store_vector4(inst, machine, result); 5223464ebd5Sriastradh } 5233464ebd5Sriastradh break; 5243464ebd5Sriastradh case OPCODE_DP2: 5253464ebd5Sriastradh { 5263464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 5273464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 5283464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 5293464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = DOT2(a, b); 5303464ebd5Sriastradh store_vector4(inst, machine, result); 5313464ebd5Sriastradh if (DEBUG_PROG) { 5323464ebd5Sriastradh printf("DP2 %g = (%g %g) . (%g %g)\n", 5333464ebd5Sriastradh result[0], a[0], a[1], b[0], b[1]); 5343464ebd5Sriastradh } 5353464ebd5Sriastradh } 5363464ebd5Sriastradh break; 5373464ebd5Sriastradh case OPCODE_DP3: 5383464ebd5Sriastradh { 5393464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 5403464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 5413464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 5423464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = DOT3(a, b); 5433464ebd5Sriastradh store_vector4(inst, machine, result); 5443464ebd5Sriastradh if (DEBUG_PROG) { 5453464ebd5Sriastradh printf("DP3 %g = (%g %g %g) . (%g %g %g)\n", 5463464ebd5Sriastradh result[0], a[0], a[1], a[2], b[0], b[1], b[2]); 5473464ebd5Sriastradh } 5483464ebd5Sriastradh } 5493464ebd5Sriastradh break; 5503464ebd5Sriastradh case OPCODE_DP4: 5513464ebd5Sriastradh { 5523464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 5533464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 5543464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 5553464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = DOT4(a, b); 5563464ebd5Sriastradh store_vector4(inst, machine, result); 5573464ebd5Sriastradh if (DEBUG_PROG) { 5583464ebd5Sriastradh printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n", 5593464ebd5Sriastradh result[0], a[0], a[1], a[2], a[3], 5603464ebd5Sriastradh b[0], b[1], b[2], b[3]); 5613464ebd5Sriastradh } 5623464ebd5Sriastradh } 5633464ebd5Sriastradh break; 5643464ebd5Sriastradh case OPCODE_DPH: 5653464ebd5Sriastradh { 5663464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 5673464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 5683464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 5693464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = DOT3(a, b) + b[3]; 5703464ebd5Sriastradh store_vector4(inst, machine, result); 5713464ebd5Sriastradh } 5723464ebd5Sriastradh break; 5733464ebd5Sriastradh case OPCODE_DST: /* Distance vector */ 5743464ebd5Sriastradh { 5753464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 5763464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 5773464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 5783464ebd5Sriastradh result[0] = 1.0F; 5793464ebd5Sriastradh result[1] = a[1] * b[1]; 5803464ebd5Sriastradh result[2] = a[2]; 5813464ebd5Sriastradh result[3] = b[3]; 5823464ebd5Sriastradh store_vector4(inst, machine, result); 5833464ebd5Sriastradh } 5843464ebd5Sriastradh break; 5853464ebd5Sriastradh case OPCODE_EXP: 5863464ebd5Sriastradh { 5873464ebd5Sriastradh GLfloat t[4], q[4], floor_t0; 5883464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, t); 58901e04c3fSmrg floor_t0 = floorf(t[0]); 5903464ebd5Sriastradh if (floor_t0 > FLT_MAX_EXP) { 5913464ebd5Sriastradh SET_POS_INFINITY(q[0]); 5923464ebd5Sriastradh SET_POS_INFINITY(q[2]); 5933464ebd5Sriastradh } 5943464ebd5Sriastradh else if (floor_t0 < FLT_MIN_EXP) { 5953464ebd5Sriastradh q[0] = 0.0F; 5963464ebd5Sriastradh q[2] = 0.0F; 5973464ebd5Sriastradh } 5983464ebd5Sriastradh else { 59901e04c3fSmrg q[0] = ldexpf(1.0, (int) floor_t0); 6003464ebd5Sriastradh /* Note: GL_NV_vertex_program expects 6013464ebd5Sriastradh * result.z = result.x * APPX(result.y) 6023464ebd5Sriastradh * We do what the ARB extension says. 6033464ebd5Sriastradh */ 60401e04c3fSmrg q[2] = exp2f(t[0]); 6053464ebd5Sriastradh } 6063464ebd5Sriastradh q[1] = t[0] - floor_t0; 6073464ebd5Sriastradh q[3] = 1.0F; 6083464ebd5Sriastradh store_vector4( inst, machine, q ); 6093464ebd5Sriastradh } 6103464ebd5Sriastradh break; 6113464ebd5Sriastradh case OPCODE_EX2: /* Exponential base 2 */ 6123464ebd5Sriastradh { 6133464ebd5Sriastradh GLfloat a[4], result[4], val; 6143464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 61501e04c3fSmrg val = exp2f(a[0]); 6163464ebd5Sriastradh /* 6177ec681f3Smrg if (util_is_inf_or_nan(val)) 6183464ebd5Sriastradh val = 1.0e10; 6193464ebd5Sriastradh */ 6203464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = val; 6213464ebd5Sriastradh store_vector4(inst, machine, result); 6223464ebd5Sriastradh } 6233464ebd5Sriastradh break; 6243464ebd5Sriastradh case OPCODE_FLR: 6253464ebd5Sriastradh { 6263464ebd5Sriastradh GLfloat a[4], result[4]; 6273464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 62801e04c3fSmrg result[0] = floorf(a[0]); 62901e04c3fSmrg result[1] = floorf(a[1]); 63001e04c3fSmrg result[2] = floorf(a[2]); 63101e04c3fSmrg result[3] = floorf(a[3]); 6323464ebd5Sriastradh store_vector4(inst, machine, result); 6333464ebd5Sriastradh } 6343464ebd5Sriastradh break; 6353464ebd5Sriastradh case OPCODE_FRC: 6363464ebd5Sriastradh { 6373464ebd5Sriastradh GLfloat a[4], result[4]; 6383464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 63901e04c3fSmrg result[0] = a[0] - floorf(a[0]); 64001e04c3fSmrg result[1] = a[1] - floorf(a[1]); 64101e04c3fSmrg result[2] = a[2] - floorf(a[2]); 64201e04c3fSmrg result[3] = a[3] - floorf(a[3]); 6433464ebd5Sriastradh store_vector4(inst, machine, result); 6443464ebd5Sriastradh } 6453464ebd5Sriastradh break; 6463464ebd5Sriastradh case OPCODE_IF: 6473464ebd5Sriastradh { 6483464ebd5Sriastradh GLboolean cond; 64901e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 6503464ebd5Sriastradh == OPCODE_ELSE || 65101e04c3fSmrg program->arb.Instructions[inst->BranchTarget].Opcode 6523464ebd5Sriastradh == OPCODE_ENDIF); 6533464ebd5Sriastradh /* eval condition */ 65401e04c3fSmrg GLfloat a[4]; 65501e04c3fSmrg fetch_vector1(&inst->SrcReg[0], machine, a); 65601e04c3fSmrg cond = (a[0] != 0.0F); 6573464ebd5Sriastradh if (DEBUG_PROG) { 6583464ebd5Sriastradh printf("IF: %d\n", cond); 6593464ebd5Sriastradh } 6603464ebd5Sriastradh /* do if/else */ 6613464ebd5Sriastradh if (cond) { 6623464ebd5Sriastradh /* do if-clause (just continue execution) */ 6633464ebd5Sriastradh } 6643464ebd5Sriastradh else { 6653464ebd5Sriastradh /* go to the instruction after ELSE or ENDIF */ 6663464ebd5Sriastradh assert(inst->BranchTarget >= 0); 6673464ebd5Sriastradh pc = inst->BranchTarget; 6683464ebd5Sriastradh } 6693464ebd5Sriastradh } 6703464ebd5Sriastradh break; 6713464ebd5Sriastradh case OPCODE_ELSE: 6723464ebd5Sriastradh /* goto ENDIF */ 67301e04c3fSmrg assert(program->arb.Instructions[inst->BranchTarget].Opcode 6743464ebd5Sriastradh == OPCODE_ENDIF); 6753464ebd5Sriastradh assert(inst->BranchTarget >= 0); 6763464ebd5Sriastradh pc = inst->BranchTarget; 6773464ebd5Sriastradh break; 6783464ebd5Sriastradh case OPCODE_ENDIF: 6793464ebd5Sriastradh /* nothing */ 6803464ebd5Sriastradh break; 6813464ebd5Sriastradh case OPCODE_KIL: /* ARB_f_p only */ 6823464ebd5Sriastradh { 6833464ebd5Sriastradh GLfloat a[4]; 6843464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 6853464ebd5Sriastradh if (DEBUG_PROG) { 6863464ebd5Sriastradh printf("KIL if (%g %g %g %g) <= 0.0\n", 6873464ebd5Sriastradh a[0], a[1], a[2], a[3]); 6883464ebd5Sriastradh } 6893464ebd5Sriastradh 6903464ebd5Sriastradh if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) { 6913464ebd5Sriastradh return GL_FALSE; 6923464ebd5Sriastradh } 6933464ebd5Sriastradh } 6943464ebd5Sriastradh break; 6953464ebd5Sriastradh case OPCODE_LG2: /* log base 2 */ 6963464ebd5Sriastradh { 6973464ebd5Sriastradh GLfloat a[4], result[4], val; 6983464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 6993464ebd5Sriastradh /* The fast LOG2 macro doesn't meet the precision requirements. 7003464ebd5Sriastradh */ 7013464ebd5Sriastradh if (a[0] == 0.0F) { 7023464ebd5Sriastradh val = -FLT_MAX; 7033464ebd5Sriastradh } 7043464ebd5Sriastradh else { 70501e04c3fSmrg val = logf(a[0]) * 1.442695F; 7063464ebd5Sriastradh } 7073464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = val; 7083464ebd5Sriastradh store_vector4(inst, machine, result); 7093464ebd5Sriastradh } 7103464ebd5Sriastradh break; 7113464ebd5Sriastradh case OPCODE_LIT: 7123464ebd5Sriastradh { 7133464ebd5Sriastradh const GLfloat epsilon = 1.0F / 256.0F; /* from NV VP spec */ 7143464ebd5Sriastradh GLfloat a[4], result[4]; 7153464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 7163464ebd5Sriastradh a[0] = MAX2(a[0], 0.0F); 7173464ebd5Sriastradh a[1] = MAX2(a[1], 0.0F); 7183464ebd5Sriastradh /* XXX ARB version clamps a[3], NV version doesn't */ 7193464ebd5Sriastradh a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon)); 7203464ebd5Sriastradh result[0] = 1.0F; 7213464ebd5Sriastradh result[1] = a[0]; 7223464ebd5Sriastradh /* XXX we could probably just use pow() here */ 7233464ebd5Sriastradh if (a[0] > 0.0F) { 72401e04c3fSmrg if (a[1] == 0.0F && a[3] == 0.0F) 7253464ebd5Sriastradh result[2] = 1.0F; 7263464ebd5Sriastradh else 72701e04c3fSmrg result[2] = powf(a[1], a[3]); 7283464ebd5Sriastradh } 7293464ebd5Sriastradh else { 7303464ebd5Sriastradh result[2] = 0.0F; 7313464ebd5Sriastradh } 7323464ebd5Sriastradh result[3] = 1.0F; 7333464ebd5Sriastradh store_vector4(inst, machine, result); 7343464ebd5Sriastradh if (DEBUG_PROG) { 7353464ebd5Sriastradh printf("LIT (%g %g %g %g) : (%g %g %g %g)\n", 7363464ebd5Sriastradh result[0], result[1], result[2], result[3], 7373464ebd5Sriastradh a[0], a[1], a[2], a[3]); 7383464ebd5Sriastradh } 7393464ebd5Sriastradh } 7403464ebd5Sriastradh break; 7413464ebd5Sriastradh case OPCODE_LOG: 7423464ebd5Sriastradh { 7433464ebd5Sriastradh GLfloat t[4], q[4], abs_t0; 7443464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, t); 74501e04c3fSmrg abs_t0 = fabsf(t[0]); 7463464ebd5Sriastradh if (abs_t0 != 0.0F) { 7477ec681f3Smrg if (util_is_inf_or_nan(abs_t0)) 7483464ebd5Sriastradh { 7493464ebd5Sriastradh SET_POS_INFINITY(q[0]); 7503464ebd5Sriastradh q[1] = 1.0F; 7513464ebd5Sriastradh SET_POS_INFINITY(q[2]); 7523464ebd5Sriastradh } 7533464ebd5Sriastradh else { 7543464ebd5Sriastradh int exponent; 75501e04c3fSmrg GLfloat mantissa = frexpf(t[0], &exponent); 7563464ebd5Sriastradh q[0] = (GLfloat) (exponent - 1); 75701e04c3fSmrg q[1] = 2.0F * mantissa; /* map [.5, 1) -> [1, 2) */ 7583464ebd5Sriastradh 7593464ebd5Sriastradh /* The fast LOG2 macro doesn't meet the precision 7603464ebd5Sriastradh * requirements. 7613464ebd5Sriastradh */ 76201e04c3fSmrg q[2] = logf(t[0]) * 1.442695F; 7633464ebd5Sriastradh } 7643464ebd5Sriastradh } 7653464ebd5Sriastradh else { 7663464ebd5Sriastradh SET_NEG_INFINITY(q[0]); 7673464ebd5Sriastradh q[1] = 1.0F; 7683464ebd5Sriastradh SET_NEG_INFINITY(q[2]); 7693464ebd5Sriastradh } 7703464ebd5Sriastradh q[3] = 1.0; 7713464ebd5Sriastradh store_vector4(inst, machine, q); 7723464ebd5Sriastradh } 7733464ebd5Sriastradh break; 7743464ebd5Sriastradh case OPCODE_LRP: 7753464ebd5Sriastradh { 7763464ebd5Sriastradh GLfloat a[4], b[4], c[4], result[4]; 7773464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 7783464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 7793464ebd5Sriastradh fetch_vector4(&inst->SrcReg[2], machine, c); 7803464ebd5Sriastradh result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0]; 7813464ebd5Sriastradh result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1]; 7823464ebd5Sriastradh result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2]; 7833464ebd5Sriastradh result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3]; 7843464ebd5Sriastradh store_vector4(inst, machine, result); 7853464ebd5Sriastradh if (DEBUG_PROG) { 7863464ebd5Sriastradh printf("LRP (%g %g %g %g) = (%g %g %g %g), " 7873464ebd5Sriastradh "(%g %g %g %g), (%g %g %g %g)\n", 7883464ebd5Sriastradh result[0], result[1], result[2], result[3], 7893464ebd5Sriastradh a[0], a[1], a[2], a[3], 7903464ebd5Sriastradh b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]); 7913464ebd5Sriastradh } 7923464ebd5Sriastradh } 7933464ebd5Sriastradh break; 7943464ebd5Sriastradh case OPCODE_MAD: 7953464ebd5Sriastradh { 7963464ebd5Sriastradh GLfloat a[4], b[4], c[4], result[4]; 7973464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 7983464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 7993464ebd5Sriastradh fetch_vector4(&inst->SrcReg[2], machine, c); 8003464ebd5Sriastradh result[0] = a[0] * b[0] + c[0]; 8013464ebd5Sriastradh result[1] = a[1] * b[1] + c[1]; 8023464ebd5Sriastradh result[2] = a[2] * b[2] + c[2]; 8033464ebd5Sriastradh result[3] = a[3] * b[3] + c[3]; 8043464ebd5Sriastradh store_vector4(inst, machine, result); 8053464ebd5Sriastradh if (DEBUG_PROG) { 8063464ebd5Sriastradh printf("MAD (%g %g %g %g) = (%g %g %g %g) * " 8073464ebd5Sriastradh "(%g %g %g %g) + (%g %g %g %g)\n", 8083464ebd5Sriastradh result[0], result[1], result[2], result[3], 8093464ebd5Sriastradh a[0], a[1], a[2], a[3], 8103464ebd5Sriastradh b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]); 8113464ebd5Sriastradh } 8123464ebd5Sriastradh } 8133464ebd5Sriastradh break; 8143464ebd5Sriastradh case OPCODE_MAX: 8153464ebd5Sriastradh { 8163464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 8173464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 8183464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 8193464ebd5Sriastradh result[0] = MAX2(a[0], b[0]); 8203464ebd5Sriastradh result[1] = MAX2(a[1], b[1]); 8213464ebd5Sriastradh result[2] = MAX2(a[2], b[2]); 8223464ebd5Sriastradh result[3] = MAX2(a[3], b[3]); 8233464ebd5Sriastradh store_vector4(inst, machine, result); 8243464ebd5Sriastradh if (DEBUG_PROG) { 8253464ebd5Sriastradh printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n", 8263464ebd5Sriastradh result[0], result[1], result[2], result[3], 8273464ebd5Sriastradh a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); 8283464ebd5Sriastradh } 8293464ebd5Sriastradh } 8303464ebd5Sriastradh break; 8313464ebd5Sriastradh case OPCODE_MIN: 8323464ebd5Sriastradh { 8333464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 8343464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 8353464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 8363464ebd5Sriastradh result[0] = MIN2(a[0], b[0]); 8373464ebd5Sriastradh result[1] = MIN2(a[1], b[1]); 8383464ebd5Sriastradh result[2] = MIN2(a[2], b[2]); 8393464ebd5Sriastradh result[3] = MIN2(a[3], b[3]); 8403464ebd5Sriastradh store_vector4(inst, machine, result); 8413464ebd5Sriastradh } 8423464ebd5Sriastradh break; 8433464ebd5Sriastradh case OPCODE_MOV: 8443464ebd5Sriastradh { 8453464ebd5Sriastradh GLfloat result[4]; 8463464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, result); 8473464ebd5Sriastradh store_vector4(inst, machine, result); 8483464ebd5Sriastradh if (DEBUG_PROG) { 8493464ebd5Sriastradh printf("MOV (%g %g %g %g)\n", 8503464ebd5Sriastradh result[0], result[1], result[2], result[3]); 8513464ebd5Sriastradh } 8523464ebd5Sriastradh } 8533464ebd5Sriastradh break; 8543464ebd5Sriastradh case OPCODE_MUL: 8553464ebd5Sriastradh { 8563464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 8573464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 8583464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 8593464ebd5Sriastradh result[0] = a[0] * b[0]; 8603464ebd5Sriastradh result[1] = a[1] * b[1]; 8613464ebd5Sriastradh result[2] = a[2] * b[2]; 8623464ebd5Sriastradh result[3] = a[3] * b[3]; 8633464ebd5Sriastradh store_vector4(inst, machine, result); 8643464ebd5Sriastradh if (DEBUG_PROG) { 8653464ebd5Sriastradh printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n", 8663464ebd5Sriastradh result[0], result[1], result[2], result[3], 8673464ebd5Sriastradh a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); 8683464ebd5Sriastradh } 8693464ebd5Sriastradh } 8703464ebd5Sriastradh break; 8713464ebd5Sriastradh case OPCODE_NOISE1: 8723464ebd5Sriastradh { 8733464ebd5Sriastradh GLfloat a[4], result[4]; 8743464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 8753464ebd5Sriastradh result[0] = 8763464ebd5Sriastradh result[1] = 8773464ebd5Sriastradh result[2] = 8783464ebd5Sriastradh result[3] = _mesa_noise1(a[0]); 8793464ebd5Sriastradh store_vector4(inst, machine, result); 8803464ebd5Sriastradh } 8813464ebd5Sriastradh break; 8823464ebd5Sriastradh case OPCODE_NOISE2: 8833464ebd5Sriastradh { 8843464ebd5Sriastradh GLfloat a[4], result[4]; 8853464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 8863464ebd5Sriastradh result[0] = 8873464ebd5Sriastradh result[1] = 8883464ebd5Sriastradh result[2] = result[3] = _mesa_noise2(a[0], a[1]); 8893464ebd5Sriastradh store_vector4(inst, machine, result); 8903464ebd5Sriastradh } 8913464ebd5Sriastradh break; 8923464ebd5Sriastradh case OPCODE_NOISE3: 8933464ebd5Sriastradh { 8943464ebd5Sriastradh GLfloat a[4], result[4]; 8953464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 8963464ebd5Sriastradh result[0] = 8973464ebd5Sriastradh result[1] = 8983464ebd5Sriastradh result[2] = 8993464ebd5Sriastradh result[3] = _mesa_noise3(a[0], a[1], a[2]); 9003464ebd5Sriastradh store_vector4(inst, machine, result); 9013464ebd5Sriastradh } 9023464ebd5Sriastradh break; 9033464ebd5Sriastradh case OPCODE_NOISE4: 9043464ebd5Sriastradh { 9053464ebd5Sriastradh GLfloat a[4], result[4]; 9063464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 9073464ebd5Sriastradh result[0] = 9083464ebd5Sriastradh result[1] = 9093464ebd5Sriastradh result[2] = 9103464ebd5Sriastradh result[3] = _mesa_noise4(a[0], a[1], a[2], a[3]); 9113464ebd5Sriastradh store_vector4(inst, machine, result); 9123464ebd5Sriastradh } 9133464ebd5Sriastradh break; 9143464ebd5Sriastradh case OPCODE_NOP: 9153464ebd5Sriastradh break; 9163464ebd5Sriastradh case OPCODE_POW: 9173464ebd5Sriastradh { 9183464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 9193464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 9203464ebd5Sriastradh fetch_vector1(&inst->SrcReg[1], machine, b); 9213464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] 92201e04c3fSmrg = powf(a[0], b[0]); 9233464ebd5Sriastradh store_vector4(inst, machine, result); 9243464ebd5Sriastradh } 9253464ebd5Sriastradh break; 9263464ebd5Sriastradh 9273464ebd5Sriastradh case OPCODE_RCP: 9283464ebd5Sriastradh { 9293464ebd5Sriastradh GLfloat a[4], result[4]; 9303464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 9313464ebd5Sriastradh if (DEBUG_PROG) { 9323464ebd5Sriastradh if (a[0] == 0) 9333464ebd5Sriastradh printf("RCP(0)\n"); 9347ec681f3Smrg else if (util_is_inf_or_nan(a[0])) 9353464ebd5Sriastradh printf("RCP(inf)\n"); 9363464ebd5Sriastradh } 9373464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] = 1.0F / a[0]; 9383464ebd5Sriastradh store_vector4(inst, machine, result); 9393464ebd5Sriastradh } 9403464ebd5Sriastradh break; 9413464ebd5Sriastradh case OPCODE_RET: /* return from subroutine (conditional) */ 94201e04c3fSmrg if (machine->StackDepth == 0) { 94301e04c3fSmrg return GL_TRUE; /* Per GL_NV_vertex_program2 spec */ 9443464ebd5Sriastradh } 94501e04c3fSmrg /* subtract one because of pc++ in the for loop */ 94601e04c3fSmrg pc = machine->CallStack[--machine->StackDepth] - 1; 9473464ebd5Sriastradh break; 9483464ebd5Sriastradh case OPCODE_RSQ: /* 1 / sqrt() */ 9493464ebd5Sriastradh { 9503464ebd5Sriastradh GLfloat a[4], result[4]; 9513464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 95201e04c3fSmrg a[0] = fabsf(a[0]); 95301e04c3fSmrg result[0] = result[1] = result[2] = result[3] = 1.0f / sqrtf(a[0]); 9543464ebd5Sriastradh store_vector4(inst, machine, result); 9553464ebd5Sriastradh if (DEBUG_PROG) { 9563464ebd5Sriastradh printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]); 9573464ebd5Sriastradh } 9583464ebd5Sriastradh } 9593464ebd5Sriastradh break; 9603464ebd5Sriastradh case OPCODE_SCS: /* sine and cos */ 9613464ebd5Sriastradh { 9623464ebd5Sriastradh GLfloat a[4], result[4]; 9633464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 96401e04c3fSmrg result[0] = cosf(a[0]); 96501e04c3fSmrg result[1] = sinf(a[0]); 96601e04c3fSmrg result[2] = 0.0F; /* undefined! */ 96701e04c3fSmrg result[3] = 0.0F; /* undefined! */ 9683464ebd5Sriastradh store_vector4(inst, machine, result); 9693464ebd5Sriastradh } 9703464ebd5Sriastradh break; 9713464ebd5Sriastradh case OPCODE_SGE: /* set on greater or equal */ 9723464ebd5Sriastradh { 9733464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 9743464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 9753464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 9763464ebd5Sriastradh result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F; 9773464ebd5Sriastradh result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F; 9783464ebd5Sriastradh result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F; 9793464ebd5Sriastradh result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F; 9803464ebd5Sriastradh store_vector4(inst, machine, result); 9813464ebd5Sriastradh if (DEBUG_PROG) { 9823464ebd5Sriastradh printf("SGE (%g %g %g %g) = (%g %g %g %g) >= (%g %g %g %g)\n", 9833464ebd5Sriastradh result[0], result[1], result[2], result[3], 9843464ebd5Sriastradh a[0], a[1], a[2], a[3], 9853464ebd5Sriastradh b[0], b[1], b[2], b[3]); 9863464ebd5Sriastradh } 9873464ebd5Sriastradh } 9883464ebd5Sriastradh break; 9893464ebd5Sriastradh case OPCODE_SIN: 9903464ebd5Sriastradh { 9913464ebd5Sriastradh GLfloat a[4], result[4]; 9923464ebd5Sriastradh fetch_vector1(&inst->SrcReg[0], machine, a); 9933464ebd5Sriastradh result[0] = result[1] = result[2] = result[3] 99401e04c3fSmrg = sinf(a[0]); 9953464ebd5Sriastradh store_vector4(inst, machine, result); 9963464ebd5Sriastradh } 9973464ebd5Sriastradh break; 9983464ebd5Sriastradh case OPCODE_SLT: /* set on less */ 9993464ebd5Sriastradh { 10003464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 10013464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 10023464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 10033464ebd5Sriastradh result[0] = (a[0] < b[0]) ? 1.0F : 0.0F; 10043464ebd5Sriastradh result[1] = (a[1] < b[1]) ? 1.0F : 0.0F; 10053464ebd5Sriastradh result[2] = (a[2] < b[2]) ? 1.0F : 0.0F; 10063464ebd5Sriastradh result[3] = (a[3] < b[3]) ? 1.0F : 0.0F; 10073464ebd5Sriastradh store_vector4(inst, machine, result); 10083464ebd5Sriastradh if (DEBUG_PROG) { 10093464ebd5Sriastradh printf("SLT (%g %g %g %g) = (%g %g %g %g) < (%g %g %g %g)\n", 10103464ebd5Sriastradh result[0], result[1], result[2], result[3], 10113464ebd5Sriastradh a[0], a[1], a[2], a[3], 10123464ebd5Sriastradh b[0], b[1], b[2], b[3]); 10133464ebd5Sriastradh } 10143464ebd5Sriastradh } 10153464ebd5Sriastradh break; 10163464ebd5Sriastradh case OPCODE_SSG: /* set sign (-1, 0 or +1) */ 10173464ebd5Sriastradh { 10183464ebd5Sriastradh GLfloat a[4], result[4]; 10193464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 10203464ebd5Sriastradh result[0] = (GLfloat) ((a[0] > 0.0F) - (a[0] < 0.0F)); 10213464ebd5Sriastradh result[1] = (GLfloat) ((a[1] > 0.0F) - (a[1] < 0.0F)); 10223464ebd5Sriastradh result[2] = (GLfloat) ((a[2] > 0.0F) - (a[2] < 0.0F)); 10233464ebd5Sriastradh result[3] = (GLfloat) ((a[3] > 0.0F) - (a[3] < 0.0F)); 10243464ebd5Sriastradh store_vector4(inst, machine, result); 10253464ebd5Sriastradh } 10263464ebd5Sriastradh break; 10273464ebd5Sriastradh case OPCODE_SUB: 10283464ebd5Sriastradh { 10293464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 10303464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 10313464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 10323464ebd5Sriastradh result[0] = a[0] - b[0]; 10333464ebd5Sriastradh result[1] = a[1] - b[1]; 10343464ebd5Sriastradh result[2] = a[2] - b[2]; 10353464ebd5Sriastradh result[3] = a[3] - b[3]; 10363464ebd5Sriastradh store_vector4(inst, machine, result); 10373464ebd5Sriastradh if (DEBUG_PROG) { 10383464ebd5Sriastradh printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n", 10393464ebd5Sriastradh result[0], result[1], result[2], result[3], 10403464ebd5Sriastradh a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); 10413464ebd5Sriastradh } 10423464ebd5Sriastradh } 10433464ebd5Sriastradh break; 10443464ebd5Sriastradh case OPCODE_SWZ: /* extended swizzle */ 10453464ebd5Sriastradh { 10463464ebd5Sriastradh const struct prog_src_register *source = &inst->SrcReg[0]; 10473464ebd5Sriastradh const GLfloat *src = get_src_register_pointer(source, machine); 10483464ebd5Sriastradh GLfloat result[4]; 10493464ebd5Sriastradh GLuint i; 10503464ebd5Sriastradh for (i = 0; i < 4; i++) { 10513464ebd5Sriastradh const GLuint swz = GET_SWZ(source->Swizzle, i); 10523464ebd5Sriastradh if (swz == SWIZZLE_ZERO) 10533464ebd5Sriastradh result[i] = 0.0; 10543464ebd5Sriastradh else if (swz == SWIZZLE_ONE) 10553464ebd5Sriastradh result[i] = 1.0; 10563464ebd5Sriastradh else { 105701e04c3fSmrg assert(swz <= 3); 10583464ebd5Sriastradh result[i] = src[swz]; 10593464ebd5Sriastradh } 10603464ebd5Sriastradh if (source->Negate & (1 << i)) 10613464ebd5Sriastradh result[i] = -result[i]; 10623464ebd5Sriastradh } 10633464ebd5Sriastradh store_vector4(inst, machine, result); 10643464ebd5Sriastradh } 10653464ebd5Sriastradh break; 10663464ebd5Sriastradh case OPCODE_TEX: /* Both ARB and NV frag prog */ 10673464ebd5Sriastradh /* Simple texel lookup */ 10683464ebd5Sriastradh { 10693464ebd5Sriastradh GLfloat texcoord[4], color[4]; 10703464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, texcoord); 10713464ebd5Sriastradh 1072af69d88dSmrg /* For TEX, texcoord.Q should not be used and its value should not 1073af69d88dSmrg * matter (at most, we pass coord.xyz to texture3D() in GLSL). 1074af69d88dSmrg * Set Q=1 so that FetchTexelDeriv() doesn't get a garbage value 1075af69d88dSmrg * which is effectively what happens when the texcoord swizzle 1076af69d88dSmrg * is .xyzz 1077af69d88dSmrg */ 1078af69d88dSmrg texcoord[3] = 1.0f; 1079af69d88dSmrg 10803464ebd5Sriastradh fetch_texel(ctx, machine, inst, texcoord, 0.0, color); 10813464ebd5Sriastradh 10823464ebd5Sriastradh if (DEBUG_PROG) { 10833464ebd5Sriastradh printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g]\n", 10843464ebd5Sriastradh color[0], color[1], color[2], color[3], 10853464ebd5Sriastradh inst->TexSrcUnit, 10863464ebd5Sriastradh texcoord[0], texcoord[1], texcoord[2], texcoord[3]); 10873464ebd5Sriastradh } 10883464ebd5Sriastradh store_vector4(inst, machine, color); 10893464ebd5Sriastradh } 10903464ebd5Sriastradh break; 10913464ebd5Sriastradh case OPCODE_TXB: /* GL_ARB_fragment_program only */ 10923464ebd5Sriastradh /* Texel lookup with LOD bias */ 10933464ebd5Sriastradh { 10943464ebd5Sriastradh GLfloat texcoord[4], color[4], lodBias; 10953464ebd5Sriastradh 10963464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, texcoord); 10973464ebd5Sriastradh 10983464ebd5Sriastradh /* texcoord[3] is the bias to add to lambda */ 10993464ebd5Sriastradh lodBias = texcoord[3]; 11003464ebd5Sriastradh 11013464ebd5Sriastradh fetch_texel(ctx, machine, inst, texcoord, lodBias, color); 11023464ebd5Sriastradh 11033464ebd5Sriastradh if (DEBUG_PROG) { 11043464ebd5Sriastradh printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]" 11053464ebd5Sriastradh " bias %g\n", 11063464ebd5Sriastradh color[0], color[1], color[2], color[3], 11073464ebd5Sriastradh inst->TexSrcUnit, 11083464ebd5Sriastradh texcoord[0], 11093464ebd5Sriastradh texcoord[1], 11103464ebd5Sriastradh texcoord[2], 11113464ebd5Sriastradh texcoord[3], 11123464ebd5Sriastradh lodBias); 11133464ebd5Sriastradh } 11143464ebd5Sriastradh 11153464ebd5Sriastradh store_vector4(inst, machine, color); 11163464ebd5Sriastradh } 11173464ebd5Sriastradh break; 111801e04c3fSmrg case OPCODE_TXD: 11193464ebd5Sriastradh /* Texture lookup w/ partial derivatives for LOD */ 11203464ebd5Sriastradh { 11213464ebd5Sriastradh GLfloat texcoord[4], dtdx[4], dtdy[4], color[4]; 11223464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, texcoord); 11233464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, dtdx); 11243464ebd5Sriastradh fetch_vector4(&inst->SrcReg[2], machine, dtdy); 11253464ebd5Sriastradh machine->FetchTexelDeriv(ctx, texcoord, dtdx, dtdy, 11263464ebd5Sriastradh 0.0, /* lodBias */ 11273464ebd5Sriastradh inst->TexSrcUnit, color); 11283464ebd5Sriastradh store_vector4(inst, machine, color); 11293464ebd5Sriastradh } 11303464ebd5Sriastradh break; 11313464ebd5Sriastradh case OPCODE_TXL: 11323464ebd5Sriastradh /* Texel lookup with explicit LOD */ 11333464ebd5Sriastradh { 11343464ebd5Sriastradh GLfloat texcoord[4], color[4], lod; 11353464ebd5Sriastradh 11363464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, texcoord); 11373464ebd5Sriastradh 11383464ebd5Sriastradh /* texcoord[3] is the LOD */ 11393464ebd5Sriastradh lod = texcoord[3]; 11403464ebd5Sriastradh 11413464ebd5Sriastradh machine->FetchTexelLod(ctx, texcoord, lod, 11423464ebd5Sriastradh machine->Samplers[inst->TexSrcUnit], color); 11433464ebd5Sriastradh 11443464ebd5Sriastradh store_vector4(inst, machine, color); 11453464ebd5Sriastradh } 11463464ebd5Sriastradh break; 11473464ebd5Sriastradh case OPCODE_TXP: /* GL_ARB_fragment_program only */ 11483464ebd5Sriastradh /* Texture lookup w/ projective divide */ 11493464ebd5Sriastradh { 11503464ebd5Sriastradh GLfloat texcoord[4], color[4]; 11513464ebd5Sriastradh 11523464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, texcoord); 11533464ebd5Sriastradh /* Not so sure about this test - if texcoord[3] is 115401e04c3fSmrg * zero, we'd probably be fine except for an assert in 11553464ebd5Sriastradh * IROUND_POS() which gets triggered by the inf values created. 11563464ebd5Sriastradh */ 115701e04c3fSmrg if (texcoord[3] != 0.0F) { 11583464ebd5Sriastradh texcoord[0] /= texcoord[3]; 11593464ebd5Sriastradh texcoord[1] /= texcoord[3]; 11603464ebd5Sriastradh texcoord[2] /= texcoord[3]; 11613464ebd5Sriastradh } 11623464ebd5Sriastradh 11633464ebd5Sriastradh fetch_texel(ctx, machine, inst, texcoord, 0.0, color); 11643464ebd5Sriastradh 11653464ebd5Sriastradh store_vector4(inst, machine, color); 11663464ebd5Sriastradh } 11673464ebd5Sriastradh break; 11683464ebd5Sriastradh case OPCODE_TRUNC: /* truncate toward zero */ 11693464ebd5Sriastradh { 11703464ebd5Sriastradh GLfloat a[4], result[4]; 11713464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 11723464ebd5Sriastradh result[0] = (GLfloat) (GLint) a[0]; 11733464ebd5Sriastradh result[1] = (GLfloat) (GLint) a[1]; 11743464ebd5Sriastradh result[2] = (GLfloat) (GLint) a[2]; 11753464ebd5Sriastradh result[3] = (GLfloat) (GLint) a[3]; 11763464ebd5Sriastradh store_vector4(inst, machine, result); 11773464ebd5Sriastradh } 11783464ebd5Sriastradh break; 11793464ebd5Sriastradh case OPCODE_XPD: /* cross product */ 11803464ebd5Sriastradh { 11813464ebd5Sriastradh GLfloat a[4], b[4], result[4]; 11823464ebd5Sriastradh fetch_vector4(&inst->SrcReg[0], machine, a); 11833464ebd5Sriastradh fetch_vector4(&inst->SrcReg[1], machine, b); 11843464ebd5Sriastradh result[0] = a[1] * b[2] - a[2] * b[1]; 11853464ebd5Sriastradh result[1] = a[2] * b[0] - a[0] * b[2]; 11863464ebd5Sriastradh result[2] = a[0] * b[1] - a[1] * b[0]; 11873464ebd5Sriastradh result[3] = 1.0; 11883464ebd5Sriastradh store_vector4(inst, machine, result); 11893464ebd5Sriastradh if (DEBUG_PROG) { 11903464ebd5Sriastradh printf("XPD (%g %g %g %g) = (%g %g %g) X (%g %g %g)\n", 11913464ebd5Sriastradh result[0], result[1], result[2], result[3], 11923464ebd5Sriastradh a[0], a[1], a[2], b[0], b[1], b[2]); 11933464ebd5Sriastradh } 11943464ebd5Sriastradh } 11953464ebd5Sriastradh break; 11963464ebd5Sriastradh case OPCODE_END: 11973464ebd5Sriastradh return GL_TRUE; 11983464ebd5Sriastradh default: 11993464ebd5Sriastradh _mesa_problem(ctx, "Bad opcode %d in _mesa_execute_program", 12003464ebd5Sriastradh inst->Opcode); 12013464ebd5Sriastradh return GL_TRUE; /* return value doesn't matter */ 12023464ebd5Sriastradh } 12033464ebd5Sriastradh 12043464ebd5Sriastradh numExec++; 12053464ebd5Sriastradh if (numExec > maxExec) { 12063464ebd5Sriastradh static GLboolean reported = GL_FALSE; 12073464ebd5Sriastradh if (!reported) { 12083464ebd5Sriastradh _mesa_problem(ctx, "Infinite loop detected in fragment program"); 12093464ebd5Sriastradh reported = GL_TRUE; 12103464ebd5Sriastradh } 12113464ebd5Sriastradh return GL_TRUE; 12123464ebd5Sriastradh } 12133464ebd5Sriastradh 12143464ebd5Sriastradh } /* for pc */ 12153464ebd5Sriastradh 12163464ebd5Sriastradh return GL_TRUE; 12173464ebd5Sriastradh} 1218