gallium/draw: Remove unnecessary headers.
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline.c
index dad54690a5a00744205e571bd2a5f1b35c738dfb..2c996e730872b581c67d802aab404e63d94ce2b1 100644 (file)
  *
  **************************************************************************/
 
-#include "pipe/p_util.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
 #include "draw/draw_context.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"
+#include "draw/draw_gs.h"
 
 
 struct fetch_pipeline_middle_end {
@@ -51,11 +52,14 @@ struct fetch_pipeline_middle_end {
 
 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
                                     unsigned prim,
-                                   unsigned opt )
+                                   unsigned opt,
+                                    unsigned *max_vertices )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
-   struct draw_vertex_shader *vs = draw->vertex_shader;
+   struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+   unsigned i;
+   unsigned instance_id_index = ~0;
 
    /* Add one to num_outputs because the pipeline occasionally tags on
     * an additional texcoord, eg for AA lines.
@@ -63,6 +67,15 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
    unsigned nr = MAX2( vs->info.num_inputs,
                       vs->info.num_outputs + 1 );
 
+   /* Scan for instanceID system value.
+    */
+   for (i = 0; i < vs->info.num_inputs; i++) {
+      if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
+         instance_id_index = i;
+         break;
+      }
+   }
+
    fpme->prim = prim;
    fpme->opt = opt;
 
@@ -75,30 +88,41 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
    
 
    draw_pt_fetch_prepare( fpme->fetch, 
-                         fpme->vertex_size );
-
+                          vs->info.num_inputs,
+                          fpme->vertex_size,
+                          instance_id_index );
    /* XXX: it's not really gl rasterization rules we care about here,
     * but gl vs dx9 clip spaces.
     */
    draw_pt_post_vs_prepare( fpme->post_vs,
-                           draw->bypass_clipping,
-                           draw->identity_viewport,
-                           draw->rasterizer->gl_rasterization_rules );
-                           
+                           (boolean)draw->bypass_clipping,
+                           (boolean)(draw->identity_viewport ||
+                           draw->rasterizer->bypass_vs_clip_and_viewport),
+                           (boolean)draw->rasterizer->gl_rasterization_rules,
+                           (draw->vs.edgeflag_output ? true : false) );    
 
-   if (!(opt & PT_PIPELINE)) 
+   if (!(opt & PT_PIPELINE)) {
       draw_pt_emit_prepare( fpme->emit, 
-                           prim );
+                           prim,
+                            max_vertices );
+
+      *max_vertices = MAX2( *max_vertices,
+                            DRAW_PIPE_MAX_VERTICES );
+   }
+   else {
+      *max_vertices = DRAW_PIPE_MAX_VERTICES; 
+   }
+
+   /* return even number */
+   *max_vertices = *max_vertices & ~1;
 
    /* No need to prepare the shader.
     */
    vs->prepare(vs, draw);
-
 }
 
 
 
-
 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
                                 const unsigned *fetch_elts,
                                 unsigned fetch_count,
@@ -107,9 +131,10 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
-   struct draw_vertex_shader *shader = draw->vertex_shader;
+   struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
+   struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
    unsigned opt = fpme->opt;
-   unsigned alloc_count = align_int( fetch_count, 4 );
+   unsigned alloc_count = align( fetch_count, 4 );
 
    struct vertex_header *pipeline_verts = 
       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
