nv20: set surface status in clear()
[mesa.git] / src / gallium / drivers / softpipe / sp_fs_exec.c
index 9ad30a768171fe25563a2b376a0577dbc72d1e6c..453b0373f0feffdf554b2c8fdfb3b3e5e695ba1f 100644 (file)
 
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_util.h"
+#include "util/u_memory.h"
 #include "pipe/p_inlines.h"
-#include "tgsi/exec/tgsi_exec.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_parse.h"
 
-struct sp_exec_fragment_shader {
+struct sp_exec_fragment_shader
+{
    struct sp_fragment_shader base;
 };
 
 
+/** cast wrapper */
+static INLINE struct sp_exec_fragment_shader *
+sp_exec_fragment_shader(const struct sp_fragment_shader *base)
+{
+   return (struct sp_exec_fragment_shader *) base;
+}
+
+
+/**
+ * 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)
+{
+   uint chan;
+   /* do X */
+   quadpos->xyzw[0].f[0] = x;
+   quadpos->xyzw[0].f[1] = x + 1;
+   quadpos->xyzw[0].f[2] = x;
+   quadpos->xyzw[0].f[3] = x + 1;
+
+   /* do Y */
+   quadpos->xyzw[1].f[0] = y;
+   quadpos->xyzw[1].f[1] = y;
+   quadpos->xyzw[1].f[2] = y + 1;
+   quadpos->xyzw[1].f[3] = y + 1;
+
+   /* do Z and W for all fragments in the quad */
+   for (chan = 2; chan < 4; chan++) {
+      const float dadx = coef->dadx[chan];
+      const float dady = coef->dady[chan];
+      const float a0 = coef->a0[chan] + dadx * x + dady * y;
+      quadpos->xyzw[chan].f[0] = a0;
+      quadpos->xyzw[chan].f[1] = a0 + dadx;
+      quadpos->xyzw[chan].f[2] = a0 + dady;
+      quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
+   }
+}
 
 
 static void
-exec_prepare( struct sp_fragment_shader *base,
+exec_prepare( const struct sp_fragment_shader *base,
              struct tgsi_exec_machine *machine,
-             struct tgsi_sampler *samplers )
+             struct tgsi_sampler **samplers )
 {
-   tgsi_exec_machine_bind_shader( machine,
-                                 base->shader.tokens,
-                                 PIPE_MAX_SAMPLERS,
-                                 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 );
+   }
 }
 
 
@@ -63,14 +113,14 @@ exec_prepare( struct sp_fragment_shader *base,
  * interface:
  */
 static unsigned 
-exec_run( struct sp_fragment_shader *base,
+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->x0, (float)quad->y0, 
+                      (float)quad->input.x0, (float)quad->input.y0, 
                       &machine->QuadPos);
    
    return tgsi_exec_machine_run( machine );
@@ -81,6 +131,7 @@ exec_run( struct sp_fragment_shader *base,
 static void 
 exec_delete( struct sp_fragment_shader *base )
 {
+   FREE((void *) base->shader.tokens);
    FREE(base);
 }
 
@@ -102,7 +153,8 @@ softpipe_create_fs_exec(struct softpipe_context *softpipe,
    if (!shader)
       return NULL;
 
-   shader->base.shader = *templ;
+   /* we need to keep a local copy of the tokens */
+   shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
    shader->base.prepare = exec_prepare;
    shader->base.run = exec_run;
    shader->base.delete = exec_delete;