summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/draw/draw_cliptest_tmp.h30
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c42
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h5
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h2
7 files changed, 79 insertions, 17 deletions
diff --git a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
index 7dba49b2870..bff266b8f98 100644
--- a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
@@ -36,12 +36,19 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
/* const */ float (*plane)[4] = pvs->draw->plane;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
+ unsigned cd[2];
const unsigned ef = pvs->draw->vs.edgeflag_output;
const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
const unsigned flags = (FLAGS);
unsigned need_pipeline = 0;
unsigned j;
unsigned i;
+ bool have_cd = false;
+ cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
+ cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
+
+ if (cd[0] != pos || cd[1] != pos)
+ have_cd = true;
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
@@ -89,14 +96,31 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
if (flags & DO_CLIP_USER) {
unsigned ucp_mask = ucp_enable;
-
+ int num_written_clipdistance = pvs->draw->vs.vertex_shader->info.num_written_clipdistance;
while (ucp_mask) {
unsigned plane_idx = ffs(ucp_mask)-1;
ucp_mask &= ~(1 << plane_idx);
plane_idx += 6;
- if (dot4(clipvertex, plane[plane_idx]) < 0) {
- mask |= 1 << plane_idx;
+ /*
+ * for user clipping check if we have a clip distance output
+ * and the shader has written to it, otherwise use clipvertex
+ * to decide when the plane is clipping.
+ */
+ if (have_cd && num_written_clipdistance) {
+ float clipdist;
+ i = plane_idx - 6;
+ out->have_clipdist = 1;
+ /* first four clip distance in first vector etc. */
+ if (i < 4)
+ clipdist = out->data[cd[0]][i];
+ else
+ clipdist = out->data[cd[1]][i-4];
+ if (clipdist < 0)
+ mask |= 1 << plane_idx;
+ } else {
+ if (dot4(clipvertex, plane[plane_idx]) < 0)
+ mask |= 1 << plane_idx;
}
}
}
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 6d7075e5452..7e554dcbb00 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -701,6 +701,12 @@ draw_current_shader_clipvertex_output(const struct draw_context *draw)
return draw->vs.clipvertex_output;
}
+uint
+draw_current_shader_clipdistance_output(const struct draw_context *draw, int index)
+{
+ return draw->vs.clipdistance_output[index];
+}
+
/**
* Return a pointer/handle for a driver/CSO rasterizer object which
* disabled culling, stippling, unfilled tris, etc.
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
index fbc8f675129..f7019725fdf 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -119,13 +119,17 @@ static void interp( const struct clip_stage *clip,
const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
+ unsigned clip_dist[2];
unsigned j;
+ clip_dist[0] = draw_current_shader_clipdistance_output(clip->stage.draw, 0);
+ clip_dist[1] = draw_current_shader_clipdistance_output(clip->stage.draw, 1);
+
/* Vertex header.
*/
dst->clipmask = 0;
dst->edgeflag = 0; /* will get overwritten later */
- dst->pad = 0;
+ dst->have_clipdist = in->have_clipdist;
dst->vertex_id = UNDEFINED_VERTEX_ID;
/* Interpolate the clip-space coords.
@@ -241,6 +245,29 @@ dot4(const float *a, const float *b)
a[3] * b[3]);
}
+/*
+ * this function extracts the clip distance for the current plane,
+ * it first checks if the shader provided a clip distance, otherwise
+ * it works out the value using the clipvertex
+ */
+static INLINE float getclipdist(const struct clip_stage *clipper,
+ struct vertex_header *vert,
+ int plane_idx)
+{
+ const float *plane;
+ float dp;
+ if (vert->have_clipdist && plane_idx >= 6) {
+ /* pick the correct clipdistance element from the output vectors */
+ int _idx = plane_idx - 6;
+ int cdi = _idx >= 4;
+ int vidx = cdi ? _idx - 4 : _idx;
+ dp = vert->data[draw_current_shader_clipdistance_output(clipper->stage.draw, cdi)][vidx];
+ } else {
+ plane = clipper->plane[plane_idx];
+ dp = dot4(vert->clip, plane);
+ }
+ return dp;
+}
/* Clip a triangle against the viewport and user clip planes.
*/
@@ -281,12 +308,12 @@ do_clip_tri( struct draw_stage *stage,
while (clipmask && n >= 3) {
const unsigned plane_idx = ffs(clipmask)-1;
const boolean is_user_clip_plane = plane_idx >= 6;
- const float *plane = clipper->plane[plane_idx];
struct vertex_header *vert_prev = inlist[0];
boolean *edge_prev = &inEdges[0];
- float dp_prev = dot4( vert_prev->clip, plane );
+ float dp_prev;
unsigned outcount = 0;
+ dp_prev = getclipdist(clipper, vert_prev, plane_idx);
clipmask &= ~(1<<plane_idx);
assert(n < MAX_CLIPPED_VERTICES);
@@ -299,7 +326,7 @@ do_clip_tri( struct draw_stage *stage,
struct vertex_header *vert = inlist[i];
boolean *edge = &inEdges[i];
- float dp = dot4( vert->clip, plane );
+ float dp = getclipdist(clipper, vert, plane_idx);
if (!IS_NEGATIVE(dp_prev)) {
assert(outcount < MAX_CLIPPED_VERTICES);
@@ -421,17 +448,14 @@ do_clip_line( struct draw_stage *stage,
const struct clip_stage *clipper = clip_stage( stage );
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
- const float *pos0 = v0->clip;
- const float *pos1 = v1->clip;
float t0 = 0.0F;
float t1 = 0.0F;
struct prim_header newprim;
while (clipmask) {
const unsigned plane_idx = ffs(clipmask)-1;
- const float *plane = clipper->plane[plane_idx];
- const float dp0 = dot4( pos0, plane );
- const float dp1 = dot4( pos1, plane );
+ const float dp0 = getclipdist(clipper, v0, plane_idx);
+ const float dp1 = getclipdist(clipper, v1, plane_idx);
if (dp1 < 0.0F) {
float t = dp1 / (dp1 - dp0);
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index aa9b602a353..31beb4b98e3 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -72,7 +72,7 @@ struct tgsi_sampler;
struct vertex_header {
unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
unsigned edgeflag:1;
- unsigned pad:1;
+ unsigned have_clipdist:1;
unsigned vertex_id:16;
float clip[4];
@@ -232,7 +232,7 @@ struct draw_context
uint position_output;
uint edgeflag_output;
uint clipvertex_output;
-
+ uint clipdistance_output[2];
/** TGSI program interpreter runtime state */
struct tgsi_exec_machine *machine;
@@ -381,6 +381,7 @@ void draw_gs_destroy( struct draw_context *draw );
uint draw_current_shader_outputs(const struct draw_context *draw);
uint draw_current_shader_position_output(const struct draw_context *draw);
uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
+uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index);
void draw_remove_extra_vertex_attribs(struct draw_context *draw);
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index a8d65fd5d7b..a83bb59a748 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -31,7 +31,7 @@
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
-
+#include "draw/draw_vs.h"
#define DO_CLIP_XY 0x1
#define DO_CLIP_FULL_Z 0x2
@@ -56,7 +56,7 @@ initialize_vertex_header(struct vertex_header *header)
{
header->clipmask = 0;
header->edgeflag = 1;
- header->pad = 0;
+ header->have_clipdist = 0;
header->vertex_id = UNDEFINED_VERTEX_ID;
}
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index 150653c669a..56c4f882cae 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -132,6 +132,11 @@ draw_create_vertex_shader(struct draw_context *draw,
vs->info.output_semantic_index[i] == 0) {
found_clipvertex = TRUE;
vs->clipvertex_output = i;
+ } else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
+ if (vs->info.output_semantic_index[i] == 0)
+ vs->clipdistance_output[0] = i;
+ else
+ vs->clipdistance_output[1] = i;
}
}
if (!found_clipvertex)
@@ -156,6 +161,8 @@ draw_bind_vertex_shader(struct draw_context *draw,
draw->vs.position_output = dvs->position_output;
draw->vs.edgeflag_output = dvs->edgeflag_output;
draw->vs.clipvertex_output = dvs->clipvertex_output;
+ draw->vs.clipdistance_output[0] = dvs->clipdistance_output[0];
+ draw->vs.clipdistance_output[1] = dvs->clipdistance_output[1];
dvs->prepare( dvs, draw );
}
else {
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index a3b90faa24b..8a440911af7 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -112,7 +112,7 @@ struct draw_vertex_shader {
unsigned position_output;
unsigned edgeflag_output;
unsigned clipvertex_output;
-
+ unsigned clipdistance_output[2];
/* Extracted from shader:
*/
const float (*immediates)[4];