draw: turn fse path into a middle end
authorKeith Whitwell <keith@tungstengraphics.com>
Mon, 12 May 2008 18:40:20 +0000 (19:40 +0100)
committerKeith Whitwell <keith@tungstengraphics.com>
Mon, 12 May 2008 18:40:20 +0000 (19:40 +0100)
Also add some util functions in pt_util.c

src/gallium/auxiliary/draw/Makefile
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
src/gallium/auxiliary/draw/draw_pt_middle_fse.c [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_pt_util.c [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_pt_varray.c
src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
src/gallium/auxiliary/draw/draw_pt_vcache.c

index 68e7744..67d78bd 100644 (file)
@@ -27,8 +27,10 @@ C_SOURCES = \
        draw_pt_fetch.c \
        draw_pt_fetch_emit.c \
        draw_pt_fetch_shade_emit.c \
+       draw_pt_middle_fse.c \
        draw_pt_fetch_shade_pipeline.c \
        draw_pt_post_vs.c \
+        draw_pt_util.c \
         draw_pt_varray.c \
        draw_pt_vcache.c \
        draw_vertex.c \
index cbe64cd..86b901a 100644 (file)
@@ -124,7 +124,7 @@ struct draw_context
    struct {
       struct {
          struct draw_pt_middle_end *fetch_emit;
-         /*struct draw_pt_middle_end *fetch_shade_emit;*/
+         struct draw_pt_middle_end *fetch_shade_emit;
          struct draw_pt_middle_end *general;
       } middle;
 
index d9e73a2..91e35db 100644 (file)
@@ -75,6 +75,8 @@ draw_pt_arrays(struct draw_context *draw,
 
    if (opt == 0) 
       middle = draw->pt.middle.fetch_emit;
+   else if (opt == PT_SHADE && draw->pt.test_fse)
+      middle = draw->pt.middle.fetch_shade_emit;
    else
       middle = draw->pt.middle.general;
 
@@ -83,9 +85,11 @@ draw_pt_arrays(struct draw_context *draw,
     */
    if (draw->pt.user.elts || (opt & PT_PIPELINE)) {
       frontend = draw->pt.front.vcache;
+#if 0
    } else if (opt == PT_SHADE && draw->pt.test_fse) {
       /* should be a middle end.. */
       frontend = draw->pt.front.fetch_shade_emit;
+#endif
    } else {
       frontend = draw->pt.front.varray;
    }
@@ -105,6 +109,8 @@ draw_pt_arrays(struct draw_context *draw,
 
 boolean draw_pt_init( struct draw_context *draw )
 {
+   draw->pt.test_fse = GETENV("DRAW_FSE") != NULL;
+
    draw->pt.front.vcache = draw_pt_vcache( draw );
    if (!draw->pt.front.vcache)
       return FALSE;
@@ -117,8 +123,11 @@ boolean draw_pt_init( struct draw_context *draw )
    if (!draw->pt.middle.fetch_emit)
       return FALSE;
 
-   draw->pt.test_fse = GETENV("DRAW_FSE") != NULL;
    if (draw->pt.test_fse) {
+      draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw );
+      if (!draw->pt.middle.fetch_shade_emit)
+         return FALSE;
+
       draw->pt.front.fetch_shade_emit = draw_pt_fetch_shade_emit( draw );
       if (!draw->pt.front.fetch_shade_emit)
          return FALSE;
@@ -145,6 +154,11 @@ void draw_pt_destroy( struct draw_context *draw )
       draw->pt.middle.fetch_emit = NULL;
    }
 
+   if (draw->pt.middle.fetch_shade_emit) {
+      draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit );
+      draw->pt.middle.fetch_shade_emit = NULL;
+   }
+
    if (draw->pt.front.fetch_shade_emit) {
       draw->pt.front.fetch_shade_emit->destroy( draw->pt.front.fetch_shade_emit );
       draw->pt.front.fetch_shade_emit = NULL;
@@ -163,19 +177,6 @@ void draw_pt_destroy( struct draw_context *draw )
 
 
 
-static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
-   PIPE_PRIM_POINTS,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES
-};
-
 
 /**
  * Draw vertex arrays
@@ -188,9 +189,10 @@ void
 draw_arrays(struct draw_context *draw, unsigned prim,
             unsigned start, unsigned count)
 {
-   if (reduced_prim[prim] != draw->reduced_prim) {
+   unsigned reduced_prim = draw_pt_reduced_prim(prim);
+   if (reduced_prim != draw->reduced_prim) {
       draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
-      draw->reduced_prim = reduced_prim[prim];
+      draw->reduced_prim = reduced_prim;
    }
 
    /* drawing done here: */
index bcd89f6..cdae46b 100644 (file)
@@ -134,7 +134,7 @@ struct draw_pt_front_end *draw_pt_fetch_shade_emit( struct draw_context *draw );
  * vertex_elements.
  */
 struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
-//struct draw_pt_middle_end *draw_pt_fetch_shade_emit( struct draw_context *draw );
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
 
 
@@ -213,4 +213,11 @@ struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw );
 void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
 
 
+/*******************************************************************************
+ * Utils: 
+ */
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
+unsigned draw_pt_reduced_prim(unsigned prim);
+
+
 #endif
index 9e1d1ad..f756d3e 100644 (file)
@@ -434,43 +434,6 @@ static void fse_prepare( struct draw_pt_front_end *fe,
 }
 
 
-static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
-{
-   switch (prim) {
-   case PIPE_PRIM_POINTS:
-      *first = 1;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_LINES:
-      *first = 2;
-      *incr = 2;
-      return TRUE;
-   case PIPE_PRIM_LINE_STRIP:
-      *first = 2;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_TRIANGLES:
-      *first = 3;
-      *incr = 3;
-      return TRUE;
-   case PIPE_PRIM_TRIANGLE_STRIP:
-      *first = 3;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_QUADS:
-      *first = 4;
-      *incr = 4;
-      return TRUE;
-   case PIPE_PRIM_QUAD_STRIP:
-      *first = 4;
-      *incr = 2;
-      return TRUE;
-   default:
-      *first = 0;
-      *incr = 1;               /* set to one so that count % incr works */
-      return FALSE;
-   }
-}
 
 
 
@@ -596,7 +559,7 @@ fse_run(struct draw_pt_front_end *fe,
    
    //debug_printf("%s prim %d start %d count %d\n", __FUNCTION__, prim, start, count);
    
-   split_prim_inplace(fse->prim, &first, &incr);
+   draw_pt_split_prim(fse->prim, &first, &incr);
 
    count -= (count - first) % incr; 
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_middle_fse.c b/src/gallium/auxiliary/draw/draw_pt_middle_fse.c
new file mode 100644 (file)
index 0000000..cdb7d26
--- /dev/null
@@ -0,0 +1,705 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+
+#include "translate/translate.h"
+
+struct fetch_shade_emit;
+
+struct fse_shader {
+   struct translate_key key;
+
+   void (*run_linear)( const struct fetch_shade_emit *fse,
+                       unsigned start,
+                       unsigned count,
+                       char *buffer );
+
+   void (*run_elts)( const struct fetch_shade_emit *fse,
+                     const unsigned *fetch_elts,
+                     unsigned fetch_count,
+                     char *buffer );
+
+};
+
+/* Prototype fetch, shade, emit-hw-verts all in one go.
+ */
+struct fetch_shade_emit {
+   struct draw_pt_middle_end base;
+   struct draw_context *draw;
+
+   struct translate_key key;
+
+   /* Temporaries:
+    */
+   const float *constants;
+   unsigned pitch[PIPE_MAX_ATTRIBS];
+   const ubyte *src[PIPE_MAX_ATTRIBS];
+   unsigned prim;
+
+   /* Points to one of the three hardwired example shaders, below:
+    */
+   struct fse_shader *active;
+
+   /* Temporary: A list of hard-wired shaders.  Of course the plan
+    * would be to generate these for a given (vertex-shader,
+    * translate-key) pair...
+    */
+   struct fse_shader shader[10];
+   int nr_shaders;
+};
+
+
+
+/* Not quite passthrough yet -- we're still running the 'shader' here,
+ * inlined into the vertex fetch function.
+ */
+static void shader0_run_linear( const struct fetch_shade_emit *fse,
+                                   unsigned start,
+                                   unsigned count,
+                                   char *buffer )
+{
+   unsigned i;
+
+   const float *m = fse->constants;
+   const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+   const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+   const ubyte *st = fse->src[2] + start * fse->pitch[2];
+   
+   float *out = (float *)buffer;
+
+   /* loop over vertex attributes (vertex shader inputs)
+    */
+   for (i = 0; i < count; i++) {
+      {
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+        xyz += fse->pitch[0];
+      }
+
+      {
+        const float *in = (const float *)rgb;
+        out[4] = in[0];
+        out[5] = in[1];
+        out[6] = in[2];
+        out[7] = 1.0f;
+         rgb += fse->pitch[1];
+      }
+
+      {
+        const float *in = (const float *)st; 
+        out[8] = in[0];
+        out[9] = in[1];
+        out[10] = 0.0f;
+        out[11] = 1.0f;
+         st += fse->pitch[2];
+      }
+
+      out += 12;
+   }
+}
+
+
+
+static void shader1_run_linear( const struct fetch_shade_emit *fse,
+                          unsigned start,
+                          unsigned count,
+                           char *buffer )
+{
+   unsigned i;
+   const float *m = (const float *)fse->constants;
+   const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+   const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+   float *out = (float *)buffer;
+
+//   debug_printf("rgb %f %f %f\n", rgb[0], rgb[1], rgb[2]);
+
+
+   for (i = 0; i < count; i++) {
+      {
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+        xyz += fse->pitch[0];
+      }
+
+      {
+        const float *in = (const float *)rgb;
+        out[4] = in[0];
+        out[5] = in[1];
+        out[6] = in[2];
+        out[7] = 1.0f;
+         rgb += fse->pitch[1];
+      }
+
+      out += 8;
+   }
+}
+
+
+
+
+static void shader2_run_linear( const struct fetch_shade_emit *fse,
+                               unsigned start,
+                               unsigned count,
+                                char *buffer )
+{
+   unsigned i;
+   const float *m = (const float *)fse->constants;
+   const ubyte *xyz = fse->src[0] + start * fse->pitch[0];
+   const ubyte *rgb = fse->src[1] + start * fse->pitch[1];
+   const float psiz = 1.0;
+   float *out = (float *)buffer;
+
+
+   assert(fse->pitch[1] == 0);
+
+   for (i = 0; i < count; i++) {
+      {
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+        xyz += fse->pitch[0];
+      }
+
+      {
+        const float *in = (const float *)rgb;
+        out[4] = in[0];
+        out[5] = in[1];
+        out[6] = in[2];
+        out[7] = 1.0f;
+         rgb += fse->pitch[1];
+      }
+
+      {
+        out[8] = psiz;
+      }
+
+      out += 9;
+   }
+}
+
+
+
+
+static void shader0_run_elts( const struct fetch_shade_emit *fse,
+                              const unsigned *elts,
+                              unsigned count,
+                              char *buffer )
+{
+   unsigned i;
+   const float *m = fse->constants;
+   float *out = (float *)buffer;
+
+
+   /* loop over vertex attributes (vertex shader inputs)
+    */
+   for (i = 0; i < count; i++) {
+      unsigned elt = elts[i];
+      {
+         const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+      }
+
+      {
+         const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+        const float *in = (const float *)rgb;
+        out[4] = in[0];
+        out[5] = in[1];
+        out[6] = in[2];
+        out[7] = 1.0f;
+      }
+
+      {
+         const ubyte *st = fse->src[2] + elt * fse->pitch[2];
+        const float *in = (const float *)st;
+        out[8] = in[0];
+        out[9] = in[1];
+        out[10] = 0.0f;
+        out[11] = 1.0f;
+      }
+
+      out += 12;
+   }
+}
+
+
+
+static void shader1_run_elts( const struct fetch_shade_emit *fse,
+                              const unsigned *elts,
+                              unsigned count,
+                              char *buffer )
+{
+   unsigned i;
+   const float *m = (const float *)fse->constants;
+   float *out = (float *)buffer;
+
+   for (i = 0; i < count; i++) {
+      unsigned elt = elts[i];
+
+      {
+         const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+        xyz += fse->pitch[0];
+      }
+
+      {
+         const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+        const float *in = (const float *)rgb;
+        out[4] = in[0];
+        out[5] = in[1];
+        out[6] = in[2];
+        out[7] = 1.0f;
+         rgb += fse->pitch[1];
+      }
+
+      out += 8;
+   }
+}
+
+
+
+
+static void shader2_run_elts( const struct fetch_shade_emit *fse,
+                              const unsigned *elts,
+                              unsigned count,
+                              char *buffer )
+{
+   unsigned i;
+   const float *m = (const float *)fse->constants;
+   const float psiz = 1.0;
+   float *out = (float *)buffer;
+
+   for (i = 0; i < count; i++) {
+      unsigned elt = elts[i];
+      {
+         const ubyte *xyz = fse->src[0] + elt * fse->pitch[0];
+        const float *in = (const float *)xyz;
+        const float ix = in[0], iy = in[1], iz = in[2];
+
+        out[0] = m[0] * ix + m[4] * iy + m[8]  * iz + m[12];
+        out[1] = m[1] * ix + m[5] * iy + m[9]  * iz + m[13];
+        out[2] = m[2] * ix + m[6] * iy + m[10] * iz + m[14];
+        out[3] = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
+      }
+
+      {
+         const ubyte *rgb = fse->src[1] + elt * fse->pitch[1];
+        out[4] = rgb[0];
+        out[5] = rgb[1];
+        out[6] = rgb[2];
+        out[7] = 1.0f;
+      }
+
+      {
+        out[8] = psiz;
+      }
+
+      out += 9;
+   }
+}
+
+
+                              
+static void fse_prepare( struct draw_pt_middle_end *middle,
+                         unsigned prim, 
+                         unsigned opt )
+{
+   struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+   struct draw_context *draw = fse->draw;
+   unsigned num_vs_inputs = draw->vertex_shader->info.num_inputs;
+   unsigned num_vs_outputs = draw->vertex_shader->info.num_outputs;
+   const struct vertex_info *vinfo;
+   unsigned i;
+   boolean need_psize = 0;
+   
+
+   if (draw->pt.user.elts) {
+      assert(0);
+      return ;
+   }
+
+   if (!draw->render->set_primitive( draw->render, 
+                                     prim )) {
+      assert(0);
+      return;
+   }
+
+   /* Must do this after set_primitive() above:
+    */
+   vinfo = draw->render->get_vertex_info(draw->render);
+   
+
+
+   fse->key.nr_elements = MAX2(num_vs_outputs,     /* outputs - translate to hw format */
+                               num_vs_inputs);     /* inputs - fetch from api format */
+
+   fse->key.output_stride = vinfo->size * 4;
+   memset(fse->key.element, 0, 
+          fse->key.nr_elements * sizeof(fse->key.element[0]));
+
+   for (i = 0; i < num_vs_inputs; i++) {
+      const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+      fse->key.element[i].input_format = src->src_format;
+
+      /* Consider ignoring these at this point, ie make generated
+       * programs independent of this state:
+       */
+      fse->key.element[i].input_buffer = 0; //src->vertex_buffer_index;
+      fse->key.element[i].input_offset = 0; //src->src_offset;
+   }
+   
+
+   {
+      unsigned dst_offset = 0;
+
+      for (i = 0; i < vinfo->num_attribs; i++) {
+         unsigned emit_sz = 0;
+         unsigned output_format = PIPE_FORMAT_NONE;
+         unsigned vs_output = vinfo->src_index[i];
+
+         switch (vinfo->emit[i]) {
+         case EMIT_4F:
+            output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+            emit_sz = 4 * sizeof(float);
+            break;
+         case EMIT_3F:
+            output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+            emit_sz = 3 * sizeof(float);
+            break;
+         case EMIT_2F:
+            output_format = PIPE_FORMAT_R32G32_FLOAT;
+            emit_sz = 2 * sizeof(float);
+            break;
+         case EMIT_1F:
+            output_format = PIPE_FORMAT_R32_FLOAT;
+            emit_sz = 1 * sizeof(float);
+            break;
+         case EMIT_1F_PSIZE:
+            need_psize = 1;
+            output_format = PIPE_FORMAT_R32_FLOAT;
+            emit_sz = 1 * sizeof(float);
+            vs_output = num_vs_outputs + 1;
+         
+            break;
+         default:
+            assert(0);
+            break;
+         }
+
+         /* The elements in the key correspond to vertex shader output
+          * numbers, not to positions in the hw vertex description --
+          * that's handled by the output_offset field.
+          */
+         fse->key.element[vs_output].output_format = output_format;
+         fse->key.element[vs_output].output_offset = dst_offset;
+      
+         dst_offset += emit_sz;
+         assert(fse->key.output_stride >= dst_offset);
+      }
+   }
+
+   /* To make psize work, really need to tell the vertex shader to
+    * copy that value from input->output.  For 'translate' this was
+    * implicit for all elements.
+    */
+#if 0
+   if (need_psize) {
+      unsigned input = num_vs_inputs + 1;
+      const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+      fse->key.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
+      fse->key.element[i].input_buffer = 0; //nr_buffers + 1;
+      fse->key.element[i].input_offset = 0; 
+
+      fse->key.nr_elements += 1;
+      
+   }
+#endif
+   
+   fse->constants = draw->pt.user.constants;
+
+   /* Would normally look up a vertex shader and peruse its list of
+    * varients somehow.  We omitted that step and put all the
+    * hardcoded "shaders" into an array.  We're just making the
+    * assumption that this happens to be a matching shader...  ie
+    * you're running isosurf, aren't you?
+    */
+   fse->active = NULL;
+   for (i = 0; i < fse->nr_shaders; i++) {
+      if (translate_key_compare( &fse->key, &fse->shader[i].key) == 0)
+         fse->active = &fse->shader[i];
+   }
+
+   if (!fse->active) {
+      assert(0);
+      return ;
+   }
+
+   /* Now set buffer pointers:
+    */
+   for (i = 0; i < num_vs_inputs; i++) {
+      unsigned buf = draw->pt.vertex_element[i].vertex_buffer_index;
+
+      fse->src[i] = ((const ubyte *) draw->pt.user.vbuffer[buf] + 
+                     draw->pt.vertex_buffer[buf].buffer_offset + 
+                     draw->pt.vertex_element[i].src_offset);
+
+      fse->pitch[i] = draw->pt.vertex_buffer[buf].pitch;
+
+   }
+
+   
+   //return TRUE;
+}
+
+
+
+
+
+
+
+static void fse_run_linear( struct draw_pt_middle_end *middle, 
+                            unsigned start, 
+                            unsigned count )
+{
+   struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+   struct draw_context *draw = fse->draw;
+
+   char *hw_verts;
+
+   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+    */
+   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+   hw_verts = draw->render->allocate_vertices( draw->render,
+                                               (ushort)fse->key.output_stride,
+                                               (ushort)count );
+
+   if (!hw_verts) {
+      assert(0);
+      return;
+   }
+
+   /* Single routine to fetch vertices, run shader and emit HW verts.
+    * Clipping and viewport transformation are done elsewhere --
+    * either by the API or on hardware, or for some other reason not
+    * required...
+    */
+   fse->active->run_linear( fse, 
+                            start, count,
+                            hw_verts );
+
+   /* Draw arrays path to avoid re-emitting index list again and
+    * again.
+    */
+   draw->render->draw_arrays( draw->render,
+                              0,
+                              count );
+   
+
+   draw->render->release_vertices( draw->render, 
+                                  hw_verts, 
+                                  fse->key.output_stride, 
+                                  count );
+}
+
+
+static void
+fse_run(struct draw_pt_middle_end *middle,
+        const unsigned *fetch_elts,
+        unsigned fetch_count,
+        const ushort *draw_elts,
+        unsigned draw_count )
+{
+   struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+   struct draw_context *draw = fse->draw;
+   void *hw_verts;
+   
+   /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 
+    */
+   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+   hw_verts = draw->render->allocate_vertices( draw->render,
+                                               (ushort)fse->key.output_stride,
+                                               (ushort)fetch_count );
+   if (!hw_verts) {
+      assert(0);
+      return;
+   }
+         
+                                       
+   /* Single routine to fetch vertices, run shader and emit HW verts.
+    */
+   fse->active->run_elts( fse, 
+                           fetch_elts,
+                           fetch_count,
+                           hw_verts );
+
+   draw->render->draw( draw->render, 
+                       draw_elts, 
+                       draw_count );
+
+   draw->render->release_vertices( draw->render, 
+                                   hw_verts, 
+                                   fse->key.output_stride, 
+                                   fetch_count );
+
+}
+
+
+static void fse_finish( struct draw_pt_middle_end *middle )
+{
+}
+
+
+static void
+fse_destroy( struct draw_pt_middle_end *middle ) 
+{
+   FREE(middle);
+}
+
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw )
+{
+   struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);
+   if (!fse)
+      return NULL;
+
+   fse->base.prepare = fse_prepare;
+   fse->base.run = fse_run;
+   fse->base.run_linear = fse_run_linear;
+   fse->base.finish = fse_finish;
+   fse->base.destroy = fse_destroy;
+   fse->draw = draw;
+
+   fse->shader[0].run_linear = shader0_run_linear;
+   fse->shader[0].run_elts = shader0_run_elts;
+   fse->shader[0].key.nr_elements = 3;
+   fse->shader[0].key.output_stride = 12 * sizeof(float);
+
+   fse->shader[0].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[0].key.element[0].input_buffer = 0; 
+   fse->shader[0].key.element[0].input_offset = 0; 
+   fse->shader[0].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[0].key.element[0].output_offset = 0; 
+
+   fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[0].key.element[1].input_buffer = 0; 
+   fse->shader[0].key.element[1].input_offset = 0; 
+   fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[0].key.element[1].output_offset = 16; 
+
+   fse->shader[0].key.element[1].input_format = PIPE_FORMAT_R32G32_FLOAT;
+   fse->shader[0].key.element[1].input_buffer = 0; 
+   fse->shader[0].key.element[1].input_offset = 0; 
+   fse->shader[0].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[0].key.element[1].output_offset = 32; 
+
+   fse->shader[1].run_linear = shader1_run_linear;
+   fse->shader[1].run_elts = shader1_run_elts;
+   fse->shader[1].key.nr_elements = 2;
+   fse->shader[1].key.output_stride = 8 * sizeof(float);
+
+   fse->shader[1].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[1].key.element[0].input_buffer = 0; 
+   fse->shader[1].key.element[0].input_offset = 0; 
+   fse->shader[1].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[1].key.element[0].output_offset = 0; 
+
+   fse->shader[1].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[1].key.element[1].input_buffer = 0; 
+   fse->shader[1].key.element[1].input_offset = 0; 
+   fse->shader[1].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[1].key.element[1].output_offset = 16; 
+
+   fse->shader[2].run_linear = shader2_run_linear;
+   fse->shader[2].run_elts = shader2_run_elts;
+   fse->shader[2].key.nr_elements = 3;
+   fse->shader[2].key.output_stride = 9 * sizeof(float);
+
+   fse->shader[2].key.element[0].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[2].key.element[0].input_buffer = 0; 
+   fse->shader[2].key.element[0].input_offset = 0; 
+   fse->shader[2].key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[2].key.element[0].output_offset = 0; 
+
+   fse->shader[2].key.element[1].input_format = PIPE_FORMAT_R32G32B32_FLOAT;
+   fse->shader[2].key.element[1].input_buffer = 0; 
+   fse->shader[2].key.element[1].input_offset = 0; 
+   fse->shader[2].key.element[1].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   fse->shader[2].key.element[1].output_offset = 16; 
+
+   /* psize is special 
+    *    -- effectively add it here as another input!?! 
+    *    -- who knows how to add it as a buffer?
+    */
+   fse->shader[2].key.element[2].input_format = PIPE_FORMAT_R32_FLOAT;
+   fse->shader[2].key.element[2].input_buffer = 0; 
+   fse->shader[2].key.element[2].input_offset = 0; 
+   fse->shader[2].key.element[2].output_format = PIPE_FORMAT_R32_FLOAT;
+   fse->shader[2].key.element[2].output_offset = 32; 
+
+   fse->nr_shaders = 3;
+
+   return &fse->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c
new file mode 100644 (file)
index 0000000..32c8a96
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
+{
+   switch (prim) {
+   case PIPE_PRIM_POINTS:
+      *first = 1;
+      *incr = 1;
+      break;
+   case PIPE_PRIM_LINES:
+      *first = 2;
+      *incr = 2;
+      break;
+   case PIPE_PRIM_LINE_STRIP:
+   case PIPE_PRIM_LINE_LOOP:
+      *first = 2;
+      *incr = 1;
+      break;
+   case PIPE_PRIM_TRIANGLES:
+      *first = 3;
+      *incr = 3;
+      break;
+   case PIPE_PRIM_TRIANGLE_STRIP:
+   case PIPE_PRIM_TRIANGLE_FAN:
+   case PIPE_PRIM_POLYGON:
+      *first = 3;
+      *incr = 1;
+      break;
+   case PIPE_PRIM_QUADS:
+      *first = 4;
+      *incr = 4;
+      break;
+   case PIPE_PRIM_QUAD_STRIP:
+      *first = 4;
+      *incr = 2;
+      break;
+   default:
+      assert(0);
+      *first = 0;
+      *incr = 1;               /* set to one so that count % incr works */
+      break;
+   }
+}
+
+
+unsigned draw_pt_reduced_prim(unsigned prim)
+{
+   switch (prim) {
+   case PIPE_PRIM_POINTS:
+      return PIPE_PRIM_POINTS;
+   case PIPE_PRIM_LINES:
+   case PIPE_PRIM_LINE_STRIP:
+   case PIPE_PRIM_LINE_LOOP:
+      return PIPE_PRIM_LINES;
+   case PIPE_PRIM_TRIANGLES:
+   case PIPE_PRIM_TRIANGLE_STRIP:
+   case PIPE_PRIM_TRIANGLE_FAN:
+   case PIPE_PRIM_POLYGON:
+   case PIPE_PRIM_QUADS:
+   case PIPE_PRIM_QUAD_STRIP:
+      return PIPE_PRIM_TRIANGLES;
+   default:
+      assert(0);
+      return PIPE_PRIM_POINTS;
+   }
+}
+
+
index d92ad4f..af6e2d5 100644 (file)
@@ -106,51 +106,6 @@ static INLINE void fetch_init(struct varray_frontend *varray,
 }
 
 
-static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
-{
-   switch (prim) {
-   case PIPE_PRIM_POINTS:
-      *first = 1;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_LINES:
-      *first = 2;
-      *incr = 2;
-      return TRUE;
-   case PIPE_PRIM_LINE_STRIP:
-      *first = 2;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_TRIANGLES:
-      *first = 3;
-      *incr = 3;
-      return TRUE;
-   case PIPE_PRIM_TRIANGLE_STRIP:
-      *first = 3;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_TRIANGLE_FAN:
-      *first = 3;
-      *incr = 1;
-      return TRUE;
-   case PIPE_PRIM_QUADS:
-      *first = 4;
-      *incr = 4;
-      return TRUE;
-   case PIPE_PRIM_QUAD_STRIP:
-      *first = 4;
-      *incr = 2;
-      return TRUE;
-   case PIPE_PRIM_POLYGON:
-      *first = 3;
-      *incr = 1;
-      return TRUE;
-   default:
-      *first = 0;
-      *incr = 1;               /* set to one so that count % incr works */
-      return FALSE;
-   }
-}
 
 
 static INLINE void add_draw_el(struct varray_frontend *varray,
index 1395275..6979f6b 100644 (file)
@@ -15,7 +15,7 @@ static void FUNC(struct draw_pt_front_end *frontend,
 
    varray->fetch_start = start;
 
-   split_prim_inplace(varray->input_prim, &first, &incr);
+   draw_pt_split_prim(varray->input_prim, &first, &incr);
 
 #if 0
    debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
index b6f1f0c..114ed37 100644 (file)
@@ -16,7 +16,13 @@ static void FUNC(struct draw_pt_front_end *frontend,
 
    varray->fetch_start = start;
 
-   split_prim_inplace(varray->input_prim, &first, &incr);
+   draw_pt_split_prim(varray->input_prim, &first, &incr);
+   
+   /* Sanitize primitive length:
+    */
+   count = trim(count, first, incr); 
+   if (count < first)
+      return;
 
 #if 0
    debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
@@ -32,7 +38,6 @@ static void FUNC(struct draw_pt_front_end *frontend,
    case PIPE_PRIM_TRIANGLE_STRIP:
    case PIPE_PRIM_QUADS:
    case PIPE_PRIM_QUAD_STRIP:
-      
       for (j = 0; j < count;) {
          unsigned remaining = count - j;
          unsigned nr = trim( MIN2(FETCH_MAX, remaining), first, incr );
index 6b3fb14..a3495f2 100644 (file)
@@ -204,19 +204,6 @@ static void vcache_ef_quad( struct vcache_frontend *vcache,
 
 
 
-static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
-   PIPE_PRIM_POINTS,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLES
-};
-
 
 
 static void vcache_prepare( struct draw_pt_front_end *frontend,
@@ -236,7 +223,7 @@ static void vcache_prepare( struct draw_pt_front_end *frontend,
    }
 
    vcache->input_prim = prim;
-   vcache->output_prim = reduced_prim[prim];
+   vcache->output_prim = draw_pt_reduced_prim(prim);
 
    vcache->middle = middle;
    middle->prepare( middle, vcache->output_prim, opt );