draw: make pt run pipeline when need_pipeline is true, not just when clipped
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline.c
index b49c9efa65b5a629ea467bf3e4efd75e746da93c..52be4a64aa63eb61ac6c74abb1f111f0769b3c6f 100644 (file)
 #include "draw/draw_vbuf.h"
 #include "draw/draw_vertex.h"
 #include "draw/draw_pt.h"
+#include "translate/translate.h"
+
 
 struct fetch_pipeline_middle_end {
    struct draw_pt_middle_end base;
    struct draw_context *draw;
 
-   struct {
-      const ubyte *ptr;
-      unsigned pitch;
-      void (*fetch)( const void *from, float *attrib);
-      void (*emit)( const float *attrib, float **out );
-   } fetch[PIPE_MAX_ATTRIBS];
+   struct translate *translate;
 
-   unsigned nr_fetch;
    unsigned pipeline_vertex_size;
-   unsigned hw_vertex_size;
    unsigned prim;
+   unsigned opt;
 };
 
-#if 0
-static void emit_R32_FLOAT( const float *attrib,
-                            float **out )
-{
-   (*out)[0] = attrib[0];
-   (*out) += 1;
-}
-
-static void emit_R32G32_FLOAT( const float *attrib,
-                               float **out )
-{
-   (*out)[0] = attrib[0];
-   (*out)[1] = attrib[1];
-   (*out) += 2;
-}
-
-static void emit_R32G32B32_FLOAT( const float *attrib,
-                                  float **out )
-{
-   (*out)[0] = attrib[0];
-   (*out)[1] = attrib[1];
-   (*out)[2] = attrib[2];
-   (*out) += 3;
-}
-#endif
-static void emit_R32G32B32A32_FLOAT( const float *attrib,
-                                     float **out )
-{
-   (*out)[0] = attrib[0];
-   (*out)[1] = attrib[1];
-   (*out)[2] = attrib[2];
-   (*out)[3] = attrib[3];
-   (*out) += 4;
-}
 
 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
-                                    unsigned prim )
+                                    unsigned prim,
+                                   unsigned opt )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
-   unsigned i, nr = 0;
+   unsigned i;
    boolean ok;
    const struct vertex_info *vinfo;
+   unsigned dst_offset;
+   struct translate_key hw_key;
 
    fpme->prim = prim;
+   fpme->opt = opt;
 
    ok = draw->render->set_primitive(draw->render, prim);
    if (!ok) {
       assert(0);
       return;
    }
+
    /* Must do this after set_primitive() above:
     */
    vinfo = draw->render->get_vertex_info(draw->render);
 
-   /* Need to look at vertex shader inputs (we know it is a
-    * passthrough shader, so these define the outputs too).  If we
-    * were running a shader, we'd still be looking at the inputs at
-    * this point.
+
+   /* In passthrough mode, need to translate from vertex shader
+    * outputs to hw vertices.
     */
-   for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) {
-      unsigned buf = draw->vertex_element[i].vertex_buffer_index;
-      enum pipe_format format  = draw->vertex_element[i].src_format;
+   dst_offset = 0;
+   for (i = 0; i < vinfo->num_attribs; i++) {
+      unsigned emit_sz = 0;
+      unsigned src_buffer = 0;
+      unsigned output_format;
+      unsigned src_offset = (sizeof(struct vertex_header) + 
+                            vinfo->src_index[i] * 4 * sizeof(float) );
+
+
+         
+      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:
+         output_format = PIPE_FORMAT_R32_FLOAT;
+        emit_sz = 1 * sizeof(float);
+         src_buffer = 1;
+        src_offset = 0;
+         break;
+      case EMIT_4UB:
+         output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+        emit_sz = 4 * sizeof(ubyte);
+      default:
+         assert(0);
+         output_format = PIPE_FORMAT_NONE;
+        emit_sz = 0;
+         break;
+      }
+      
+      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+      hw_key.element[i].input_buffer = src_buffer;
+      hw_key.element[i].input_offset = src_offset;
+      hw_key.element[i].output_format = output_format;
+      hw_key.element[i].output_offset = dst_offset;
+
+      dst_offset += emit_sz;
+   }
 
