Consolidate _swrast_write_texture_span() into _swrast_write_rgba_span().
[mesa.git] / src / mesa / swrast / s_nvfragprog.c
index 127cc4f0b4de50d157916ffbb03de097d3c1d9f1..5d9979c5c62d6a36eecb749d7799eec6b28eb947 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.3
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -120,6 +120,11 @@ get_register_pointer( GLcontext *ctx,
          ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
          src = machine->Inputs[source->Index];
          break;
+      case PROGRAM_OUTPUT:
+         /* This is only for PRINT */
+         ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
+         src = machine->Outputs[source->Index];
+         break;
       case PROGRAM_LOCAL_PARAM:
          ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
          src = program->Base.LocalParams[source->Index];
@@ -128,10 +133,8 @@ get_register_pointer( GLcontext *ctx,
          ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_PARAMS);
          src = ctx->FragmentProgram.Parameters[source->Index];
          break;
-
       case PROGRAM_STATE_VAR:
-                       /* Fallthrough */
-
+         /* Fallthrough */
       case PROGRAM_NAMED_PARAM:
          ASSERT(source->Index < (GLint) program->Parameters->NumParameters);
          src = program->Parameters->Parameters[source->Index].Values;
@@ -342,7 +345,7 @@ fetch_vector1( GLcontext *ctx,
 }
 
 
-/*
+/**
  * Test value against zero and return GT, LT, EQ or UN if NaN.
  */
 static INLINE GLuint
@@ -357,7 +360,8 @@ generate_cc( float value )
    return COND_EQ;
 }
 
-/*
+
+/**
  * Test if the ccMaskRule is satisfied by the given condition code.
  * Used to mask destination writes according to the current condition codee.
  */
