Merge branch 'draw-instanced'
[mesa.git] / src / mesa / program / prog_execute.c
index f85c6513f3194c92d7c183674863a7841cce55d2..e7553c69dbed71622f4e898b7b3ffa4453b0d423 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "main/glheader.h"
 #include "main/colormac.h"
-#include "main/context.h"
+#include "main/macros.h"
 #include "prog_execute.h"
 #include "prog_instruction.h"
 #include "prog_parameter.h"
@@ -80,6 +80,22 @@ static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
 
 
 
+/**
+ * Return TRUE for +0 and other positive values, FALSE otherwise.
+ * Used for RCC opcode.
+ */
+static INLINE GLboolean
+positive(float x)
+{
+   fi_type fi;
+   fi.f = x;
+   if (fi.i & 0x80000000)
+      return GL_FALSE;
+   return GL_TRUE;
+}
+
+
+
 /**
  * Return a pointer to the 4-element float vector specified by the given
  * source register.
@@ -143,6 +159,10 @@ get_src_register_pointer(const struct prog_src_register *source,
          return ZeroVec;
       return prog->Parameters->ParameterValues[reg];
 
+   case PROGRAM_SYSTEM_VALUE:
+      assert(reg < Elements(machine->SystemValues));
+      return machine->SystemValues[reg];
+
    default:
       _mesa_problem(NULL,
          "Invalid src register file %d in get_src_register_pointer()",
@@ -280,7 +300,7 @@ fetch_vector4ui(const struct prog_src_register *source,
  * XXX this currently only works for fragment program input attribs.
  */
 static void
-fetch_vector4_deriv(GLcontext * ctx,
+fetch_vector4_deriv(struct gl_context * ctx,
                     const struct prog_src_register *source,
                     const struct gl_program_machine *machine,
                     char xOrY, GLfloat result[4])
@@ -364,7 +384,7 @@ fetch_vector1ui(const struct prog_src_register *source,
  * Fetch texel from texture.  Use partial derivatives when possible.
  */
 static INLINE void
-fetch_texel(GLcontext *ctx,
+fetch_texel(struct gl_context *ctx,
             const struct gl_program_machine *machine,
             const struct prog_instruction *inst,
             const GLfloat texcoord[4], GLfloat lodBias,
@@ -614,7 +634,7 @@ store_vector4ui(const struct prog_instruction *inst,
  * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
  */
 GLboolean
-_mesa_execute_program(GLcontext * ctx,
+_mesa_execute_program(struct gl_context * ctx,
                       const struct gl_program *program,
                       struct gl_program_machine *machine)
 {
@@ -755,6 +775,13 @@ _mesa_execute_program(GLcontext * ctx,
             result[2] = a[2] < 0.0F ? b[2] : c[2];
             result[3] = a[3] < 0.0F ? b[3] : c[3];
             store_vector4(inst, machine, result);
+            if (DEBUG_PROG) {
+               printf("CMP (%g %g %g %g) = (%g %g %g %g) < 0 ? (%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],
+                      c[0], c[1], c[2], c[3]);
+            }
          }
          break;
       case OPCODE_COS:
@@ -1340,6 +1367,44 @@ _mesa_execute_program(GLcontext * ctx,
             store_vector4(inst, machine, result);
          }
          break;
+      case OPCODE_RCC:  /* clamped riciprocal */
+         {
+            const float largest = 1.884467e+19, smallest = 5.42101e-20;
+            GLfloat a[4], r, result[4];
+            fetch_vector1(&inst->SrcReg[0], machine, a);
+            if (DEBUG_PROG) {
+               if (a[0] == 0)
+                  printf("RCC(0)\n");
+               else if (IS_INF_OR_NAN(a[0]))
+                  printf("RCC(inf)\n");
+            }
+            if (a[0] == 1.0F) {
+               r = 1.0F;
+            }
+            else {
+               r = 1.0F / a[0];
+            }
+            if (positive(r)) {
+               if (r > largest) {
+                  r = largest;
+               }
+               else if (r < smallest) {
+                  r = smallest;
+               }
+            }
+            else {
+               if (r < -largest) {
+                  r = -largest;
+               }
+               else if (r > -smallest) {
+                  r = -smallest;
+               }
+            }
+            result[0] = result[1] = result[2] = result[3] = r;
+            store_vector4(inst, machine, result);
+         }
+         break;
+
       case OPCODE_RCP:
          {
             GLfloat a[4], result[4];
@@ -1609,6 +1674,18 @@ _mesa_execute_program(GLcontext * ctx,
 
             fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
 
+            if (DEBUG_PROG) {
+               printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]"
+                      "  bias %g\n",
+                      color[0], color[1], color[2], color[3],
+                      inst->TexSrcUnit,
+                      texcoord[0],
+                      texcoord[1],
+                      texcoord[2],
+                      texcoord[3],
+                      lodBias);
+            }
+
             store_vector4(inst, machine, color);
          }
          break;
@@ -1625,6 +1702,22 @@ _mesa_execute_program(GLcontext * ctx,
             store_vector4(inst, machine, color);
          }
          break;
+      case OPCODE_TXL:
+         /* Texel lookup with explicit LOD */
+         {
+            GLfloat texcoord[4], color[4], lod;
+
+            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+
+            /* texcoord[3] is the LOD */
+            lod = texcoord[3];
+
+           machine->FetchTexelLod(ctx, texcoord, lod,
+                                  machine->Samplers[inst->TexSrcUnit], color);
+
+            store_vector4(inst, machine, color);
+         }
+         break;
       case OPCODE_TXP:         /* GL_ARB_fragment_program only */
          /* Texture lookup w/ projective divide */
          {
@@ -1788,7 +1881,11 @@ _mesa_execute_program(GLcontext * ctx,
 
       numExec++;
       if (numExec > maxExec) {
-         _mesa_problem(ctx, "Infinite loop detected in fragment program");
+        static GLboolean reported = GL_FALSE;
+        if (!reported) {
+           _mesa_problem(ctx, "Infinite loop detected in fragment program");
+           reported = GL_TRUE;
+        }
          return GL_TRUE;
       }