glsl: fix crash in loop analysis when some controls can't be determined
[mesa.git] / src / gallium / drivers / softpipe / sp_fs_exec.c
index 3c7ba565d6c42e7b6321c5f5a817ca9901125c38..346e1b402baba023916102fdc59789429216e3ab 100644 (file)
  * 
  **************************************************************************/
 
+/**
+ * Execute fragment shader using the TGSI interpreter.
+ */
 
 #include "sp_context.h"
 #include "sp_state.h"
 #include "sp_fs.h"
 #include "sp_quad.h"
 
-
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
-#include "pipe/p_inlines.h"
 #include "tgsi/tgsi_exec.h"
 #include "tgsi/tgsi_parse.h"
 
+
+/**
+ * Subclass of sp_fragment_shader
+ */
 struct sp_exec_fragment_shader
 {
    struct sp_fragment_shader base;
+   /* No other members for now */
 };
 
 
@@ -53,15 +59,34 @@ sp_exec_fragment_shader(const struct sp_fragment_shader *base)
 }
 
 
+static void
+exec_prepare( const struct sp_fragment_shader *base,
+             struct tgsi_exec_machine *machine,
+             struct tgsi_sampler **samplers )
+{
+   /*
+    * Bind tokens/shader to the interpreter's machine state.
+    * Avoid redundant binding.
+    */
+   if (machine->Tokens != base->shader.tokens) {
+      tgsi_exec_machine_bind_shader( machine,
+                                     base->shader.tokens,
+                                     PIPE_MAX_SAMPLERS,
+                                     samplers );
+   }
+}
+
+
+
 /**
  * Compute quad X,Y,Z,W for the four fragments in a quad.
  *
  * This should really be part of the compiled shader.
  */
-void
-sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
-                   float x, float y,
-                   struct tgsi_exec_vector *quadpos)
+static void
+setup_pos_vector(const struct tgsi_interp_coef *coef,
+                 float x, float y,
+                 struct tgsi_exec_vector *quadpos)
 {
    uint chan;
    /* do X */
@@ -89,26 +114,6 @@ sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
 }
 
 
-static void
-exec_prepare( const struct sp_fragment_shader *base,
-             struct tgsi_exec_machine *machine,
-             struct tgsi_sampler **samplers )
-{
-   /*
-    * Bind tokens/shader to the interpreter's machine state.
-    * Avoid redundant binding.
-    */
-   if (machine->Tokens != base->shader.tokens) {
-      tgsi_exec_machine_bind_shader( machine,
-                                     base->shader.tokens,
-                                     PIPE_MAX_SAMPLERS,
-                                     samplers );
-   }
-}
-
-
-
-
 /* TODO: hide the machine struct in here somewhere, remove from this
  * interface:
  */
@@ -117,15 +122,61 @@ exec_run( const struct sp_fragment_shader *base,
          struct tgsi_exec_machine *machine,
          struct quad_header *quad )
 {
-
    /* Compute X, Y, Z, W vals for this quad */
-   sp_setup_pos_vector(quad->posCoef, 
-                      (float)quad->input.x0, (float)quad->input.y0, 
-                      &machine->QuadPos);
-   
-   return tgsi_exec_machine_run( machine );
-}
+   setup_pos_vector(quad->posCoef, 
+                    (float)quad->input.x0, (float)quad->input.y0, 
+                    &machine->QuadPos);
+
+   /* convert 0 to 1.0 and 1 to -1.0 */
+   machine->Face = (float) (quad->input.facing * -2 + 1);
+
+   quad->inout.mask &= tgsi_exec_machine_run( machine );
+   if (quad->inout.mask == 0)
+      return FALSE;
+
+   /* store outputs */
+   {
+      const ubyte *sem_name = base->info.output_semantic_name;
+      const ubyte *sem_index = base->info.output_semantic_index;
+      const uint n = base->info.num_outputs;
+      uint i;
+      for (i = 0; i < n; i++) {
+         switch (sem_name[i]) {
+         case TGSI_SEMANTIC_COLOR:
+            {
+               uint cbuf = sem_index[i];
+
+               assert(sizeof(quad->output.color[cbuf]) ==
+                      sizeof(machine->Outputs[i]));
+
+               /* copy float[4][4] result */
+               memcpy(quad->output.color[cbuf],
+                      &machine->Outputs[i],
+                      sizeof(quad->output.color[0]) );
+            }
+            break;
+         case TGSI_SEMANTIC_POSITION:
+            {
+               uint j;
+
+               for (j = 0; j < 4; j++)
+                  quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j];
+            }
+            break;
+         case TGSI_SEMANTIC_STENCIL:
+            {
+               uint j;
+
+               for (j = 0; j < 4; j++)
+                  quad->output.stencil[j] = (unsigned)machine->Outputs[i].xyzw[1].f[j];
+            }
+            break;
+         }
+      }
+   }
 
+   return TRUE;
+}
 
 
 static void 
@@ -136,9 +187,6 @@ exec_delete( struct sp_fragment_shader *base )
 }
 
 
-
-
-
 struct sp_fragment_shader *
 softpipe_create_fs_exec(struct softpipe_context *softpipe,
                        const struct pipe_shader_state *templ)
@@ -161,4 +209,3 @@ softpipe_create_fs_exec(struct softpipe_context *softpipe,
 
    return &shader->base;
 }
-