mesa: call _mesa_compute_version() to set context's version info
[mesa.git] / src / mesa / shader / prog_execute.c
index 0bc8d5f6a79a5f115f8c1fe5c2305c25ddf81000..7f034520cd474ff967af35748107074fdfc3f15c 100644 (file)
  * Set x to positive or negative infinity.
  */
 #if defined(USE_IEEE) || defined(_WIN32)
-#define SET_POS_INFINITY(x)  ( *((GLuint *) (void *)&x) = 0x7F800000 )
-#define SET_NEG_INFINITY(x)  ( *((GLuint *) (void *)&x) = 0xFF800000 )
+#define SET_POS_INFINITY(x)                  \
+   do {                                      \
+         fi_type fi;                         \
+         fi.i = 0x7F800000;                  \
+         x = fi.f;                           \
+   } while (0)
+#define SET_NEG_INFINITY(x)                  \
+   do {                                      \
+         fi_type fi;                         \
+         fi.i = 0xFF800000;                  \
+         x = fi.f;                           \
+   } while (0)
 #elif defined(VMS)
 #define SET_POS_INFINITY(x)  x = __MAXFLOAT
 #define SET_NEG_INFINITY(x)  x = -__MAXFLOAT
@@ -212,24 +222,26 @@ fetch_vector4(const struct prog_src_register *source,
       result[3] = src[GET_SWZ(source->Swizzle, 3)];
    }
 
-   if (source->NegateBase) {
-      result[0] = -result[0];
-      result[1] = -result[1];
-      result[2] = -result[2];
-      result[3] = -result[3];
-   }
    if (source->Abs) {
       result[0] = FABSF(result[0]);
       result[1] = FABSF(result[1]);
       result[2] = FABSF(result[2]);
       result[3] = FABSF(result[3]);
    }
-   if (source->NegateAbs) {
+   if (source->Negate) {
+      ASSERT(source->Negate == NEGATE_XYZW);
       result[0] = -result[0];
       result[1] = -result[1];
       result[2] = -result[2];
       result[3] = -result[3];
    }
+
+#ifdef NAN_CHECK
+   assert(!IS_INF_OR_NAN(result[0]));
+   assert(!IS_INF_OR_NAN(result[0]));
+   assert(!IS_INF_OR_NAN(result[0]));
+   assert(!IS_INF_OR_NAN(result[0]));
+#endif
 }
 
 
@@ -259,7 +271,7 @@ fetch_vector4ui(const struct prog_src_register *source,
       result[3] = src[GET_SWZ(source->Swizzle, 3)];
    }
 
-   /* Note: no NegateBase, Abs, NegateAbs here */
+   /* Note: no Negate or Abs here */
 }
 
 
@@ -299,19 +311,14 @@ fetch_vector4_deriv(GLcontext * ctx,
       result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
       result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
       
-      if (source->NegateBase) {
-         result[0] = -result[0];
-         result[1] = -result[1];
-         result[2] = -result[2];
-         result[3] = -result[3];
-      }
       if (source->Abs) {
          result[0] = FABSF(result[0]);
          result[1] = FABSF(result[1]);
          result[2] = FABSF(result[2]);
          result[3] = FABSF(result[3]);
       }
-      if (source->NegateAbs) {
+      if (source->Negate) {
+         ASSERT(source->Negate == NEGATE_XYZW);
          result[0] = -result[0];
          result[1] = -result[1];
          result[2] = -result[2];
@@ -336,13 +343,10 @@ fetch_vector1(const struct prog_src_register *source,
 
    result[0] = src[GET_SWZ(source->Swizzle, 0)];
 
-   if (source->NegateBase) {
-      result[0] = -result[0];
-   }
    if (source->Abs) {
       result[0] = FABSF(result[0]);
    }
-   if (source->NegateAbs) {
+   if (source->Negate) {
       result[0] = -result[0];
    }
 }
@@ -492,6 +496,13 @@ store_vector4(const struct prog_instruction *inst,
       }
    }
 
+#ifdef NAN_CHECK
+   assert(!IS_INF_OR_NAN(value[0]));
+   assert(!IS_INF_OR_NAN(value[0]));
+   assert(!IS_INF_OR_NAN(value[0]));
+   assert(!IS_INF_OR_NAN(value[0]));
+#endif
+
    if (writeMask & WRITEMASK_X)
       dst[0] = value[0];
    if (writeMask & WRITEMASK_Y)
@@ -673,9 +684,13 @@ _mesa_execute_program(GLcontext * ctx,
          break;
       case OPCODE_BGNLOOP:
          /* no-op */
+         ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                == OPCODE_ENDLOOP);
          break;
       case OPCODE_ENDLOOP:
          /* subtract 1 here since pc is incremented by for(pc) loop */
+         ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                == OPCODE_BGNLOOP);
          pc = inst->BranchTarget - 1;   /* go to matching BNGLOOP */
          break;
       case OPCODE_BGNSUB:      /* begin subroutine */
@@ -683,12 +698,26 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_ENDSUB:      /* end subroutine */
          break;
       case OPCODE_BRA:         /* branch (conditional) */
-         /* fall-through */
+         if (eval_condition(machine, inst)) {
+            /* take branch */
+            /* Subtract 1 here since we'll do pc++ below */
+            pc = inst->BranchTarget - 1;
+         }
+         break;
       case OPCODE_BRK:         /* break out of loop (conditional) */
-         /* fall-through */
+         ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                == OPCODE_ENDLOOP);
+         if (eval_condition(machine, inst)) {
+            /* break out of loop */
+            /* pc++ at end of for-loop will put us after the ENDLOOP inst */
+            pc = inst->BranchTarget;
+         }
+         break;
       case OPCODE_CONT:        /* continue loop (conditional) */
+         ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                == OPCODE_ENDLOOP);
          if (eval_condition(machine, inst)) {
-            /* take branch */
+            /* continue at ENDLOOP */
             /* Subtract 1 here since we'll do pc++ at end of for-loop */
             pc = inst->BranchTarget - 1;
          }
