llvmpipe: Texture cache in 4 ubytes instead of 4 floats.
[mesa.git] / src / gallium / auxiliary / draw / draw_pipe_wide_point.c
index df92e3f2d06fff6c96db162406cc73a2d1b3832c..7d76a7dbf39e32cfc7d385e59826453a23e21f42 100644 (file)
 /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "pipe/p_util.h"
+/**
+ * Notes on wide points and sprite mode:
+ *
+ * In wide point/sprite mode we effectively need to convert each incoming
+ * vertex into four outgoing vertices specifying the corners of a quad.
+ * Since we don't (yet) have geometry shaders, we have to handle this here
+ * in the draw module.
+ *
+ * For sprites, it also means that this is where we have to handle texcoords
+ * for the vertices of the quad.  OpenGL's GL_COORD_REPLACE state specifies
+ * if/how enabled texcoords are automatically generated for sprites.  We pass
+ * that info through gallium in the pipe_rasterizer_state::sprite_coord_mode
+ * array.
+ *
+ * Additionally, GLSL's gl_PointCoord fragment attribute has to be handled
+ * here as well.  This is basically an additional texture/generic attribute
+ * that varies .x from 0 to 1 horizontally across the point and varies .y
+ * vertically from 0 to 1 down the sprite.
+ *
+ * With geometry shaders, the state tracker could create a GS to do
+ * most/all of this.
+ */
+
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_shader_tokens.h"
 #include "draw_vs.h"
@@ -50,6 +75,8 @@ struct widepoint_stage {
    uint num_texcoords;
 
    int psize_slot;
+
+   int point_coord_fs_input;  /**< input for pointcoord */
 };
 
 
@@ -61,8 +88,6 @@ widepoint_stage( struct draw_stage *stage )
 }
 
 
-
-
 /**
  * Set the vertex texcoords for sprite mode.
  * Coords may be left untouched or set to a right-side-up or upside-down
@@ -84,6 +109,15 @@ static void set_texcoords(const struct widepoint_stage *wide,
          v->data[j][3] = tc[3];
       }
    }
+
+   if (wide->point_coord_fs_input >= 0) {
+      /* put gl_PointCoord into the extra vertex slot */
+      uint slot = wide->stage.draw->extra_vp_outputs.slot;
+      v->data[slot][0] = tc[0];
+      v->data[slot][1] = tc[1];
+      v->data[slot][2] = 0.0F;
+      v->data[slot][3] = 1.0F;
+   }
 }
 
 
@@ -96,6 +130,7 @@ static void widepoint_point( struct draw_stage *stage,
                              struct prim_header *header )
 {
    const struct widepoint_stage *wide = widepoint_stage(stage);
+   const unsigned pos = stage->draw->vs.position_output;
    const boolean sprite = (boolean) stage->draw->rasterizer->point_sprite;
    float half_size;
    float left_adj, right_adj, bot_adj, top_adj;
@@ -108,10 +143,10 @@ static void widepoint_point( struct draw_stage *stage,
    struct vertex_header *v2 = dup_vert(stage, header->v[0], 2);
    struct vertex_header *v3 = dup_vert(stage, header->v[0], 3);
 
-   float *pos0 = v0->data[0];
-   float *pos1 = v1->data[0];
-   float *pos2 = v2->data[0];
-   float *pos3 = v3->data[0];
+   float *pos0 = v0->data[pos];
+   float *pos1 = v1->data[pos];
+   float *pos2 = v2->data[pos];
+   float *pos3 = v3->data[pos];
 
    /* point size is either per-vertex or fixed size */
    if (wide->psize_slot >= 0) {
@@ -170,6 +205,16 @@ static void widepoint_point( struct draw_stage *stage,
 }
 
 
+static int
+find_pntc_input_attrib(struct draw_context *draw)
+{
+   /* Scan the fragment program's input decls to find the pointcoord
+    * attribute.  The xy components will store the point coord.
+    */
+   return 0; /* XXX fix this */
+}
+
+
 static void widepoint_first_point( struct draw_stage *stage, 
                              struct prim_header *header )
 {
@@ -207,6 +252,18 @@ static void widepoint_first_point( struct draw_stage *stage,
          }
       }
       wide->num_texcoords = j;
+
+      /* find fragment shader PointCoord input */
+      wide->point_coord_fs_input = find_pntc_input_attrib(draw);
+
+      /* setup extra vp output (point coord implemented as a texcoord) */
+      draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
+      draw->extra_vp_outputs.semantic_index = 0;
+      draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs;
+   }
+   else {
+      wide->point_coord_fs_input = -1;
+      draw->extra_vp_outputs.slot = 0;
    }
 
    wide->psize_slot = -1;
@@ -230,6 +287,7 @@ static void widepoint_flush( struct draw_stage *stage, unsigned flags )
 {
    stage->point = widepoint_first_point;
    stage->next->flush( stage->next, flags );
+   stage->draw->extra_vp_outputs.slot = 0;
 }
 
 
@@ -256,6 +314,7 @@ struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
       goto fail;
 
    wide->stage.draw = draw;
+   wide->stage.name = "wide-point";
    wide->stage.next = NULL;
    wide->stage.point = widepoint_first_point;
    wide->stage.line = draw_pipe_passthrough_line;