draw/llvmpipe: fix transform feedback position + enable other extensions
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_so_emit.c
index 80a164a0d7da1110cf8e4cef8c2771286dc30368..13d8470e4ecb900e093155e6c5f9e86097f87e8d 100644 (file)
@@ -42,20 +42,24 @@ struct pt_so_emit {
 
    unsigned input_vertex_stride;
    const float (*inputs)[4];
-
+   const float (*pre_clip_pos)[4];
    boolean has_so;
-
+   boolean use_pre_clip_pos;
+   int pos_idx;
    unsigned emitted_primitives;
    unsigned emitted_vertices;
    unsigned generated_primitives;
 };
 
 
-void draw_pt_so_emit_prepare(struct pt_so_emit *emit)
+void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos)
 {
    struct draw_context *draw = emit->draw;
 
+   emit->use_pre_clip_pos = use_pre_clip_pos;
    emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs > 0);
+   if (use_pre_clip_pos)
+      emit->pos_idx = draw_current_shader_position_output(draw);
 
    /* if we have a state with outputs make sure we have
     * buffers to output to */
@@ -87,12 +91,15 @@ static void so_emit_prim(struct pt_so_emit *so,
    unsigned input_vertex_stride = so->input_vertex_stride;
    struct draw_context *draw = so->draw;
    const float (*input_ptr)[4];
+   const float (*pcp_ptr)[4] = NULL;
    const struct pipe_stream_output_info *state =
       &draw->vs.vertex_shader->state.stream_output;
    float *buffer;
    int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
 
    input_ptr = so->inputs;
+   if (so->use_pre_clip_pos)
+      pcp_ptr = so->pre_clip_pos;
 
    ++so->generated_primitives;
 
@@ -117,12 +124,17 @@ static void so_emit_prim(struct pt_so_emit *so,
 
    for (i = 0; i < num_vertices; ++i) {
       const float (*input)[4];
+      const float (*pre_clip_pos)[4];
       unsigned total_written_compos = 0;
       int ob;
       /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
       input = (const float (*)[4])(
          (const char *)input_ptr + (indices[i] * input_vertex_stride));
 
+      if (pcp_ptr)
+         pre_clip_pos = (const float (*)[4])(
+         (const char *)pcp_ptr + (indices[i] * input_vertex_stride));
+
       for (slot = 0; slot < state->num_outputs; ++slot) {
          unsigned idx = state->output[slot].register_index;
          unsigned start_comp = state->output[slot].start_component;
@@ -133,7 +145,10 @@ static void so_emit_prim(struct pt_so_emit *so,
          buffer = (float *)((char *)draw->so.targets[ob]->mapping +
                             draw->so.targets[ob]->target.buffer_offset +
                             draw->so.targets[ob]->internal_offset) + state->output[slot].dst_offset;
-         memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float));
+         if (idx == so->pos_idx && pcp_ptr)
+            memcpy(buffer, &pre_clip_pos[start_comp], num_comps * sizeof(float));
+         else
+            memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float));
          total_written_compos += num_comps;
       }
       for (ob = 0; ob < draw->so.num_targets; ++ob)
@@ -203,6 +218,9 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
    emit->emitted_primitives = 0;
    emit->generated_primitives = 0;
    emit->input_vertex_stride = input_verts->stride;
+   if (emit->use_pre_clip_pos)
+     emit->pre_clip_pos = (const float (*)[4])input_verts->verts->pre_clip_pos;
+
    emit->inputs = (const float (*)[4])input_verts->verts->data;
 
    /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/