-      fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] +
-                            draw->vertex_buffer[buf].buffer_offset +
-                            draw->vertex_element[i].src_offset);
+   hw_key.nr_elements = vinfo->num_attribs;
+   hw_key.output_stride = vinfo->size * 4;
 
-      fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch;
-      fpme->fetch[nr].fetch = draw_get_fetch_func( format );
+   /* Don't bother with caching at this stage:
+    */
+   if (!fpme->translate ||
+       memcmp(&fpme->translate->key, &hw_key, sizeof(hw_key)) != 0) 
+   {
+      if (fpme->translate)
+        fpme->translate->release(fpme->translate);
 
-      /* Always do this -- somewhat redundant...
-       */
-      fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT;
-      nr++;
+      fpme->translate = translate_generic_create( &hw_key );
    }
 
-   fpme->nr_fetch = nr;
+
+
    //fpme->pipeline_vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
-   fpme->pipeline_vertex_size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
-   fpme->hw_vertex_size = vinfo->size * 4;
+   fpme->pipeline_vertex_size = MAX_VERTEX_ALLOCATION;
 }
 
 
@@ -145,6 +160,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    struct draw_context *draw = fpme->draw;
    struct draw_vertex_shader *shader = draw->vertex_shader;
    char *pipeline_verts;
+   unsigned pipeline = PT_PIPELINE;
 
    pipeline_verts = MALLOC(fpme->pipeline_vertex_size *
                           fetch_count);
@@ -158,9 +174,17 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    /* Shade
     */
    shader->prepare(shader, draw);
+
    if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts,
-                   fpme->pipeline_vertex_size)) {
-      /* Run the pipeline */
+                  fpme->pipeline_vertex_size))
+   {
+      pipeline |= PT_CLIPTEST;
+   }
+
+
+   /* Do we need to run the pipeline?
+    */
+   if (fpme->opt & pipeline) {
       draw_pt_run_pipeline( fpme->draw,
                             fpme->prim,
                             pipeline_verts,
@@ -169,45 +193,42 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
                             draw_elts,
                             draw_count );
    } else {
-      unsigned i, j;
+      struct translate *translate = fpme->translate;
       void *hw_verts;
-      float *out;
 
       /* 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)fpme->hw_vertex_size,
+                                                 (ushort)fpme->translate->key.output_stride,
                                                  (ushort)fetch_count);
       if (!hw_verts) {
          assert(0);
          return;
       }
 
-      out = (float *)hw_verts;
-      for (i = 0; i < fetch_count; i++) {
-         struct vertex_header *header =
-            (struct vertex_header*)(pipeline_verts + (fpme->pipeline_vertex_size * i));
-
-         for (j = 0; j < fpme->nr_fetch; j++) {
-            float *attrib = header->data[j];
-            /*debug_printf("emiting [%f, %f, %f, %f]\n",
-                         attrib[0], attrib[1],
-                         attrib[2], attrib[3]);*/
-            fpme->fetch[j].emit(attrib, &out);
-         }
-      }
-      /* XXX: Draw arrays path to avoid re-emitting index list again and
-       * again.
-       */
+      translate->set_buffer(translate, 
+                           0, 
+                           pipeline_verts,
+                           fpme->pipeline_vertex_size );
+
+      translate->set_buffer(translate, 
+                           1, 
+                           &fpme->draw->rasterizer->point_size,
+                           0);
+
+      translate->run( translate,
+                     0, fetch_count,
+                     hw_verts );
+
       draw->render->draw(draw->render,
                          draw_elts,
                          draw_count);
 
       draw->render->release_vertices(draw->render,
                                      hw_verts,
-                                     fpme->hw_vertex_size,
+                                     fpme->translate->key.output_stride,
                                      fetch_count);
    }