@@ -391,6 +395,7 @@ store_vector4( const struct fp_instruction *inst,
    const GLboolean clamp = inst->Saturate;
    const GLboolean updateCC = inst->UpdateCondRegister;
    GLfloat *dstReg;
+   GLfloat dummyReg[4];
    GLfloat clampedValue[4];
    const GLboolean *writeMask = dest->WriteMask;
    GLboolean condWriteMask[4];
@@ -402,6 +407,9 @@ store_vector4( const struct fp_instruction *inst,
       case PROGRAM_TEMPORARY:
          dstReg = machine->Temporaries[dest->Index];
          break;
+      case PROGRAM_WRITE_ONLY:
+         dstReg = dummyReg;
+         return;
       default:
          _mesa_problem(NULL, "bad register file in store_vector4(fp)");
          return;
@@ -478,9 +486,11 @@ init_machine_deriv( GLcontext *ctx,
    /* copy existing machine */
    _mesa_memcpy(dMachine, machine, sizeof(struct fp_machine));
 
-   /* Clear temporary registers */
-   _mesa_bzero( (void*) machine->Temporaries,
-               MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
+   if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
+      /* Clear temporary registers (undefined for ARB_f_p) */
+      _mesa_bzero( (void*) machine->Temporaries,
+                   MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
+   }
 
    /* Add derivatives */
    if (program->InputsRead & (1 << FRAG_ATTRIB_WPOS)) {
@@ -708,6 +718,10 @@ execute_program( GLcontext *ctx,
                result[0] = result[1] = result[2] = result[3] = 
                   a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
                store_vector4( inst, machine, result );
+#if DEBUG_FRAG
+               printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
+                      result[0], a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+#endif
             }
             break;
          case FP_OPCODE_DPH:
@@ -763,7 +777,7 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
-         case FP_OPCODE_KIL:
+         case FP_OPCODE_KIL_NV: /* NV_f_p only */
             {
                const GLuint *swizzle = inst->DstReg.CondSwizzle;
                const GLuint condMask = inst->DstReg.CondMask;
@@ -775,6 +789,15 @@ execute_program( GLcontext *ctx,
                }
             }
             break;
+         case FP_OPCODE_KIL: /* ARB_f_p only */
+            {
+               GLfloat a[4];
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
+               if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
+                  return GL_FALSE;
+               }
+            }
+            break;
          case FP_OPCODE_LG2:  /* log base 2 */
             {
                GLfloat a[4], result[4];
@@ -786,14 +809,16 @@ execute_program( GLcontext *ctx,
             break;
          case FP_OPCODE_LIT:
             {
+               const GLfloat epsilon = 1.0F / 256.0F; /* from NV VP spec */
                GLfloat a[4], result[4];
                fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
-               if (a[0] < 0.0F)
-                  a[0] = 0.0F;
-               if (a[1] < 0.0F)
-                  a[1] = 0.0F;
+               a[0] = MAX2(a[0], 0.0F);
+               a[1] = MAX2(a[1], 0.0F);
+               /* XXX ARB version clamps a[3], NV version doesn't */
+               a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon));
                result[0] = 1.0F;
                result[1] = a[0];
+               /* XXX we could probably just use pow() here */
                result[2] = (a[0] > 0.0F) ? (GLfloat) exp(a[3] * log(a[1])) : 0.0F;
                result[3] = 1.0F;
                store_vector4( inst, machine, result );
@@ -835,6 +860,12 @@ execute_program( GLcontext *ctx,
                result[2] = MAX2(a[2], b[2]);
                result[3] = MAX2(a[3], b[3]);
                store_vector4( inst, machine, result );
+#if DEBUG_FRAG
+               printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
+                      result[0], result[1], result[2], result[3], 
+                      a[0], a[1], a[2], a[3],
+                      b[0], b[1], b[2], b[3]);
+#endif
             }
             break;
          case FP_OPCODE_MIN:
@@ -854,6 +885,10 @@ execute_program( GLcontext *ctx,
                GLfloat result[4];
                fetch_vector4( ctx, &inst->SrcReg[0], machine, program, result );
                store_vector4( inst, machine, result );
+#if DEBUG_FRAG
+               printf("MOV (%g %g %g %g)\n",
+                      result[0], result[1], result[2], result[3]);
+#endif
             }
             break;
          case FP_OPCODE_MUL:
@@ -1131,19 +1166,19 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
-         case FP_OPCODE_TEX:
+         case FP_OPCODE_TEX: /* Both ARB and NV frag prog */
             /* Texel lookup */
             {
                GLfloat texcoord[4], color[4];
                fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
-               /* XXX: Undo perspective divide from interpolate_texcoords() */
-               fetch_texel( ctx, texcoord,
-                            span->array->lambda[inst->TexSrcUnit][column],
-                            inst->TexSrcUnit, color );
+               /* Note: we pass 0 for LOD.  The ARB extension requires it
+                * while the NV extension says it's implementation dependant.
+                */
+               fetch_texel( ctx, texcoord, 0.0F, inst->TexSrcUnit, color );
                store_vector4( inst, machine, color );
             }
             break;
-         case FP_OPCODE_TXB:
+         case FP_OPCODE_TXB: /* GL_ARB_fragment_program only */
             /* Texel lookup with LOD bias */
             {
                GLfloat texcoord[4], color[4], bias, lambda;
@@ -1159,7 +1194,7 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, color );
             }
             break;
-         case FP_OPCODE_TXD:
+         case FP_OPCODE_TXD: /* GL_NV_fragment_program only */
             /* Texture lookup w/ partial derivatives for LOD */
             {
                GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
@@ -1171,12 +1206,29 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, color );
             }
             break;
-         case FP_OPCODE_TXP:
-            /* Texture lookup w/ perspective divide */
+         case FP_OPCODE_TXP: /* GL_ARB_fragment_program only */
+            /* Texture lookup w/ projective divide */
+            {
+               GLfloat texcoord[4], color[4];
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
+               texcoord[0] /= texcoord[3];
+               texcoord[1] /= texcoord[3];
+               texcoord[2] /= texcoord[3];
+               /* Note: LOD=0 */
+               fetch_texel( ctx, texcoord, 0.0F, inst->TexSrcUnit, color );
+               store_vector4( inst, machine, color );
+            }
+            break;
+         case FP_OPCODE_TXP_NV: /* GL_NV_fragment_program only */
+            /* Texture lookup w/ projective divide */
             {
                GLfloat texcoord[4], color[4];
                fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
-               /* Already did perspective divide in interpolate_texcoords() */
+               if (inst->TexSrcBit != TEXTURE_CUBE_BIT) {
+                  texcoord[0] /= texcoord[3];
+                  texcoord[1] /= texcoord[3];
+                  texcoord[2] /= texcoord[3];
+               }
                fetch_texel( ctx, texcoord,
                             span->array->lambda[inst->TexSrcUnit][column],
                             inst->TexSrcUnit, color );
@@ -1215,9 +1267,9 @@ execute_program( GLcontext *ctx,
                const GLuint *rawBits = (const GLuint *) a;
                fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
                result[0] = (((rawBits[0] >>  0) & 0xff) - 128) / 127.0F;
-               result[0] = (((rawBits[0] >>  8) & 0xff) - 128) / 127.0F;
-               result[0] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F;
-               result[0] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F;
+               result[1] = (((rawBits[0] >>  8) & 0xff) - 128) / 127.0F;
+               result[2] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F;
+               result[3] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F;
                store_vector4( inst, machine, result );
             }
             break;
@@ -1227,9 +1279,9 @@ execute_program( GLcontext *ctx,
                const GLuint *rawBits = (const GLuint *) a;
                fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
                result[0] = ((rawBits[0] >>  0) & 0xff) / 255.0F;
-               result[0] = ((rawBits[0] >>  8) & 0xff) / 255.0F;
-               result[0] = ((rawBits[0] >> 16) & 0xff) / 255.0F;
-               result[0] = ((rawBits[0] >> 24) & 0xff) / 255.0F;
+               result[1] = ((rawBits[0] >>  8) & 0xff) / 255.0F;
+               result[2] = ((rawBits[0] >> 16) & 0xff) / 255.0F;
+               result[3] = ((rawBits[0] >> 24) & 0xff) / 255.0F;
                store_vector4( inst, machine, result );
             }
             break;
@@ -1258,6 +1310,19 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
+         case FP_OPCODE_PRINT:
+            {
+               if (inst->SrcReg[0].File != -1) {
+                  GLfloat a[4];
+                  fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
+                  _mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
+                               a[0], a[1], a[2], a[3]);
+               }
+               else {
+                  _mesa_printf("%s\n", (const char *) inst->Data);
+               }
+            }
+            break;
          case FP_OPCODE_END:
             return GL_TRUE;
          default:
@@ -1281,9 +1346,11 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
    if (ctx->FragmentProgram.CallbackEnabled)
       inputsRead = ~0;
 
-   /* Clear temporary registers */
-   _mesa_bzero(machine->Temporaries,
-               MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
+   if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
+      /* Clear temporary registers (undefined for ARB_f_p) */
+      _mesa_bzero(machine->Temporaries,
+                  MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
+   }
 
    /* Load input registers */
    if (inputsRead & (1 << FRAG_ATTRIB_WPOS)) {
@@ -1348,10 +1415,18 @@ _swrast_exec_fragment_program( GLcontext *ctx, struct sw_span *span )
          init_machine(ctx, &ctx->FragmentProgram.Machine,
                       ctx->FragmentProgram.Current, span, i);
 
+#ifdef USE_TCC
+         if (!_swrast_execute_codegen_program(ctx, program, ~0,
+                                             &ctx->FragmentProgram.Machine,
+                                             span, i)) {
+            span->array->mask[i] = GL_FALSE;  /* killed fragment */
+         }
+#else
          if (!execute_program(ctx, program, ~0,
                               &ctx->FragmentProgram.Machine, span, i)) {
             span->array->mask[i] = GL_FALSE;  /* killed fragment */
          }
+#endif
 
          /* Store output registers */
          {