@@ -836,7 +865,7 @@ _mesa_execute_program(GLcontext * ctx,
                 * result.z = result.x * APPX(result.y)
                 * We do what the ARB extension says.
                 */
-               q[2] = (GLfloat) pow(2.0, t[0]);
+               q[2] = (GLfloat) _mesa_pow(2.0, t[0]);
             }
             q[1] = t[0] - floor_t0;
             q[3] = 1.0F;
@@ -845,10 +874,14 @@ _mesa_execute_program(GLcontext * ctx,
          break;
       case OPCODE_EX2:         /* Exponential base 2 */
          {
-            GLfloat a[4], result[4];
+            GLfloat a[4], result[4], val;
             fetch_vector1(&inst->SrcReg[0], machine, a);
-            result[0] = result[1] = result[2] = result[3] =
-               (GLfloat) _mesa_pow(2.0, a[0]);
+            val = (GLfloat) _mesa_pow(2.0, a[0]);
+            /*
+            if (IS_INF_OR_NAN(val))
+               val = 1.0e10;
+            */
+            result[0] = result[1] = result[2] = result[3] = val;
             store_vector4(inst, machine, result);
          }
          break;
@@ -877,6 +910,10 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_IF:
          {
             GLboolean cond;
+            ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                   == OPCODE_ELSE ||
+                   program->Instructions[inst->BranchTarget].Opcode
+                   == OPCODE_ENDIF);
             /* eval condition */
             if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
                GLfloat a[4];
@@ -896,14 +933,16 @@ _mesa_execute_program(GLcontext * ctx,
             else {
                /* go to the instruction after ELSE or ENDIF */
                assert(inst->BranchTarget >= 0);
-               pc = inst->BranchTarget - 1;
+               pc = inst->BranchTarget;
             }
          }
          break;
       case OPCODE_ELSE:
          /* goto ENDIF */
+         ASSERT(program->Instructions[inst->BranchTarget].Opcode
+                == OPCODE_ENDIF);
          assert(inst->BranchTarget >= 0);
-         pc = inst->BranchTarget - 1;
+         pc = inst->BranchTarget;
          break;
       case OPCODE_ENDIF:
          /* nothing */
@@ -917,6 +956,11 @@ _mesa_execute_program(GLcontext * ctx,
          {
             GLfloat a[4];
             fetch_vector4(&inst->SrcReg[0], machine, a);
+            if (DEBUG_PROG) {
+               printf("KIL if (%g %g %g %g) <= 0.0\n",
+                      a[0], a[1], a[2], a[3]);
+            }
+
             if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
                return GL_FALSE;
             }
@@ -924,12 +968,17 @@ _mesa_execute_program(GLcontext * ctx,
          break;
       case OPCODE_LG2:         /* log base 2 */
          {
-            GLfloat a[4], result[4];
+            GLfloat a[4], result[4], val;
             fetch_vector1(&inst->SrcReg[0], machine, a);
            /* The fast LOG2 macro doesn't meet the precision requirements.
             */
-            result[0] = result[1] = result[2] = result[3] =
-               (log(a[0]) * 1.442695F);
+            if (a[0] == 0.0F) {
+               val = -FLT_MAX;
+            }
+            else {
+               val = log(a[0]) * 1.442695F;
+            }
+            result[0] = result[1] = result[2] = result[3] = val;
             store_vector4(inst, machine, result);
          }
          break;
@@ -949,7 +998,7 @@ _mesa_execute_program(GLcontext * ctx,
                if (a[1] == 0.0 && a[3] == 0.0)
                   result[2] = 1.0;
                else
-                  result[2] = EXPF(a[3] * LOGF(a[1]));
+                  result[2] = (GLfloat) _mesa_pow(a[1], a[3]);
             }
             else {
                result[2] = 0.0;
@@ -1514,7 +1563,7 @@ _mesa_execute_program(GLcontext * ctx,
                   ASSERT(swz <= 3);
                   result[i] = src[swz];
                }
-               if (source->NegateBase & (1 << i))
+               if (source->Negate & (1 << i))
                   result[i] = -result[i];
             }
             store_vector4(inst, machine, result);
@@ -1540,17 +1589,12 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_TXB:         /* GL_ARB_fragment_program only */
          /* Texel lookup with LOD bias */
          {
-            const GLuint unit = machine->Samplers[inst->TexSrcUnit];
-            const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
             GLfloat texcoord[4], color[4], lodBias;
 
             fetch_vector4(&inst->SrcReg[0], machine, texcoord);
 
             /* texcoord[3] is the bias to add to lambda */
-            lodBias = texUnit->LodBias + texcoord[3];
-            if (texUnit->_Current) {
-               lodBias += texUnit->_Current->LodBias;
-            }
+            lodBias = texcoord[3];
 
             fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
 
@@ -1625,11 +1669,12 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_UP2H:        /* unpack two 16-bit floats */
          {
             GLfloat a[4], result[4];
-            const GLuint *rawBits = (const GLuint *) a;
+            fi_type fi;
             GLhalfNV hx, hy;
             fetch_vector1(&inst->SrcReg[0], machine, a);
-            hx = rawBits[0] & 0xffff;
-            hy = rawBits[0] >> 16;
+            fi.f = a[0];
+            hx = fi.i & 0xffff;
+            hy = fi.i >> 16;
             result[0] = result[2] = _mesa_half_to_float(hx);
             result[1] = result[3] = _mesa_half_to_float(hy);
             store_vector4(inst, machine, result);
@@ -1638,11 +1683,12 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_UP2US:       /* unpack two GLushorts */
          {
             GLfloat a[4], result[4];
-            const GLuint *rawBits = (const GLuint *) a;
+            fi_type fi;
             GLushort usx, usy;
             fetch_vector1(&inst->SrcReg[0], machine, a);
-            usx = rawBits[0] & 0xffff;
-            usy = rawBits[0] >> 16;
+            fi.f = a[0];
+            usx = fi.i & 0xffff;
+            usy = fi.i >> 16;
             result[0] = result[2] = usx * (1.0f / 65535.0f);
             result[1] = result[3] = usy * (1.0f / 65535.0f);
             store_vector4(inst, machine, result);
@@ -1651,24 +1697,26 @@ _mesa_execute_program(GLcontext * ctx,
       case OPCODE_UP4B:        /* unpack four GLbytes */
          {
             GLfloat a[4], result[4];
-            const GLuint *rawBits = (const GLuint *) a;
+            fi_type fi;
             fetch_vector1(&inst->SrcReg[0], machine, a);
-            result[0] = (((rawBits[0] >> 0) & 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;
+            fi.f = a[0];
+            result[0] = (((fi.i >> 0) & 0xff) - 128) / 127.0F;
+            result[1] = (((fi.i >> 8) & 0xff) - 128) / 127.0F;
+            result[2] = (((fi.i >> 16) & 0xff) - 128) / 127.0F;
+            result[3] = (((fi.i >> 24) & 0xff) - 128) / 127.0F;
             store_vector4(inst, machine, result);
          }
          break;
       case OPCODE_UP4UB:       /* unpack four GLubytes */
          {
             GLfloat a[4], result[4];
-            const GLuint *rawBits = (const GLuint *) a;
+            fi_type fi;
             fetch_vector1(&inst->SrcReg[0], machine, a);
-            result[0] = ((rawBits[0] >> 0) & 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;
+            fi.f = a[0];
+            result[0] = ((fi.i >> 0) & 0xff) / 255.0F;
+            result[1] = ((fi.i >> 8) & 0xff) / 255.0F;
+            result[2] = ((fi.i >> 16) & 0xff) / 255.0F;
+            result[3] = ((fi.i >> 24) & 0xff) / 255.0F;
             store_vector4(inst, machine, result);
          }
          break;