@@ -129,19 +154,27 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
                      (char *)pipeline_verts );
 
    /* Run the shader, note that this overwrites the data[] parts of
-    * the pipeline verts.  If there is no shader, ie a bypass shader,
-    * then the inputs == outputs, and are already in the correct
-    * place.
+    * the pipeline verts.  If there is no shader, eg if
+    * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+    * already in the correct place.
     */
    if (opt & PT_SHADE)
    {
-      shader->run_linear(shader, 
-                        (const float (*)[4])pipeline_verts->data,
-                        (      float (*)[4])pipeline_verts->data,
-                        (const float (*)[4])draw->pt.user.constants,
-                        fetch_count,
-                        fpme->vertex_size,
-                        fpme->vertex_size);
+      vshader->run_linear(vshader,
+                          (const float (*)[4])pipeline_verts->data,
+                          (      float (*)[4])pipeline_verts->data,
+                          (const float (*)[4])draw->pt.user.vs_constants,
+                          fetch_count,
+                          fpme->vertex_size,
+                          fpme->vertex_size);
+      if (gshader)
+         draw_geometry_shader_run(gshader,
+                                  (const float (*)[4])pipeline_verts->data,
+                                  (      float (*)[4])pipeline_verts->data,
+                                  (const float (*)[4])draw->pt.user.gs_constants,
+                                  fetch_count,
+                                  fpme->vertex_size,
+                                  fpme->vertex_size);
    }
 
    if (draw_pt_post_vs_run( fpme->post_vs,
@@ -183,9 +216,10 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
-   struct draw_vertex_shader *shader = draw->vertex_shader;
+   struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+   struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
    unsigned opt = fpme->opt;
-   unsigned alloc_count = align_int( count, 4 );
+   unsigned alloc_count = align( count, 4 );
 
    struct vertex_header *pipeline_verts =
       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
@@ -205,19 +239,28 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
                              (char *)pipeline_verts );
 
    /* Run the shader, note that this overwrites the data[] parts of
-    * the pipeline verts.  If there is no shader, ie a bypass shader,
-    * then the inputs == outputs, and are already in the correct
-    * place.
+    * the pipeline verts.  If there is no shader, ie if
+    * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+    * already in the correct place.
     */
    if (opt & PT_SHADE)
    {
       shader->run_linear(shader,
                         (const float (*)[4])pipeline_verts->data,
                         (      float (*)[4])pipeline_verts->data,
-                        (const float (*)[4])draw->pt.user.constants,
+                        (const float (*)[4])draw->pt.user.vs_constants,
                         count,
                         fpme->vertex_size,
                         fpme->vertex_size);
+
+      if (geometry_shader)
+         draw_geometry_shader_run(geometry_shader,
+                                  (const float (*)[4])pipeline_verts->data,
+                                  (      float (*)[4])pipeline_verts->data,
+                                  (const float (*)[4])draw->pt.user.gs_constants,
+                                  count,
+                                  fpme->vertex_size,
+                                  fpme->vertex_size);
    }
 
    if (draw_pt_post_vs_run( fpme->post_vs,
@@ -240,9 +283,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
    else {
       draw_pt_emit_linear( fpme->emit,
                            (const float (*)[4])pipeline_verts->data,
-                           count,
                            fpme->vertex_size,
-                           0, /*start*/
                            count );
    }
 
@@ -251,6 +292,91 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
 
 
 
+static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
+                                            unsigned start,
+                                            unsigned count,
+                                            const ushort *draw_elts,
+                                            unsigned draw_count )
+{
+   struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+   struct draw_context *draw = fpme->draw;
+   struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+   struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
+   unsigned opt = fpme->opt;
+   unsigned alloc_count = align( count, 4 );
+
+   struct vertex_header *pipeline_verts =
+      (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+
+   if (!pipeline_verts) 
+      return FALSE;
+
+   /* Fetch into our vertex buffer
+    */
+   draw_pt_fetch_run_linear( fpme->fetch,
+                             start,
+                             count,
+                             (char *)pipeline_verts );
+
+   /* Run the shader, note that this overwrites the data[] parts of
+    * the pipeline verts.  If there is no shader, ie if
+    * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+    * already in the correct place.
+    */
+   if (opt & PT_SHADE)
+   {
+      shader->run_linear(shader,
+                        (const float (*)[4])pipeline_verts->data,
+                        (      float (*)[4])pipeline_verts->data,
+                        (const float (*)[4])draw->pt.user.vs_constants,
+                        count,
+                        fpme->vertex_size,
+                        fpme->vertex_size);
+
+      if (geometry_shader)
+         draw_geometry_shader_run(geometry_shader,
+                                  (const float (*)[4])pipeline_verts->data,
+                                  (      float (*)[4])pipeline_verts->data,
+                                  (const float (*)[4])draw->pt.user.gs_constants,
+                                  count,
+                                  fpme->vertex_size,
+                                  fpme->vertex_size);
+   }
+
+   if (draw_pt_post_vs_run( fpme->post_vs,
+                           pipeline_verts,
+                           count,
+                           fpme->vertex_size ))
+   {
+      opt |= PT_PIPELINE;
+   }
+
+   /* Do we need to run the pipeline?
+    */
+   if (opt & PT_PIPELINE) {
+      draw_pipeline_run( fpme->draw,
+                         fpme->prim,
+                         pipeline_verts,
+                         count,
+                         fpme->vertex_size,
+                         draw_elts,
+                         draw_count );
+   }
+   else {
+      draw_pt_emit( fpme->emit,
+                   (const float (*)[4])pipeline_verts->data,
+                   count,
+                   fpme->vertex_size,
+                   draw_elts,
+                   draw_count );
+   }
+
+   FREE(pipeline_verts);
+   return TRUE;
+}
+
+
+
 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
 {
    /* nothing to do */
@@ -282,6 +408,7 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *
    fpme->base.prepare        = fetch_pipeline_prepare;
    fpme->base.run            = fetch_pipeline_run;
    fpme->base.run_linear     = fetch_pipeline_linear_run;
+   fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
    fpme->base.finish         = fetch_pipeline_finish;
    fpme->base.destroy        = fetch_pipeline_destroy;